home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / radius_2.zip / radiusd.c < prev    next >
C/C++ Source or Header  |  1996-06-04  |  46KB  |  1,814 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. /* don't look here for the version, run radiusd -v or look in version.c */
  29. static char sccsid[] =
  30. "@(#)radiusd.c    1.17 Copyright 1992 Livingston Enterprises Inc";
  31.  
  32. #include    <sys/types.h>
  33. #include    <sys/socket.h>
  34. #include    <sys/time.h>
  35. #include    <sys/file.h>
  36. #include    <netinet/in.h>
  37.  
  38. #include    <stdio.h>
  39. #include    <stdlib.h>
  40. #include    <netdb.h>
  41. #include    <fcntl.h>
  42. #include    <pwd.h>
  43. #include    <time.h>
  44. #include    <ctype.h>
  45. #include    <unistd.h>
  46. #include    <signal.h>
  47. #include    <errno.h>
  48. #include   <process.h>
  49. #include    <sys/wait.h>
  50. #include    <io.h>
  51.  
  52. #if !defined(NOSHADOW)
  53. /*#include    <shadow.h>*/
  54. #endif /* !NOSHADOW */
  55.  
  56. #include    "radius.h"
  57.  
  58. char        recv_buffer[4096];
  59. char        send_buffer[4096];
  60. char        *progname;
  61. int            sockfd;
  62. int            acctfd;
  63. int            debug_flag;
  64. int            spawn_flag;
  65. int            acct_flag;
  66. int            acct_pid;
  67. char        *radius_dir;
  68. char        *radacct_dir;
  69. #ifdef OS2
  70. char        radius_dir_hold[256];
  71. char        radacct_dir_hold[256]; 
  72. #endif
  73. UINT4        expiration_seconds;
  74. UINT4        warning_seconds;
  75. int    errno;
  76. static AUTH_REQ    *first_request;
  77.  
  78. void        sig_fatal();
  79. void        sig_hup();
  80. void        sig_cleanup();
  81. void        rad_passchange();
  82. void       usage(void);
  83. int        config_init();
  84. int        radrespond(AUTH_REQ    *authreq,int        activefd);
  85. int        rad_spawn_child(AUTH_REQ    *authreq,int        activefd);
  86. void         rad_authenticate(AUTH_REQ    *authreq,int        activefd);
  87. void        send_reject(AUTH_REQ    *authreq,char        *msg,int        activefd);
  88. int        set_expiration(VALUE_PAIR    *user_check,UINT4        expiration);
  89. void        send_pwack(AUTH_REQ    *authreq,int        activefd);
  90. int        calc_digest(u_char        *digest,AUTH_REQ    *authreq);
  91. int        pw_expired(UINT4    exptime);
  92. void        send_challenge(AUTH_REQ    *authreq,char *msg,char *state,int activefd);
  93. int        unix_pass(char    *name,char    *passwd);
  94. void        send_accept(AUTH_REQ *authreq,VALUE_PAIR *reply,char *msg,int activefd);
  95.  
  96. int
  97. main(argc, argv)
  98. int    argc;
  99. char    **argv;
  100. {
  101.     int            salen;
  102.     int            result;
  103.     struct        sockaddr    salocal;
  104.     struct        sockaddr    saremote;
  105.     struct        sockaddr_in    *sin;
  106.     struct        servent        *svp;
  107.     u_short        lport;
  108.     AUTH_REQ    *authreq;
  109.     AUTH_REQ    *radrecv();
  110.     char        argval;
  111.     int            t;
  112. #ifndef OS2
  113.     int            pid;
  114. #else
  115.    char        work_dir[256];
  116. #endif
  117.     int            cons;
  118.     fd_set        readfds;
  119.     int            status;
  120.     char *nargv[20];
  121.  
  122.     for ( t=0;t<argc ;t++ )
  123.        nargv[t] = argv[t];
  124.     nargv[t++]="-i";
  125.     nargv[t]=NULL;
  126.  
  127.     progname = *argv++;
  128.     argc--;
  129.  
  130.     debug_flag = 1;
  131.     acct_flag = 0;
  132.     spawn_flag = 1;
  133. #ifndef OS2
  134.     radacct_dir = RADACCT_DIR;
  135.     radius_dir = RADIUS_DIR;
  136. #else
  137.     sprintf(work_dir,"%s%s",getenv("ETC"),RADIUS_DIR);
  138.     _abspath(radius_dir_hold,work_dir,256);
  139.     sprintf(work_dir,"%s%s",getenv("ETC"),RADACCT_DIR);
  140.     _abspath(radacct_dir_hold,work_dir,256);
  141.     radius_dir = radius_dir_hold;
  142.    radacct_dir = radacct_dir_hold;
  143. #endif
  144.     signal(SIGHUP, sig_hup);
  145.     signal(SIGINT, sig_fatal);
  146.     signal(SIGQUIT, sig_fatal);
  147.     signal(SIGILL, sig_fatal);
  148. //    signal(SIGTRAP, sig_fatal);
  149. //    signal(SIGIOT, sig_fatal);
  150.     signal(SIGFPE, sig_fatal);
  151.     signal(SIGTERM, sig_fatal);
  152.     signal(SIGCHLD, sig_cleanup);
  153.  
  154.     while(argc) {
  155.  
  156.         if(**argv != '-') {
  157.             usage();
  158.         }
  159.  
  160.         argval = *(*argv + 1);
  161.         argc--;
  162.         argv++;
  163.  
  164.         switch(argval) {
  165.  
  166.         case 'a':
  167.             if(argc == 0) {
  168.                 usage();
  169.             }
  170.             radacct_dir = *argv;
  171.            argc--;
  172.             argv++;
  173.             DEBUG("diff acct dir\n");
  174.              break;
  175.         
  176.         case 'd':
  177.             if(argc == 0) {
  178.                 usage();
  179.             }
  180.             radius_dir = *argv;
  181.             argc--;
  182.             argv++;
  183.              DEBUG("diff radius dir\n");
  184.             break;
  185.         
  186.         case 's':    /* Single process mode */
  187.            spawn_flag = 0;
  188.            acct_flag = 1;
  189.            DEBUG("Single process mode\n");
  190.            break;
  191.  
  192.         case 'v':
  193.             version();
  194.             break;
  195.  
  196.         case 'x':
  197.             debug_flag = 1;
  198.              DEBUG("Debug mode\n");
  199.             break;
  200.         
  201.         case 'i':
  202.             acct_flag = 1;
  203.             sockfd = -1;
  204.              DEBUG("Accounting spawn process\n");
  205.             break;
  206.  
  207.         default:
  208.             usage();
  209.             break;
  210.         }
  211.     }
  212.  
  213.     /* Initialize the dictionary */
  214.     if(dict_init() != 0) {
  215.         exit(-1);
  216.     }
  217.     DEBUG("dict_init complete\n");
  218.     /* Initialize Configuration Values */
  219.     if(config_init() != 0) {
  220.         exit(-1);
  221.     }
  222.     DEBUG("config_init complete\n");
  223.  
  224.     if ( sockfd != -1 ) {
  225.         svp = getservbyname ("radius", "udp");
  226.         if (svp == (struct servent *) 0) {
  227.             fprintf (stderr, "%s: No such service: radius/udp\n", progname);
  228.             exit(-1);
  229.         }
  230.         lport = (u_short) svp->s_port;
  231.  
  232.         sockfd = socket (AF_INET, SOCK_DGRAM, 0);
  233.         if (sockfd < 0) {
  234.             (void) perror ("auth socket");
  235.             exit(-1);
  236.         }
  237.  
  238.         sin = (struct sockaddr_in *) & salocal;
  239.         memset ((char *) sin, '\0', sizeof (salocal));
  240.         sin->sin_family = AF_INET;
  241.         sin->sin_addr.s_addr = INADDR_ANY;
  242.         sin->sin_port = lport;
  243.  
  244.         result = bind (sockfd, & salocal, sizeof (*sin));
  245.  
  246.         if (result < 0) {
  247.             (void) perror ("auth bind");
  248.             exit(-1);
  249.         }
  250.         DEBUG("Author socket complete\n");
  251.     }
  252.     /*
  253.      * Open Accounting Socket.
  254.      */
  255.     svp = getservbyname ("radacct", "udp");
  256.     if (svp == (struct servent *) 0) {
  257.        fprintf (stderr, "%s: No such service: %s/%s\n",
  258.           progname, "radacct", "udp");
  259.        exit(-1);
  260.     }
  261.     //do not delete:  lport = htons(ntohs(lport) +1);
  262.     lport = (u_short) svp->s_port;
  263.     acctfd = socket (AF_INET, SOCK_DGRAM, 0);
  264.     if (acctfd < 0) {
  265.        (void) perror ("acct socket");
  266.        exit(-1);
  267.     }
  268.  
  269.     sin = (struct sockaddr_in *) & salocal;
  270.     memset ((char *) sin, '\0', sizeof (salocal));
  271.     sin->sin_family = AF_INET;
  272.     sin->sin_addr.s_addr = INADDR_ANY;
  273.     sin->sin_port = lport;
  274.  
  275.     result = bind (acctfd, & salocal, sizeof (*sin));
  276.  
  277.     if (result < 0) {
  278.        (void) perror ("acct bind");
  279.        exit(-1);
  280.     }
  281.     DEBUG("Radacct socket complete\n");
  282.     /*
  283.      *    Disconnect from session
  284.      */
  285. #ifndef OS2
  286.     if(debug_flag == 0) {
  287.         pid = fork();
  288.         if(pid < 0) {
  289.             fprintf(stderr, "%s: Couldn't fork\n", progname);
  290.             exit(-1);
  291.         }
  292.         if(pid > 0) {
  293.             exit(0);
  294.         }
  295.     }
  296. #endif
  297.  
  298.     /*
  299.      *    Disconnect from tty
  300.      */
  301.     for (t = 32; t >= 3; t--) {
  302.         if(t != sockfd && t != acctfd) {
  303.             close(t);
  304.         }
  305.     }
  306.  
  307. #if !defined(M_UNIX)
  308.     /*
  309.      * Open system console as stderr
  310.      */
  311.     cons = open("/dev/console", O_WRONLY | O_NOCTTY);
  312.     if(cons != 2) {
  313.         dup2(cons, 2);
  314.         close(cons);
  315.     }
  316. #endif
  317.     /*
  318.      * If we are able to spawn processes, we will start a child
  319.      * to listen for Accounting requests.  If not, we will 
  320.      * listen for them ourself.
  321.      */
  322.     if( spawn_flag && !acct_flag ) {
  323. #ifndef OS2
  324.         acct_pid = fork();
  325. #else
  326.         acct_pid = spawnv(P_NOWAIT,nargv[0],nargv); 
  327. /*       acct_pid = spawnl(P_NOWAIT,argv[0],argv[0],"-x","-i",(char *)0); */
  328. #endif
  329.         DEBUG("Accounting Spawned\n");
  330.          if(acct_pid < 0) {
  331.             fprintf(stderr, "%s: Couldn't fork\n", progname);
  332.             exit(-1);
  333.         }
  334.         if(acct_pid > 0) {
  335.             close(acctfd);
  336.             acctfd = -1;
  337.         }
  338.         else {
  339.             if ( sockfd != -1 )
  340.                close(sockfd);
  341.             sockfd = -1;
  342.         }
  343.     }
  344.         
  345.     /*
  346.      *    Receive user requests
  347.      */
  348.     sin = (struct sockaddr_in *) & saremote;
  349.     DEBUG("Ready to receive user requests\n");
  350.     for(;;) {
  351.        FD_ZERO(&readfds);
  352.        if(sockfd >= 0) {
  353.           FD_SET(sockfd, &readfds);
  354.        }
  355.        if(acctfd >= 0) {
  356.           FD_SET(acctfd, &readfds);
  357.        }
  358.  
  359.        status = select(32, &readfds, NULL, NULL, NULL);
  360.  
  361.        if(status == -1) {
  362.           if (errno == EINTR)
  363.              continue;
  364.           sig_fatal(101);
  365.        }
  366.        if(sockfd >= 0 && FD_ISSET(sockfd, &readfds)) {
  367.           DEBUG("try to read sockfd\n");
  368.           salen = sizeof (saremote);
  369.           result = recvfrom (sockfd, (char *) recv_buffer,
  370.              (int) sizeof(recv_buffer),
  371.              (int) 0, & saremote, & salen);
  372.  
  373.           if(result > 0) {
  374.              DEBUG("try to receive authreq\n");
  375.              authreq =    radrecv(ntohl(sin->sin_addr.s_addr),
  376.                                   ntohs(sin->sin_port),
  377.                                   recv_buffer, result);
  378.              radrespond(authreq, sockfd);
  379.           }
  380.           else {
  381.              if    (result < 0 && errno == EINTR) {
  382.                    result = 0;
  383.              }
  384.           }
  385.        } /* if(sockfd >= 0 && FD_ISSET(so */
  386.        if(acctfd >=0 && FD_ISSET(acctfd, &readfds)) {
  387.             DEBUG("try to read acctfd\n");
  388.             salen = sizeof (saremote);
  389.             result = recvfrom (acctfd, (char *) recv_buffer,
  390.                 (int) sizeof(recv_buffer),
  391.                 (int) 0, & saremote, & salen);
  392.  
  393.             if(result > 0) {
  394.                 authreq = radrecv(    ntohl(sin->sin_addr.s_addr),
  395.                                     ntohs(sin->sin_port),
  396.                                     recv_buffer, result);
  397.                 radrespond(authreq, acctfd);
  398.             }
  399.             else if(result < 0 && errno == EINTR) {
  400.                 result = 0;
  401.             }
  402.         }
  403.     }
  404. }
  405.  
  406. /*************************************************************************
  407.  *
  408.  *    Function: radrecv
  409.  *
  410.  *    Purpose: Receive UDP client requests, build an authorization request
  411.  *         structure, and attach attribute-value pairs contained in
  412.  *         the request to the new structure.
  413.  *
  414.  *************************************************************************/
  415.  
  416. AUTH_REQ    *
  417. radrecv(host, udp_port, buffer, length)
  418. UINT4    host;
  419. u_short    udp_port;
  420. u_char    *buffer;
  421. int    length;
  422. {
  423.     u_char        *ptr;
  424.     AUTH_HDR    *auth;
  425.     int            totallen;
  426.     int            attribute;
  427.     int            attrlen;
  428.     DICT_ATTR    *attr;
  429.     DICT_ATTR    *dict_attrget();
  430. /*    char        string[64];*/
  431.     UINT4        lvalue;
  432.     char        *ip_hostname();
  433.     VALUE_PAIR    *first_pair;
  434.     VALUE_PAIR    *prev;
  435.     VALUE_PAIR    *pair;
  436.     AUTH_REQ    *authreq;
  437.  
  438.     /*
  439.      * Pre-allocate the new request data structure
  440.      */
  441.  
  442.     if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) == (AUTH_REQ *)NULL) {
  443.         fprintf(stderr, "%s: no memory\n", progname);
  444.         exit(-1);
  445.     }
  446.  
  447.     auth = (AUTH_HDR *)buffer;
  448.     totallen = ntohs(auth->length);
  449.  
  450.     DEBUG("radrecv: Request from host %lx code=%d, id=%d, length=%d\n",
  451.                 (u_long)host, auth->code, auth->id, totallen);
  452.  
  453.     /*
  454.      * Fill header fields
  455.      */
  456.     authreq->ipaddr = host;
  457.     authreq->udp_port = udp_port;
  458.     authreq->id = auth->id;
  459.     authreq->code = auth->code;
  460.     memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
  461.  
  462.     /*
  463.      * Extract attribute-value pairs
  464.      */
  465.     ptr = auth->data;
  466.     length -= AUTH_HDR_LEN;
  467.     first_pair = (VALUE_PAIR *)NULL;
  468.     prev = (VALUE_PAIR *)NULL;
  469.  
  470.     while(length > 0) {
  471.  
  472.         attribute = *ptr++;
  473.         attrlen = *ptr++;
  474.         if(attrlen < 2) {
  475.             length = 0;
  476.             continue;
  477.         }
  478.         attrlen -= 2;
  479.         if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
  480.             DEBUG("Received unknown attribute %d\n", attribute);
  481.         }
  482.         else if ( attrlen >= AUTH_STRING_LEN ) {
  483.             DEBUG("attribute %d too long, %d >= %d\n", attribute,
  484.                 attrlen, AUTH_STRING_LEN);
  485.         }
  486.         else {
  487.             if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
  488.                         (VALUE_PAIR *)NULL) {
  489.                 fprintf(stderr, "%s: no memory\n", progname);
  490.                 exit(-1);
  491.             }
  492.             strcpy(pair->name, attr->name);
  493.             pair->attribute = attr->value;
  494.             pair->type = attr->type;
  495.             pair->next = (VALUE_PAIR *)NULL;
  496.  
  497.             switch(attr->type) {
  498.  
  499.             case PW_TYPE_STRING:
  500.                 memcpy(pair->strvalue, ptr, attrlen);
  501.                 pair->strvalue[attrlen] = '\0';
  502.                 debug_pair(stdout, pair);
  503.                 if(first_pair == (VALUE_PAIR *)NULL) {
  504.                     first_pair = pair;
  505.                 }
  506.                 else {
  507.                     prev->next = pair;
  508.                 }
  509.                 prev = pair;
  510.                 break;
  511.             
  512.             case PW_TYPE_INTEGER:
  513.             case PW_TYPE_IPADDR:
  514.                 memcpy(&lvalue, ptr, sizeof(UINT4));
  515.                 pair->lvalue = ntohl(lvalue);
  516.                 debug_pair(stdout, pair);
  517.                 if(first_pair == (VALUE_PAIR *)NULL) {
  518.                     first_pair = pair;
  519.                 }
  520.                 else {
  521.                     prev->next = pair;
  522.                 }
  523.                 prev = pair;
  524.                 break;
  525.             
  526.             default:
  527.                 DEBUG("    %s (Unknown Type %d)\n", attr->name,attr->type);
  528.                 free(pair);
  529.                 break;
  530.             }
  531.  
  532.         }
  533.         ptr += attrlen;
  534.         length -= attrlen + 2;
  535.     }
  536.     authreq->request = first_pair;
  537.     return(authreq);
  538. }
  539.  
  540. /*************************************************************************
  541.  *
  542.  *    Function: radrespond
  543.  *
  544.  *    Purpose: Respond to supported requests:
  545.  *
  546.  *         PW_AUTHENTICATION_REQUEST - Authentication request from
  547.  *                a client network access server.
  548.  *
  549.  *         PW_ACCOUNTING_REQUEST - Accounting request from
  550.  *                a client network access server.
  551.  *
  552.  *         PW_PASSWORD_REQUEST - User request to change a password.
  553.  *
  554.  *************************************************************************/
  555. int
  556. radrespond(authreq, activefd)
  557. AUTH_REQ    *authreq;
  558. int        activefd;
  559. {
  560.     switch(authreq->code) {
  561.  
  562.     case PW_AUTHENTICATION_REQUEST:
  563.         if(spawn_flag) {
  564. #ifndef OS2
  565.            rad_spawn_child(authreq, activefd);
  566. #else
  567.            rad_authenticate(authreq, activefd);
  568. #endif
  569.         }
  570.         else {
  571.             rad_authenticate(authreq, activefd);
  572.         }
  573.         break;
  574.     
  575.     case PW_ACCOUNTING_REQUEST:
  576.         rad_accounting(authreq, activefd);
  577.         break;
  578.     
  579.     case PW_PASSWORD_REQUEST:
  580.         rad_passchange(authreq, activefd);
  581.         break;
  582.     
  583.     default:
  584.         break;
  585.     }
  586.     return(0);
  587. }
  588.  
  589.  
  590.  
  591. /*************************************************************************
  592.  *
  593.  *    Function: rad_spawn_child
  594.  *
  595.  *    Purpose: Spawns child processes to perform password authentication
  596.  *         and respond to RADIUS clients.  This functions also
  597.  *         cleans up complete child requests, and verifies that there
  598.  *         is only one process responding to each request (duplicate
  599.  *         requests are filtered out.
  600.  *
  601.  *************************************************************************/
  602. int
  603. rad_spawn_child(authreq, activefd)
  604. AUTH_REQ    *authreq;
  605. int        activefd;
  606. {
  607.     AUTH_REQ    *curreq;
  608.     AUTH_REQ    *prevreq;
  609.     UINT4        curtime;
  610.     int        request_count;
  611.     char        msg[128];
  612.     char        *ip_hostname();
  613.     int        child_pid;
  614.  
  615.     curtime = (UINT4)time(0);
  616.     request_count = 0;
  617.     curreq = first_request;
  618.     prevreq = (AUTH_REQ *)NULL;
  619.     while(curreq != (AUTH_REQ *)NULL) {
  620.         if(curreq->child_pid == -1 &&
  621.                 curreq->timestamp + CLEANUP_DELAY <= curtime) {
  622.             /* Request completed, delete it */
  623.             if(prevreq == (AUTH_REQ *)NULL) {
  624.                 first_request = curreq->next;
  625.                 pairfree(curreq->request);
  626.                 free(curreq);
  627.                 curreq = first_request;
  628.             }
  629.             else {
  630.                 prevreq->next = curreq->next;
  631.                 pairfree(curreq->request);
  632.                 free(curreq);
  633.                 curreq = prevreq->next;
  634.             }
  635.         }
  636.         else if(curreq->ipaddr == authreq->ipaddr &&
  637.                     curreq->id == authreq->id) {
  638.             /* This is a duplicate request - just drop it */
  639.             sprintf(msg, "Dropping duplicate: from %s - ID: %d\n",
  640.                 ip_hostname(authreq->ipaddr), authreq->id);
  641.             log_err(msg);
  642.             pairfree(authreq->request);
  643.             free(authreq);
  644.             return(0);
  645.         }
  646.         else {
  647.             if(curreq->timestamp + MAX_REQUEST_TIME <= curtime &&
  648.                         curreq->child_pid != -1) {
  649.                 /* This request seems to have hung - kill it */
  650.                 child_pid = curreq->child_pid;
  651.                 sprintf(msg,
  652.                     "Killing unresponsive child pid %d\n",
  653.                                 child_pid);
  654.                 log_err(msg);
  655.                 curreq->child_pid = -1;
  656.                 kill(child_pid, SIGHUP);
  657.             }
  658.             prevreq = curreq;
  659.             curreq = curreq->next;
  660.             request_count++;
  661.         }
  662.     }
  663.  
  664.     /* This is a new request */
  665.     if(request_count > MAX_REQUESTS) {
  666.         sprintf(msg, "Dropping request (too many): from %s - ID: %d\n",
  667.                 ip_hostname(authreq->ipaddr), authreq->id);
  668.         log_err(msg);
  669.         pairfree(authreq->request);
  670.         free(authreq);
  671.         return(0);
  672.     }
  673.  
  674.     /* Add this request to the list */
  675.     authreq->next = (AUTH_REQ *)NULL;
  676.     authreq->child_pid = -1;
  677.     authreq->timestamp = curtime;
  678.  
  679.     if(prevreq == (AUTH_REQ *)NULL) {
  680.         first_request = authreq;
  681.     }
  682.     else {
  683.         prevreq->next = authreq;
  684.     }
  685.  
  686.     /* fork our child */
  687.     child_pid = fork();
  688.  
  689.     if(child_pid < 0) {
  690.         sprintf(msg, "Fork failed for request from %s - ID: %d\n",
  691.                 ip_hostname(authreq->ipaddr), authreq->id);
  692.         log_err(msg);
  693.     }
  694.     if(child_pid == 0) {
  695.         /* This is the child, it should go ahead and respond */
  696.         rad_authenticate(authreq, activefd);
  697.         exit(0);
  698.     }
  699.  
  700.     /* Register the Child */
  701.     authreq->child_pid = child_pid;
  702.     return(0);
  703. }
  704.  
  705. void
  706. sig_cleanup()
  707. {
  708.     int        status;
  709.         pid_t        pid;
  710.     AUTH_REQ    *curreq;
  711.  
  712.         for (;;) {
  713.         pid = waitpid((pid_t)-1,&status,WNOHANG);
  714.         signal(SIGCHLD, sig_cleanup);
  715.                 if (pid <= 0)
  716.                         return;
  717.  
  718. #if defined (aix)
  719.         kill(pid, SIGKILL);
  720. #endif
  721.  
  722.         if(pid == acct_pid) {
  723.             sig_fatal(100);
  724.         }
  725.         curreq = first_request;
  726.         while(curreq != (AUTH_REQ *)NULL) {
  727.             if(curreq->child_pid == pid) {
  728.                 curreq->child_pid = -1;
  729.                 curreq->timestamp = (UINT4)time(0);
  730.                 break;
  731.             }
  732.             curreq = curreq->next;
  733.         }
  734.         }
  735. }
  736.  
  737. /*************************************************************************
  738.  *
  739.  *    Function: rad_passchange
  740.  *
  741.  *    Purpose: Change a users password
  742.  *
  743.  *************************************************************************/
  744.  
  745. void
  746. rad_passchange(authreq, activefd)
  747. AUTH_REQ    *authreq;
  748. int        activefd;
  749. {
  750.     VALUE_PAIR    *namepair;
  751.     VALUE_PAIR    *check_item;
  752.     VALUE_PAIR    *newpasspair;
  753.     VALUE_PAIR    *oldpasspair;
  754.     VALUE_PAIR    *curpass;
  755.     VALUE_PAIR    *user_check;
  756.     VALUE_PAIR    *user_reply;
  757.     char        pw_digest[16];
  758.     char        string[64];
  759.     char        passbuf[AUTH_PASS_LEN];
  760.     int            i;
  761.     int            secretlen;
  762.     char        msg[128];
  763.     char        *ip_hostname();
  764.  
  765.     /* Get the username */
  766.     namepair = authreq->request;
  767.     while(namepair != (VALUE_PAIR *)NULL) {
  768.         if(namepair->attribute == PW_USER_NAME) {
  769.             break;
  770.         }
  771.         namepair = namepair->next;
  772.     }
  773.     if(namepair == (VALUE_PAIR *)NULL) {
  774.         sprintf(msg,
  775.             "Passchange: from %s - No User name supplied\n",
  776.             ip_hostname(authreq->ipaddr));
  777.         log_err(msg);
  778.         pairfree(authreq->request);
  779.         memset(authreq, 0, sizeof(AUTH_REQ));
  780.         free(authreq);
  781.         return;
  782.     }
  783.  
  784.     /*
  785.      * Look the user up in the database
  786.      */
  787.     if(user_find(namepair->strvalue, &user_check, &user_reply) != 0) {
  788.         sprintf(msg,
  789.             "Passchange: from %s - Invalid User: %s\n",
  790.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  791.         log_err(msg);
  792.         send_reject(authreq, (char *)NULL, activefd);
  793.         pairfree(authreq->request);
  794.         memset(authreq, 0, sizeof(AUTH_REQ));
  795.         free(authreq);
  796.         return;
  797.     }
  798.  
  799.     /*
  800.      * Validate the user -
  801.      *
  802.      * We have to unwrap this in a special way to decrypt the
  803.      * old and new passwords.  The MD5 calculation is based
  804.      * on the old password.  The vector is different.  The old
  805.      * password is encrypted using the encrypted new password
  806.      * as its vector.  The new password is encrypted using the
  807.      * random encryption vector in the request header.
  808.      */
  809.  
  810.     /* Extract the attr-value pairs for the old and new passwords */
  811.     check_item = authreq->request;
  812.     while(check_item != (VALUE_PAIR *)NULL) {
  813.         if(check_item->attribute == PW_PASSWORD) {
  814.             newpasspair = check_item;
  815.         }
  816.         else if(check_item->attribute == PW_OLD_PASSWORD) {
  817.             oldpasspair = check_item;
  818.         }
  819.         check_item = check_item->next;
  820.     }
  821.  
  822.     /* Verify that both encrypted passwords were supplied */
  823.     if(newpasspair == (VALUE_PAIR *)NULL ||
  824.                     oldpasspair == (VALUE_PAIR *)NULL) {
  825.         /* Missing one of the passwords */
  826.         sprintf(msg,
  827.             "Passchange: from %s - Missing Password: %s\n",
  828.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  829.         log_err(msg);
  830.         send_reject(authreq, (char *)NULL, activefd);
  831.         pairfree(authreq->request);
  832.         pairfree(user_check);
  833.         pairfree(user_reply);
  834.         memset(authreq, 0, sizeof(AUTH_REQ));
  835.         free(authreq);
  836.         return;
  837.     }
  838.  
  839.     /* Get the current password from the database */
  840.     curpass = user_check;
  841.     while(curpass != (VALUE_PAIR *)NULL) {
  842.         if(curpass->attribute == PW_PASSWORD) {
  843.             break;
  844.         }
  845.         curpass = curpass->next;
  846.     }
  847.     if((curpass == (VALUE_PAIR *)NULL) || curpass->strvalue == (char *)NULL) {
  848.         /* Missing our local copy of the password */
  849.         sprintf(msg,
  850.             "Passchange: from %s - Missing Local Password: %s\n",
  851.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  852.         log_err(msg);
  853.         send_reject(authreq, (char *)NULL, activefd);
  854.         pairfree(authreq->request);
  855.         pairfree(user_check);
  856.         pairfree(user_reply);
  857.         memset(authreq, 0, sizeof(AUTH_REQ));
  858.         free(authreq);
  859.         return;
  860.     }
  861.     if(strcmp(curpass->strvalue,"UNIX") == 0) {
  862.         /* Can't change passwords that aren't in users file */
  863.         sprintf(msg,
  864.             "Passchange: from %s - system password change not allowed: %s\n",
  865.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  866.         log_err(msg);
  867.         send_reject(authreq, (char *)NULL, activefd);
  868.         pairfree(authreq->request);
  869.         pairfree(user_check);
  870.         pairfree(user_reply);
  871.         memset(authreq, 0, sizeof(AUTH_REQ));
  872.         free(authreq);
  873.         return;
  874.     }
  875.  
  876.     /* Decrypt the old password */
  877.     secretlen = strlen(curpass->strvalue);
  878.     memcpy(string, curpass->strvalue, secretlen);
  879.     memcpy(string + secretlen, newpasspair->strvalue, AUTH_VECTOR_LEN);
  880.     md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen);
  881.     memcpy(passbuf, oldpasspair->strvalue, AUTH_PASS_LEN);
  882.     for(i = 0;i < AUTH_PASS_LEN;i++) {
  883.         passbuf[i] ^= pw_digest[i];
  884.     }
  885.  
  886.     /* Did they supply the correct password ??? */
  887.     if(strncmp(passbuf, curpass->strvalue, AUTH_PASS_LEN) != 0) {
  888.         sprintf(msg,
  889.             "Passchange: from %s - Incorrect Password: %s\n",
  890.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  891.         log_err(msg);
  892.         send_reject(authreq, (char *)NULL, activefd);
  893.         pairfree(authreq->request);
  894.         pairfree(user_check);
  895.         pairfree(user_reply);
  896.         memset(authreq, 0, sizeof(AUTH_REQ));
  897.         free(authreq);
  898.         return;
  899.     }
  900.  
  901.     /* Decrypt the new password */
  902.     memcpy(string, curpass->strvalue, secretlen);
  903.     memcpy(string + secretlen, authreq->vector, AUTH_VECTOR_LEN);
  904.     md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen);
  905.     memcpy(passbuf, newpasspair->strvalue, AUTH_PASS_LEN);
  906.     for(i = 0;i < AUTH_PASS_LEN;i++) {
  907.         passbuf[i] ^= pw_digest[i];
  908.     }
  909.  
  910.     /* Update the users password */
  911.     strncpy(curpass->strvalue, passbuf, AUTH_PASS_LEN);
  912.  
  913.     /* Add a new expiration date if we are aging passwords */
  914.     if(expiration_seconds != (UINT4)0) {
  915.         set_expiration(user_check, expiration_seconds);
  916.     }
  917.  
  918.     /* Update the database */
  919.     if(user_update(namepair->strvalue, user_check, user_reply) != 0) {
  920.         send_reject(authreq, (char *)NULL, activefd);
  921.         sprintf(msg,
  922.             "Passchange: unable to update password for %s\n",
  923.             namepair->strvalue);
  924.         log_err(msg);
  925.  
  926.     }
  927.     else {
  928.         send_pwack(authreq, activefd);
  929.     }
  930.     pairfree(authreq->request);
  931.     pairfree(user_check);
  932.     pairfree(user_reply);
  933.     memset(authreq, 0, sizeof(AUTH_REQ));
  934.     free(authreq);
  935.     return;
  936. }
  937.  
  938. /*************************************************************************
  939.  *
  940.  *    Function: rad_authenticate
  941.  *
  942.  *    Purpose: Process and reply to an authentication request
  943.  *
  944.  *************************************************************************/
  945. void
  946. rad_authenticate(authreq, activefd)
  947. AUTH_REQ    *authreq;
  948. int        activefd;
  949. {
  950.     VALUE_PAIR    *namepair;
  951.     VALUE_PAIR    *check_item;
  952.     VALUE_PAIR    *auth_item;
  953.     VALUE_PAIR    *user_check;
  954.     VALUE_PAIR    *user_reply;
  955.     int            result;
  956.     char        pw_digest[16];
  957.     char        string[128];
  958.     int            i;
  959.     char        msg[128];
  960.     char        umsg[128];
  961.     char        *user_msg;
  962.     char        *ip_hostname();
  963.     int            retval;
  964.     char        *ptr;
  965.  
  966.     /* Get the username from the request */
  967.     namepair = authreq->request;
  968.     while(namepair != (VALUE_PAIR *)NULL) {
  969.         if(namepair->attribute == PW_USER_NAME) {
  970.             break;
  971.         }
  972.         namepair = namepair->next;
  973.     }
  974.     if((namepair == (VALUE_PAIR *)NULL) || 
  975.        (strlen(namepair->strvalue) <= 0)) {
  976.         sprintf(msg,    "Authenticate: from %s - No User Name\n", 
  977.                         ip_hostname(authreq->ipaddr));
  978.         log_err(msg);
  979.         pairfree(authreq->request);
  980.         memset(authreq, 0, sizeof(AUTH_REQ));
  981.         free(authreq);
  982.         return;
  983.     }
  984.  
  985.     /* Verify the client and Calculate the MD5 Password Digest */
  986.     if    (calc_digest(pw_digest, authreq) != 0) {
  987.         DEBUG("failed password !!\n");
  988.         /* We dont respond when this fails */
  989.         sprintf(msg, "Authenticate: from %s - Security Breach: %s\n",
  990.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  991.         log_err(msg);
  992.         pairfree(authreq->request);
  993.         memset(authreq, 0, sizeof(AUTH_REQ));
  994.         free(authreq);
  995.         return;
  996.     }
  997.  
  998.     /* Get the user from the database */
  999.     if    (user_find(namepair->strvalue, &user_check, &user_reply) != 0) {
  1000.         DEBUG("Authenticate: from %s - Invalid User: %s\n",
  1001.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  1002.         sprintf(msg, "Authenticate: from %s - Invalid User: %s\n",
  1003.             ip_hostname(authreq->ipaddr), namepair->strvalue);
  1004.         log_err(msg);
  1005.         send_reject(authreq, (char *)NULL, activefd);
  1006.         pairfree(authreq->request);
  1007.         memset(authreq, 0, sizeof(AUTH_REQ));
  1008.         free(authreq);
  1009.         DEBUG("failed authentication\n");
  1010.         return;
  1011.     }
  1012.  
  1013.     /* Validate the user */
  1014.     DEBUG("we ought to be able to validate from here\n");
  1015.     /* Look for matching check items */
  1016.     result = 0;
  1017.     user_msg = (char *)NULL;
  1018.     check_item = user_check;
  1019.     while(result == 0 && check_item != (VALUE_PAIR *)NULL) {
  1020.         DEBUG("inside the while loop\n");
  1021.         /*
  1022.          * Check expiration date if we are doing password aging.
  1023.          */
  1024.         if(check_item->attribute == PW_EXPIRATION) {
  1025.             /* Has this user's password expired */
  1026.             retval = pw_expired(check_item->lvalue);
  1027.             if(retval < 0) {
  1028.                 result = -1;
  1029.                 user_msg = "Password Has Expired\r\n";
  1030.             }
  1031.             else {
  1032.                 if(retval > 0) {
  1033.                     sprintf(umsg, "Password Will Expire in %d Days\r\n", retval);
  1034.                     user_msg = umsg;
  1035.                 }
  1036.                 check_item = check_item->next;
  1037.             }
  1038.             continue;
  1039.         }
  1040.  
  1041.         /*
  1042.          * Look for the matching attribute in the request.
  1043.          */
  1044.         auth_item = authreq->request;
  1045.         while(auth_item != (VALUE_PAIR *)NULL) {
  1046.             if(check_item->attribute == auth_item->attribute) {
  1047.                 break;
  1048.             }
  1049.             if(check_item->attribute == PW_PASSWORD &&
  1050.                      auth_item->attribute == PW_CHAP_PASSWORD) {
  1051.                 break;
  1052.             }
  1053.  
  1054.             auth_item = auth_item->next;
  1055.         }
  1056.         if(auth_item == (VALUE_PAIR *)NULL) {
  1057.             result = -1;
  1058.             continue;
  1059.         }
  1060.  
  1061.         /*
  1062.          * Special handling for passwords which are encrypted,
  1063.          * and sometimes authenticated against the UNIX passwd database.
  1064.          * Also they can come using the Three-Way CHAP.
  1065.          *
  1066.          */
  1067.         if    (check_item->attribute == PW_PASSWORD) {
  1068.             if    (auth_item->attribute == PW_CHAP_PASSWORD) {
  1069.                 /* Use MD5 to verify */
  1070.                 ptr = string;
  1071.                 *ptr++ = *auth_item->strvalue;
  1072.                 strcpy(ptr, check_item->strvalue);
  1073.                 ptr += strlen(check_item->strvalue);
  1074.                 memcpy(ptr, authreq->vector, AUTH_VECTOR_LEN);
  1075.                 md5_calc(pw_digest, string,
  1076.                     1 + CHAP_VALUE_LENGTH +
  1077.                     strlen(check_item->strvalue));
  1078.                 /* Compare them */
  1079.                 if(memcmp(pw_digest, auth_item->strvalue + 1, CHAP_VALUE_LENGTH) != 0) {
  1080.                     result = -1;
  1081.                 }
  1082.             }
  1083.             else {
  1084.                 /* Decrypt the password */
  1085.                 memcpy(string, auth_item->strvalue, AUTH_PASS_LEN);
  1086.                 for(i = 0;i < AUTH_PASS_LEN;i++) {
  1087.                     string[i] ^= pw_digest[i];
  1088.                 }
  1089.                 string[AUTH_PASS_LEN] = '\0';
  1090.                 /* Test Code for Challenge */
  1091.                 if(strcmp(string, "challenge") == 0) {
  1092.                     send_challenge(authreq, 
  1093.                         "You want me to challenge you??\r\nOkay I will",
  1094.                         "1",activefd);
  1095.                     pairfree(authreq->request);
  1096.                     memset(authreq, 0, sizeof(AUTH_REQ));
  1097.                     free(authreq);
  1098.                     return;
  1099.                 }
  1100.                 if(strcmp(check_item->strvalue, "UNIX") == 0) {
  1101.                     if(unix_pass(namepair->strvalue, string) != 0) {
  1102.                         result = -1;
  1103.                         user_msg = (char *)NULL;
  1104.                     }
  1105.                 }
  1106.                 else if(strcmp(check_item->strvalue, string) != 0) {
  1107.                     DEBUG("failed password check\b\b\b\n");
  1108.                     result = -1;
  1109.                     user_msg = (char *)NULL;
  1110.                 }
  1111.             }
  1112.         }
  1113.         else {
  1114.             switch(check_item->type) {
  1115.  
  1116.             case PW_TYPE_STRING:
  1117.                 if(strcmp(check_item->strvalue, auth_item->strvalue) != 0) {
  1118.                     result = -1;
  1119.                 }
  1120.                 break;
  1121.  
  1122.             case PW_TYPE_INTEGER:
  1123.             case PW_TYPE_IPADDR:
  1124.                 if(check_item->lvalue != auth_item->lvalue) {
  1125.                     result = -1;
  1126.                 }
  1127.                 break;
  1128.  
  1129.             default:
  1130.                 result = -1;
  1131.                 break;
  1132.             }
  1133.         }
  1134.         check_item = check_item->next;
  1135.     }
  1136.     DEBUG("outside the while loop, result == %d\n", result);
  1137.     if(result != 0) {
  1138.         send_reject(authreq, user_msg, activefd);
  1139.         DEBUG("failed : \b\b\b%s\n", user_msg);
  1140.     }
  1141.     else {
  1142.         send_accept(authreq, user_reply, user_msg, activefd);
  1143.         DEBUG("Succeeded : \b%s\nSucceeded : %s\n", user_reply->name, user_msg);
  1144.     }
  1145.     pairfree(authreq->request);
  1146.     memset(authreq, 0, sizeof(AUTH_REQ));
  1147.     free(authreq);
  1148.     pairfree(user_check);
  1149.     pairfree(user_reply);
  1150.     return;
  1151. }
  1152.  
  1153. /*************************************************************************
  1154.  *
  1155.  *    Function: send_reject
  1156.  *
  1157.  *    Purpose: Reply to the request with a REJECT.  Also attach
  1158.  *         any user message provided.
  1159.  *
  1160.  *************************************************************************/
  1161. void
  1162. send_reject(authreq, msg, activefd)
  1163. AUTH_REQ    *authreq;
  1164. char        *msg;
  1165. int        activefd;
  1166. {
  1167.     AUTH_HDR    *auth;
  1168.     struct        sockaddr    saremote;
  1169.     struct        sockaddr_in    *sin;
  1170.     char        *ip_hostname();
  1171.     char        digest[AUTH_VECTOR_LEN];
  1172.     int            secretlen;
  1173.     int            total_length;
  1174.     u_char        *ptr;
  1175.     int            len;
  1176.  
  1177.     auth = (AUTH_HDR *)send_buffer;
  1178.  
  1179.     /* Build standard response header */
  1180.     if(authreq->code == PW_PASSWORD_REQUEST) {
  1181.         auth->code = PW_PASSWORD_REJECT;
  1182.     }
  1183.     else {
  1184.         auth->code = PW_AUTHENTICATION_REJECT;
  1185.     }
  1186.     auth->id = authreq->id;
  1187.     memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN);
  1188.     total_length = AUTH_HDR_LEN;
  1189.  
  1190.     /* Append the user message */
  1191.     if    (msg != (char *)NULL) {
  1192.         len = strlen(msg);
  1193.         if    (len > 0 && len < AUTH_STRING_LEN) {
  1194.             ptr = auth->data;
  1195.             *ptr++ = PW_PORT_MESSAGE;
  1196.             *ptr++ = len + 2;
  1197.             memcpy(ptr, msg, len);
  1198.             ptr += len;
  1199.             total_length += len + 2;
  1200.         }
  1201.     }
  1202.  
  1203.     /* Set total length in the header */
  1204.     auth->length = htons(total_length);
  1205.  
  1206.     /* Calculate the response digest */
  1207.     secretlen = strlen(authreq->secret);
  1208.     memcpy(send_buffer + total_length, authreq->secret, secretlen);
  1209.     md5_calc(digest, (char *)auth, total_length + secretlen);
  1210.     memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
  1211.     memset(send_buffer + total_length, 0, secretlen);
  1212.  
  1213.     sin = (struct sockaddr_in *) &saremote;
  1214.     memset ((char *) sin, '\0', sizeof (saremote));
  1215.     sin->sin_family = AF_INET;
  1216.     sin->sin_addr.s_addr = htonl(authreq->ipaddr);
  1217.     sin->sin_port = htons(authreq->udp_port);
  1218.  
  1219.     DEBUG("Sending Reject of id %d to %lx (%s)\n",
  1220.         authreq->id, (u_long)authreq->ipaddr,
  1221.         ip_hostname(authreq->ipaddr));
  1222.     
  1223.     /* Send it to the user */
  1224.     sendto(activefd, (char *)auth, (int)total_length, (int)0,
  1225.             (struct sockaddr *) &saremote, sizeof(struct sockaddr_in));
  1226. }
  1227.  
  1228. /*************************************************************************
  1229.  *
  1230.  *    Function: send_challenge
  1231.  *
  1232.  *    Purpose: Reply to the request with a CHALLENGE.  Also attach
  1233.  *         any user message provided and a state value.
  1234.  *
  1235.  *************************************************************************/
  1236. void
  1237. send_challenge(authreq, msg, state, activefd)
  1238. AUTH_REQ    *authreq;
  1239. char        *msg;
  1240. char        *state;
  1241. int            activefd;
  1242. {
  1243.     AUTH_HDR    *auth;
  1244.     struct        sockaddr_in    saremote;
  1245.     struct        sockaddr_in    *sin;
  1246.     char        *ip_hostname();
  1247.     char        digest[AUTH_VECTOR_LEN];
  1248.     int            secretlen;
  1249.     int            total_length;
  1250.     u_char        *ptr;
  1251.     int            len;
  1252.  
  1253.     auth = (AUTH_HDR *)send_buffer;
  1254.  
  1255.     /* Build standard response header */
  1256.     auth->code = PW_ACCESS_CHALLENGE;
  1257.     auth->id = authreq->id;
  1258.     memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN);
  1259.     total_length = AUTH_HDR_LEN;
  1260.  
  1261.     /* Append the user message */
  1262.     if    (msg != (char *)NULL) {
  1263.         len = strlen(msg);
  1264.         if    (len > 0 && len < AUTH_STRING_LEN) {
  1265.             ptr = auth->data;
  1266.             *ptr++ = PW_PORT_MESSAGE;
  1267.             *ptr++ = len + 2;
  1268.             memcpy(ptr, msg, len);
  1269.             ptr += len;
  1270.             total_length += len + 2;
  1271.         }
  1272.     }
  1273.  
  1274.     /* Append the state info */
  1275.     if    ((state != (char *)NULL) && (strlen(state) > 0)) {
  1276.         len = strlen(state);
  1277.         *ptr++ = PW_STATE;
  1278.         *ptr++ = len + 2;
  1279.         memcpy(ptr, state, len);
  1280.         ptr += len;
  1281.         total_length += len + 2;
  1282.     }
  1283.  
  1284.     /* Set total length in the header */
  1285.     auth->length = htons(total_length);
  1286.  
  1287.     /* Calculate the response digest */
  1288.     secretlen = strlen(authreq->secret);
  1289.     memcpy(send_buffer + total_length, authreq->secret, secretlen);
  1290.     md5_calc(digest, (char *)auth, total_length + secretlen);
  1291.     memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
  1292.     memset(send_buffer + total_length, 0, secretlen);
  1293.  
  1294.     sin = (struct sockaddr_in *) &saremote;
  1295.     memset ((char *) sin, '\0', sizeof (saremote));
  1296.     sin->sin_family = AF_INET;
  1297.     sin->sin_addr.s_addr = htonl(authreq->ipaddr);
  1298.     sin->sin_port = htons(authreq->udp_port);
  1299.  
  1300.     DEBUG("Sending Challenge of id %d to %lx (%s)\n",
  1301.         authreq->id, (u_long)authreq->ipaddr,
  1302.         ip_hostname(authreq->ipaddr));
  1303.     
  1304.     /* Send it to the user */
  1305.     sendto(activefd, (char *)auth, (int)total_length, (int)0,
  1306.             (struct sockaddr *) &saremote, sizeof(struct sockaddr_in));
  1307. }
  1308.  
  1309. /*************************************************************************
  1310.  *
  1311.  *    Function: send_pwack
  1312.  *
  1313.  *    Purpose: Reply to the request with an ACKNOWLEDGE.
  1314.  *         User password has been successfully changed.
  1315.  *
  1316.  *************************************************************************/
  1317. void
  1318. send_pwack(authreq, activefd)
  1319. AUTH_REQ    *authreq;
  1320. int        activefd;
  1321. {
  1322.     AUTH_HDR    *auth;
  1323.     struct        sockaddr    saremote;
  1324.     struct        sockaddr_in    *sin;
  1325.     char        *ip_hostname();
  1326.     char        digest[AUTH_VECTOR_LEN];
  1327.     int            secretlen;
  1328.  
  1329.     auth = (AUTH_HDR *)send_buffer;
  1330.  
  1331.     /* Build standard response header */
  1332.     auth->code = PW_PASSWORD_ACK;
  1333.     auth->id = authreq->id;
  1334.     memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN);
  1335.     auth->length = htons(AUTH_HDR_LEN);
  1336.  
  1337.     /* Calculate the response digest */
  1338.     secretlen = strlen(authreq->secret);
  1339.     DEBUG("PWACK Secret :%s :%d\n",authreq->secret,secretlen);
  1340.     memcpy(send_buffer + AUTH_HDR_LEN, authreq->secret, secretlen);
  1341.     md5_calc(digest, (char *)auth, AUTH_HDR_LEN + secretlen);
  1342.     memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
  1343.     memset(send_buffer + AUTH_HDR_LEN, 0, secretlen);
  1344.  
  1345.     sin = (struct sockaddr_in *) &saremote;
  1346.     memset ((char *) sin, '\0', sizeof (saremote));
  1347.     sin->sin_family = AF_INET;
  1348.     sin->sin_addr.s_addr = htonl(authreq->ipaddr);
  1349.     sin->sin_port = htons(authreq->udp_port);
  1350.  
  1351.     DEBUG("Sending PW Ack of id %d to %lx (%s)\n",
  1352.         authreq->id, (u_long)authreq->ipaddr,
  1353.         ip_hostname(authreq->ipaddr));
  1354.     
  1355.     /* Send it to the user */
  1356.     sendto(activefd, (char *)auth, (int)AUTH_HDR_LEN, (int)0,
  1357.             &saremote, sizeof(struct sockaddr_in));
  1358. }
  1359.  
  1360. /*************************************************************************
  1361.  *
  1362.  *    Function: send_accept
  1363.  *
  1364.  *    Purpose: Reply to the request with an ACKNOWLEDGE.  Also attach
  1365.  *         reply attribute value pairs and any user message provided.
  1366.  *
  1367.  *************************************************************************/
  1368. void
  1369. send_accept(authreq, reply, msg, activefd)
  1370. AUTH_REQ    *authreq;
  1371. VALUE_PAIR    *reply;
  1372. char        *msg;
  1373. int            activefd;
  1374. {
  1375.     AUTH_HDR    *auth;
  1376.     u_short        total_length;
  1377.     struct        sockaddr    saremote;
  1378.     struct        sockaddr_in    *sin;
  1379.     u_char        *ptr;
  1380.     int            len;
  1381.     UINT4        lvalue;
  1382.     u_char        digest[16];
  1383.     int            secretlen;
  1384.     char        *ip_hostname();
  1385.  
  1386.     auth = (AUTH_HDR *)send_buffer;
  1387.  
  1388.     /* Build standard header */
  1389.     auth->code = PW_AUTHENTICATION_ACK;
  1390.     auth->id = authreq->id;
  1391.     memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN);
  1392.  
  1393.     DEBUG("Sending Ack of id %d to %lx (%s)\n",
  1394.         authreq->id, (u_long)authreq->ipaddr,
  1395.         ip_hostname(authreq->ipaddr));
  1396.  
  1397.     total_length = AUTH_HDR_LEN;
  1398.  
  1399.     /* Load up the configuration values for the user */
  1400.     ptr = auth->data;
  1401.     while(reply != (VALUE_PAIR *)NULL) {
  1402.         debug_pair(stdout, reply);
  1403.         *ptr++ = reply->attribute;
  1404.  
  1405.         switch(reply->type) {
  1406.  
  1407.         case PW_TYPE_STRING:
  1408.             len = strlen(reply->strvalue);
  1409.             if (len >= AUTH_STRING_LEN) {
  1410.                 len = AUTH_STRING_LEN - 1;
  1411.             }
  1412.             *ptr++ = len + 2;
  1413.             memcpy(ptr, reply->strvalue,len);
  1414.             ptr += len;
  1415.             total_length += len + 2;
  1416.             break;
  1417.             
  1418.         case PW_TYPE_INTEGER:
  1419.         case PW_TYPE_IPADDR:
  1420.             *ptr++ = sizeof(UINT4) + 2;
  1421.             lvalue = htonl(reply->lvalue);
  1422.             memcpy(ptr, &lvalue, sizeof(UINT4));
  1423.             ptr += sizeof(UINT4);
  1424.             total_length += sizeof(UINT4) + 2;
  1425.             break;
  1426.  
  1427.         default:
  1428.             break;
  1429.         }
  1430.  
  1431.         reply = reply->next;
  1432.     }
  1433.  
  1434.     /* Append the user message */
  1435.     if    (msg != (char *)NULL) {
  1436.         len = strlen(msg);
  1437.         if    (len > 0 && len < AUTH_STRING_LEN) {
  1438.             *ptr++ = PW_PORT_MESSAGE;
  1439.             *ptr++ = len + 2;
  1440.             memcpy(ptr, msg, len);
  1441.             ptr += len;
  1442.             total_length += len + 2;
  1443.         }
  1444.     }
  1445.  
  1446.     auth->length = htons(total_length);
  1447.  
  1448.     /* Append secret and calculate the response digest */
  1449.     secretlen = strlen(authreq->secret);
  1450.     DEBUG("ACCPT Secret :%s :%d\n",authreq->secret,secretlen);
  1451.     memcpy(send_buffer + total_length, authreq->secret, secretlen);
  1452.     md5_calc(digest, (char *)auth, total_length + secretlen);
  1453.     memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
  1454.     memset(send_buffer + total_length, 0, secretlen);
  1455.  
  1456.     sin = (struct sockaddr_in *) &saremote;
  1457.     memset ((char *) sin, '\0', sizeof (saremote));
  1458.     sin->sin_family = AF_INET;
  1459.     sin->sin_addr.s_addr = htonl(authreq->ipaddr);
  1460.     sin->sin_port = htons(authreq->udp_port);
  1461.     //DEBUG("sin_port = %d\n", sin->sin_port);
  1462.     //DEBUG("s_addr   = %ld\n",sin->sin_addr.s_addr);
  1463.     /* Send it to the user */
  1464.     sendto(activefd, (char *)auth, (int)total_length, (int)0,
  1465.             &saremote, sizeof(struct sockaddr_in));
  1466. }
  1467.  
  1468. /*************************************************************************
  1469.  *
  1470.  *    Function: unix_pass
  1471.  *
  1472.  *    Purpose: Check the users password against the standard UNIX
  1473.  *         password table.
  1474.  *
  1475.  *************************************************************************/
  1476. int
  1477. unix_pass(name, passwd)
  1478. char    *name;
  1479. char    *passwd;
  1480. {
  1481.     struct    passwd    *pwd;
  1482.     struct    passwd    *getpwnam();
  1483.     char    *encpw;
  1484.     char    *crypt();
  1485.     char    *encrypted_pass;
  1486.  
  1487. #if !defined(NOSHADOW)
  1488. #if defined(M_UNIX)
  1489.     struct passwd    *spwd;
  1490. #else
  1491.     struct passwd    *spwd;
  1492. #endif
  1493. #endif /* !NOSHADOW */
  1494.  
  1495.     encpw = NULL;
  1496.  
  1497.     /* Get encrypted password from password file */
  1498.     if((pwd = getpwnam(name)) == NULL) {
  1499.         return(-1);
  1500.     }
  1501.  
  1502.     encrypted_pass = pwd->pw_passwd;
  1503.  
  1504. #if !defined(NOSHADOW)
  1505.     if(strcmp(pwd->pw_passwd, "x") == 0) {
  1506. /*        if((spwd = getspnam(name)) == NULL) {
  1507.             return(-1);
  1508.         }
  1509.         */
  1510.       #if defined(M_UNIX)
  1511.         encrypted_pass = spwd->pw_passwd;
  1512. #else
  1513.        encrypted_pass = spwd->pw_passwd;
  1514. #endif    /* M_UNIX */
  1515.     }
  1516. #endif    /* !NOSHADOW */
  1517.  
  1518.     /* Run encryption algorythm */
  1519.     encpw = crypt(passwd, encrypted_pass);
  1520.  
  1521.     /* Check it */
  1522.     if(strcmp(encpw, encrypted_pass)) {
  1523.         return(-1);
  1524.     }
  1525.     return(0);
  1526. }
  1527. /*************************************************************************
  1528.  *
  1529.  *    Function: calc_digest
  1530.  *
  1531.  *    Purpose: Validates the requesting client NAS.  Calculates the
  1532.  *         digest to be used for decrypting the users password
  1533.  *         based on the clients private key.
  1534.  *
  1535.  *************************************************************************/
  1536. int
  1537. calc_digest(digest, authreq)
  1538. u_char        *digest;
  1539. AUTH_REQ    *authreq;
  1540. {
  1541.     FILE    *clientfd;
  1542.     u_char    buffer[128];
  1543.     u_char    secret[64];
  1544.     char    hostnm[256];
  1545.     char    msg[128];
  1546.     char    *ip_hostname();
  1547.     int        secretlen;
  1548.     UINT4    ipaddr;
  1549.     UINT4    get_ipaddr();
  1550.  
  1551.     /* Find the client in the database */
  1552.     sprintf(buffer, "%s/%s", radius_dir, RADIUS_CLIENTS);
  1553.  
  1554.     if((clientfd = fopen(buffer, "r")) == (FILE *)NULL) {
  1555.         fprintf(stderr, "%s: couldn't open %s to find clients\n", progname, buffer);
  1556.         return(-1);
  1557.     }
  1558.     ipaddr = (UINT4)0;
  1559.     while(fgets(buffer, sizeof(buffer), clientfd) != (char *)NULL) {
  1560.         if(*buffer == '#') {
  1561.             continue;
  1562.         }
  1563.         if(sscanf(buffer, "%s%s", hostnm, secret) != 2) {
  1564.             continue;
  1565.         }
  1566.          DEBUG("Hostname: %s\n",hostnm);
  1567.         ipaddr = get_ipaddr(hostnm);
  1568.          DEBUG("IP ADDR: %s\n",ip_hostname(ipaddr));
  1569.         if(ipaddr == authreq->ipaddr) {
  1570.             break;
  1571.         }
  1572.     }
  1573.     fclose(clientfd);
  1574.     memset(buffer, 0, sizeof(buffer));
  1575.  
  1576.     /*
  1577.      * Validate the requesting IP address -
  1578.      * Not secure, but worth the check for accidental requests
  1579.      */
  1580.     if(ipaddr != authreq->ipaddr) {
  1581.         strcpy(hostnm,ip_hostname(ipaddr));
  1582.         sprintf(msg, "requester address mismatch: %s != %s\n",
  1583.             hostnm,
  1584.             ip_hostname(authreq->ipaddr));
  1585.         log_err(msg);
  1586.         memset(secret, 0, sizeof(secret));
  1587.         return(-1);
  1588.     }
  1589.  
  1590.     /* Use the secret to setup the decryption digest */
  1591.     secretlen = strlen(secret);
  1592.     strcpy(buffer, secret);
  1593.     memcpy(buffer + secretlen, authreq->vector, AUTH_VECTOR_LEN);
  1594.     md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN);
  1595.     strcpy(authreq->secret, secret);
  1596.     memset(buffer, 0, sizeof(buffer));
  1597.     memset(secret, 0, sizeof(secret));
  1598.     return(0);
  1599. }
  1600.  
  1601. /*************************************************************************
  1602.  *
  1603.  *    Function: debug_pair
  1604.  *
  1605.  *    Purpose: Print the Attribute-value pair to the desired File.
  1606.  *
  1607.  *************************************************************************/
  1608. void
  1609. debug_pair(fd, pair)
  1610. FILE        *fd;
  1611. VALUE_PAIR    *pair;
  1612. {
  1613.     if(debug_flag) {
  1614.         fputs("    ", fd);
  1615.         fprint_attr_val(fd, pair);
  1616.         fputs("\n", fd);
  1617.     }
  1618. }
  1619.  
  1620. /*************************************************************************
  1621.  *
  1622.  *    Function: usage
  1623.  *
  1624.  *    Purpose: Display the syntax for starting this program.
  1625.  *
  1626.  *************************************************************************/
  1627. void
  1628. usage(void)
  1629. {
  1630.     fprintf(stderr, "Usage: %s [ -a acct_dir ] [ -s ] [ -x ] [ -d db_dir ]\n",progname);
  1631.     exit(-1);
  1632. }
  1633.  
  1634. /*************************************************************************
  1635.  *
  1636.  *    Function: log_err
  1637.  *
  1638.  *    Purpose: Log the error message provided to the error log with
  1639.          a time stamp.
  1640.  *
  1641.  *************************************************************************/
  1642. int
  1643. log_err(msg)
  1644. char    *msg;
  1645. {
  1646.     FILE    *msgfd;
  1647.     char    buffer[128];
  1648.     time_t    timeval;
  1649.  
  1650.     sprintf(buffer, "%s/%s", radius_dir, RADIUS_LOG);
  1651.  
  1652.     if((msgfd = fopen(buffer, "a")) == (FILE *)NULL) {
  1653.         fprintf(stderr, "%s:Couldn't open %s for logging\n", progname, buffer);
  1654.         return(-1);
  1655.     }
  1656.     timeval = time(0);
  1657.     fprintf(msgfd, "%-24.24s: %s", ctime(&timeval), msg);
  1658.     fclose(msgfd);
  1659.     return(0);
  1660. }
  1661.  
  1662. /*************************************************************************
  1663.  *
  1664.  *    Function: config_init
  1665.  *
  1666.  *    Purpose: intializes configuration values:
  1667.  *
  1668.  *         expiration_seconds - When updating a user password,
  1669.  *            the amount of time to add to the current time
  1670.  *            to set the time when the password will expire.
  1671.  *            This is stored as the VALUE Password-Expiration
  1672.  *            in the dictionary as number of days.
  1673.  *
  1674.  *        warning_seconds - When acknowledging a user authentication
  1675.  *            time remaining for valid password to notify user
  1676.  *            of password expiration.
  1677.  *
  1678.  *************************************************************************/
  1679. int
  1680. config_init()
  1681. {
  1682.     DICT_VALUE    *dval;
  1683.     DICT_VALUE    *dict_valfind();
  1684.  
  1685.     if((dval = dict_valfind("Password-Expiration")) == (DICT_VALUE *)NULL) {
  1686.         expiration_seconds = (UINT4)0;
  1687.     }
  1688.     else {
  1689.         expiration_seconds = dval->value * (UINT4)SECONDS_PER_DAY;
  1690.     }
  1691.     if((dval = dict_valfind("Password-Warning")) == (DICT_VALUE *)NULL) {
  1692.         warning_seconds = (UINT4)0;
  1693.     }
  1694.     else {
  1695.         warning_seconds = dval->value * (UINT4)SECONDS_PER_DAY;
  1696.     }
  1697.     return(0);
  1698. }
  1699.  
  1700. /*************************************************************************
  1701.  *
  1702.  *    Function: set_expiration
  1703.  *
  1704.  *    Purpose: Set the new expiration time by updating or adding
  1705.          the Expiration attribute-value pair.
  1706.  *
  1707.  *************************************************************************/
  1708. int
  1709. set_expiration(user_check, expiration)
  1710. VALUE_PAIR    *user_check;
  1711. UINT4        expiration;
  1712. {
  1713.     VALUE_PAIR    *exppair;
  1714.     VALUE_PAIR    *prev;
  1715.     struct        timeval    tp;
  1716.     struct        timezone    tzp;
  1717.  
  1718.     if(user_check == (VALUE_PAIR *)NULL) {
  1719.         return(-1);
  1720.     }
  1721.  
  1722.     /* Look for an existing expiration entry */
  1723.     exppair = user_check;
  1724.     prev = (VALUE_PAIR *)NULL;
  1725.     while(exppair != (VALUE_PAIR *)NULL) {
  1726.         if    (exppair->attribute == PW_EXPIRATION) {
  1727.             break;
  1728.         }
  1729.         prev = exppair;
  1730.         exppair = exppair->next;
  1731.     }
  1732.     if    (exppair == (VALUE_PAIR *)NULL) {
  1733.         /* Add a new attr-value pair */
  1734.         if    ((exppair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
  1735.                     (VALUE_PAIR *)NULL) {
  1736.             fprintf(stderr, "%s: no memory\n", progname);
  1737.             exit(-1);
  1738.         }
  1739.         /* Initialize it */
  1740.         strcpy(exppair->name, "Expiration");
  1741.         exppair->attribute = PW_EXPIRATION;
  1742.         exppair->type = PW_TYPE_DATE;
  1743.         *exppair->strvalue = '\0';
  1744.         exppair->lvalue = (UINT4)0;
  1745.         exppair->next = (VALUE_PAIR *)NULL;
  1746.  
  1747.         /* Attach it to the list. */
  1748.         prev->next = exppair;
  1749.     }
  1750.  
  1751.     /* calculate a new expiration */
  1752.     gettimeofday(&tp, &tzp);
  1753.     exppair->lvalue = tp.tv_sec + expiration;
  1754.     return(0);
  1755. }
  1756.  
  1757. /*************************************************************************
  1758.  *
  1759.  *    Function: pw_expired
  1760.  *
  1761.  *    Purpose: Tests to see if the users password has expired.
  1762.  *
  1763.  *    Return: Number of days before expiration if a warning is required
  1764.  *        otherwise 0 for success and -1 for failure.
  1765.  *
  1766.  *************************************************************************/
  1767. int
  1768. pw_expired(exptime)
  1769. UINT4    exptime;
  1770. {
  1771.     struct    timeval    tp;
  1772.     struct    timezone    tzp;
  1773.     UINT4    exp_remain;
  1774.     int        exp_remain_int;
  1775.  
  1776.     if    (expiration_seconds == (UINT4)0) {
  1777.         return(0);
  1778.     }
  1779.  
  1780.     gettimeofday(&tp, &tzp);
  1781.     if    (tp.tv_sec > exptime) {
  1782.         return(-1);
  1783.     }
  1784.     if    (warning_seconds != (UINT4)0) {
  1785.         if    (tp.tv_sec > exptime - warning_seconds) {
  1786.             exp_remain = exptime - tp.tv_sec;
  1787.             exp_remain /= (UINT4)SECONDS_PER_DAY;
  1788.             exp_remain_int = exp_remain;
  1789.             return(exp_remain_int);
  1790.         }
  1791.     }
  1792.     return(0);
  1793. }
  1794.  
  1795. void
  1796. sig_fatal(sig)
  1797. int    sig;
  1798. {
  1799.     if(acct_pid > 0) {
  1800.         kill(acct_pid, SIGKILL);
  1801.     }
  1802.  
  1803.     fprintf(stderr, "%s: exit on signal (%d)\n", progname, sig);
  1804.     fflush(stderr);
  1805.     exit(1);
  1806. }
  1807.  
  1808. void
  1809. sig_hup(sig)
  1810. int    sig;
  1811. {
  1812.     return;
  1813. }
  1814.