Added pre/post-proxy sections to detail module
authoraland <aland>
Mon, 11 Aug 2003 17:06:51 +0000 (17:06 +0000)
committeraland <aland>
Mon, 11 Aug 2003 17:06:51 +0000 (17:06 +0000)
Added comments in 'radiusd.conf', to show how all stages of
packet processing can be logged with the 'detail' module.

raddb/radiusd.conf.in
src/modules/rlm_detail/rlm_detail.c

index 99c7d8d..92f4428 100644 (file)
@@ -597,7 +597,7 @@ modules {
                #  Invoke the default supported EAP type when
                #  EAP-Identity response is received.
                #
-               #  The incoming EAP messages MAY NOT specify which EAP
+               #  The incoming EAP messages DO NOT specify which EAP
                #  type they will be using, so it MUST be set here.
                #
                #  For now, only one default EAP type may be used at a time.
@@ -613,10 +613,10 @@ modules {
                #  for only a limited subset.  If the server receives
                #  a request for an EAP type it does not support, then
                #  it normally rejects the request.  By setting this
-               #  value to "yes", you can tell the server to instead
-               #  keep processing the request.  Another module MUST
-               #  then be configured to proxy the request to another
-               #  RADIUS server which supports that EAP type.
+               #  configuration to "yes", you can tell the server to
+               #  instead keep processing the request.  Another module
+               #  MUST then be configured to proxy the request to
+               #  another RADIUS server which supports that EAP type.
                #
                #  If another module is NOT configured to handle the
                #  request, then the request will still end up being
@@ -624,6 +624,12 @@ modules {
                ignore_unknown_eap_types = no
 
                # Supported EAP-types
+
+               #
+               #  We do NOT recommend using EAP-MD5 authentication
+               #  for wireless connections.  It is insecure, and does
+               #  not provide for dynamic WEP keys.
+               #
                md5 {
                }
 
@@ -645,34 +651,41 @@ modules {
                #       private_key_password = password
                #       private_key_file = /path/filename
 
-               #       If Private key & Certificate are located in the
-               #       same file, then private_key_file & certificate_file
-               #       must contain the same file name.
+                       #  If Private key & Certificate are located in
+                       #  the same file, then private_key_file &
+                       #  certificate_file must contain the same file
+                       #  name.
                #       certificate_file = /path/filename
 
-               #       Trusted Root CA list
-                       #CA_file = /path/filename
+                       #  Trusted Root CA list
+               #       CA_file = /path/filename
 
                #       dh_file = /path/filename
-                       #random_file = /path/filename
-               #
-               #       This can never exceed MAX_RADIUS_LEN (4096)
-               #       preferably half the MAX_RADIUS_LEN, to
-               #       accomodate other attributes in RADIUS packet.
-               #       On most APs the MAX packet length is configured
-               #       between 1500 - 1600. In these cases, fragment
-               #       size should be <= 1024.
-               #
+               #       random_file = /path/filename
+
+                       #
+                       #  This can never exceed the size of a RADIUS
+                       #  packet (4096 bytes), and is preferably half
+                       #  that, to accomodate other attributes in
+                       #  RADIUS packet.  On most APs the MAX packet
+                       #  length is configured between 1500 - 1600
+                       #  In these cases, fragment size should be
+                       #  1024 or less.
+                       #
                #               fragment_size = 1024
 
-               #       include_length is a flag which is by default set to yes
-               #       If set to yes, Total Length of the message is included
-               #       in EVERY packet we send.
-               #       If set to no, Total Length of the message is included
-               #       ONLY in the First packet of a fragment series.
-               #
+                               #  include_length is a flag which is
+                               #  by default set to yes If set to
+                               #  yes, Total Length of the message is
+                               #  included in EVERY packet we send.
+                               #  If set to no, Total Length of the
+                               #  message is included ONLY in the
+                               #  First packet of a fragment series.
+                               #
                #               include_length = yes
                #}
+
+
        }
 
        # Microsoft CHAP authentication
@@ -962,6 +975,71 @@ modules {
                detailperm = 0600
        }
 
+       #
+       #  Many people want to log authentication requests.
+       #  Rather than modifying the server core to print out more
+       #  messages, we can use a different instance of the 'detail'
+       #  module, to log the authentication requests to a file.
+       #
+       #  You will also need to un-comment the 'auth_log' line
+       #  in the 'authorize' section, below.
+       #
+       # detail auth_log {
+               # detailfile = ${radacctdir}/%{Client-IP-Address}/auth-detail-%Y%m%d
+
+               #
+               #  This MUST be 0600, otherwise anyone can read
+               #  the users passwords!
+               # detailperm = 0600
+       # }
+
+       #
+       #  This module logs authentication reply packets sent
+       #  to a NAS.  Both Access-Accept and Access-Reject packets
+       #  are logged.
+       #
+       #  You will also need to un-comment the 'reply_log' line
+       #  in the 'post-auth' section, below.
+       #
+       # detail reply_log {
+               # detailfile = ${radacctdir}/%{Client-IP-Address}/reply-detail-%Y%m%d
+
+               #
+               #  This MUST be 0600, otherwise anyone can read
+               #  the users passwords!
+               # detailperm = 0600
+       # }
+
+       #
+       #  This module logs packets proxied to a home server.
+       #
+       #  You will also need to un-comment the 'pre_proxy_log' line
+       #  in the 'pre-proxy' section, below.
+       #
+       # detail pre_proxy_log {
+               # detailfile = ${radacctdir}/%{Client-IP-Address}/pre-proxy-detail-%Y%m%d
+
+               #
+               #  This MUST be 0600, otherwise anyone can read
+               #  the users passwords!
+               # detailperm = 0600
+       # }
+
+       #
+       #  This module logs response packets from a home server.
+       #
+       #  You will also need to un-comment the 'post_proxy_log' line
+       #  in the 'post-post' section, below.
+       #
+       # detail post_proxy_log {
+               # detailfile = ${radacctdir}/%{Client-IP-Address}/post-proxy-detail-%Y%m%d
+
+               #
+               #  This MUST be 0600, otherwise anyone can read
+               #  the users passwords!
+               # detailperm = 0600
+       # }
+
        # Create a unique accounting session Id.  Many NASes re-use or
        # repeat values for Acct-Session-Id, causing no end of
        # confusion.
@@ -1355,6 +1433,12 @@ authorize {
        #
        #  It also adds a Client-IP-Address attribute to the request.
        preprocess
+
+       #
+       #  If you want to have a log of authentication requests,
+       #  un-comment the following line, and the 'detail auth_log'
+       #  section, above.
+#      auth_log
        
        #
        #  The chap module will set 'Auth-Type := CHAP' if we are
@@ -1541,6 +1625,12 @@ session {
 post-auth {
        #  Get an address from the IP Pool.
 #      main_pool
+
+       #
+       #  If you want to have a log of authentication replies,
+       #  un-comment the following line, and the 'detail reply_log'
+       #  section, above.
+#      reply_log
 }
 
 #
@@ -1552,7 +1642,12 @@ post-auth {
 #  Only a few modules currently have this method.
 #
 pre-proxy {
-       # attr_rewrite
+#      attr_rewrite
+
+       #  If you want to have a log of packets proxied to a home
+       #  server, un-comment the following line, and the
+       #  'detail pre_proxy_log' section, above.
+#      pre_proxy_log
 }
 
 #
@@ -1561,7 +1656,14 @@ pre-proxy {
 #  post-proxy stage.
 #
 post-proxy {
-       # attr_rewrite
+       #
+
+       #  If you want to have a log of replies from a home server,
+       #  un-comment the following line, and the 'detail post_proxy_log'
+       #  section, above.
+#      post_proxy_log
+
+#      attr_rewrite
 
        #
        #  If you are proxing LEAP, you MUST configure the EAP
index 6bf304b..6731774 100644 (file)
@@ -36,6 +36,22 @@ static const char rcsid[] = "$Id$";
 #include       "modules.h"
 #define        DIRLEN  8192
 
+static const char *packet_codes[] = {
+  "",
+  "Access-Request",
+  "Access-Accept",
+  "Access-Reject",
+  "Accounting-Request",
+  "Accounting-Response",
+  "Accounting-Status",
+  "Password-Request",
+  "Password-Accept",
+  "Password-Reject",
+  "Accounting-Message",
+  "Access-Challenge"
+};
+
+
 struct detail_instance {
        /* detail file */
        char *detailfile;
@@ -89,23 +105,34 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
        return 0;
 }
 
-static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
+/*
+ *     Do detail, compatible with old accounting
+ */
+static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
+                    int compat)
 {
        int             outfd;
        FILE            *outfp;
        char            buffer[DIRLEN];
        char            *p;
-       int             ret = RLM_MODULE_OK;
        struct stat     st;
        int             locked;
        int             lock_count;
        struct timeval  tv;
        REALM           *proxy_realm;
        char            proxy_buffer[16];
+       VALUE_PAIR      *pair = packet->vps;
 
        struct detail_instance *inst = instance;
 
        /*
+        *      Nothing to log: don't do anything.
+        */
+       if (!packet) {
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
         *      Create a directory for this nas.
         *
         *      Generate the path for the detail file.  Use the
@@ -164,7 +191,15 @@ static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
 
        /*
         *      Open & create the file, with the given permissions.
-        *
+        */
+       if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
+                         inst->detailperm)) < 0) {
+               radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+                      buffer, strerror(errno));
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
         *      If we're not using locking, we'll just pass straight though
         *      the while loop.
         *      If we fail to aquire the filelock in 80 tries (approximately
@@ -173,13 +208,6 @@ static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
        locked = 0;
        lock_count = 0;
        do {
-               if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
-                                 inst->detailperm)) < 0) {
-                       radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
-                              buffer, strerror(errno));
-                       ret = RLM_MODULE_FAIL;
-                       break;
-               }
                if (inst->locking) {
                        lseek(outfd, 0L, SEEK_SET);
                        if (rad_lockfd_nonblock(outfd, 0) < 0) {
@@ -189,7 +217,7 @@ static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
                                select(0, NULL, NULL, NULL, &tv);
                                lock_count++;
                        } else {
-                               DEBUG("rlm_detail: Aquired filelock, tried %d time(s)",
+                               DEBUG("rlm_detail: Acquired filelock, tried %d time(s)",
                                      lock_count + 1);
                                locked = 1;
                        }
@@ -199,75 +227,104 @@ static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
        if (!locked && inst->locking && lock_count >= 80) {
                radlog(L_ERR, "rlm_detail: Failed to aquire filelock for %s, giving up",
                       buffer);
-               outfd = -1;
-               ret = RLM_MODULE_FAIL;
+               return RLM_MODULE_FAIL;
        }
 
-       outfp = NULL;
-       if (outfd > -1) {
-               if ((outfp = fdopen(outfd, "a")) == NULL) {
-                       radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
-                              buffer, strerror(errno));
-                       ret = RLM_MODULE_FAIL;
-                       if (inst->locking) {
-                               lseek(outfd, 0L, SEEK_SET);
-                               rad_unlockfd(outfd, 0);
-                               DEBUG("rlm_detail: Released filelock");
-                       }
-                       close(outfd);
+       /*
+        *      Convert the FD to FP.  The FD is no longer valid
+        *      after this operation.
+        */
+       if ((outfp = fdopen(outfd, "a")) == NULL) {
+               radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+                      buffer, strerror(errno));
+               if (inst->locking) {
+                       lseek(outfd, 0L, SEEK_SET);
+                       rad_unlockfd(outfd, 0);
+                       DEBUG("rlm_detail: Released filelock");
                }
+               close(outfd);
+
+               return RLM_MODULE_FAIL;
        }
 
-       if (outfd > -1 && outfp) {
-               /* Post a timestamp */
-               fseek(outfp, 0L, SEEK_END);
-               fputs(ctime_r(&request->timestamp, buffer), outfp);
-
-               /* Write each attribute/value to the log file */
-               while (pair) {
-                       if (pair->attribute != PW_PASSWORD) {
-                               fputs("\t", outfp);
-                               vp_print(outfp, pair);
-                               fputs("\n", outfp);
-                       }
-                       pair = pair->next;
+       /*
+        *      Write the information to the file.
+        */
+       if (!compat) {
+               /*
+                *      Print out names, if they're OK.
+                *      Numbers, if not.
+                */
+               if ((packet->code > 0) &&
+                   (packet->code <= PW_ACCESS_CHALLENGE)) {
+                       fprintf(outfp, "Packet-Type = %s\n",
+                               packet_codes[packet->code]);
+               } else {
+                       fprintf(outfp, "Packet-Type = %d\n", packet->code);
                }
+       }
 
+       /*
+        *      Post a timestamp
+        */
+       fseek(outfp, 0L, SEEK_END);
+       fputs(ctime_r(&request->timestamp, buffer), outfp);
+       
+       /* Write each attribute/value to the log file */
+       while (pair) {
                /*
-                *      Add non-protocol attibutes.
+                *      Don't print passwords in old format...
                 */
-               if ((pair = pairfind(request->config_items, PW_PROXY_TO_REALM))
-                   != NULL) {
+               if (compat && (pair->attribute == PW_PASSWORD)) continue;
+
+               /*
+                *      Print all of the attributes.
+                */
+               fputs("\t", outfp);
+               vp_print(outfp, pair);
+               fputs("\n", outfp);
+               pair = pair->next;
+       }
+
+       /*
+        *      Add non-protocol attibutes.
+        */
+       if (compat) {
+               if ((pair = pairfind(request->config_items,
+                                    PW_PROXY_TO_REALM)) != NULL) {
                        proxy_realm = realm_find(pair->strvalue, TRUE);
                        if (proxy_realm) {
                                memset((char *) proxy_buffer, 0, 16);
                                ip_ntoa(proxy_buffer, proxy_realm->acct_ipaddr);
                                fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
-                                       proxy_buffer);
+                                       proxy_buffer);
                                DEBUG("rlm_detail: Freeradius-Proxied-To set to %s",
                                      proxy_buffer);
                        }
                }
                fprintf(outfp, "\tTimestamp = %ld\n", request->timestamp);
+
                if (request->packet->verified == 2)
                        fputs("\tRequest-Authenticator = Verified\n", outfp);
                else if (request->packet->verified == 1)
                        fputs("\tRequest-Authenticator = None\n", outfp);
-               pair = NULL;
-
-               fputs("\n", outfp);
-
-               if (inst->locking) {
-                       fflush(outfp);
-                       lseek(outfd, 0L, SEEK_SET);
-                       rad_unlockfd(outfd, 0);
-                       DEBUG("rlm_detail: Released filelock");
-               }
+       }
        
-               fclose(outfp);
+       fputs("\n", outfp);
+
+       if (inst->locking) {
+               fflush(outfp);
+               lseek(outfd, 0L, SEEK_SET);
+               rad_unlockfd(outfd, 0);
+               DEBUG("rlm_detail: Released filelock");
        }
+       
+       fclose(outfp);
 
-       return ret;
+       /*
+        *      And everything is fine.
+        */
+       return RLM_MODULE_OK;
 }
 
 /*
@@ -276,7 +333,7 @@ static int do_detail(void *instance, REQUEST *request, VALUE_PAIR *pair)
 static int detail_accounting(void *instance, REQUEST *request)
 {
 
-       return do_detail(instance,request,request->packet->vps);
+       return do_detail(instance,request,request->packet, TRUE);
 }
 
 /*
@@ -284,7 +341,7 @@ static int detail_accounting(void *instance, REQUEST *request)
  */
 static int detail_authorize(void *instance, REQUEST *request)
 {
-       return do_detail(instance,request,request->packet->vps);
+       return do_detail(instance,request,request->packet, FALSE);
 }
 
 /*
@@ -292,7 +349,35 @@ static int detail_authorize(void *instance, REQUEST *request)
  */
 static int detail_postauth(void *instance, REQUEST *request)
 {
-       return do_detail(instance,request,request->reply->vps);
+       return do_detail(instance,request,request->reply, FALSE);
+}
+
+
+/*
+ *     Outgoing Access-Request to home server - write the detail files.
+ */
+static int detail_pre_proxy(void *instance, REQUEST *request)
+{
+       if (request->proxy &&
+           request->proxy->vps) {
+               return do_detail(instance,request,request->proxy, FALSE);
+       }
+
+       return RLM_MODULE_NOOP;
+}
+
+
+/*
+ *     Outgoing Access-Request Reply - write the detail files.
+ */
+static int detail_post_proxy(void *instance, REQUEST *request)
+{
+       if (request->proxy_reply &&
+           request->proxy_reply->vps) {
+               return do_detail(instance,request,request->proxy_reply, FALSE);
+       }
+
+       return RLM_MODULE_NOOP;
 }
 
 
@@ -323,8 +408,8 @@ module_t rlm_detail = {
                NULL,                   /* preaccounting */
                detail_accounting,      /* accounting */
                NULL,                   /* checksimul */
-               NULL,                   /* pre-proxy */
-               NULL,                   /* post-proxy */
+               detail_pre_proxy,       /* pre-proxy */
+               detail_post_proxy,      /* post-proxy */
                detail_postauth         /* post-auth */
        },
        detail_detach,                  /* detach */