home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / radius-2.zip / src / users.c < prev    next >
C/C++ Source or Header  |  1995-01-06  |  12KB  |  556 lines

  1. /*
  2.  *
  3.  *    RADIUS
  4.  *    Remote Authentication Dial In User Service
  5.  *
  6.  *
  7.  *    Livingston Enterprises, Inc.
  8.  *    6920 Koll Center Parkway
  9.  *    Pleasanton, CA   94566
  10.  *
  11.  *    Copyright 1992 Livingston Enterprises, Inc.
  12.  *
  13.  *    Permission to use, copy, modify, and distribute this software for any
  14.  *    purpose and without fee is hereby granted, provided that this
  15.  *    copyright and permission notice appear on all copies and supporting
  16.  *    documentation, the name of Livingston Enterprises, Inc. not be used
  17.  *    in advertising or publicity pertaining to distribution of the
  18.  *    program without specific prior permission, and notice be given
  19.  *    in supporting documentation that copying and distribution is by
  20.  *    permission of Livingston Enterprises, Inc.   
  21.  *
  22.  *    Livingston Enterprises, Inc. makes no representations about
  23.  *    the suitability of this software for any purpose.  It is
  24.  *    provided "as is" without express or implied warranty.
  25.  *
  26.  */
  27.  
  28. static char sccsid[] =
  29. "@(#)users.c    1.12 Copyright 1992 Livingston Enterprises Inc";
  30.  
  31. #include    <sys/types.h>
  32. #include    <sys/socket.h>
  33. #include    <sys/time.h>
  34. #include    <netinet/in.h>
  35.  
  36. #include    <stdio.h>
  37. #include    <netdb.h>
  38. #include    <pwd.h>
  39. #include    <time.h>
  40. #include    <ctype.h>
  41.  
  42. #ifdef DBM
  43.  
  44. #include    <dbm.h>
  45.  
  46. #endif /* DBM */
  47.  
  48. #include    "radius.h"
  49.  
  50. extern char        *progname;
  51. extern int        debug_flag;
  52. extern char        *radius_dir;
  53.  
  54. static    void fieldcpy();
  55. static    int  userparse();
  56.  
  57. #define FIND_MODE_NAME    0
  58. #define FIND_MODE_REPLY    1
  59. #define FIND_MODE_SKIP    2
  60. #define FIND_MODE_FLUSH    3
  61.  
  62. /*************************************************************************
  63.  *
  64.  *    Function: user_find
  65.  *
  66.  *    Purpose: Find the named user in the database.  Create the
  67.  *         set of attribute-value pairs to check and reply with
  68.  *         for this user from the database.
  69.  *
  70.  *************************************************************************/
  71.  
  72. user_find(name, check_pairs, reply_pairs)
  73. char    *name;
  74. VALUE_PAIR    **check_pairs;
  75. VALUE_PAIR    **reply_pairs;
  76. {
  77.     FILE        *userfd;
  78.     char        buffer[256];
  79.     char        msg[128];
  80.     char        *ptr;
  81.     int        namelen;
  82.     int        mode;
  83.     VALUE_PAIR    *check_first;
  84.     VALUE_PAIR    *reply_first;
  85. #ifdef DBM
  86.     datum        named;
  87.     datum        contentd;
  88. #endif /* DBM */
  89.  
  90.     /* 
  91.      * Check for valid input, zero length names not permitted 
  92.      */
  93.  
  94.     mode = FIND_MODE_NAME;
  95.  
  96.     ptr=name;
  97.     while (*ptr != '\0') {
  98.         if (*ptr == ' ' || *ptr == '\t') {
  99.             *ptr = '\0';
  100.         } else {
  101.             ptr++;
  102.         }
  103.     }
  104.  
  105.     namelen=strlen(name);
  106.  
  107.     if (namelen < 1) {
  108.         fprintf(stderr, "%s: zero length username not permitted\n",progname);
  109.         return(-1);
  110.     }
  111.  
  112.  
  113.     /*
  114.      * Open the user table
  115.      */
  116.     sprintf(buffer, "%s/%s", radius_dir, RADIUS_USERS);
  117. #ifdef DBM
  118.     if(dbminit(buffer) != 0) {
  119. #else /* DBM */
  120.     if((userfd = fopen(buffer, "r")) == (FILE *)NULL) {
  121. #endif /* DBM */
  122.         fprintf(stderr, "%s:Couldn't open %s for reading\n",
  123.                 progname, buffer);
  124.         return(-1);
  125.     }
  126.  
  127.     check_first = (VALUE_PAIR *)NULL;
  128.     reply_first = (VALUE_PAIR *)NULL;
  129.  
  130.  
  131. #ifdef DBM
  132.     named.dptr = name;
  133.     named.dsize = strlen(name);
  134.     contentd = fetch(named);
  135.  
  136.     if(contentd.dsize == 0) {
  137.         named.dptr = "DEFAULT";
  138.         named.dsize = strlen("DEFAULT");
  139.         contentd = fetch(named);
  140.         if(contentd.dsize == 0) {
  141.             dbmclose();
  142.             return(-1);
  143.         }
  144.     }
  145.  
  146.     /*
  147.      * Parse the check values
  148.      */
  149.     ptr = contentd.dptr;
  150.     contentd.dptr[contentd.dsize] = '\0';
  151.  
  152.     if(userparse(ptr, &check_first) != 0) {
  153.         sprintf(msg, "%s: Parse error for user %s\n",
  154.                 progname, name);
  155.         fprintf(stderr, msg);
  156.         log_err(msg);
  157.         pairfree(check_first);
  158.         dbmclose();
  159.         return(-1);
  160.     }
  161.     while(*ptr != '\n' && *ptr != '\0') {
  162.         ptr++;
  163.     }
  164.     if(*ptr != '\n') {
  165.         pairfree(check_first);
  166.         dbmclose();
  167.         return(-1);
  168.     }
  169.     ptr++;
  170.     /*
  171.      * Parse the reply values
  172.      */
  173.     if(userparse(ptr, &reply_first) != 0) {
  174.         fprintf(stderr, "%s: Parse error for user %s\n",
  175.             progname, name);
  176.         pairfree(check_first);
  177.         pairfree(reply_first);
  178.         dbmclose();
  179.         return(-1);
  180.     }
  181.     dbmclose();
  182.  
  183. #else /* DBM */
  184.  
  185.     while(fgets(buffer, sizeof(buffer), userfd) != (char *)NULL) {
  186.         if(mode == FIND_MODE_NAME) {
  187.             /*
  188.              * Find the entry starting with the users name
  189.              */
  190.             if((strncmp(buffer, name, namelen) == 0 &&
  191.               (buffer[namelen] == ' ' || buffer[namelen] == '\t')) ||
  192.                      strncmp(buffer, "DEFAULT", 7) == 0) {
  193.                 if(strncmp(buffer, "DEFAULT", 7) == 0) {
  194.                     ptr = &buffer[7];
  195.                 }
  196.                 else {
  197.                     ptr = &buffer[namelen];
  198.                 }
  199.                 /*
  200.                  * Parse the check values
  201.                  */
  202.                 if(userparse(ptr, &check_first) != 0) {
  203.                     sprintf(msg,"%s: Parse error for user %s\n",
  204.                         progname, name);
  205.                     fprintf(stderr,msg);
  206.                     log_err(msg);
  207.                     pairfree(check_first);
  208.                     fclose(userfd);
  209.                     return(-1);
  210.                 }
  211.                 mode = FIND_MODE_REPLY;
  212.             }
  213.         }
  214.         else {
  215.             if(*buffer == ' ' || *buffer == '\t') {
  216.                 /*
  217.                  * Parse the reply values
  218.                  */
  219.                 if(userparse(buffer, &reply_first) != 0) {
  220.                     fprintf(stderr,
  221.                         "%s: Parse error for user %s\n",
  222.                         progname, name);
  223.                     pairfree(check_first);
  224.                     pairfree(reply_first);
  225.                     fclose(userfd);
  226.                     return(-1);
  227.                 }
  228.             }
  229.             else {
  230.                 /* We are done */
  231.                 fclose(userfd);
  232.                 *check_pairs = check_first;
  233.                 *reply_pairs = reply_first;
  234.                 return(0);
  235.             }
  236.         }
  237.     }
  238.     fclose(userfd);
  239. #endif /* DBM */
  240.  
  241.     /* Update the callers pointers */
  242.     if(reply_first != (VALUE_PAIR *)NULL) {
  243.         *check_pairs = check_first;
  244.         *reply_pairs = reply_first;
  245.         return(0);
  246.     }
  247.     return(-1);
  248. }
  249.  
  250. #define PARSE_MODE_NAME        0
  251. #define PARSE_MODE_EQUAL    1
  252. #define PARSE_MODE_VALUE    2
  253. #define PARSE_MODE_INVALID    3
  254.  
  255. /*************************************************************************
  256.  *
  257.  *    Function: userparse
  258.  *
  259.  *    Purpose: Parses the buffer to extract the attribute-value pairs.
  260.  *
  261.  *************************************************************************/
  262.  
  263. static int
  264. userparse(buffer, first_pair)
  265. char        *buffer;
  266. VALUE_PAIR    **first_pair;
  267. {
  268.     int        mode;
  269.     char        attrstr[64];
  270.     char        valstr[64];
  271.     DICT_ATTR    *attr;
  272.     DICT_ATTR    *dict_attrfind();
  273.     DICT_VALUE    *dval;
  274.     DICT_VALUE    *dict_valfind();
  275.     VALUE_PAIR    *pair;
  276.     VALUE_PAIR    *link;
  277.     UINT4        ipstr2long();
  278.     UINT4        get_ipaddr();
  279.     struct tm    *tm;
  280.     time_t        timeval;
  281.  
  282.     mode = PARSE_MODE_NAME;
  283.     while(*buffer != '\n' && *buffer != '\0') {
  284.  
  285.         if(*buffer == ' ' || *buffer == '\t' || *buffer == ',') {
  286.             buffer++;
  287.             continue;
  288.         }
  289.  
  290.         switch(mode) {
  291.  
  292.         case PARSE_MODE_NAME:
  293.             /* Attribute Name */
  294.             fieldcpy(attrstr, &buffer);
  295.             if((attr = dict_attrfind(attrstr)) ==
  296.                         (DICT_ATTR *)NULL) {
  297.                 return(-1);
  298.             }
  299.             mode = PARSE_MODE_EQUAL;
  300.             break;
  301.  
  302.         case PARSE_MODE_EQUAL:
  303.             /* Equal sign */
  304.             if(*buffer == '=') {
  305.                 mode = PARSE_MODE_VALUE;
  306.                 buffer++;
  307.             }
  308.             else {
  309.                 return(-1);
  310.             }
  311.             break;
  312.  
  313.         case PARSE_MODE_VALUE:
  314.             /* Value */
  315.             fieldcpy(valstr, &buffer);
  316.  
  317.             if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
  318.                         (VALUE_PAIR *)NULL) {
  319.                 fprintf(stderr, "%s: no memory\n",
  320.                         progname);
  321.                 exit(-1);
  322.             }
  323.             strcpy(pair->name, attr->name);
  324.             pair->attribute = attr->value;
  325.             pair->type = attr->type;
  326.  
  327.             switch(pair->type) {
  328.  
  329.             case PW_TYPE_STRING:
  330.                 strcpy(pair->strvalue, valstr);
  331.                 break;
  332.  
  333.             case PW_TYPE_INTEGER:
  334.                 if(isdigit(*valstr)) {
  335.                     pair->lvalue = atoi(valstr);
  336.                 }
  337.                 else if((dval = dict_valfind(valstr)) ==
  338.                             (DICT_VALUE *)NULL) {
  339.                     free(pair);
  340.                     return(-1);
  341.                 }
  342.                 else {
  343.                     pair->lvalue = dval->value;
  344.                 }
  345.                 break;
  346.  
  347.             case PW_TYPE_IPADDR:
  348.                 pair->lvalue = get_ipaddr(valstr);
  349.                 break;
  350.  
  351.             case PW_TYPE_DATE:
  352.                 timeval = time(0);
  353.                 tm = localtime(&timeval);
  354.                 user_gettime(valstr, tm);
  355. #ifdef TIMELOCAL
  356.                 pair->lvalue = (UINT4)timelocal(tm);
  357. #else /* TIMELOCAL */
  358.                 pair->lvalue = (UINT4)mktime(tm);
  359. #endif /* TIMELOCAL */
  360.                 break;
  361.  
  362.             default:
  363.                 free(pair);
  364.                 return(-1);
  365.             }
  366.             pair->next = (VALUE_PAIR *)NULL;
  367.             if(*first_pair == (VALUE_PAIR *)NULL) {
  368.                 *first_pair = pair;
  369.             }
  370.             else {
  371.                 link = *first_pair;
  372.                 while(link->next != (VALUE_PAIR *)NULL) {
  373.                     link = link->next;
  374.                 }
  375.                 link->next = pair;
  376.             }
  377.             mode = PARSE_MODE_NAME;
  378.             break;
  379.  
  380.         default:
  381.             mode = PARSE_MODE_NAME;
  382.             break;
  383.         }
  384.     }
  385.     return(0);
  386. }
  387.  
  388. /*************************************************************************
  389.  *
  390.  *    Function: fieldcpy
  391.  *
  392.  *    Purpose: Copy a data field from the buffer.  Advance the buffer
  393.  *         past the data field.
  394.  *
  395.  *************************************************************************/
  396.  
  397. static    void
  398. fieldcpy(string, uptr)
  399. char    *string;
  400. char    **uptr;
  401. {
  402.     char    *ptr;
  403.  
  404.     ptr = *uptr;
  405.     if(*ptr == '"') {
  406.         ptr++;
  407.         while(*ptr != '"' && *ptr != '\0' && *ptr != '\n') {
  408.             *string++ = *ptr++;
  409.         }
  410.         *string = '\0';
  411.         if(*ptr == '"') {
  412.             ptr++;
  413.         }
  414.         *uptr = ptr;
  415.         return;
  416.     }
  417.  
  418.     while(*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' &&
  419.                         *ptr != '=' && *ptr != ',') {
  420.             *string++ = *ptr++;
  421.     }
  422.     *string = '\0';
  423.     *uptr = ptr;
  424.     return;
  425. }
  426.  
  427. /*************************************************************************
  428.  *
  429.  *    Function: user_update
  430.  *
  431.  *    Purpose: Updates a user in the database.  Replaces the original
  432.  *         entry with the name, the list of check items, and the
  433.  *         list of reply items which are supplied.
  434.  *
  435.  *************************************************************************/
  436.  
  437. user_update(name, user_check, user_reply)
  438. char        *name;
  439. VALUE_PAIR    *user_check;
  440. VALUE_PAIR    *user_reply;
  441. {
  442.     FILE        *oldfd;
  443.     FILE        *userfd;
  444.     char        buffer[256];
  445.     char        buffer1[256];
  446.     int        namelen;
  447.     int        mode;
  448.  
  449.     sprintf(buffer, "%s/%s", radius_dir, RADIUS_USERS);
  450.     sprintf(buffer1, "%s/%s", radius_dir, RADIUS_HOLD);
  451.  
  452.     /* Move the user table to a temporary location */
  453.     if(rename(buffer, buffer1) != 0) {
  454.         fprintf(stderr, "%s: Couldn't rename %s\n",
  455.                 progname, buffer);
  456.         return(-1);
  457.     }
  458.  
  459.     /* Open the old user file (using the temporary name */
  460.     if((oldfd = fopen(buffer1, "r")) == (FILE *)NULL) {
  461.         fprintf(stderr, "%s: Couldn't open %s for reading\n",
  462.                 progname, buffer1);
  463.         exit(-1);
  464.     }
  465.  
  466.     /* Open the new user file */
  467.     if((userfd = fopen(buffer, "w")) == (FILE *)NULL) {
  468.         fprintf(stderr, "%s: Couldn't open %s for writing\n",
  469.                 progname, buffer);
  470.         exit(-1);
  471.     }
  472.  
  473.     mode = FIND_MODE_NAME;
  474.     namelen = strlen(name);
  475.  
  476.     /* Copy the old to the new, only recreating the changed user */
  477.     while(fgets(buffer, sizeof(buffer), oldfd) != (char *)NULL) {
  478.         if(mode == FIND_MODE_NAME) {
  479.             if((strncmp(buffer, name, namelen) == 0 &&
  480.               (buffer[namelen] == ' ' || buffer[namelen] == '\t'))) {
  481.  
  482.                 /* Write our new information */
  483.                 fprintf(userfd, "%s\t", name);
  484.                 while(user_check != (VALUE_PAIR *)NULL) {
  485.                     fprint_attr_val(userfd, user_check);
  486.                     if(user_check->next !=
  487.                             (VALUE_PAIR *)NULL) {
  488.                         fprintf(userfd, ", ");
  489.                     }
  490.                     user_check = user_check->next;
  491.                 }
  492.                 fprintf(userfd, "\n\t");
  493.                 while(user_reply != (VALUE_PAIR *)NULL) {
  494.                     fprint_attr_val(userfd, user_reply);
  495.                     if(user_reply->next !=
  496.                             (VALUE_PAIR *)NULL) {
  497.                         fprintf(userfd, ",\n\t");
  498.                     }
  499.                     user_reply = user_reply->next;
  500.                 }
  501.                 fprintf(userfd, "\n");
  502.                 mode = FIND_MODE_SKIP;
  503.             }
  504.             else {
  505.                 fputs(buffer, userfd);
  506.             }
  507.         }
  508.         else if(mode == FIND_MODE_SKIP) {
  509.             if(*buffer != ' ' && *buffer != '\t') {
  510.                 fputs(buffer, userfd);
  511.                 mode = FIND_MODE_FLUSH;
  512.             }
  513.         }
  514.         else {
  515.             fputs(buffer, userfd);
  516.         }
  517.     }
  518.     fclose(oldfd);
  519.     fclose(userfd);
  520.     return(0);
  521. }
  522.  
  523. /*************************************************************************
  524.  *
  525.  *    Function: user_prtime
  526.  *
  527.  *    Purpose: Turns printable string into correct tm struct entries
  528.  *
  529.  *************************************************************************/
  530.  
  531. static char *months[] = {
  532.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  533.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  534.  
  535. user_gettime(valstr, tm)
  536. char        *valstr;
  537. struct tm    *tm;
  538. {
  539.     char    buffer[48];
  540.     int    i;
  541.  
  542.     /* Get the month */
  543.     for(i = 0;i < 12;i++) {
  544.         if(strncmp(months[i], valstr, 3) == 0) {
  545.             tm->tm_mon = i;
  546.             i = 13;
  547.         }
  548.     }
  549.  
  550.     /* Get the Day */
  551.     tm->tm_mday = atoi(&valstr[4]);
  552.  
  553.     /* Now the year */
  554.     tm->tm_year = atoi(&valstr[7]) - 1900;
  555. }
  556.