Move yet more code around.
authoraland <aland>
Wed, 20 Oct 2004 21:22:27 +0000 (21:22 +0000)
committeraland <aland>
Wed, 20 Oct 2004 21:22:27 +0000 (21:22 +0000)
It turns out util.c is included in radrelay and radwho, so putting
server-specific stuff in there is dumb.  We now have a new file,
request_process.c, which has rad_respond (freshly moved out of
radiusd.c to threads.c, to here), and some other functions here.

src/include/radiusd.h
src/main/request_process.c [new file with mode: 0755]
src/main/threads.c
src/main/util.c

index f22cf11..3e1047e 100644 (file)
@@ -98,6 +98,7 @@ typedef struct auth_req {
 #define RAD_REQUEST_OPTION_REJECTED        (1 << 4)
 #define RAD_REQUEST_OPTION_PROXIED         (1 << 5)
 #define RAD_REQUEST_OPTION_STOP_NOW        (1 << 6)
+#define RAD_REQUEST_OPTION_REPROCESS       (1 << 7)
 
 /*
  *  Function handler for requests.
@@ -331,6 +332,9 @@ int         request_data_add(REQUEST *request,
                                 void *opaque, void (*free_opaque)(void *));
 void           *request_data_get(REQUEST *request,
                                  void *unique_ptr, int unique_int);
+
+/* request_process.c */
+int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun);
 void           request_reject(REQUEST *request, request_fail_t reason);
 void           rfc_clean(RADIUS_PACKET *packet);
 
diff --git a/src/main/request_process.c b/src/main/request_process.c
new file mode 100755 (executable)
index 0000000..e470f97
--- /dev/null
@@ -0,0 +1,805 @@
+/*\r
+ * proxy.c     Proxy stuff.\r
+ *\r
+ * Version:    $Id$\r
+ *\r
+ *   This program is free software; you can redistribute it and/or modify\r
+ *   it under the terms of the GNU General Public License as published by\r
+ *   the Free Software Foundation; either version 2 of the License, or\r
+ *   (at your option) any later version.\r
+ *\r
+ *   This program is distributed in the hope that it will be useful,\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *   GNU General Public License for more details.\r
+ *\r
+ *   You should have received a copy of the GNU General Public License\r
+ *   along with this program; if not, write to the Free Software\r
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * Copyright 2000  The FreeRADIUS server project\r
+ * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>\r
+ * Copyright 2000  Chris Parker <cparker@starnetusa.com>\r
+ */\r
+\r
+static const char rcsid[] = "$Id$";\r
+\r
+#include "autoconf.h"\r
+#include "libradius.h"\r
+\r
+#include <sys/socket.h>\r
+\r
+#ifdef HAVE_NETINET_IN_H\r
+#      include <netinet/in.h>\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+#include <string.h>\r
+\r
+#include "radiusd.h"\r
+#include "rad_assert.h"\r
+#include "modules.h"\r
+\r
+\r
+/*\r
+ *     Reprocess the request in possibly a child thread, only through\r
+ *     a subsection of the post-proxy section of radiusd.conf.\r
+ */\r
+static int process_post_proxy_fail(REQUEST *request)\r
+{\r
+       VALUE_PAIR *vps;\r
+\r
+       /*\r
+        *\r
+        */\r
+\r
+\r
+       /*\r
+        *      Hmm... this code is copied from below, which isn't good,\r
+        *      and is similar to the code in rad_respond.\r
+        */\r
+       switch (request->packet->code) {\r
+               /*\r
+                *  Accounting requests, etc. get dropped on the floor.\r
+                */\r
+       default:\r
+       case PW_ACCOUNTING_REQUEST:\r
+       case PW_STATUS_SERVER:\r
+               break;\r
+               \r
+               /*\r
+                *  Authentication requests get their Proxy-State\r
+                *  attributes copied over, and an otherwise blank\r
+                *  reject message sent.\r
+                */\r
+       case PW_AUTHENTICATION_REQUEST:\r
+               request->reply->code = PW_AUTHENTICATION_REJECT;\r
+               \r
+               /*\r
+                *  Perform RFC limitations on outgoing replies.\r
+                */\r
+               rfc_clean(request->reply);\r
+               \r
+               /*\r
+                *  Need to copy Proxy-State from request->packet->vps\r
+                */\r
+               vps = paircopy2(request->packet->vps, PW_PROXY_STATE);\r
+               if (vps != NULL)\r
+                       pairadd(&(request->reply->vps), vps);\r
+               break;\r
+       }\r
+       \r
+       /*\r
+        *      If a reply exists, send it.\r
+        *\r
+        *      But DON'T send a RADIUS packet for a fake request.\r
+        */\r
+       if ((request->reply->code != 0) &&\r
+           ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0)) {\r
+               /*\r
+                *      If we're not delaying authentication rejects,\r
+                *      then send the response immediately.  Otherwise,\r
+                *      mark the request as delayed, and do NOT send a\r
+                *      response.\r
+                */\r
+               if (mainconfig.reject_delay == 0) {\r
+                       rad_send(request->reply, request->packet,\r
+                                    request->secret);\r
+               } else {\r
+                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;\r
+               }\r
+       }\r
+\r
+       return 0;               /* ignored for now */\r
+}\r
+\r
+\r
+/*\r
+ *     If we're told to proxess the request through the post-proxy "fail"\r
+ *     subsection, do so.\r
+ *\r
+ *     Called only from request_reject in util.c\r
+ */\r
+static void proxy_failed_home_server(REQUEST *request, request_fail_t reason)\r
+{\r
+       DICT_VALUE      *val;\r
+\r
+       val = dict_valbyname(PW_POST_PROXY_TYPE, mainconfig.proxy_fail_type);\r
+       if (!val) {\r
+               DEBUG("ERROR: No such post-proxy type of \"%s\", cancelling post-proxy-failure call.", mainconfig.proxy_fail_type);\r
+               return;\r
+       }\r
+\r
+       request->options |= RAD_REQUEST_OPTION_REPROCESS;\r
+\r
+       thread_pool_addrequest(request, process_post_proxy_fail);\r
+}\r
+\r
+/*\r
+ *  Perform any RFC specified cleaning of outgoing replies\r
+ */\r
+void rfc_clean(RADIUS_PACKET *packet)\r
+{\r
+       VALUE_PAIR *vps = NULL;\r
+\r
+       switch (packet->code) {\r
+               /*\r
+                *      In the default case, we just move all of the\r
+                *      attributes over.\r
+                */\r
+       default:\r
+               vps = packet->vps;\r
+               packet->vps = NULL;\r
+               break;\r
+\r
+               /*\r
+                *      Accounting responses can only contain\r
+                *      Proxy-State and VSA's.  Note that we do NOT\r
+                *      move the Proxy-State attributes over, as the\r
+                *      Proxy-State attributes in this packet are NOT\r
+                *      the right ones to use.  The reply function\r
+                *      takes care of copying those attributes from\r
+                *      the original request, which ARE the right ones\r
+                *      to use.\r
+                */\r
+       case PW_ACCOUNTING_RESPONSE:\r
+               pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);\r
+               break;\r
+\r
+               /*\r
+                *      Authentication REJECT's can have only\r
+                *      EAP-Message, Message-Authenticator\r
+                *      Reply-Message and Proxy-State.\r
+                *\r
+                *      We delete everything other than these.\r
+                *      Proxy-State is added below, just before the\r
+                *      reply is sent.\r
+                */\r
+       case PW_AUTHENTICATION_REJECT:\r
+               pairmove2(&vps, &(packet->vps), PW_EAP_MESSAGE);\r
+               pairmove2(&vps, &(packet->vps), PW_MESSAGE_AUTHENTICATOR);\r
+               pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);\r
+               pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);\r
+               break;\r
+       }\r
+\r
+       /*\r
+        *      Move the newly cleaned attributes over.\r
+        */\r
+       pairfree(&packet->vps);\r
+       packet->vps = vps;\r
+\r
+       /*\r
+        *      FIXME: Perform other, more generic sanity checks.\r
+        */\r
+}\r
+\r
+\r
+/*\r
+ *     For debugging\r
+ */\r
+static LRAD_NAME_NUMBER request_fail_reason[] = {\r
+       { "no threads available to handle the request",\r
+         REQUEST_FAIL_NO_THREADS },\r
+\r
+       { "malformed RADIUS packet",\r
+         REQUEST_FAIL_DECODE},\r
+\r
+       { "pre-proxying failed",\r
+         REQUEST_FAIL_PROXY},\r
+\r
+       { "sending of the proxy packet failed",\r
+         REQUEST_FAIL_PROXY_SEND},\r
+\r
+       { "failure to be told how to respond",\r
+         REQUEST_FAIL_NO_RESPONSE},\r
+\r
+       { "no response from the home server",\r
+         REQUEST_FAIL_HOME_SERVER},\r
+       \r
+       { "no response from the home server after multiple tries",\r
+         REQUEST_FAIL_HOME_SERVER2},\r
+       \r
+       { "no response from the home server for a long period of time",\r
+         REQUEST_FAIL_HOME_SERVER3},\r
+\r
+       { "we were told to reject the request",\r
+         REQUEST_FAIL_NORMAL_REJECT},\r
+\r
+       { NULL, REQUEST_FAIL_UNKNOWN }\r
+};\r
+\r
+\r
+/*\r
+ *  Reject a request, by sending a trivial reply packet.\r
+ */\r
+ void request_reject(REQUEST *request, request_fail_t reason)\r
+{\r
+       VALUE_PAIR *vps;\r
+\r
+       /*\r
+        *      Already rejected.  Don't do anything.\r
+        */\r
+       if (request->options & RAD_REQUEST_OPTION_REJECTED) {\r
+               return;\r
+       }\r
+\r
+       DEBUG2("Server rejecting request %d due to %s.",\r
+              request->number, lrad_int2str(request_fail_reason,\r
+                                            reason, "unknown"));\r
+\r
+       /*\r
+        *      Remember that it was rejected.\r
+        */\r
+       request->options |= RAD_REQUEST_OPTION_REJECTED;\r
+\r
+       switch (reason) {\r
+       case REQUEST_FAIL_NO_THREADS:\r
+               DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");\r
+               break;\r
+\r
+       case REQUEST_FAIL_DECODE:\r
+               DEBUG("WARNING: Someone may be attacking your RADIUS server.");\r
+               break;\r
+\r
+       case REQUEST_FAIL_NO_RESPONSE:\r
+               DEBUG("WARNING: You did not configure the server to accept, or reject the user.  Double-check Auth-Type.");\r
+               break;\r
+\r
+               /*\r
+                *      If the home server goes down for some reason,\r
+                *      we want to be able to know when.  We do this\r
+                *      by calling a sub-section of the post_proxy section,\r
+                *      and processing any modules we find there.\r
+                *\r
+                *      Note that this subsection CAN edit the response\r
+                *      to the NAS.\r
+                */\r
+       case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */\r
+       case REQUEST_FAIL_HOME_SERVER2:\r
+       case REQUEST_FAIL_HOME_SERVER3:\r
+               if (!mainconfig.proxy_fail_type) {\r
+                       request->finished = TRUE;\r
+                       break;\r
+               }\r
+\r
+               /*\r
+                *      This function takes care of doing everything\r
+                *      below...\r
+                */\r
+               proxy_failed_home_server(request, reason);\r
+               return;         \r
+               break;\r
+\r
+       case REQUEST_FAIL_SERVER_TIMEOUT:\r
+               radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",\r
+                      request->number,\r
+                      request->module ? request->module : "<server core>",\r
+                      request->component ? request->component : "<server core>");\r
+\r
+               /*\r
+                *      Tell the server to stop processing the request\r
+                */\r
+               request->options |= RAD_REQUEST_OPTION_STOP_NOW;\r
+               break;\r
+\r
+       default:                /* no additional messages, or things to do */\r
+               break;\r
+       }\r
+\r
+       switch (request->packet->code) {\r
+               /*\r
+                *  Accounting requests, etc. get dropped on the floor.\r
+                */\r
+               default:\r
+               case PW_ACCOUNTING_REQUEST:\r
+               case PW_STATUS_SERVER:\r
+                       break;\r
+\r
+               /*\r
+                *  Authentication requests get their Proxy-State\r
+                *  attributes copied over, and an otherwise blank\r
+                *  reject message sent.\r
+                */\r
+               case PW_AUTHENTICATION_REQUEST:\r
+                       request->reply->code = PW_AUTHENTICATION_REJECT;\r
+\r
+                       /*\r
+                        *  Perform RFC limitations on outgoing replies.\r
+                        */\r
+                       rfc_clean(request->reply);\r
+\r
+                       /*\r
+                        *  Need to copy Proxy-State from request->packet->vps\r
+                        */\r
+                       vps = paircopy2(request->packet->vps, PW_PROXY_STATE);\r
+                       if (vps != NULL)\r
+                               pairadd(&(request->reply->vps), vps);\r
+                       break;\r
+       }\r
+\r
+       /*\r
+        *      If a reply exists, send it.\r
+        *\r
+        *      But DON'T send a RADIUS packet for a fake request.\r
+        */\r
+       if ((request->reply->code != 0) &&\r
+           ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0)) {\r
+               /*\r
+                *      If we're not delaying authentication rejects,\r
+                *      then send the response immediately.  Otherwise,\r
+                *      mark the request as delayed, and do NOT send a\r
+                *      response.\r
+                */\r
+               if (mainconfig.reject_delay == 0) {\r
+                       rad_send(request->reply, request->packet,\r
+                                    request->secret);\r
+               } else {\r
+                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/*\r
+ * FIXME:  The next two functions should all\r
+ * be in a module.  But not until we have\r
+ * more control over module execution.\r
+ * -jcarneal\r
+ */\r
+\r
+/*\r
+ *  Lowercase the string value of a pair.\r
+ */\r
+static int rad_lowerpair(REQUEST *request UNUSED, VALUE_PAIR *vp) {\r
+       if (vp == NULL) {\r
+               return -1;\r
+       }\r
+\r
+       rad_lowercase((char *)vp->strvalue);\r
+       DEBUG2("rad_lowerpair:  %s now '%s'", vp->name, vp->strvalue);\r
+       return 0;\r
+}\r
+\r
+/*\r
+ *  Remove spaces in a pair.\r
+ */\r
+static int rad_rmspace_pair(REQUEST *request UNUSED, VALUE_PAIR *vp) {\r
+       if (vp == NULL) {\r
+               return -1;\r
+       }\r
+\r
+       rad_rmspace((char *)vp->strvalue);\r
+       vp->length = strlen((char *)vp->strvalue);\r
+       DEBUG2("rad_rmspace_pair:  %s now '%s'", vp->name, vp->strvalue);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+/*\r
+ *  Respond to a request packet.\r
+ *\r
+ *  Maybe we reply, maybe we don't.\r
+ *  Maybe we proxy the request to another server, or else maybe\r
+ *  we replicate it to another server.\r
+ */\r
+int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)\r
+{\r
+       RADIUS_PACKET *packet, *original;\r
+       const char *secret;\r
+       int finished = FALSE;\r
+       int reprocess = 0;\r
+       int decoderesult = 0;\r
+\r
+       rad_assert(request->magic == REQUEST_MAGIC);\r
+\r
+       /*\r
+        *      Don't decode the packet if it's an internal "fake"\r
+        *      request.  Instead, just skip ahead to processing it.\r
+        */\r
+       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {\r
+               goto skip_decode;\r
+       }\r
+\r
+\r
+       /*\r
+        *      Re-process the request.\r
+        */\r
+       if ((request->options & RAD_REQUEST_OPTION_REPROCESS) != 0) {\r
+               goto skip_decode;\r
+       }\r
+\r
+       /*\r
+        *  Put the decoded packet into it's proper place.\r
+        */\r
+       if (request->proxy_reply != NULL) {\r
+               packet = request->proxy_reply;\r
+               secret = request->proxysecret;\r
+               original = request->proxy;\r
+       } else {\r
+               packet = request->packet;\r
+               secret = request->secret;\r
+               original = NULL;\r
+       }\r
+\r
+       /*\r
+        *  Decode the packet, verifying it's signature,\r
+        *  and parsing the attributes into structures.\r
+        *\r
+        *  Note that we do this CPU-intensive work in\r
+        *  a child thread, not the master.  This helps to\r
+        *  spread the load a little bit.\r
+        *\r
+        *  Internal requests (ones that never go on the\r
+        *  wire) have ->data==NULL (data is the wire\r
+        *  format) and don't need to be "decoded"\r
+        */\r
+       if (packet->data) {\r
+               decoderesult = rad_decode(packet, original, secret);\r
+               switch (decoderesult) {\r
+                       case -1:\r
+                               radlog(L_ERR, "%s", librad_errstr);\r
+                               request_reject(request, REQUEST_FAIL_DECODE);\r
+                               goto finished_request;\r
+                               break;\r
+                       case -2:\r
+                               radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);\r
+                               /* Since accounting packets get this set in\r
+                                * request_reject but no response is sent...\r
+                                */\r
+                               request->options |= RAD_REQUEST_OPTION_REJECTED;\r
+                               goto finished_request;\r
+               }\r
+       }\r
+\r
+       /*\r
+        *  For proxy replies, remove non-allowed\r
+        *  attributes from the list of VP's.\r
+        */\r
+       if (request->proxy) {\r
+               int rcode;\r
+               rcode = proxy_receive(request);\r
+               switch (rcode) {\r
+                default:  /* Don't Do Anything */\r
+                       break;\r
+                case RLM_MODULE_FAIL:\r
+                       /* on error just continue with next request */\r
+                       goto next_request;\r
+                case RLM_MODULE_HANDLED:\r
+                       /* if this was a replicated request, mark it as\r
+                        * finished first, because it was postponed\r
+                        */\r
+                       goto finished_request;\r
+               }\r
+\r
+       } else {\r
+               /*\r
+                *      This is the initial incoming request which\r
+                *      we're processing.\r
+                *\r
+                *      Some requests do NOT get cached, as they\r
+                *      CANNOT possibly have duplicates.  Set the\r
+                *      magic option here.\r
+                *\r
+                *      Status-Server messages are easy to generate,\r
+                *      so we toss them as soon as we see a reply.\r
+                *\r
+                *      Accounting-Request packets WITHOUT an\r
+                *      Acct-Delay-Time attribute are NEVER\r
+                *      duplicated, as RFC 2866 Section 4.1 says that\r
+                *      the Acct-Delay-Time MUST be updated when the\r
+                *      packet is re-sent, which means the packet\r
+                *      changes, so it MUST have a new identifier and\r
+                *      Request Authenticator.  */\r
+               if ((request->packet->code == PW_STATUS_SERVER) ||\r
+                   ((request->packet->code == PW_ACCOUNTING_REQUEST) &&\r
+                    (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {\r
+                       request->options |= RAD_REQUEST_OPTION_DONT_CACHE;\r
+               }\r
+       }\r
+\r
+ skip_decode:\r
+       /*\r
+        *      We should have a User-Name attribute now.\r
+        */\r
+       if (request->username == NULL) {\r
+               request->username = pairfind(request->packet->vps,\r
+                               PW_USER_NAME);\r
+       }\r
+\r
+       /*\r
+        *  FIXME:  All this lowercase/nospace junk will be moved\r
+        *  into a module after module failover is fully in place\r
+        *\r
+        *  See if we have to lower user/pass before processing\r
+        */\r
+       if(strcmp(mainconfig.do_lower_user, "before") == 0)\r
+               rad_lowerpair(request, request->username);\r
+       if(strcmp(mainconfig.do_lower_pass, "before") == 0)\r
+               rad_lowerpair(request,\r
+                             pairfind(request->packet->vps, PW_PASSWORD));\r
+\r
+       if(strcmp(mainconfig.do_nospace_user, "before") == 0)\r
+               rad_rmspace_pair(request, request->username);\r
+       if(strcmp(mainconfig.do_nospace_pass, "before") == 0)\r
+               rad_rmspace_pair(request,\r
+                                pairfind(request->packet->vps, PW_PASSWORD));\r
+\r
+       (*fun)(request);\r
+\r
+       /*\r
+        *      If the request took too long to process, don't do\r
+        *      anything else.\r
+        */\r
+       if (request->options & RAD_REQUEST_OPTION_REJECTED) {\r
+               finished = TRUE;\r
+               goto postpone_request;\r
+       }\r
+\r
+       /*\r
+        *      Reprocess if we rejected last time\r
+        */\r
+       if ((fun == rad_authenticate) &&\r
+           (request->reply->code == PW_AUTHENTICATION_REJECT)) {\r
+         /* See if we have to lower user/pass after processing */\r
+         if (strcmp(mainconfig.do_lower_user, "after") == 0) {\r
+                 rad_lowerpair(request, request->username);\r
+                 reprocess = 1;\r
+         }\r
+         if (strcmp(mainconfig.do_lower_pass, "after") == 0) {\r
+               rad_lowerpair(request,\r
+                             pairfind(request->packet->vps, PW_PASSWORD));\r
+               reprocess = 1;\r
+         }\r
+         if (strcmp(mainconfig.do_nospace_user, "after") == 0) {\r
+                 rad_rmspace_pair(request, request->username);\r
+                 reprocess = 1;\r
+         }\r
+         if (strcmp(mainconfig.do_nospace_pass, "after") == 0) {\r
+                 rad_rmspace_pair(request,\r
+                                  pairfind(request->packet->vps, PW_PASSWORD));\r
+                 reprocess = 1;\r
+         }\r
+\r
+         /*\r
+          *    If we're re-processing the request, re-set it.\r
+          */\r
+         if (reprocess) {\r
+                 pairfree(&request->config_items);\r
+                 pairfree(&request->reply->vps);\r
+                 request->reply->code = 0;\r
+                 (*fun)(request);\r
+                 \r
+                 /*\r
+                  *    If the request took too long to process, don't do\r
+                  *    anything else.\r
+                  */\r
+                 if (request->options & RAD_REQUEST_OPTION_REJECTED) {\r
+                         finished = TRUE;\r
+                         goto postpone_request;\r
+                 }\r
+         }\r
+       }\r
+\r
+       /*\r
+        *      Status-Server requests NEVER get proxied.\r
+        */\r
+       if (mainconfig.proxy_requests) {\r
+               if ((request->packet->code != PW_STATUS_SERVER) &&\r
+                   ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {\r
+                       int rcode;\r
+\r
+                       /*\r
+                        *      Try to proxy this request.\r
+                        */\r
+                       rcode = proxy_send(request);\r
+\r
+                       switch (rcode) {\r
+                       default:\r
+                               break;\r
+\r
+                       /*\r
+                        *  There was an error trying to proxy the request.\r
+                        *  Drop it on the floor.\r
+                        */\r
+                       case RLM_MODULE_FAIL:\r
+                               DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);\r
+                               request_reject(request, REQUEST_FAIL_PROXY);\r
+                               goto finished_request;\r
+                               break;\r
+\r
+                       /*\r
+                        *  The pre-proxy module has decided to reject\r
+                        *  the request.  Do so.\r
+                        */\r
+                       case RLM_MODULE_REJECT:\r
+                               DEBUG2("Request %d rejected in proxy_send.", request->number);\r
+                               request_reject(request, REQUEST_FAIL_PROXY_SEND);\r
+                               goto finished_request;\r
+                               break;\r
+\r
+                       /*\r
+                        *  If the proxy code has handled the request,\r
+                        *  then postpone more processing, until we get\r
+                        *  the reply packet from the home server.\r
+                        */\r
+                       case RLM_MODULE_HANDLED:\r
+                               goto postpone_request;\r
+                               break;\r
+                       }\r
+\r
+                       /*\r
+                        *  Else rcode==RLM_MODULE_NOOP\r
+                        *  and the proxy code didn't do anything, so\r
+                        *  we continue handling the request here.\r
+                        */\r
+               }\r
+       } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&\r
+                  (request->reply->code == 0)) {\r
+               /*\r
+                *  We're not configured to reply to the packet,\r
+                *  and we're not proxying, so the DEFAULT behaviour\r
+                *  is to REJECT the user.\r
+                */\r
+               DEBUG2("There was no response configured: rejecting request %d", request->number);\r
+               request_reject(request, REQUEST_FAIL_NO_RESPONSE);\r
+               goto finished_request;\r
+       }\r
+\r
+       /*\r
+        *  If we have a reply to send, copy the Proxy-State\r
+        *  attributes from the request to the tail of the reply,\r
+        *  and send the packet.\r
+        */\r
+       rad_assert(request->magic == REQUEST_MAGIC);\r
+       if (request->reply->code != 0) {\r
+               VALUE_PAIR *vp = NULL;\r
+\r
+               /*\r
+                *      Perform RFC limitations on outgoing replies.\r
+                */\r
+               rfc_clean(request->reply);\r
+\r
+               /*\r
+                *      Need to copy Proxy-State from request->packet->vps\r
+                */\r
+               vp = paircopy2(request->packet->vps, PW_PROXY_STATE);\r
+               if (vp) pairadd(&(request->reply->vps), vp);\r
+\r
+               /*\r
+                *  If the request isn't an authentication reject, OR\r
+                *  it's a reject, but the reject_delay is zero, then\r
+                *  send it immediately.\r
+                *\r
+                *  Otherwise, delay the authentication reject to shut\r
+                *  up DoS attacks.\r
+                */\r
+               if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||\r
+                   (mainconfig.reject_delay == 0)) {\r
+                       /*\r
+                        *      Send the response. IF it's a real request.\r
+                        */\r
+                       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0) {\r
+                               rad_send(request->reply, request->packet,\r
+                                        request->secret);\r
+                       }\r
+                       /*\r
+                        *      Otherwise, it's a tunneled request.\r
+                        *      Don't do anything.\r
+                        */\r
+               } else {\r
+                       DEBUG2("Delaying request %d for %d seconds",\r
+                              request->number, mainconfig.reject_delay);\r
+                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;\r
+               }\r
+       }\r
+\r
+       /*\r
+        *  We're done processing the request, set the\r
+        *  request to be finished, clean up as necessary,\r
+        *  and forget about the request.\r
+        */\r
+\r
+finished_request:\r
+\r
+       /*\r
+        *      Don't decode the packet if it's an internal "fake"\r
+        *      request.  Instead, just skip ahead to processing it.\r
+        */\r
+       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {\r
+               goto skip_free;\r
+       }\r
+\r
+       /*\r
+        *  We're done handling the request.  Free up the linked\r
+        *  lists of value pairs.  This might take a long time,\r
+        *  so it's more efficient to do it in a child thread,\r
+        *  instead of in the main handler when it eventually\r
+        *  gets around to deleting the request.\r
+        *\r
+        *  Also, no one should be using these items after the\r
+        *  request is finished, and the reply is sent.  Cleaning\r
+        *  them up here ensures that they're not being used again.\r
+        *\r
+        *  Hmm... cleaning them up in the child thread also seems\r
+        *  to make the server run more efficiently!\r
+        *\r
+        *  If we've delayed the REJECT, then do NOT clean up the request,\r
+        *  as we haven't created the REJECT message yet.\r
+        */\r
+       if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {\r
+               if (request->packet) {\r
+                       pairfree(&request->packet->vps);\r
+                       request->username = NULL;\r
+                       request->password = NULL;\r
+               }\r
+\r
+               /*\r
+                *  If we've sent a reply to the NAS, then this request is\r
+                *  pretty much finished, and we have no more need for any\r
+                *  of the value-pair's in it, including the proxy stuff.\r
+                */\r
+               if (request->reply->code != 0) {\r
+                       pairfree(&request->reply->vps);\r
+               }\r
+       }\r
+\r
+       pairfree(&request->config_items);\r
+       if (request->proxy) {\r
+               pairfree(&request->proxy->vps);\r
+       }\r
+       if (request->proxy_reply) {\r
+               pairfree(&request->proxy_reply->vps);\r
+       }\r
+\r
+ skip_free:\r
+       DEBUG2("Finished request %d", request->number);\r
+       finished = TRUE;\r
+\r
+       /*\r
+        *  Go to the next request, without marking\r
+        *  the current one as finished.\r
+        *\r
+        *  Hmm... this may not be the brightest thing to do.\r
+        */\r
+next_request:\r
+       DEBUG2("Going to the next request");\r
+\r
+postpone_request:\r
+#ifdef HAVE_PTHREAD_H\r
+       /*\r
+        *  We are finished with the child thread.  The thread is detached,\r
+        *  so that when it exits, there's nothing more for the server\r
+        *  to do.\r
+        *\r
+        *  If we're running with thread pools, then this frees up the\r
+        *  thread in the pool for another request.\r
+        */\r
+       request->child_pid = NO_SUCH_CHILD_PID;\r
+#endif\r
+       request->finished = finished; /* do as the LAST thing before exiting */\r
+       return 0;\r
+}\r
index 4949338..19f536d 100644 (file)
@@ -40,8 +40,6 @@
 static const char rcsid[] =
 "$Id$";
 
-static int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun);
-
 #ifdef HAVE_PTHREAD_H
 
 #define SEMAPHORE_LOCKED       (0)
@@ -1256,447 +1254,7 @@ int thread_pool_init(int spawn_flag)
 int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
        rad_respond(request, fun);
-
        return 1;
 }
 
 #endif /* HAVE_PTHREAD_H */
-
-/***********************************************************************
- *
- *  And now we have the code to respond to requests, finally
- *  moved out of "radiusd.c".
- *
- ***********************************************************************/
-/*
- * FIXME:  The next two functions should all
- * be in a module.  But not until we have
- * more control over module execution.
- * -jcarneal
- */
-
-/*
- *  Lowercase the string value of a pair.
- */
-static int rad_lowerpair(REQUEST *request UNUSED, VALUE_PAIR *vp) {
-       if (vp == NULL) {
-               return -1;
-       }
-
-       rad_lowercase((char *)vp->strvalue);
-       DEBUG2("rad_lowerpair:  %s now '%s'", vp->name, vp->strvalue);
-       return 0;
-}
-
-/*
- *  Remove spaces in a pair.
- */
-static int rad_rmspace_pair(REQUEST *request UNUSED, VALUE_PAIR *vp) {
-       if (vp == NULL) {
-               return -1;
-       }
-
-       rad_rmspace((char *)vp->strvalue);
-       vp->length = strlen((char *)vp->strvalue);
-       DEBUG2("rad_rmspace_pair:  %s now '%s'", vp->name, vp->strvalue);
-
-       return 0;
-}
-
-
-/*
- *  Respond to a request packet.
- *
- *  Maybe we reply, maybe we don't.
- *  Maybe we proxy the request to another server, or else maybe
- *  we replicate it to another server.
- */
-static int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
-{
-       RADIUS_PACKET *packet, *original;
-       const char *secret;
-       int finished = FALSE;
-       int reprocess = 0;
-       int decoderesult = 0;
-
-       rad_assert(request->magic == REQUEST_MAGIC);
-
-       /*
-        *      Don't decode the packet if it's an internal "fake"
-        *      request.  Instead, just skip ahead to processing it.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
-               goto skip_decode;
-       }
-
-       /*
-        *  Put the decoded packet into it's proper place.
-        */
-       if (request->proxy_reply != NULL) {
-               packet = request->proxy_reply;
-               secret = request->proxysecret;
-               original = request->proxy;
-       } else {
-               packet = request->packet;
-               secret = request->secret;
-               original = NULL;
-       }
-
-       /*
-        *  Decode the packet, verifying it's signature,
-        *  and parsing the attributes into structures.
-        *
-        *  Note that we do this CPU-intensive work in
-        *  a child thread, not the master.  This helps to
-        *  spread the load a little bit.
-        *
-        *  Internal requests (ones that never go on the
-        *  wire) have ->data==NULL (data is the wire
-        *  format) and don't need to be "decoded"
-        */
-       if (packet->data) {
-               decoderesult = rad_decode(packet, original, secret);
-               switch (decoderesult) {
-                       case -1:
-                               radlog(L_ERR, "%s", librad_errstr);
-                               request_reject(request, REQUEST_FAIL_DECODE);
-                               goto finished_request;
-                               break;
-                       case -2:
-                               radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
-                               /* Since accounting packets get this set in
-                                * request_reject but no response is sent...
-                                */
-                               request->options |= RAD_REQUEST_OPTION_REJECTED;
-                               goto finished_request;
-               }
-       }
-
-       /*
-        *  For proxy replies, remove non-allowed
-        *  attributes from the list of VP's.
-        */
-       if (request->proxy) {
-               int rcode;
-               rcode = proxy_receive(request);
-               switch (rcode) {
-                default:  /* Don't Do Anything */
-                       break;
-                case RLM_MODULE_FAIL:
-                       /* on error just continue with next request */
-                       goto next_request;
-                case RLM_MODULE_HANDLED:
-                       /* if this was a replicated request, mark it as
-                        * finished first, because it was postponed
-                        */
-                       goto finished_request;
-               }
-
-       } else {
-               /*
-                *      This is the initial incoming request which
-                *      we're processing.
-                *
-                *      Some requests do NOT get cached, as they
-                *      CANNOT possibly have duplicates.  Set the
-                *      magic option here.
-                *
-                *      Status-Server messages are easy to generate,
-                *      so we toss them as soon as we see a reply.
-                *
-                *      Accounting-Request packets WITHOUT an
-                *      Acct-Delay-Time attribute are NEVER
-                *      duplicated, as RFC 2866 Section 4.1 says that
-                *      the Acct-Delay-Time MUST be updated when the
-                *      packet is re-sent, which means the packet
-                *      changes, so it MUST have a new identifier and
-                *      Request Authenticator.  */
-               if ((request->packet->code == PW_STATUS_SERVER) ||
-                   ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
-                    (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {
-                       request->options |= RAD_REQUEST_OPTION_DONT_CACHE;
-               }
-       }
-
- skip_decode:
-       /*
-        *      We should have a User-Name attribute now.
-        */
-       if (request->username == NULL) {
-               request->username = pairfind(request->packet->vps,
-                               PW_USER_NAME);
-       }
-
-       /*
-        *  FIXME:  All this lowercase/nospace junk will be moved
-        *  into a module after module failover is fully in place
-        *
-        *  See if we have to lower user/pass before processing
-        */
-       if(strcmp(mainconfig.do_lower_user, "before") == 0)
-               rad_lowerpair(request, request->username);
-       if(strcmp(mainconfig.do_lower_pass, "before") == 0)
-               rad_lowerpair(request,
-                             pairfind(request->packet->vps, PW_PASSWORD));
-
-       if(strcmp(mainconfig.do_nospace_user, "before") == 0)
-               rad_rmspace_pair(request, request->username);
-       if(strcmp(mainconfig.do_nospace_pass, "before") == 0)
-               rad_rmspace_pair(request,
-                                pairfind(request->packet->vps, PW_PASSWORD));
-
-       (*fun)(request);
-
-       /*
-        *      If the request took too long to process, don't do
-        *      anything else.
-        */
-       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
-               finished = TRUE;
-               goto postpone_request;
-       }
-
-       /*
-        *      Reprocess if we rejected last time
-        */
-       if ((fun == rad_authenticate) &&
-           (request->reply->code == PW_AUTHENTICATION_REJECT)) {
-         /* See if we have to lower user/pass after processing */
-         if (strcmp(mainconfig.do_lower_user, "after") == 0) {
-                 rad_lowerpair(request, request->username);
-                 reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_lower_pass, "after") == 0) {
-               rad_lowerpair(request,
-                             pairfind(request->packet->vps, PW_PASSWORD));
-               reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_nospace_user, "after") == 0) {
-                 rad_rmspace_pair(request, request->username);
-                 reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_nospace_pass, "after") == 0) {
-                 rad_rmspace_pair(request,
-                                  pairfind(request->packet->vps, PW_PASSWORD));
-                 reprocess = 1;
-         }
-
-         /*
-          *    If we're re-processing the request, re-set it.
-          */
-         if (reprocess) {
-                 pairfree(&request->config_items);
-                 pairfree(&request->reply->vps);
-                 request->reply->code = 0;
-                 (*fun)(request);
-                 
-                 /*
-                  *    If the request took too long to process, don't do
-                  *    anything else.
-                  */
-                 if (request->options & RAD_REQUEST_OPTION_REJECTED) {
-                         finished = TRUE;
-                         goto postpone_request;
-                 }
-         }
-       }
-
-       /*
-        *      Status-Server requests NEVER get proxied.
-        */
-       if (mainconfig.proxy_requests) {
-               if ((request->packet->code != PW_STATUS_SERVER) &&
-                   ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
-                       int rcode;
-
-                       /*
-                        *      Try to proxy this request.
-                        */
-                       rcode = proxy_send(request);
-
-                       switch (rcode) {
-                       default:
-                               break;
-
-                       /*
-                        *  There was an error trying to proxy the request.
-                        *  Drop it on the floor.
-                        */
-                       case RLM_MODULE_FAIL:
-                               DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);
-                               request_reject(request, REQUEST_FAIL_PROXY);
-                               goto finished_request;
-                               break;
-
-                       /*
-                        *  The pre-proxy module has decided to reject
-                        *  the request.  Do so.
-                        */
-                       case RLM_MODULE_REJECT:
-                               DEBUG2("Request %d rejected in proxy_send.", request->number);
-                               request_reject(request, REQUEST_FAIL_PROXY_SEND);
-                               goto finished_request;
-                               break;
-
-                       /*
-                        *  If the proxy code has handled the request,
-                        *  then postpone more processing, until we get
-                        *  the reply packet from the home server.
-                        */
-                       case RLM_MODULE_HANDLED:
-                               goto postpone_request;
-                               break;
-                       }
-
-                       /*
-                        *  Else rcode==RLM_MODULE_NOOP
-                        *  and the proxy code didn't do anything, so
-                        *  we continue handling the request here.
-                        */
-               }
-       } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
-                  (request->reply->code == 0)) {
-               /*
-                *  We're not configured to reply to the packet,
-                *  and we're not proxying, so the DEFAULT behaviour
-                *  is to REJECT the user.
-                */
-               DEBUG2("There was no response configured: rejecting request %d", request->number);
-               request_reject(request, REQUEST_FAIL_NO_RESPONSE);
-               goto finished_request;
-       }
-
-       /*
-        *  If we have a reply to send, copy the Proxy-State
-        *  attributes from the request to the tail of the reply,
-        *  and send the packet.
-        */
-       rad_assert(request->magic == REQUEST_MAGIC);
-       if (request->reply->code != 0) {
-               VALUE_PAIR *vp = NULL;
-
-               /*
-                *      Perform RFC limitations on outgoing replies.
-                */
-               rfc_clean(request->reply);
-
-               /*
-                *      Need to copy Proxy-State from request->packet->vps
-                */
-               vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
-               if (vp) pairadd(&(request->reply->vps), vp);
-
-               /*
-                *  If the request isn't an authentication reject, OR
-                *  it's a reject, but the reject_delay is zero, then
-                *  send it immediately.
-                *
-                *  Otherwise, delay the authentication reject to shut
-                *  up DoS attacks.
-                */
-               if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||
-                   (mainconfig.reject_delay == 0)) {
-                       /*
-                        *      Send the response. IF it's a real request.
-                        */
-                       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0) {
-                               rad_send(request->reply, request->packet,
-                                        request->secret);
-                       }
-                       /*
-                        *      Otherwise, it's a tunneled request.
-                        *      Don't do anything.
-                        */
-               } else {
-                       DEBUG2("Delaying request %d for %d seconds",
-                              request->number, mainconfig.reject_delay);
-                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
-               }
-       }
-
-       /*
-        *  We're done processing the request, set the
-        *  request to be finished, clean up as necessary,
-        *  and forget about the request.
-        */
-
-finished_request:
-
-       /*
-        *      Don't decode the packet if it's an internal "fake"
-        *      request.  Instead, just skip ahead to processing it.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
-               goto skip_free;
-       }
-
-       /*
-        *  We're done handling the request.  Free up the linked
-        *  lists of value pairs.  This might take a long time,
-        *  so it's more efficient to do it in a child thread,
-        *  instead of in the main handler when it eventually
-        *  gets around to deleting the request.
-        *
-        *  Also, no one should be using these items after the
-        *  request is finished, and the reply is sent.  Cleaning
-        *  them up here ensures that they're not being used again.
-        *
-        *  Hmm... cleaning them up in the child thread also seems
-        *  to make the server run more efficiently!
-        *
-        *  If we've delayed the REJECT, then do NOT clean up the request,
-        *  as we haven't created the REJECT message yet.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {
-               if (request->packet) {
-                       pairfree(&request->packet->vps);
-                       request->username = NULL;
-                       request->password = NULL;
-               }
-
-               /*
-                *  If we've sent a reply to the NAS, then this request is
-                *  pretty much finished, and we have no more need for any
-                *  of the value-pair's in it, including the proxy stuff.
-                */
-               if (request->reply->code != 0) {
-                       pairfree(&request->reply->vps);
-               }
-       }
-
-       pairfree(&request->config_items);
-       if (request->proxy) {
-               pairfree(&request->proxy->vps);
-       }
-       if (request->proxy_reply) {
-               pairfree(&request->proxy_reply->vps);
-       }
-
- skip_free:
-       DEBUG2("Finished request %d", request->number);
-       finished = TRUE;
-
-       /*
-        *  Go to the next request, without marking
-        *  the current one as finished.
-        *
-        *  Hmm... this may not be the brightest thing to do.
-        */
-next_request:
-       DEBUG2("Going to the next request");
-
-postpone_request:
-#ifdef HAVE_PTHREAD_H
-       /*
-        *  We are finished with the child thread.  The thread is detached,
-        *  so that when it exits, there's nothing more for the server
-        *  to do.
-        *
-        *  If we're running with thread pools, then this frees up the
-        *  thread in the pool for another request.
-        */
-       request->child_pid = NO_SUCH_CHILD_PID;
-#endif
-       request->finished = finished; /* do as the LAST thing before exiting */
-       return 0;
-}
index 03a548d..ea0e705 100644 (file)
@@ -407,206 +407,3 @@ REQUEST *request_alloc_fake(REQUEST *oldreq)
 }
 
 
-/*
- *  Perform any RFC specified cleaning of outgoing replies
- */
-void rfc_clean(RADIUS_PACKET *packet)
-{
-       VALUE_PAIR *vps = NULL;
-
-       switch (packet->code) {
-               /*
-                *      In the default case, we just move all of the
-                *      attributes over.
-                */
-       default:
-               vps = packet->vps;
-               packet->vps = NULL;
-               break;
-
-               /*
-                *      Accounting responses can only contain
-                *      Proxy-State and VSA's.  Note that we do NOT
-                *      move the Proxy-State attributes over, as the
-                *      Proxy-State attributes in this packet are NOT
-                *      the right ones to use.  The reply function
-                *      takes care of copying those attributes from
-                *      the original request, which ARE the right ones
-                *      to use.
-                */
-       case PW_ACCOUNTING_RESPONSE:
-               pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
-               break;
-
-               /*
-                *      Authentication REJECT's can have only
-                *      EAP-Message, Message-Authenticator
-                *      Reply-Message and Proxy-State.
-                *
-                *      We delete everything other than these.
-                *      Proxy-State is added below, just before the
-                *      reply is sent.
-                */
-       case PW_AUTHENTICATION_REJECT:
-               pairmove2(&vps, &(packet->vps), PW_EAP_MESSAGE);
-               pairmove2(&vps, &(packet->vps), PW_MESSAGE_AUTHENTICATOR);
-               pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
-               pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
-               break;
-       }
-
-       /*
-        *      Move the newly cleaned attributes over.
-        */
-       pairfree(&packet->vps);
-       packet->vps = vps;
-
-       /*
-        *      FIXME: Perform other, more generic sanity checks.
-        */
-}
-
-
-/*
- *     For debugging
- */
-static LRAD_NAME_NUMBER request_fail_reason[] = {
-       { "no threads available to handle the request",
-         REQUEST_FAIL_NO_THREADS },
-
-       { "malformed RADIUS packet",
-         REQUEST_FAIL_DECODE},
-
-       { "pre-proxying failed",
-         REQUEST_FAIL_PROXY},
-
-       { "sending of the proxy packet failed",
-         REQUEST_FAIL_PROXY_SEND},
-
-       { "failure to be told how to respond",
-         REQUEST_FAIL_NO_RESPONSE},
-
-       { "no response from the home server",
-         REQUEST_FAIL_HOME_SERVER},
-       
-       { "no response from the home server after multiple tries",
-         REQUEST_FAIL_HOME_SERVER2},
-       
-       { "no response from the home server for a long period of time",
-         REQUEST_FAIL_HOME_SERVER3},
-
-       { "we were told to reject the request",
-         REQUEST_FAIL_NORMAL_REJECT},
-
-       { NULL, REQUEST_FAIL_UNKNOWN }
-};
-
-
-/*
- *  Reject a request, by sending a trivial reply packet.
- */
- void request_reject(REQUEST *request, request_fail_t reason)
-{
-       VALUE_PAIR *vps;
-
-       /*
-        *      Already rejected.  Don't do anything.
-        */
-       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
-               return;
-       }
-
-       DEBUG2("Server rejecting request %d due to %s.",
-              request->number, lrad_int2str(request_fail_reason,
-                                            reason, "unknown"));
-       switch (request->packet->code) {
-               /*
-                *  Accounting requests, etc. get dropped on the floor.
-                */
-               default:
-               case PW_ACCOUNTING_REQUEST:
-               case PW_STATUS_SERVER:
-                       break;
-
-               /*
-                *  Authentication requests get their Proxy-State
-                *  attributes copied over, and an otherwise blank
-                *  reject message sent.
-                */
-               case PW_AUTHENTICATION_REQUEST:
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-
-                       /*
-                        *  Perform RFC limitations on outgoing replies.
-                        */
-                       rfc_clean(request->reply);
-
-                       /*
-                        *  Need to copy Proxy-State from request->packet->vps
-                        */
-                       vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
-                       if (vps != NULL)
-                               pairadd(&(request->reply->vps), vps);
-                       break;
-       }
-
-       /*
-        *      If a reply exists, send it.
-        *
-        *      But DON'T send a RADIUS packet for a fake request.
-        */
-       if ((request->reply->code != 0) &&
-           ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0)) {
-               /*
-                *      If we're not delaying authentication rejects,
-                *      then send the response immediately.  Otherwise,
-                *      mark the request as delayed, and do NOT send a
-                *      response.
-                */
-               if (mainconfig.reject_delay == 0) {
-                       rad_send(request->reply, request->packet,
-                                    request->secret);
-               } else {
-                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
-               }
-       }
-
-       /*
-        *      Remember that it was rejected.
-        */
-       request->options |= RAD_REQUEST_OPTION_REJECTED;
-
-       switch (reason) {
-       case REQUEST_FAIL_NO_THREADS:
-               DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");
-               break;
-
-       case REQUEST_FAIL_DECODE:
-               DEBUG("WARNING: Someone may be attacking your RADIUS server.");
-               break;
-
-       case REQUEST_FAIL_NO_RESPONSE:
-               DEBUG("WARNING: You did not configure the server to accept, or reject the user.  Double-check Auth-Type.");
-               break;
-
-       case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */
-       case REQUEST_FAIL_HOME_SERVER2:
-       case REQUEST_FAIL_HOME_SERVER3:
-               break;
-
-       case REQUEST_FAIL_SERVER_TIMEOUT:
-               radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",
-                      request->number,
-                      request->module ? request->module : "<server core>",
-                      request->component ? request->component : "<server core>");
-
-               /*
-                *      Tell the server to stop processing the request
-                */
-               request->options |= RAD_REQUEST_OPTION_STOP_NOW;
-               break;
-
-       default:                /* no additional messages, or things to do */
-               break;
-       }
-}