6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Chris Parker <cparker@starnetusa.com>
25 static const char rcsid[] = "$Id$";
27 #include <freeradius-devel/autoconf.h>
29 #include <sys/socket.h>
31 #ifdef HAVE_NETINET_IN_H
32 # include <netinet/in.h>
40 #include <freeradius-devel/radiusd.h>
41 #include <freeradius-devel/rad_assert.h>
42 #include <freeradius-devel/modules.h>
46 * Reprocess the request in possibly a child thread, only through
47 * a subsection of the post-proxy section of radiusd.conf.
49 static int process_post_proxy_fail(REQUEST *request)
59 * Hmm... this code is copied from below, which isn't good,
60 * and is similar to the code in rad_respond.
62 switch (request->packet->code) {
64 * Accounting requests, etc. get dropped on the floor.
67 case PW_ACCOUNTING_REQUEST:
68 case PW_STATUS_SERVER:
72 * Authentication requests get their Proxy-State
73 * attributes copied over, and an otherwise blank
74 * reject message sent.
76 case PW_AUTHENTICATION_REQUEST:
77 request->reply->code = PW_AUTHENTICATION_REJECT;
80 * Perform RFC limitations on outgoing replies.
82 rfc_clean(request->reply);
85 * Need to copy Proxy-State from request->packet->vps
87 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
89 pairadd(&(request->reply->vps), vps);
94 * Send the reply. The sender takes care of quenching
97 request->listener->send(request->listener, request);
99 return 0; /* ignored for now */
104 * Perform any RFC specified cleaning of outgoing replies
106 void rfc_clean(RADIUS_PACKET *packet)
108 VALUE_PAIR *vps = NULL;
110 switch (packet->code) {
112 * In the default case, we just move all of the
121 * Accounting responses can only contain
122 * Proxy-State and VSA's. Note that we do NOT
123 * move the Proxy-State attributes over, as the
124 * Proxy-State attributes in this packet are NOT
125 * the right ones to use. The reply function
126 * takes care of copying those attributes from
127 * the original request, which ARE the right ones
130 case PW_ACCOUNTING_RESPONSE:
131 pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
135 * Authentication REJECT's can have only
136 * EAP-Message, Message-Authenticator
137 * Reply-Message and Proxy-State.
139 * We delete everything other than these.
140 * Proxy-State is added below, just before the
143 case PW_AUTHENTICATION_REJECT:
144 pairmove2(&vps, &(packet->vps), PW_EAP_MESSAGE);
145 pairmove2(&vps, &(packet->vps), PW_MESSAGE_AUTHENTICATOR);
146 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
151 * Move the newly cleaned attributes over.
153 pairfree(&packet->vps);
157 * FIXME: Perform other, more generic sanity checks.
165 static const LRAD_NAME_NUMBER request_fail_reason[] = {
166 { "no threads available to handle the request",
167 REQUEST_FAIL_NO_THREADS },
169 { "malformed RADIUS packet",
170 REQUEST_FAIL_DECODE},
172 { "pre-proxying failed",
175 { "sending of the proxy packet failed",
176 REQUEST_FAIL_PROXY_SEND},
178 { "failure to be told how to respond",
179 REQUEST_FAIL_NO_RESPONSE},
181 { "no response from the home server",
182 REQUEST_FAIL_HOME_SERVER},
184 { "no response from the home server after multiple tries",
185 REQUEST_FAIL_HOME_SERVER2},
187 { "no response from the home server for a long period of time",
188 REQUEST_FAIL_HOME_SERVER3},
190 { "we were told to reject the request",
191 REQUEST_FAIL_NORMAL_REJECT},
193 { NULL, REQUEST_FAIL_UNKNOWN }
198 * Reject a request, by sending a trivial reply packet.
200 void request_reject(REQUEST *request, request_fail_t reason)
205 * Already rejected. Don't do anything.
207 if (request->options & RAD_REQUEST_OPTION_REJECTED) {
211 DEBUG2("Server rejecting request %d due to %s.",
212 request->number, lrad_int2str(request_fail_reason,
216 * Remember that it was rejected.
218 request->options |= RAD_REQUEST_OPTION_REJECTED;
221 case REQUEST_FAIL_NO_THREADS:
222 DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");
225 case REQUEST_FAIL_DECODE:
226 DEBUG("WARNING: Someone may be attacking your RADIUS server.");
229 case REQUEST_FAIL_NO_RESPONSE:
230 DEBUG("WARNING: You did not configure the server to accept, or reject the user. Double-check Auth-Type.");
234 * If the home server goes down for some reason,
235 * we want to be able to know when. We do this
236 * by calling a sub-section of the post_proxy section,
237 * and processing any modules we find there.
239 * Note that this subsection CAN edit the response
242 case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */
243 case REQUEST_FAIL_HOME_SERVER2:
244 case REQUEST_FAIL_HOME_SERVER3:
246 * Conditionally disable the home server we sent
249 realm_disable(request);
252 * Not supposed to re-process it,
254 if (mainconfig.proxy_fail_type) {
257 val = dict_valbyname(PW_POST_PROXY_TYPE, mainconfig.proxy_fail_type);
259 DEBUG("ERROR: No such post-proxy type of \"%s\", cancelling post-proxy-failure call.", mainconfig.proxy_fail_type);
263 request->options |= RAD_REQUEST_OPTION_REPROCESS;
265 thread_pool_addrequest(request, process_post_proxy_fail);
270 case REQUEST_FAIL_SERVER_TIMEOUT:
271 radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",
273 request->module ? request->module : "<server core>",
274 request->component ? request->component : "<server core>");
275 request->options |= RAD_REQUEST_OPTION_STOP_NOW;
278 default: /* no additional messages, or things to do */
282 switch (request->packet->code) {
284 * Accounting requests, etc. get dropped on the floor.
287 case PW_ACCOUNTING_REQUEST:
288 case PW_STATUS_SERVER:
292 * Authentication requests get their Proxy-State
293 * attributes copied over, and an otherwise blank
294 * reject message sent.
296 case PW_AUTHENTICATION_REQUEST:
297 request->reply->code = PW_AUTHENTICATION_REJECT;
300 * Perform RFC limitations on outgoing replies.
302 rfc_clean(request->reply);
305 * Need to copy Proxy-State from request->packet->vps
307 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
309 pairadd(&(request->reply->vps), vps);
314 * Reject the request. The sender will take care of delaying
315 * or quenching rejects.
317 request->listener->send(request->listener, request);
322 * Respond to a request packet.
324 * Maybe we reply, maybe we don't.
325 * Maybe we proxy the request to another server, or else maybe
326 * we replicate it to another server.
328 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
330 RADIUS_PACKET *packet, *original;
332 int finished = FALSE;
334 rad_assert(request->magic == REQUEST_MAGIC);
337 * Don't decode the packet if it's an internal "fake"
338 * request. Instead, just skip ahead to processing it.
340 if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
345 * Re-process the request.
347 if ((request->options & RAD_REQUEST_OPTION_REPROCESS) != 0) {
352 * Put the decoded packet into it's proper place.
354 if (request->proxy_reply != NULL) {
355 packet = request->proxy_reply;
356 secret = request->proxysecret;
357 original = request->proxy;
359 packet = request->packet;
360 secret = request->secret;
365 * Decode the packet, verifying it's signature,
366 * and parsing the attributes into structures.
368 * Note that we do this CPU-intensive work in
369 * a child thread, not the master. This helps to
370 * spread the load a little bit.
372 * Internal requests (ones that never go on the
373 * wire) have ->data==NULL (data is the wire
374 * format) and don't need to be "decoded"
380 * Fails verification: silently discard it.
382 decoderesult = rad_verify(packet, original, secret);
383 if (decoderesult < 0) {
384 radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
385 /* Since accounting packets get this set in
386 * request_reject but no response is sent...
388 request->options |= RAD_REQUEST_OPTION_REJECTED;
389 goto finished_request;
393 * Can't decode it. This usually means we're out
396 decoderesult = rad_decode(packet, original, secret);
397 if (decoderesult < 0) {
398 radlog(L_ERR, "%s", librad_errstr);
399 request_reject(request, REQUEST_FAIL_DECODE);
400 goto finished_request;
405 * For proxy replies, remove non-allowed
406 * attributes from the list of VP's.
408 if (request->proxy) {
410 rcode = proxy_receive(request);
412 default: /* Don't Do Anything */
414 case RLM_MODULE_FAIL:
415 /* on error just continue with next request */
417 case RLM_MODULE_HANDLED:
418 /* if this was a replicated request, mark it as
419 * finished first, because it was postponed
421 goto finished_request;
426 * This is the initial incoming request which
429 * Some requests do NOT get cached, as they
430 * CANNOT possibly have duplicates. Set the
433 * Status-Server messages are easy to generate,
434 * so we toss them as soon as we see a reply.
436 * Accounting-Request packets WITHOUT an
437 * Acct-Delay-Time attribute are NEVER
438 * duplicated, as RFC 2866 Section 4.1 says that
439 * the Acct-Delay-Time MUST be updated when the
440 * packet is re-sent, which means the packet
441 * changes, so it MUST have a new identifier and
442 * Request Authenticator. */
443 if ((request->packet->code == PW_STATUS_SERVER) ||
444 ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
445 (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {
446 request->options |= RAD_REQUEST_OPTION_DONT_CACHE;
452 * We should have a User-Name attribute now.
454 if (request->username == NULL) {
455 request->username = pairfind(request->packet->vps,
462 * If the request took too long to process, don't do
465 if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
467 goto postpone_request;
471 * If the request took too long to process, don't do
474 if (request->options & RAD_REQUEST_OPTION_REJECTED) {
476 goto postpone_request;
480 * Status-Server requests NEVER get proxied.
482 if (mainconfig.proxy_requests) {
483 if ((request->packet->code != PW_STATUS_SERVER) &&
484 ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
488 * Try to proxy this request.
490 rcode = proxy_send(request);
497 * There was an error trying to proxy the request.
498 * Drop it on the floor.
500 case RLM_MODULE_FAIL:
501 DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);
502 request_reject(request, REQUEST_FAIL_PROXY);
503 goto finished_request;
507 * The pre-proxy module has decided to reject
508 * the request. Do so.
510 case RLM_MODULE_REJECT:
511 DEBUG2("Request %d rejected in proxy_send.", request->number);
512 request_reject(request, REQUEST_FAIL_PROXY_SEND);
513 goto finished_request;
517 * If the proxy code has handled the request,
518 * then postpone more processing, until we get
519 * the reply packet from the home server.
521 case RLM_MODULE_HANDLED:
522 goto postpone_request;
527 * Else rcode==RLM_MODULE_NOOP
528 * and the proxy code didn't do anything, so
529 * we continue handling the request here.
532 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
533 (request->reply->code == 0)) {
535 * We're not configured to reply to the packet,
536 * and we're not proxying, so the DEFAULT behaviour
537 * is to REJECT the user.
539 request_reject(request, REQUEST_FAIL_NO_RESPONSE);
540 goto finished_request;
544 * If we have a reply to send, copy the Proxy-State
545 * attributes from the request to the tail of the reply,
546 * and send the packet.
548 rad_assert(request->magic == REQUEST_MAGIC);
549 if (request->reply->code != 0) {
550 VALUE_PAIR *vp = NULL;
553 * Perform RFC limitations on outgoing replies.
555 rfc_clean(request->reply);
558 * Need to copy Proxy-State from request->packet->vps
560 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
561 if (vp) pairadd(&(request->reply->vps), vp);
565 * ALWAYS call the sender to send the reply. The sender
566 * will take care of doing the appropriate work to
567 * suppress packets which aren't supposed to be sent over
568 * the wire, or to be delayed.
570 request->listener->send(request->listener, request);
573 * We're done processing the request, set the
574 * request to be finished, clean up as necessary,
575 * and forget about the request.
581 * Don't decode the packet if it's an internal "fake"
582 * request. Instead, just skip ahead to processing it.
584 if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
589 * We're done handling the request. Free up the linked
590 * lists of value pairs. This might take a long time,
591 * so it's more efficient to do it in a child thread,
592 * instead of in the main handler when it eventually
593 * gets around to deleting the request.
595 * Also, no one should be using these items after the
596 * request is finished, and the reply is sent. Cleaning
597 * them up here ensures that they're not being used again.
599 * Hmm... cleaning them up in the child thread also seems
600 * to make the server run more efficiently!
602 * If we've delayed the REJECT, then do NOT clean up the request,
603 * as we haven't created the REJECT message yet.
605 if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {
606 if (request->packet) {
607 pairfree(&request->packet->vps);
608 request->username = NULL;
609 request->password = NULL;
613 * If we've sent a reply to the NAS, then this request is
614 * pretty much finished, and we have no more need for any
615 * of the value-pair's in it, including the proxy stuff.
617 if (request->reply->code != 0) {
618 pairfree(&request->reply->vps);
622 pairfree(&request->config_items);
623 if (request->proxy) {
624 pairfree(&request->proxy->vps);
626 if (request->proxy_reply) {
627 pairfree(&request->proxy_reply->vps);
631 DEBUG2("Finished request %d", request->number);
635 * Go to the next request, without marking
636 * the current one as finished.
638 * Hmm... this may not be the brightest thing to do.
641 DEBUG2("Going to the next request");
644 #ifdef HAVE_PTHREAD_H
646 * We are finished with the child thread. The thread is detached,
647 * so that when it exits, there's nothing more for the server
650 * If we're running with thread pools, then this frees up the
651 * thread in the pool for another request.
653 request->child_pid = NO_SUCH_CHILD_PID;
655 request->finished = finished; /* do as the LAST thing before exiting */