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,2006 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Chris Parker <cparker@starnetusa.com>
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/autoconf.h>
30 #include <sys/socket.h>
32 #ifdef HAVE_NETINET_IN_H
33 # include <netinet/in.h>
41 #include <freeradius-devel/radiusd.h>
42 #include <freeradius-devel/rad_assert.h>
43 #include <freeradius-devel/modules.h>
47 * Reprocess the request in possibly a child thread, only through
48 * a subsection of the post-proxy section of radiusd.conf.
50 static int process_post_proxy_fail(REQUEST *request)
60 * Hmm... this code is copied from below, which isn't good,
61 * and is similar to the code in rad_respond.
63 switch (request->packet->code) {
65 * Accounting requests, etc. get dropped on the floor.
68 case PW_ACCOUNTING_REQUEST:
69 case PW_STATUS_SERVER:
73 * Authentication requests get their Proxy-State
74 * attributes copied over, and an otherwise blank
75 * reject message sent.
77 case PW_AUTHENTICATION_REQUEST:
78 request->reply->code = PW_AUTHENTICATION_REJECT;
81 * Need to copy Proxy-State from request->packet->vps
83 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
85 pairadd(&(request->reply->vps), vps);
90 * Send the reply. The sender takes care of quenching
93 request->listener->send(request->listener, request);
95 return 0; /* ignored for now */
101 static const LRAD_NAME_NUMBER request_fail_reason[] = {
102 { "no threads available to handle the request",
103 REQUEST_FAIL_NO_THREADS },
105 { "malformed RADIUS packet",
106 REQUEST_FAIL_DECODE},
108 { "pre-proxying failed",
111 { "sending of the proxy packet failed",
112 REQUEST_FAIL_PROXY_SEND},
114 { "failure to be told how to respond",
115 REQUEST_FAIL_NO_RESPONSE},
117 { "no response from the home server",
118 REQUEST_FAIL_HOME_SERVER},
120 { "no response from the home server after multiple tries",
121 REQUEST_FAIL_HOME_SERVER2},
123 { "no response from the home server for a long period of time",
124 REQUEST_FAIL_HOME_SERVER3},
126 { "we were told to reject the request",
127 REQUEST_FAIL_NORMAL_REJECT},
129 { NULL, REQUEST_FAIL_UNKNOWN }
134 * Reject a request, by sending a trivial reply packet.
136 void request_reject(REQUEST *request, request_fail_t reason)
141 * Already rejected. Don't do anything.
143 if (request->options & RAD_REQUEST_OPTION_REJECTED) {
147 DEBUG2("Server rejecting request %d due to %s.",
148 request->number, lrad_int2str(request_fail_reason,
152 * Remember that it was rejected.
154 request->options |= RAD_REQUEST_OPTION_REJECTED;
157 case REQUEST_FAIL_NO_THREADS:
158 DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");
161 case REQUEST_FAIL_DECODE:
162 DEBUG("WARNING: Someone may be attacking your RADIUS server.");
165 case REQUEST_FAIL_NO_RESPONSE:
166 DEBUG("WARNING: You did not configure the server to accept, or reject the user. Double-check Auth-Type.");
170 * If the home server goes down for some reason,
171 * we want to be able to know when. We do this
172 * by calling a sub-section of the post_proxy section,
173 * and processing any modules we find there.
175 * Note that this subsection CAN edit the response
178 case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */
179 case REQUEST_FAIL_HOME_SERVER2:
180 case REQUEST_FAIL_HOME_SERVER3:
182 * Conditionally disable the home server we sent
185 realm_disable(request);
188 * Not supposed to re-process it,
190 if (mainconfig.proxy_fail_type) {
193 val = dict_valbyname(PW_POST_PROXY_TYPE, mainconfig.proxy_fail_type);
195 DEBUG("ERROR: No such post-proxy type of \"%s\", cancelling post-proxy-failure call.", mainconfig.proxy_fail_type);
199 request->options |= RAD_REQUEST_OPTION_REPROCESS;
201 thread_pool_addrequest(request, process_post_proxy_fail);
206 case REQUEST_FAIL_SERVER_TIMEOUT:
207 radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",
209 request->module ? request->module : "<server core>",
210 request->component ? request->component : "<server core>");
211 request->options |= RAD_REQUEST_OPTION_STOP_NOW;
214 default: /* no additional messages, or things to do */
218 switch (request->packet->code) {
220 * Accounting requests, etc. get dropped on the floor.
223 case PW_ACCOUNTING_REQUEST:
224 case PW_STATUS_SERVER:
228 * Authentication requests get their Proxy-State
229 * attributes copied over, and an otherwise blank
230 * reject message sent.
232 case PW_AUTHENTICATION_REQUEST:
233 request->reply->code = PW_AUTHENTICATION_REJECT;
236 * Need to copy Proxy-State from request->packet->vps
238 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
240 pairadd(&(request->reply->vps), vps);
245 * Reject the request. The sender will take care of delaying
246 * or quenching rejects.
248 request->listener->send(request->listener, request);
253 * Respond to a request packet.
255 * Maybe we reply, maybe we don't.
256 * Maybe we proxy the request to another server, or else maybe
257 * we replicate it to another server.
259 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
261 RADIUS_PACKET *packet, *original;
263 int finished = FALSE;
265 rad_assert(request->magic == REQUEST_MAGIC);
268 * Don't decode the packet if it's an internal "fake"
269 * request. Instead, just skip ahead to processing it.
271 if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
276 * Re-process the request.
278 if ((request->options & RAD_REQUEST_OPTION_REPROCESS) != 0) {
283 * Put the decoded packet into it's proper place.
285 if (request->proxy_reply != NULL) {
286 packet = request->proxy_reply;
287 secret = request->proxysecret;
288 original = request->proxy;
290 packet = request->packet;
291 secret = request->secret;
296 * Decode the packet, verifying it's signature,
297 * and parsing the attributes into structures.
299 * Note that we do this CPU-intensive work in
300 * a child thread, not the master. This helps to
301 * spread the load a little bit.
303 * Internal requests (ones that never go on the
304 * wire) have ->data==NULL (data is the wire
305 * format) and don't need to be "decoded"
311 * Fails verification: silently discard it.
313 decoderesult = rad_verify(packet, original, secret);
314 if (decoderesult < 0) {
315 radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
316 /* Since accounting packets get this set in
317 * request_reject but no response is sent...
319 request->options |= RAD_REQUEST_OPTION_REJECTED;
320 goto finished_request;
324 * Can't decode it. This usually means we're out
327 decoderesult = rad_decode(packet, original, secret);
328 if (decoderesult < 0) {
329 radlog(L_ERR, "%s", librad_errstr);
330 request_reject(request, REQUEST_FAIL_DECODE);
331 goto finished_request;
336 * For proxy replies, remove non-allowed
337 * attributes from the list of VP's.
339 if (request->proxy) {
341 rcode = proxy_receive(request);
343 default: /* Don't Do Anything */
345 case RLM_MODULE_FAIL:
346 /* on error just continue with next request */
348 case RLM_MODULE_HANDLED:
349 /* if this was a replicated request, mark it as
350 * finished first, because it was postponed
352 goto finished_request;
357 * This is the initial incoming request which
360 * Some requests do NOT get cached, as they
361 * CANNOT possibly have duplicates. Set the
364 * Status-Server messages are easy to generate,
365 * so we toss them as soon as we see a reply.
367 * Accounting-Request packets WITHOUT an
368 * Acct-Delay-Time attribute are NEVER
369 * duplicated, as RFC 2866 Section 4.1 says that
370 * the Acct-Delay-Time MUST be updated when the
371 * packet is re-sent, which means the packet
372 * changes, so it MUST have a new identifier and
373 * Request Authenticator. */
374 if ((request->packet->code == PW_STATUS_SERVER) ||
375 ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
376 (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {
377 request->options |= RAD_REQUEST_OPTION_DONT_CACHE;
383 * We should have a User-Name attribute now.
385 if (request->username == NULL) {
386 request->username = pairfind(request->packet->vps,
393 * If the request took too long to process, don't do
396 if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
398 goto postpone_request;
402 * If the request took too long to process, don't do
405 if (request->options & RAD_REQUEST_OPTION_REJECTED) {
407 goto postpone_request;
411 * Status-Server requests NEVER get proxied.
413 if (mainconfig.proxy_requests) {
414 if ((request->packet->code != PW_STATUS_SERVER) &&
415 ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
419 * Try to proxy this request.
421 rcode = proxy_send(request);
428 * There was an error trying to proxy the request.
429 * Drop it on the floor.
431 case RLM_MODULE_FAIL:
432 DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);
433 request_reject(request, REQUEST_FAIL_PROXY);
434 goto finished_request;
438 * The pre-proxy module has decided to reject
439 * the request. Do so.
441 case RLM_MODULE_REJECT:
442 DEBUG2("Request %d rejected in proxy_send.", request->number);
443 request_reject(request, REQUEST_FAIL_PROXY_SEND);
444 goto finished_request;
448 * If the proxy code has handled the request,
449 * then postpone more processing, until we get
450 * the reply packet from the home server.
452 case RLM_MODULE_HANDLED:
453 goto postpone_request;
458 * Else rcode==RLM_MODULE_NOOP
459 * and the proxy code didn't do anything, so
460 * we continue handling the request here.
463 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
464 (request->reply->code == 0)) {
466 * We're not configured to reply to the packet,
467 * and we're not proxying, so the DEFAULT behaviour
468 * is to REJECT the user.
470 request_reject(request, REQUEST_FAIL_NO_RESPONSE);
471 goto finished_request;
475 * If we have a reply to send, copy the Proxy-State
476 * attributes from the request to the tail of the reply,
477 * and send the packet.
479 rad_assert(request->magic == REQUEST_MAGIC);
480 if (request->reply->code != 0) {
481 VALUE_PAIR *vp = NULL;
484 * Need to copy Proxy-State from request->packet->vps
486 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
487 if (vp) pairadd(&(request->reply->vps), vp);
491 * ALWAYS call the sender to send the reply. The sender
492 * will take care of doing the appropriate work to
493 * suppress packets which aren't supposed to be sent over
494 * the wire, or to be delayed.
496 request->listener->send(request->listener, request);
499 * We're done processing the request, set the
500 * request to be finished, clean up as necessary,
501 * and forget about the request.
507 * Don't decode the packet if it's an internal "fake"
508 * request. Instead, just skip ahead to processing it.
510 if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
515 * We're done handling the request. Free up the linked
516 * lists of value pairs. This might take a long time,
517 * so it's more efficient to do it in a child thread,
518 * instead of in the main handler when it eventually
519 * gets around to deleting the request.
521 * Also, no one should be using these items after the
522 * request is finished, and the reply is sent. Cleaning
523 * them up here ensures that they're not being used again.
525 * Hmm... cleaning them up in the child thread also seems
526 * to make the server run more efficiently!
528 * If we've delayed the REJECT, then do NOT clean up the request,
529 * as we haven't created the REJECT message yet.
531 if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {
532 if (request->packet) {
533 pairfree(&request->packet->vps);
534 request->username = NULL;
535 request->password = NULL;
539 * If we've sent a reply to the NAS, then this request is
540 * pretty much finished, and we have no more need for any
541 * of the value-pair's in it, including the proxy stuff.
543 if (request->reply->code != 0) {
544 pairfree(&request->reply->vps);
548 pairfree(&request->config_items);
549 if (request->proxy) {
550 pairfree(&request->proxy->vps);
552 if (request->proxy_reply) {
553 pairfree(&request->proxy_reply->vps);
557 DEBUG2("Finished request %d", request->number);
561 * Go to the next request, without marking
562 * the current one as finished.
564 * Hmm... this may not be the brightest thing to do.
567 DEBUG2("Going to the next request");