Enable building #WITHOUT_PROXY
[freeradius.git] / src / modules / rlm_detail / rlm_detail.c
index 66401c6..6446359 100644 (file)
 #include       <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include       <freeradius-devel/autoconf.h>
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
+#include       <freeradius-devel/detail.h>
 
 #include       <sys/stat.h>
-#include       <sys/select.h>
-
-#include       <stdlib.h>
-#include       <string.h>
 #include       <ctype.h>
 #include       <fcntl.h>
 
-#include       <freeradius-devel/radiusd.h>
-#include       <freeradius-devel/modules.h>
-#include       <freeradius-devel/rad_assert.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;
@@ -77,7 +56,7 @@ struct detail_instance {
        /* log src/dst information */
        int log_srcdst;
 
-       lrad_hash_table_t *ht;
+       fr_hash_table_t *ht;
 };
 
 static const CONF_PARSER module_config[] = {
@@ -103,11 +82,8 @@ static const CONF_PARSER module_config[] = {
 static int detail_detach(void *instance)
 {
         struct detail_instance *inst = instance;
-       free((char *) inst->detailfile);
-
        free((char*) inst->last_made_directory);
-
-       if (inst->ht) lrad_hash_table_free(inst->ht);
+       if (inst->ht) fr_hash_table_free(inst->ht);
 
         free(inst);
        return 0;
@@ -117,7 +93,7 @@ static int detail_detach(void *instance)
 static uint32_t detail_hash(const void *data)
 {
        const DICT_ATTR *da = data;
-       return lrad_hash(&(da->attr), sizeof(da->attr));
+       return fr_hash(&(da->attr), sizeof(da->attr));
 }
 
 static int detail_cmp(const void *a, const void *b)
@@ -154,7 +130,7 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
        if (cs) {
                CONF_ITEM       *ci;
 
-               inst->ht = lrad_hash_table_create(detail_hash, detail_cmp,
+               inst->ht = fr_hash_table_create(detail_hash, detail_cmp,
                                                  NULL);
 
                for (ci = cf_item_find_next(cs, NULL);
@@ -164,7 +140,7 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
                        DICT_ATTR       *da;
 
                        if (!cf_item_is_pair(ci)) continue;
-                                               
+
                        attr = cf_pair_attr(cf_itemtopair(ci));
                        if (!attr) continue; /* pair-anoia */
 
@@ -180,7 +156,7 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
                         *      since the suppression list will usually
                         *      be small, it doesn't matter.
                         */
-                       if (!lrad_hash_table_insert(inst->ht, da)) {
+                       if (!fr_hash_table_insert(inst->ht, da)) {
                                radlog(L_ERR, "rlm_detail: Failed trying to remember %s", attr);
                                detail_detach(inst);
                                return -1;
@@ -208,12 +184,12 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        int             locked;
        int             lock_count;
        struct timeval  tv;
-       REALM           *proxy_realm;
-       char            proxy_buffer[16];
-       VALUE_PAIR      *pair = packet->vps;
+       VALUE_PAIR      *pair;
 
        struct detail_instance *inst = instance;
 
+       rad_assert(request != NULL);
+
        /*
         *      Nothing to log: don't do anything.
         */
@@ -230,7 +206,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
         *      variables.
         */
        radius_xlat(buffer, sizeof(buffer), inst->detailfile, request, NULL);
-       DEBUG2("rlm_detail: %s expands to %s", inst->detailfile, buffer);
+       RDEBUG2("%s expands to %s", inst->detailfile, buffer);
 
        /*
         *      Grab the last directory delimiter.
@@ -268,7 +244,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                 *      deleted a directory that the server was using.
                 */
                if (rad_mkdir(inst->last_made_directory, inst->dirperm) < 0) {
-                       radlog(L_ERR, "rlm_detail: Failed to create directory %s: %s", inst->last_made_directory, strerror(errno));
+                       radlog_request(L_ERR, 0, request, "rlm_detail: Failed to create directory %s: %s", inst->last_made_directory, strerror(errno));
                        return RLM_MODULE_FAIL;
                }
 
@@ -284,7 +260,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                 */
                if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
                                  inst->detailperm)) < 0) {
-                       radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+                       radlog_request(L_ERR, 0, request, "rlm_detail: Couldn't open file %s: %s",
                               buffer, strerror(errno));
                        return RLM_MODULE_FAIL;
                }
@@ -310,20 +286,20 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                         *      the lock (race condition)
                         */
                        if (fstat(outfd, &st) != 0) {
-                               radlog(L_ERR, "rlm_detail: Couldn't stat file %s: %s",
+                               radlog_request(L_ERR, 0, request, "rlm_detail: Couldn't stat file %s: %s",
                                       buffer, strerror(errno));
                                close(outfd);
                                return RLM_MODULE_FAIL;
                        }
                        if (st.st_nlink == 0) {
-                               DEBUG("rlm_detail: File %s removed by another program, retrying",
+                               RDEBUG2("File %s removed by another program, retrying",
                                      buffer);
                                close(outfd);
                                lock_count = 0;
                                continue;
                        }
 
-                       DEBUG("rlm_detail: Acquired filelock, tried %d time(s)",
+                       RDEBUG2("Acquired filelock, tried %d time(s)",
                              lock_count + 1);
                        locked = 1;
                }
@@ -331,7 +307,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 
        if (inst->locking && !locked) {
                close(outfd);
-               radlog(L_ERR, "rlm_detail: Failed to aquire filelock for %s, giving up",
+               radlog_request(L_ERR, 0, request, "rlm_detail: Failed to acquire filelock for %s, giving up",
                       buffer);
                return RLM_MODULE_FAIL;
        }
@@ -341,12 +317,12 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
         *      after this operation.
         */
        if ((outfp = fdopen(outfd, "a")) == NULL) {
-               radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+               radlog_request(L_ERR, 0, request, "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");
+                       RDEBUG2("Released filelock");
                }
                close(outfd);   /* automatically releases the lock */
 
@@ -369,9 +345,9 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                 *      Numbers, if not.
                 */
                if ((packet->code > 0) &&
-                   (packet->code <= PW_ACCESS_CHALLENGE)) {
+                   (packet->code < FR_MAX_PACKET_CODE)) {
                        fprintf(outfp, "\tPacket-Type = %s\n",
-                               packet_codes[packet->code]);
+                               fr_packet_codes[packet->code]);
                } else {
                        fprintf(outfp, "\tPacket-Type = %d\n", packet->code);
                }
@@ -380,25 +356,26 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        if (inst->log_srcdst) {
                VALUE_PAIR src_vp, dst_vp;
 
-               src_vp.name[0] = dst_vp.name[0] = '\0'; /* for vp_prints() */
+               memset(&src_vp, 0, sizeof(src_vp));
+               memset(&dst_vp, 0, sizeof(dst_vp));
                src_vp.operator = dst_vp.operator = T_OP_EQ;
 
                switch (packet->src_ipaddr.af) {
                case AF_INET:
                        src_vp.type = PW_TYPE_IPADDR;
                        src_vp.attribute = PW_PACKET_SRC_IP_ADDRESS;
-                       src_vp.lvalue = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+                       src_vp.vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
                        dst_vp.type = PW_TYPE_IPADDR;
                        dst_vp.attribute = PW_PACKET_DST_IP_ADDRESS;
-                       dst_vp.lvalue = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
+                       dst_vp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
                        break;
                case AF_INET6:
-                       src_vp.type = PW_TYPE_IPV6ADDR; 
+                       src_vp.type = PW_TYPE_IPV6ADDR;
                        src_vp.attribute = PW_PACKET_SRC_IPV6_ADDRESS;
                        memcpy(src_vp.vp_strvalue,
                               &packet->src_ipaddr.ipaddr.ip6addr,
                               sizeof(packet->src_ipaddr.ipaddr.ip6addr));
-                       dst_vp.type = PW_TYPE_IPV6ADDR; 
+                       dst_vp.type = PW_TYPE_IPV6ADDR;
                        dst_vp.attribute = PW_PACKET_DST_IPV6_ADDRESS;
                        memcpy(dst_vp.vp_strvalue,
                               &packet->dst_ipaddr.ipaddr.ip6addr,
@@ -417,10 +394,10 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 
                src_vp.attribute = PW_PACKET_SRC_PORT;
                src_vp.type = PW_TYPE_INTEGER;
-               src_vp.lvalue = packet->src_port;
+               src_vp.vp_integer = packet->src_port;
                dst_vp.attribute = PW_PACKET_DST_PORT;
                dst_vp.type = PW_TYPE_INTEGER;
-               dst_vp.lvalue = packet->dst_port;
+               dst_vp.vp_integer = packet->dst_port;
 
                fputs("\t", outfp);
                vp_print(outfp, &src_vp);
@@ -431,12 +408,12 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        }
 
        /* Write each attribute/value to the log file */
-       for (; pair != NULL; pair = pair->next) {
+       for (pair = packet->vps; pair != NULL; pair = pair->next) {
                DICT_ATTR da;
                da.attr = pair->attribute;
 
                if (inst->ht &&
-                   lrad_hash_table_finddata(inst->ht, &da)) continue;
+                   fr_hash_table_finddata(inst->ht, &da)) continue;
 
                /*
                 *      Don't print passwords in old format...
@@ -455,30 +432,28 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
         *      Add non-protocol attibutes.
         */
        if (compat) {
-               if ((pair = pairfind(request->config_items,
-                                    PW_PROXY_TO_REALM)) != NULL) {
-                       proxy_realm = realm_find(pair->vp_strvalue, TRUE);
-                       if (proxy_realm) {
-                               memset((char *) proxy_buffer, 0, 16);
-
-                               rad_assert(proxy_realm->acct_ipaddr.af == AF_INET);
-
-                               inet_ntop(proxy_realm->acct_ipaddr.af,
-                                         &proxy_realm->acct_ipaddr.ipaddr,
-                                         proxy_buffer, sizeof(proxy_buffer));
-                               fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
+#ifdef WITH_PROXY
+               if (request->proxy) {
+                       char proxy_buffer[128];
+
+                       inet_ntop(request->proxy->dst_ipaddr.af,
+                                 &request->proxy->dst_ipaddr.ipaddr,
+                                 proxy_buffer, sizeof(proxy_buffer));
+                       fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
                                        proxy_buffer);
-                               DEBUG("rlm_detail: Freeradius-Proxied-To set to %s",
+                               RDEBUG("Freeradius-Proxied-To = %s",
                                      proxy_buffer);
-                       }
                }
+#endif
+
                fprintf(outfp, "\tTimestamp = %ld\n",
                        (unsigned long) 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);
+               /*
+                *      We no longer permit Accounting-Request packets
+                *      with an authenticator of zero.
+                */
+               fputs("\tRequest-Authenticator = Verified\n", outfp);
        }
 
        fputs("\n", outfp);
@@ -487,7 +462,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                fflush(outfp);
                lseek(outfd, 0L, SEEK_SET);
                rad_unlockfd(outfd, 0);
-               DEBUG("rlm_detail: Released filelock");
+               RDEBUG2("Released filelock");
        }
 
        fclose(outfp);
@@ -503,6 +478,12 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
  */
 static int detail_accounting(void *instance, REQUEST *request)
 {
+       if (request->listener->type == RAD_LISTEN_DETAIL &&
+           strcmp(((struct detail_instance *)instance)->detailfile,
+                  ((listen_detail_t *)request->listener->data)->filename) == 0) {
+               RDEBUG("Suppressing writes to detail file as the request was just read from a detail file.");
+               return RLM_MODULE_NOOP;
+       }
 
        return do_detail(instance,request,request->packet, TRUE);
 }
@@ -523,10 +504,28 @@ static int detail_postauth(void *instance, REQUEST *request)
        return do_detail(instance,request,request->reply, FALSE);
 }
 
+#ifdef WITH_COA
+/*
+ *     Incoming CoA - write the detail files.
+ */
+static int detail_recv_coa(void *instance, REQUEST *request)
+{
+       return do_detail(instance,request,request->packet, FALSE);
+}
+
+/*
+ *     Outgoing CoA - write the detail files.
+ */
+static int detail_send_coa(void *instance, REQUEST *request)
+{
+       return do_detail(instance,request,request->reply, FALSE);
+}
+#endif
 
 /*
  *     Outgoing Access-Request to home server - write the detail files.
  */
+#ifdef WITH_PROXY
 static int detail_pre_proxy(void *instance, REQUEST *request)
 {
        if (request->proxy &&
@@ -548,15 +547,33 @@ static int detail_post_proxy(void *instance, REQUEST *request)
                return do_detail(instance,request,request->proxy_reply, FALSE);
        }
 
+       /*
+        *      No reply: we must be doing Post-Proxy-Type = Fail.
+        *
+        *      Note that we just call the normal accounting function,
+        *      to minimize the amount of code, and to highlight that
+        *      it's doing normal accounting.
+        */
+       if (!request->proxy_reply) {
+               int rcode;
+
+               rcode = detail_accounting(instance, request);
+               if (rcode == RLM_MODULE_OK) {
+                       request->reply->code = PW_ACCOUNTING_RESPONSE;
+               }
+               return rcode;
+       }
+
        return RLM_MODULE_NOOP;
 }
+#endif
 
 
 /* globally exported name */
 module_t rlm_detail = {
        RLM_MODULE_INIT,
        "detail",
-       RLM_TYPE_THREAD_UNSAFE,        /* type: reserved */
+       RLM_TYPE_THREAD_UNSAFE | RLM_TYPE_CHECK_CONFIG_SAFE | RLM_TYPE_HUP_SAFE,
        detail_instantiate,             /* instantiation */
        detail_detach,                  /* detach */
        {
@@ -565,9 +582,17 @@ module_t rlm_detail = {
                NULL,                   /* preaccounting */
                detail_accounting,      /* accounting */
                NULL,                   /* checksimul */
+#ifdef WITH_PROXY
                detail_pre_proxy,       /* pre-proxy */
                detail_post_proxy,      /* post-proxy */
+#else
+               NULL, NULL,
+#endif
                detail_postauth         /* post-auth */
+#ifdef WITH_COA
+               , detail_recv_coa,
+               detail_send_coa
+#endif
        },
 };