home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / INTERNET / UPC2S1.ZIP / SECURITY.C < prev    next >
C/C++ Source or Header  |  1993-10-03  |  34KB  |  875 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    s e c u r i t y . c                                             */
  3. /*                                                                    */
  4. /*    Security routines for UUPC/extended                             */
  5. /*                                                                    */
  6. /*    Copyright (c) 1991, Andrew H. Derbyshire                        */
  7. /*    See README.PRN for additional copyrights and restrictions       */
  8. /*--------------------------------------------------------------------*/
  9.  
  10. /*--------------------------------------------------------------------*/
  11. /*                          RCS Information                           */
  12. /*--------------------------------------------------------------------*/
  13.  
  14. /*
  15.  *    $Id: security.c 1.9 1993/10/03 20:37:34 ahd Exp $
  16.  *
  17.  *    Revision history:
  18.  *    $Log: security.c $
  19.  *     Revision 1.9  1993/10/03  20:37:34  ahd
  20.  *     Lower case all strings loaded into directory array
  21.  *
  22.  *     Revision 1.8  1993/09/20  04:38:11  ahd
  23.  *     TCP/IP support from Dave Watt
  24.  *     't' protocol support
  25.  *     OS/2 2.x support
  26.  *
  27.  *     Revision 1.7  1993/08/03  03:11:49  ahd
  28.  *     Make missing directories non-fatal
  29.  *
  30.  *     Revision 1.6  1993/05/06  03:41:48  ahd
  31.  *     Use NULL to denote current directory, not "."
  32.  *
  33.  *     Revision 1.5  1993/04/11  00:31:04  ahd
  34.  *     Global edits for year, TEXT, etc.
  35.  *
  36.  *     Revision 1.4  1993/03/06  22:48:23  ahd
  37.  *     Re-do compare of sort to void bug in some qsort() functions
  38.  *
  39.  * Revision 1.3  1992/11/22  20:58:55  ahd
  40.  * Normalize directories as read
  41.  * Use strpool to allocate const strings
  42.  *
  43.  * Revision 1.2  1992/11/19  02:57:31  ahd
  44.  * drop rcsid
  45.  *
  46.  * Revision 1.1  1992/11/16  05:00:26  ahd
  47.  * Initial revision
  48.  *
  49.  */
  50.  
  51. /*--------------------------------------------------------------------*/
  52. /*                        System include files                        */
  53. /*--------------------------------------------------------------------*/
  54.  
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <ctype.h>
  58. #include <string.h>
  59. #include <sys/types.h>        /* Only really needed for MS C         */
  60. #include <sys/stat.h>
  61. #include <time.h>
  62. #include <direct.h>
  63.  
  64. /*--------------------------------------------------------------------*/
  65. /*                    UUPC/extended include files                     */
  66. /*--------------------------------------------------------------------*/
  67.  
  68. #include "lib.h"
  69. #include "hostable.h"
  70. #include "security.h"
  71. #include "usertabl.h"
  72. #include "expath.h"
  73. #include "hlib.h"
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*                           Local defines                            */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. static boolean InitEntry( char *buf, const char *fname);
  80.  
  81. static size_t InitDir( char *directories,
  82.          const REMOTE_ACCESS access,
  83.          const boolean grant,
  84.          struct HostSecurity *anchor,
  85.          size_t max_elements );
  86.  
  87. int dircmp( const void *a , const void *b );
  88.  
  89. /*--------------------------------------------------------------------*/
  90. /*                          Global varables                           */
  91. /*--------------------------------------------------------------------*/
  92.  
  93. struct HostSecurity *securep = NULL;
  94. static struct HostSecurity *default_security = NULL;
  95. static char drive[] = "C:";
  96.  
  97. currentfile();
  98.  
  99. /*--------------------------------------------------------------------*/
  100. /*    L o a d S e c u r i t y                                         */
  101. /*                                                                    */
  102. /*    Initialize security processing; returns TRUE if security        */
  103. /*    initialized, otherewise FALSE                                   */
  104. /*--------------------------------------------------------------------*/
  105.  
  106. boolean LoadSecurity( void )
  107. {
  108.    char fname[FILENAME_MAX];
  109.    char buffer[BUFSIZ*4];     /* Allows around 2K for the data       */
  110.    struct HostTable *hostp;
  111.    FILE *stream;
  112.  
  113. /*--------------------------------------------------------------------*/
  114. /*      Generate a filename for the permissions file and open it      */
  115. /*--------------------------------------------------------------------*/
  116.  
  117.    mkfilename(fname, E_confdir, PERMISSIONS);
  118.    stream  = FOPEN( fname, "r",TEXT_MODE);
  119.  
  120.    if ( stream == NULL )      /* Did the file open?                  */
  121.    {                          /* No --> Report failure to caller     */
  122.       printerr( fname );
  123.       return FALSE;
  124.    } /* ( stream == NULL ) */
  125.  
  126. /*--------------------------------------------------------------------*/
  127. /*              Get current drive for normalizing names               */
  128. /*--------------------------------------------------------------------*/
  129.  
  130.    getcwd( buffer, sizeof buffer );
  131.    *drive = *buffer;
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*               Begin processing the PERMISSIONS file                */
  135. /*--------------------------------------------------------------------*/
  136.  
  137.    while ( !feof( stream ) )
  138.    {
  139.       char *next = buffer;
  140.  
  141. /*--------------------------------------------------------------------*/
  142. /*                Build up the buffer to be processed                 */
  143. /*--------------------------------------------------------------------*/
  144.  
  145.       *next = '\0';
  146.       while( fgets( next, sizeof buffer - strlen(next), stream ) != NULL)
  147.       {
  148.          if ((*next == '#') || (*next == '\n'))
  149.          {
  150.             *next = '\0';
  151.             continue;
  152.          }
  153.  
  154.          next = next + strlen( next ) - 1;
  155.          if (*next == '\n')
  156.             *next-- = '\0';
  157.          else if (!feof( stream ))  /* Did we hit EOF?               */
  158.          {                    /* No --> Presume the buffer overflowed*/
  159.             printmsg(0,"LoadSecurity: buffer overflow while reading %s",
  160.              fname);
  161.             fclose( stream );
  162.             return FALSE;
  163.          }
  164.  
  165.          while( isspace( *next ))   /* Dump trailing white space     */
  166.             *next-- = '\0';
  167.  
  168.          if (*next == '\\')
  169.             *next = '\0';
  170.          else
  171.             break;
  172.       } /* while( fgets( next, sizeof available, stream )) != NULL)) */
  173.  
  174. /*--------------------------------------------------------------------*/
  175. /*            Done read the data; verify we had no errors             */
  176. /*--------------------------------------------------------------------*/
  177.  
  178.       if (ferror( stream ))
  179.       {
  180.          printerr( fname );
  181.          clearerr( stream );
  182.          return FALSE;
  183.       } /* if */
  184.  
  185. /*--------------------------------------------------------------------*/
  186. /*              Build entries for one permissions entry               */
  187. /*--------------------------------------------------------------------*/
  188.  
  189.       printmsg(10,"Buffer is \"%s\"", buffer );
  190.       if ((*next != '\0') && !InitEntry( buffer , fname))
  191.       {
  192.          fclose( stream );
  193.          return FALSE;
  194.       }
  195.  
  196.    } /* while ( !feof( stream ) ) */
  197.  
  198. /*--------------------------------------------------------------------*/
  199. /*                    Initialize local host entry                     */
  200. /*--------------------------------------------------------------------*/
  201.  
  202.    hostp = checkname( E_nodename );
  203.    if ( hostp == NULL )
  204.       panic();
  205.    hostp->hsecure = malloc( sizeof *hostp->hsecure );
  206.    checkref( hostp->hsecure );
  207.    memset( hostp->hsecure , '\0', sizeof *hostp->hsecure);
  208.                               /* Clear pointers                      */
  209.    hostp->hsecure->local = TRUE;
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*                          Return to caller                          */
  213. /*--------------------------------------------------------------------*/
  214.  
  215.    fclose( stream );
  216.    return TRUE;
  217.  
  218. } /* LoadSecurity */
  219.  
  220. /*--------------------------------------------------------------------*/
  221. /*    I n i t i a l i z e E n t r y                                   */
  222. /*                                                                    */
  223. /*    Initialize a single permissions file entry                      */
  224. /*--------------------------------------------------------------------*/
  225.  
  226. static boolean InitEntry( char *buf, const char *fname)
  227. {
  228.  
  229. /*--------------------------------------------------------------------*/
  230. /*                      Configuration variables                       */
  231. /*--------------------------------------------------------------------*/
  232.  
  233.   static char *myname, *validate, *commands;
  234.  
  235.   static char *callback, *xpubdir, *machine, *noread, *nowrite;
  236.   static char *request, *read, *sendfiles,  *write, *logname;
  237.  
  238.   static CONFIGTABLE securetable[] = {
  239.      { "callback",      &callback,     B_TOKEN  | B_UUXQT } ,
  240.      { "commands",      &commands,     B_CLIST  | B_UUXQT } ,
  241.      { "logname",       &logname,      B_TOKEN  | B_UUXQT } ,
  242.      { "machine",       &machine,      B_TOKEN  | B_UUXQT | B_MALLOC } ,
  243.      { "myname",        &myname,       B_TOKEN  | B_UUXQT } ,
  244.      { "pubdir",        &xpubdir,      B_PATH   | B_UUXQT } ,
  245.      { "noread",        &noread,       B_TOKEN  | B_UUXQT | B_MALLOC } ,
  246.      { "nowrite",       &nowrite,      B_TOKEN  | B_UUXQT | B_MALLOC } ,
  247.      { "read",          &read,         B_TOKEN  | B_UUXQT | B_MALLOC} ,
  248.      { "request",       &request,      B_TOKEN  | B_UUXQT } ,
  249.      { "sendfiles",     &sendfiles,    B_TOKEN  | B_UUXQT } ,
  250.      { "validate",      &validate,     B_CLIST  | B_UUXQT } ,
  251.      { "write",         &write,        B_TOKEN  | B_UUXQT | B_MALLOC } ,
  252.      { nil(char) }
  253. }; /* securetable */
  254.  
  255.    struct HostSecurity *anchor = malloc( sizeof *anchor );
  256.  
  257. /*--------------------------------------------------------------------*/
  258. /*                  Default list of allowed commands                  */
  259. /*--------------------------------------------------------------------*/
  260.  
  261.    static char *command_list[] = { "rmail", "rnews" , NULL } ;
  262.  
  263. /*--------------------------------------------------------------------*/
  264. /*                          Other variables                           */
  265. /*--------------------------------------------------------------------*/
  266.  
  267.    boolean success = TRUE;
  268.    CONFIGTABLE *tptr;
  269.    char *token = buf;
  270.    char *parameter;
  271.    struct UserTable *userp;
  272.    struct HostTable *hostp;
  273.    size_t max_elements = 16;
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*                 Initialize the security structure                  */
  277. /*--------------------------------------------------------------------*/
  278.  
  279.    checkref( anchor );
  280.    memset( anchor , '\0', sizeof *anchor); /* Clear pointers         */
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*                        Initialize the table                        */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    for (tptr = securetable; tptr->sym != nil(char); tptr++)
  287.       if (tptr->bits & (B_TOKEN | B_STRING | B_LIST| B_CLIST))
  288.          *(tptr->loc) = nil(char);
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*                 Parse the information in the table                 */
  292. /*--------------------------------------------------------------------*/
  293.  
  294.    while ( (parameter = strtok( token, WHITESPACE )) != NULL)
  295.    {
  296.       token = strtok( NULL, ""); /* Save for next pass               */
  297. #ifdef _DEBUG
  298.       printmsg(8,"InitEntry: Parameter is \"%s\"", parameter);
  299.       if ( token != NULL )
  300.          printmsg(10,"InitEntry: Buffer remaining is \"%s\"", token);
  301. #endif
  302.       if (!processconfig(parameter, SYSTEM_CONFIG,B_UUXQT,securetable,NULL))
  303.       {
  304.          printmsg(0,
  305.           "Unknown keyword \"%s\" in %s ignored",parameter, fname);
  306.          success = FALSE;
  307.       } /* if */
  308.    } /* while ( (parameter = strtok( token, WHITESPACE )) != NULL) */
  309.  
  310.    anchor->commands = (char **) commands;
  311.    anchor->validate = (char **) validate;
  312.  
  313. /*--------------------------------------------------------------------*/
  314. /*    Now we have the data procesed by keyword, break it down more    */
  315. /*--------------------------------------------------------------------*/
  316.  
  317.    if ((logname == NULL) && (machine == NULL))
  318.    {
  319.       printmsg(0,"InitEntry: No machine or logname given in %s",
  320.                   fname );
  321.       success = FALSE;
  322.    } /* if ((logname == NULL) && (machine == NULL)) */
  323.  
  324. /*--------------------------------------------------------------------*/
  325. /*                        Handle a login name                         */
  326. /*--------------------------------------------------------------------*/
  327.  
  328.    if (logname != NULL)
  329.    {
  330.       printmsg(10,"InitEntry: Processing logname=%s",logname );
  331.       userp = checkuser( logname );
  332.       if ( userp == BADUSER )
  333.       {
  334.          printmsg(0,"InitEntry: Invalid user id in %s, LOGNAME=%s",
  335.                      fname, logname );
  336.          success = FALSE;
  337.       } /* if ( userp == BADUSER ) */
  338.       else if (userp->hsecure == NULL)
  339.          userp->hsecure = anchor;
  340.       else {
  341.          printmsg(0,"InitEntry: Duplicate user id in %s, LOGNAME=%s",
  342.                      fname, logname );
  343.          success = FALSE;
  344.       } /* else */
  345.    } /* if (logname != NULL) */
  346.  
  347. /*--------------------------------------------------------------------*/
  348. /*                        Handle machine names                        */
  349. /*--------------------------------------------------------------------*/
  350.  
  351.    token = machine;
  352.    while( token != NULL )
  353.    {
  354.       char *host = strtok( token, ":");
  355.       printmsg(10,"InitEntry: Processing machine=%s", host );
  356.  
  357.       token = strtok( NULL, "");
  358.       if ( equal( host , ANY_HOST ) )
  359.       {
  360.          if ( default_security == NULL )
  361.             default_security = anchor;
  362.          else {
  363.             printmsg(0,"InitEntry: "
  364.                        "Multiple MACHINE entries in %s which specify OTHER",
  365.                        fname);
  366.             success = FALSE;
  367.          } /* else */
  368.       } /* if ( equal( host , ANY_HOST ) ) */
  369.       else {
  370.          hostp = checkreal( host );
  371.          if ( hostp == BADUSER )
  372.          {
  373.             printmsg(0,"InitEntry: Invalid host id in %s, MACHINE=%s",
  374.                         fname, host );
  375.             success = FALSE;
  376.          } /* if ( hostp == BADUSER ) */
  377.          else if (hostp->hsecure == NULL)
  378.             hostp->hsecure = anchor;
  379.          else {
  380.             printmsg(0,"InitEntry: Duplicate host id in %s, MACHINE=%s",
  381.                         fname, token );
  382.             success = FALSE;
  383.          } /* else */
  384.       } /* else */
  385.    } /* while( token != NULL ) */
  386.  
  387.    if ( machine != NULL )
  388.       free( machine );
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*                       Handle validated names                       */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.    if ( anchor->validate != NULL )
  395.    {
  396.       char **plist = anchor->validate;
  397.  
  398.       while ( *plist != NULL )
  399.       {
  400.          hostp = checkreal( *plist );
  401.  
  402.          if ( hostp == BADUSER )
  403.          {
  404.             printmsg(0,"InitEntry: Invalid host id in %s, VALIDATE=%s",
  405.                         fname, *plist);
  406.             success = FALSE;
  407.          } /* if ( hostp == BADUSER ) */
  408.          else
  409.             hostp->anylogin = FALSE;   /* Flag we must use specific
  410.                                           login                      */
  411.  
  412.          plist++;             /* Step to next hostname in list       */
  413.  
  414.       } /* while ( *plist != NULL ) */
  415.  
  416.    } /* if ( anchor->validate != NULL ) */
  417.  
  418. /*--------------------------------------------------------------------*/
  419. /*                          Handle CALLBACK                           */
  420. /*--------------------------------------------------------------------*/
  421.  
  422.    if ( callback != NULL )
  423.    {
  424.       if (equal(strlwr(callback),"no"))
  425.          anchor->callback = FALSE;
  426.       else if (equal(callback,"yes"))
  427.          anchor->callback = TRUE;
  428.       else {
  429.          printmsg(0,"InitEntry: Invalid value in %s, CALLBACK=%s",
  430.                      fname, callback );
  431.          success = FALSE;
  432.       } /* else */
  433.    } /* if ( callback != NULL ) */
  434.  
  435. /*--------------------------------------------------------------------*/
  436. /*                          Handle REQUEST                            */
  437. /*--------------------------------------------------------------------*/
  438.  
  439.    if ( request != NULL )
  440.    {
  441.       if (equal(strlwr(request),"no"))
  442.          anchor->request = FALSE;
  443.       else if (equal(request,"yes"))
  444.          anchor->request = TRUE;
  445.       else {
  446.          printmsg(0,"InitEntry: Invalid value in %s, REQUEST=%s",
  447.                      fname, request );
  448.          success = FALSE;
  449.       } /* else */
  450.  
  451.    } /* if ( request != NULL ) */
  452.  
  453. /*--------------------------------------------------------------------*/
  454. /*                          Handle SENDFILES                          */
  455. /*--------------------------------------------------------------------*/
  456.  
  457.    if ( sendfiles != NULL)
  458.    {
  459.       if (equal(strlwr(sendfiles),"call"))
  460.          anchor->sendfiles = FALSE;
  461.       else if (equal(sendfiles,"yes"))
  462.          anchor->sendfiles = TRUE;
  463.       else {
  464.          printmsg(0,"InitEntry: Invalid value in %s, SENDFILES=%s",
  465.                      fname, sendfiles );
  466.          success = FALSE;
  467.       } /* else */
  468.    } /* if */
  469.  
  470. /*--------------------------------------------------------------------*/
  471. /*                          handle commands                           */
  472. /*--------------------------------------------------------------------*/
  473.  
  474.    if ( anchor->commands == NULL )
  475.       anchor->commands = command_list;
  476.  
  477. /*--------------------------------------------------------------------*/
  478. /*                 Handle local system name aliasing                  */
  479. /*--------------------------------------------------------------------*/
  480.  
  481.    if (myname == NULL)
  482.       anchor->myname = E_nodename;
  483.    else
  484.       anchor->myname = myname;
  485.  
  486. /*--------------------------------------------------------------------*/
  487. /*                      Directory processing                          */
  488. /*--------------------------------------------------------------------*/
  489.  
  490.    anchor->dirlist = malloc( sizeof anchor->dirlist[0] * max_elements );
  491.    checkref( anchor->dirlist );
  492.  
  493.    max_elements = InitDir( read,    ALLOW_READ,  TRUE,  anchor,
  494.             max_elements );
  495.    free( read );
  496.    max_elements = InitDir( noread,  ALLOW_READ,  FALSE, anchor,
  497.             max_elements );
  498.    free( noread );
  499.    max_elements = InitDir( write,   ALLOW_WRITE, TRUE,  anchor,
  500.             max_elements );
  501.    free( write );
  502.    max_elements = InitDir( nowrite, ALLOW_WRITE, FALSE, anchor,
  503.                            max_elements );
  504.    free( nowrite );
  505.  
  506. /*--------------------------------------------------------------------*/
  507. /*                 Provide a default public directory                 */
  508. /*--------------------------------------------------------------------*/
  509.  
  510.    if (xpubdir == NULL)
  511.        anchor->pubdir = E_pubdir;
  512.    else
  513.        anchor->pubdir = xpubdir;
  514.  
  515. /*--------------------------------------------------------------------*/
  516. /*    If no explicit directories given, give them access to pubdir    */
  517. /*--------------------------------------------------------------------*/
  518.  
  519.    if ( anchor->dirsize == 0)
  520.    {
  521.       max_elements = InitDir( anchor->pubdir, ALLOW_READ, TRUE,
  522.                               anchor, max_elements );
  523.       max_elements = InitDir( anchor->pubdir, ALLOW_WRITE, TRUE,
  524.                               anchor, max_elements );
  525.    }
  526.  
  527.    if ( max_elements == 0 )
  528.       success = FALSE;
  529.    else {
  530.       size_t subscript;
  531.       anchor->dirlist = realloc( anchor->dirlist,
  532.                                  anchor->dirsize * sizeof anchor->dirlist[0]);
  533.       checkref( anchor->dirlist );
  534.       qsort(anchor->dirlist, anchor->dirsize, sizeof(anchor->dirlist[0]),
  535.                dircmp);
  536.       if ( debuglevel > 4 )
  537.       for ( subscript = 0; subscript < anchor->dirsize; subscript++ )
  538.          printmsg(4, "InitEntry: dirlist[%d] %s\t%s\t%s",
  539.                   subscript,
  540.                   anchor->dirlist[subscript].grant ? "grant" : "deny" ,
  541.                   anchor->dirlist[subscript].priv == ALLOW_WRITE ?
  542.                            "WRITE" : "READ" ,
  543.                   anchor->dirlist[subscript].path );
  544.    } /* else */
  545.  
  546. /*--------------------------------------------------------------------*/
  547. /*                          Return to caller                          */
  548. /*--------------------------------------------------------------------*/
  549.  
  550.    return success;
  551.  
  552. } /* InitEntry */
  553.  
  554. /*--------------------------------------------------------------------*/
  555. /*    I n i t D i r                                                   */
  556. /*                                                                    */
  557. /*    Initialize security table directory entries                     */
  558. /*--------------------------------------------------------------------*/
  559.  
  560. static size_t InitDir( char *directories,
  561.          const REMOTE_ACCESS access,
  562.          const boolean grant,
  563.          struct HostSecurity *anchor,
  564.          size_t max_elements )
  565. {
  566.    char *field = directories;
  567.    char *token = directories;
  568.    struct  stat    statbuf;
  569.    size_t subscript;
  570.  
  571. /*--------------------------------------------------------------------*/
  572. /*    Don't process data if no input or we previously had an error    */
  573. /*--------------------------------------------------------------------*/
  574.  
  575.    if ( (directories == NULL ) || ( max_elements == 0) )
  576.       return max_elements;
  577.  
  578. /*--------------------------------------------------------------------*/
  579. /*              Begin loop to process names in the path               */
  580. /*--------------------------------------------------------------------*/
  581.  
  582.    while ( (token = NextField( field )) != NULL)
  583.    {
  584.       char path[FILENAME_MAX];
  585.       if ( anchor->dirsize == max_elements )
  586.       {
  587.          max_elements = max_elements * 2;
  588.          anchor->dirlist = realloc( anchor->dirlist,
  589.                 sizeof anchor->dirlist[0] * max_elements );
  590.          checkref( anchor->dirlist );
  591.       }
  592.  
  593. /*--------------------------------------------------------------------*/
  594. /*                      Normalize directory name                      */
  595. /*--------------------------------------------------------------------*/
  596.  
  597.       strcpy( path, token);
  598.       if (isalpha(path[0]) && (path[1] != ':') && (strlen(path) == 2))
  599.          ;                 /* Yup, do nothing for root drive names  */
  600.       else if ( expand_path( path, NULL, E_pubdir , NULL) == NULL )
  601.       {
  602.          printmsg(0, "Unable to expand path \"%s\"",path );
  603.          return 0;
  604.       } /* else */
  605.  
  606.       printmsg(5,"InitDir: Normalizing path %s", path );
  607.       field = newstr( normalize( path ));
  608.  
  609. /*--------------------------------------------------------------------*/
  610. /*               Verify it really is a valid directory                */
  611. /*--------------------------------------------------------------------*/
  612.  
  613.       if ( strlen( field ) > 2 ) /* More than just drive/colon? (x:) */
  614.       {                       /* Yes --> Go check disk for path      */
  615.          if (stat(field , &statbuf) != 0)
  616.          {
  617.             printmsg(0,"Warning ... invalid PERMISSIONS file entry %s:",
  618.                        token );
  619.             printerr(field);
  620.          }
  621.          else if ((statbuf.st_mode & S_IFDIR) == 0)
  622.             printmsg(0,"InitDir: \"%s\" is a file, not a directory",
  623.                         field);
  624.       } /* if ( strlen( field ) > 2 ) */
  625.  
  626.       strlwr( field);            // Lower case for compares
  627.  
  628. /*--------------------------------------------------------------------*/
  629. /*           Verify this directory not already in the list            */
  630. /*--------------------------------------------------------------------*/
  631.  
  632.       for (subscript = 0; subscript < anchor->dirsize ; subscript++)
  633.       {
  634.          if ( (access == anchor->dirlist[subscript].priv) &&
  635.               equal( field, anchor->dirlist[subscript].path))
  636.          {
  637.             printmsg(0,"InitDir: Duplicate directory %s/", field);
  638.             return 0;
  639.          } /* if */
  640.       } /* for */
  641.  
  642. /*--------------------------------------------------------------------*/
  643. /*            No conflict, add this directory to the list             */
  644. /*--------------------------------------------------------------------*/
  645.  
  646.       printmsg(10,"InitDir: Adding \"%s\" as \"%s\"", token , field);
  647.       anchor->dirlist[subscript].path  = field;
  648.       anchor->dirlist[subscript].priv  = access;
  649.       anchor->dirlist[subscript].grant = grant;
  650.       anchor->dirsize++;
  651.  
  652.       field = NULL;           /* Look at next field next pass        */
  653.  
  654.    } /* while ( (field = NextField( field )) != NULL) */
  655.  
  656. /*--------------------------------------------------------------------*/
  657. /*                          Return to caller                          */
  658. /*--------------------------------------------------------------------*/
  659.  
  660.    return max_elements;
  661. } /* InitDir */
  662.  
  663. /*--------------------------------------------------------------------*/
  664. /*    d i r c m p                                                     */
  665. /*                                                                    */
  666. /*                                                                    */
  667. /*    Compares two directory structures for sorting                   */
  668. /*--------------------------------------------------------------------*/
  669.  
  670. int dircmp( const void *a , const void *b )
  671. {
  672.    struct DIRLIST *x = (struct DIRLIST*) a;
  673.    struct DIRLIST *y = (struct DIRLIST*) b;
  674.  
  675.    int result = strcmp(x->path, y->path);
  676.  
  677.    if (result == 0 && (x->priv != y->priv))
  678.       result = ( x->priv < y->priv ) ? -1 : 1;
  679.  
  680.    return result;
  681. }  /*dircmp*/
  682.  
  683. /*--------------------------------------------------------------------*/
  684. /*    V a l i d a t e H o s t                                         */
  685. /*                                                                    */
  686. /*    Determine that a host is allowed for a specific login           */
  687. /*--------------------------------------------------------------------*/
  688.  
  689. boolean ValidateHost( const char *host )
  690. {
  691.    char **target;
  692.  
  693. /*--------------------------------------------------------------------*/
  694. /*      If this host has no security profile, reject the access       */
  695. /*--------------------------------------------------------------------*/
  696.  
  697.    if ( securep == NULL )
  698.       return FALSE;
  699.  
  700. /*--------------------------------------------------------------------*/
  701. /*    If we allow any host on this user id, use it if the calling     */
  702. /*    host is not supported any other profile                         */
  703. /*--------------------------------------------------------------------*/
  704.  
  705.    target = securep->validate;
  706.    if ( target == NULL )      /* No validate list for this user?     */
  707.    {                          /* Correct --> Use if none for host    */
  708.       struct HostTable *hostp = checkreal( host );
  709.       if ( hostp == BADHOST ) /* Host exist?                         */
  710.          panic();             /* No --> Internal error, abort        */
  711.  
  712.       return hostp->anylogin; /* Allow action if generic access
  713.                                  allowed for host                    */
  714.    }  /* if ( target == NULL ) */
  715.  
  716. /*--------------------------------------------------------------------*/
  717. /*          Determine if this host is allowed for this login          */
  718. /*--------------------------------------------------------------------*/
  719.  
  720.    while (*target != NULL)
  721.    {
  722.       if ( equal(*target++, host ))
  723.          return TRUE;
  724.    } /* (*target != NULL) */
  725.  
  726. /*--------------------------------------------------------------------*/
  727. /*                 We didn't find the host; reject it                 */
  728. /*--------------------------------------------------------------------*/
  729.  
  730.    return FALSE;
  731.  
  732. } /* ValidateHost */
  733.  
  734. /*--------------------------------------------------------------------*/
  735. /*    V a l i d a t e F i l e                                         */
  736. /*                                                                    */
  737. /*    Allow or reject access to a file by name                        */
  738. /*--------------------------------------------------------------------*/
  739.  
  740. boolean ValidateFile( const char *input,  /* Full path name          */
  741.                       const REMOTE_ACCESS needed )
  742. {
  743.    char path[FILENAME_MAX];
  744.    char *column;
  745.  
  746. /*--------------------------------------------------------------------*/
  747. /*                  Validate the length of the name                   */
  748. /*--------------------------------------------------------------------*/
  749.  
  750.    printmsg(5,"ValidateFile: Checking %s access for file \"%s\"",
  751.             (needed == ALLOW_WRITE) ? "WRITE" : "READ" , input);
  752.  
  753.    if ( strlen( input ) >= sizeof path)   /* Reject all invalid names*/
  754.    {
  755.       printmsg(0,"ValidateFile: Access rejected, name too long: %s",
  756.                  input);
  757.       return FALSE;
  758.    }
  759.  
  760. /*--------------------------------------------------------------------*/
  761. /*     Validate format of name; we don't allow parent directories     */
  762. /*--------------------------------------------------------------------*/
  763.  
  764.    if ( strstr( input, "..") )            /* Games with parent dir?  */
  765.    {
  766.       printmsg(0,"ValidateFile: Access rejected, name not normalized: %s",
  767.                  input);
  768.       return FALSE;
  769.    }
  770.  
  771. /*--------------------------------------------------------------------*/
  772. /*                Validate the security table is okay                 */
  773. /*--------------------------------------------------------------------*/
  774.  
  775.    if ( securep == NULL )
  776.       panic();
  777.  
  778. /*--------------------------------------------------------------------*/
  779. /*                        Handle local system                         */
  780. /*--------------------------------------------------------------------*/
  781.  
  782.    if ( securep->local )      /* Local system?                       */
  783.       return TRUE;            /* Yes --> Bless the request           */
  784.  
  785. /*--------------------------------------------------------------------*/
  786. /*       Determine if the user is allowed to request files            */
  787. /*--------------------------------------------------------------------*/
  788.  
  789.    if ((needed == ALLOW_READ) && !securep->request)
  790.    {
  791.       printmsg(0,"ValidateFile: access rejected, "
  792.                  "REQUEST not enabled in permissions file");
  793.       return FALSE;
  794.    }
  795.  
  796. /*--------------------------------------------------------------------*/
  797. /*                           Copy path name                           */
  798. /*--------------------------------------------------------------------*/
  799.  
  800.    if ( input[1] == ':' )
  801.       strcpy( path, input );
  802.    else
  803.       strcat( strcpy( path , drive ), input );
  804.    strlwr( path );
  805.  
  806. /*--------------------------------------------------------------------*/
  807. /*              Locate the best file match for the path               */
  808. /*--------------------------------------------------------------------*/
  809.  
  810.    while( (column = strrchr( path, '/')) != NULL )
  811.    {
  812.       int lower = 0;
  813.       int upper = securep->dirsize - 1;
  814.  
  815.       *column = '\0';
  816.       printmsg(10,"ValidateFile: Searching for %s", path);
  817.  
  818.       while( lower <= upper )
  819.       {
  820.          int midpoint = (lower + upper) / 2;
  821.          int hit = strcmp(path, securep->dirlist[midpoint].path);
  822.  
  823.          printmsg(10,"ValidateFile: Comparing %s and %s",
  824.                         path, securep->dirlist[midpoint].path);
  825.  
  826.          if ( hit == 0 )
  827.             hit = (int) needed - (int) securep->dirlist[midpoint].priv;
  828.  
  829.          if (hit > 0)
  830.             lower = midpoint + 1;
  831.          else if (hit < 0)
  832.             upper = midpoint - 1;
  833.          else {
  834.             printmsg( securep->dirlist[midpoint].grant ? 5 : 0 ,
  835.                      "ValidateFile: Found path \"%s\", access %s to \"%s\"",
  836.                      securep->dirlist[midpoint].path,
  837.                      securep->dirlist[midpoint].grant ?
  838.                                     "granted" : "denied", input);
  839.             return securep->dirlist[midpoint].grant;
  840.          }
  841.       } /* while( lower <= upper ) */
  842.    } /* while( (column = strrchr( path, '/')) != NULL ) */
  843.  
  844. /*--------------------------------------------------------------------*/
  845. /*          We didn't find the file; reject all access to it          */
  846. /*--------------------------------------------------------------------*/
  847.  
  848.    printmsg(0,"ValidateFile: No access definition found for \
  849. \"%s\", access denied",
  850.             input);
  851.    return FALSE;
  852.  
  853. } /* ValidateFile */
  854.  
  855.  
  856. /*--------------------------------------------------------------------*/
  857. /*    G e t S e c u r i t y                                           */
  858. /*                                                                    */
  859. /*    Return security structure for to use when calling out to        */
  860. /*    another system                                                  */
  861. /*--------------------------------------------------------------------*/
  862.  
  863. struct HostSecurity *GetSecurity( struct HostTable *hostp)
  864. {
  865.    if ((hostp->hsecure == NULL) && (default_security != NULL ))
  866.    {
  867.       printmsg(2,"GetSecurity: Using security for MACHINE=OTHER for \
  868. system \"%s\"", hostp->hostname );
  869.       hostp->hsecure = default_security;
  870.    } /* if  */
  871.  
  872.    return hostp->hsecure;
  873.  
  874. } /* GetSecurity */
  875.