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