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