home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / radius_2.zip / acct.c next >
C/C++ Source or Header  |  1996-05-24  |  6KB  |  242 lines

  1. /*
  2.  *
  3.  *    RADIUS Accounting
  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 - 1994 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. "@(#)acct.c    1.6  Copyright 1994 Livingston Enterprises Inc";
  30.  
  31. #include    <sys/types.h>
  32. #include    <sys/socket.h>
  33. #include    <sys/time.h>
  34. #include    <sys/file.h>
  35. #include    <netinet/in.h>
  36.  
  37. #include    <stdio.h>
  38. #include    <stdlib.h>
  39. #include    <netdb.h>
  40. #include    <pwd.h>
  41. #include    <time.h>
  42. #include    <ctype.h>
  43. #include    <unistd.h>
  44. #include    <signal.h>
  45. #include    <errno.h>
  46. #include    <sys/wait.h>
  47.  
  48. #include    "radius.h"
  49.  
  50. extern char        recv_buffer[4096];
  51. extern char        send_buffer[4096];
  52. extern char        *progname;
  53. extern int        debug_flag;
  54. extern char        *radacct_dir;
  55. extern char        *radius_dir;
  56. extern UINT4        expiration_seconds;
  57. extern UINT4        warning_seconds;
  58. extern int        errno;
  59.  
  60. UINT4            calctime();
  61.  
  62. void
  63. rad_accounting(authreq, activefd)
  64. AUTH_REQ    *authreq;
  65. int        activefd;
  66. {
  67.     char        pw_digest[16];
  68.     FILE        *outfd;
  69.     char        *ip_hostname();
  70.     char        clientname[128];
  71.     char        buffer[512];
  72.     char        msg[128];
  73.     VALUE_PAIR    *pair;
  74.     long        curtime;
  75.  
  76.     /* Verify the client and Calculate the MD5 Password Digest */
  77.     if    (calc_digest(pw_digest, authreq) != 0) {
  78.         DEBUG("failed password !!\n");
  79.         /* We dont respond when this fails */
  80.         sprintf(msg, "Acctounting Authenticate: from %s\n",
  81.             ip_hostname(authreq->ipaddr));
  82.         log_err(msg);
  83.         pairfree(authreq->request);
  84.         memset(authreq, 0, sizeof(AUTH_REQ));
  85.         free(authreq);
  86.         return;
  87.     }
  88.  
  89.     strcpy(clientname, ip_hostname(authreq->ipaddr));
  90.  
  91.     /*
  92.      * Create a directory for this client.
  93.      */
  94.     sprintf(buffer, "%s/%s", radacct_dir, clientname);
  95.     mkdir(buffer, 0755);
  96.  
  97.     /*
  98.      * Write Detail file.
  99.      */
  100.     sprintf(buffer, "%s/%s/detail", radacct_dir, clientname);
  101.     if((outfd = fopen(buffer, "a")) == (FILE *)NULL) {
  102.         sprintf(buffer,
  103.             "Acct: Couldn't open file %s/%s/detail\n",
  104.             radacct_dir, clientname);
  105.         log_err(buffer);
  106.         /* don't respond if we can't save record */
  107.     } else {
  108.  
  109.         /* Post a timestamp */
  110.         curtime = time(0);
  111.         fputs(ctime(&curtime), outfd);
  112.  
  113.         /* Write each attribute/value to the log file */
  114.         pair = authreq->request;
  115.         while(pair != (VALUE_PAIR *)NULL) {
  116.             fputs("\t", outfd);
  117.             fprint_attr_val(outfd, pair);
  118.             fputs("\n", outfd);
  119.         pair = pair->next;
  120.         }
  121.         fputs("\n", outfd);
  122.         fclose(outfd);
  123.         /* let NAS know it is OK to delete from buffer */
  124.         send_acct_reply(authreq, (VALUE_PAIR *)NULL, 
  125.                 (char *)NULL,activefd);
  126.     }
  127.  
  128.     pairfree(authreq->request);
  129.     memset(authreq, 0, sizeof(AUTH_REQ));
  130.     free(authreq);
  131.     return;
  132. }
  133.  
  134. /*************************************************************************
  135.  *
  136.  *    Function: send_acct_reply
  137.  *
  138.  *    Purpose: Reply to the request with an ACKNOWLEDGE.  Also attach
  139.  *         reply attribute value pairs and any user message provided.
  140.  *
  141.  *************************************************************************/
  142. void
  143. send_acct_reply(authreq, reply, msg, activefd)
  144. AUTH_REQ    *authreq;
  145. VALUE_PAIR    *reply;
  146. char        *msg;
  147. int        activefd;
  148. {
  149.     AUTH_HDR        *auth;
  150.     u_short            total_length;
  151.     struct            sockaddr_in    saremote;
  152.     struct            sockaddr_in    *sin;
  153.     u_char            *ptr;
  154.     int                len;
  155.     UINT4            lvalue;
  156.     u_char            digest[16];
  157.     int                secretlen;
  158.     char            *ip_hostname();
  159.  
  160.     auth = (AUTH_HDR *)send_buffer;
  161.  
  162.     /* Build standard header */
  163.     auth->code = PW_ACCOUNTING_RESPONSE;
  164.     auth->id = authreq->id;
  165.     memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN);
  166.  
  167.     DEBUG("Sending Accounting Ack of id %d to %lx (%s)\n",
  168.         authreq->id, authreq->ipaddr, ip_hostname(authreq->ipaddr));
  169.  
  170.     total_length = AUTH_HDR_LEN;
  171.  
  172.     /* Load up the configuration values for the user */
  173.     ptr = auth->data;
  174.     while(reply != (VALUE_PAIR *)NULL) {
  175.         debug_pair(stdout, reply);
  176.         *ptr++ = reply->attribute;
  177.          DEBUG("Accounting in while loop:%d\n",reply->type);
  178.  
  179.         switch(reply->type) {
  180.  
  181.         case PW_TYPE_STRING:
  182.             len = strlen(reply->strvalue);
  183.            if (len >= AUTH_STRING_LEN) {
  184.               len = AUTH_STRING_LEN - 1;
  185.            }
  186.            *ptr++ = len + 2;
  187.            memcpy(ptr, reply->strvalue,len);
  188. /*           strcpy(ptr, reply->strvalue);*/
  189.             ptr += len;
  190.             total_length += len + 2;
  191.             break;
  192.             
  193.         case PW_TYPE_INTEGER:
  194.         case PW_TYPE_IPADDR:
  195.             *ptr++ = sizeof(UINT4) + 2;
  196.             lvalue = htonl(reply->lvalue);
  197.             memcpy(ptr, &lvalue, sizeof(UINT4));
  198.             ptr += sizeof(UINT4);
  199.             total_length += sizeof(UINT4) + 2;
  200.             break;
  201.  
  202.         default:
  203.             break;
  204.         }
  205.  
  206.         reply = reply->next;
  207.     }
  208.  
  209.     /* Append the user message */
  210.     if(msg != (char *)NULL) {
  211.         len = strlen(msg);
  212.         if(len > 0 && len < AUTH_STRING_LEN) {
  213.             *ptr++ = PW_PORT_MESSAGE;
  214.             *ptr++ = len + 2;
  215.             memcpy(ptr, msg, len);
  216.             ptr += len;
  217.             total_length += len + 2;
  218.         }
  219.     }
  220.     DEBUG("Accounting user message:%s\n",msg);
  221.  
  222.     auth->length = htons(total_length);
  223.  
  224.     /* Calculate the response digest */
  225.     secretlen = strlen(authreq->secret);
  226.     DEBUG("ACCT Secret :%s :%d\n",authreq->secret,secretlen);
  227.     memcpy(send_buffer + total_length, authreq->secret, secretlen);
  228.     md5_calc(digest, (char *)auth, total_length + secretlen);
  229.     memcpy(auth->vector, digest, AUTH_VECTOR_LEN);
  230.     memset(send_buffer + total_length, 0, secretlen);
  231.  
  232.     sin = (struct sockaddr_in *) &saremote;
  233.         memset ((char *) sin, '\0', sizeof (saremote));
  234.     sin->sin_family = AF_INET;
  235.     sin->sin_addr.s_addr = htonl(authreq->ipaddr);
  236.     sin->sin_port = htons(authreq->udp_port);
  237.  
  238.     /* Send it to the user */
  239.     sendto(activefd, (char *)auth, (int)total_length, (int)0,
  240.             (struct sockaddr *) sin, sizeof(struct sockaddr_in));
  241. }
  242.