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