Pull fix from branch_1_1
[freeradius.git] / src / main / request_process.c
1 /*
2  * proxy.c      Proxy stuff.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
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>
23  */
24
25 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/autoconf.h>
29
30 #include <sys/socket.h>
31
32 #ifdef HAVE_NETINET_IN_H
33 #       include <netinet/in.h>
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 #include <string.h>
40
41 #include <freeradius-devel/radiusd.h>
42 #include <freeradius-devel/rad_assert.h>
43 #include <freeradius-devel/modules.h>
44
45
46 /*
47  *      Reprocess the request in possibly a child thread, only through
48  *      a subsection of the post-proxy section of radiusd.conf.
49  */
50 static int process_post_proxy_fail(REQUEST *request)
51 {
52         VALUE_PAIR *vps;
53
54         /*
55          *
56          */
57
58
59         /*
60          *      Hmm... this code is copied from below, which isn't good,
61          *      and is similar to the code in rad_respond.
62          */
63         switch (request->packet->code) {
64                 /*
65                  *  Accounting requests, etc. get dropped on the floor.
66                  */
67         default:
68         case PW_ACCOUNTING_REQUEST:
69         case PW_STATUS_SERVER:
70                 break;
71                 
72                 /*
73                  *  Authentication requests get their Proxy-State
74                  *  attributes copied over, and an otherwise blank
75                  *  reject message sent.
76                  */
77         case PW_AUTHENTICATION_REQUEST:
78                 request->reply->code = PW_AUTHENTICATION_REJECT;
79                 
80                 /*
81                  *  Need to copy Proxy-State from request->packet->vps
82                  */
83                 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
84                 if (vps != NULL)
85                         pairadd(&(request->reply->vps), vps);
86                 break;
87         }
88         
89         /*
90          *      Send the reply.  The sender takes care of quenching
91          *      packets.
92          */
93         request->listener->send(request->listener, request);
94
95         return 0;               /* ignored for now */
96 }
97
98 /*
99  *      For debugging
100  */
101 static const LRAD_NAME_NUMBER request_fail_reason[] = {
102         { "no threads available to handle the request",
103           REQUEST_FAIL_NO_THREADS },
104
105         { "malformed RADIUS packet",
106           REQUEST_FAIL_DECODE},
107
108         { "pre-proxying failed",
109           REQUEST_FAIL_PROXY},
110
111         { "sending of the proxy packet failed",
112           REQUEST_FAIL_PROXY_SEND},
113
114         { "failure to be told how to respond",
115           REQUEST_FAIL_NO_RESPONSE},
116
117         { "no response from the home server",
118           REQUEST_FAIL_HOME_SERVER},
119         
120         { "no response from the home server after multiple tries",
121           REQUEST_FAIL_HOME_SERVER2},
122         
123         { "no response from the home server for a long period of time",
124           REQUEST_FAIL_HOME_SERVER3},
125
126         { "we were told to reject the request",
127           REQUEST_FAIL_NORMAL_REJECT},
128
129         { NULL, REQUEST_FAIL_UNKNOWN }
130 };
131
132
133 /*
134  *  Reject a request, by sending a trivial reply packet.
135  */
136  void request_reject(REQUEST *request, request_fail_t reason)
137 {
138         VALUE_PAIR *vps;
139
140         /*
141          *      Already rejected.  Don't do anything.
142          */
143         if (request->options & RAD_REQUEST_OPTION_REJECTED) {
144                 return;
145         }
146
147         DEBUG2("Server rejecting request %d due to %s.",
148                request->number, lrad_int2str(request_fail_reason,
149                                              reason, "unknown"));
150
151         /*
152          *      Remember that it was rejected.
153          */
154         request->options |= RAD_REQUEST_OPTION_REJECTED;
155
156         switch (reason) {
157         case REQUEST_FAIL_NO_THREADS:
158                 DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");
159                 break;
160
161         case REQUEST_FAIL_DECODE:
162                 DEBUG("WARNING: Someone may be attacking your RADIUS server.");
163                 break;
164
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.");
167                 break;
168
169                 /*
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.
174                  *
175                  *      Note that this subsection CAN edit the response
176                  *      to the NAS.
177                  */
178         case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */
179         case REQUEST_FAIL_HOME_SERVER2:
180         case REQUEST_FAIL_HOME_SERVER3:
181                 /*
182                  *      Conditionally disable the home server we sent
183                  *      packets to.
184                  */
185                 realm_disable(request);
186                 
187                 /*
188                  *      Not supposed to re-process it, 
189                  */
190                 if (mainconfig.proxy_fail_type) {
191                         DICT_VALUE      *val;
192
193                         val = dict_valbyname(PW_POST_PROXY_TYPE, mainconfig.proxy_fail_type);
194                         if (!val) {
195                                 DEBUG("ERROR: No such post-proxy type of \"%s\", cancelling post-proxy-failure call.", mainconfig.proxy_fail_type);
196                                 return;
197                         }
198                         
199                         request->options |= RAD_REQUEST_OPTION_REPROCESS;
200                         
201                         thread_pool_addrequest(request, process_post_proxy_fail);
202                         return;
203                 }
204                 break;
205
206         case REQUEST_FAIL_SERVER_TIMEOUT:
207                 radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",
208                        request->number,
209                        request->module ? request->module : "<server core>",
210                        request->component ? request->component : "<server core>");
211                 request->options |= RAD_REQUEST_OPTION_STOP_NOW;
212                 break;
213
214         default:                /* no additional messages, or things to do */
215                 break;
216         }
217
218         switch (request->packet->code) {
219                 /*
220                  *  Accounting requests, etc. get dropped on the floor.
221                  */
222                 default:
223                 case PW_ACCOUNTING_REQUEST:
224                 case PW_STATUS_SERVER:
225                         break;
226
227                 /*
228                  *  Authentication requests get their Proxy-State
229                  *  attributes copied over, and an otherwise blank
230                  *  reject message sent.
231                  */
232                 case PW_AUTHENTICATION_REQUEST:
233                         request->reply->code = PW_AUTHENTICATION_REJECT;
234
235                         /*
236                          *  Need to copy Proxy-State from request->packet->vps
237                          */
238                         vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
239                         if (vps != NULL)
240                                 pairadd(&(request->reply->vps), vps);
241                         break;
242         }
243
244         /*
245          *      Reject the request.  The sender will take care of delaying
246          *      or quenching rejects.
247          */
248         request->listener->send(request->listener, request);
249 }
250
251
252 /*
253  *  Respond to a request packet.
254  *
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.
258  */
259 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
260 {
261         RADIUS_PACKET *packet, *original;
262         const char *secret;
263         int finished = FALSE;
264
265         rad_assert(request->magic == REQUEST_MAGIC);
266
267         /*
268          *      Don't decode the packet if it's an internal "fake"
269          *      request.  Instead, just skip ahead to processing it.
270          */
271         if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
272                 goto skip_decode;
273         }
274
275         /*
276          *      Re-process the request.
277          */
278         if ((request->options & RAD_REQUEST_OPTION_REPROCESS) != 0) {
279                 goto skip_decode;
280         }
281
282         /*
283          *  Put the decoded packet into it's proper place.
284          */
285         if (request->proxy_reply != NULL) {
286                 packet = request->proxy_reply;
287                 secret = request->proxysecret;
288                 original = request->proxy;
289         } else {
290                 packet = request->packet;
291                 secret = request->secret;
292                 original = NULL;
293         }
294
295         /*
296          *  Decode the packet, verifying it's signature,
297          *  and parsing the attributes into structures.
298          *
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.
302          *
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"
306          */
307         if (packet->data) {
308                 int decoderesult;
309
310                 /*
311                  *      Fails verification: silently discard it.
312                  */
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...
318                          */
319                         request->options |= RAD_REQUEST_OPTION_REJECTED;
320                         goto finished_request;
321                 }
322
323                 /*
324                  *      Can't decode it.  This usually means we're out
325                  *      of memory.
326                  */
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;
332                 }
333         }
334
335         /*
336          *  For proxy replies, remove non-allowed
337          *  attributes from the list of VP's.
338          */
339         if (request->proxy) {
340                 int rcode;
341                 rcode = proxy_receive(request);
342                 switch (rcode) {
343                 default:  /* Don't Do Anything */
344                         break;
345                 case RLM_MODULE_FAIL:
346                         /* on error just continue with next request */
347                         goto next_request;
348                 case RLM_MODULE_HANDLED:
349                         /* if this was a replicated request, mark it as
350                          * finished first, because it was postponed
351                          */
352                         goto finished_request;
353                 }
354
355         } else {
356                 /*
357                  *      This is the initial incoming request which
358                  *      we're processing.
359                  *
360                  *      Some requests do NOT get cached, as they
361                  *      CANNOT possibly have duplicates.  Set the
362                  *      magic option here.
363                  *
364                  *      Status-Server messages are easy to generate,
365                  *      so we toss them as soon as we see a reply.
366                  *
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;
378                 }
379         }
380
381  skip_decode:
382         /*
383          *      We should have a User-Name attribute now.
384          */
385         if (request->username == NULL) {
386                 request->username = pairfind(request->packet->vps,
387                                 PW_USER_NAME);
388         }
389
390         (*fun)(request);
391
392         /*
393          *      If the request took too long to process, don't do
394          *      anything else.
395          */
396         if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
397                 finished = TRUE;
398                 goto postpone_request;
399         }
400
401         /*
402          *      If the request took too long to process, don't do
403          *      anything else.
404          */
405         if (request->options & RAD_REQUEST_OPTION_REJECTED) {
406                 finished = TRUE;
407                 goto postpone_request;
408         }
409
410         /*
411          *      Status-Server requests NEVER get proxied.
412          */
413         if (mainconfig.proxy_requests) {
414                 if ((request->packet->code != PW_STATUS_SERVER) &&
415                     ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
416                         int rcode;
417
418                         /*
419                          *      Try to proxy this request.
420                          */
421                         rcode = proxy_send(request);
422
423                         switch (rcode) {
424                         default:
425                                 break;
426
427                         /*
428                          *  There was an error trying to proxy the request.
429                          *  Drop it on the floor.
430                          */
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;
435                                 break;
436
437                         /*
438                          *  The pre-proxy module has decided to reject
439                          *  the request.  Do so.
440                          */
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;
445                                 break;
446
447                         /*
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.
451                          */
452                         case RLM_MODULE_HANDLED:
453                                 goto postpone_request;
454                                 break;
455                         }
456
457                         /*
458                          *  Else rcode==RLM_MODULE_NOOP
459                          *  and the proxy code didn't do anything, so
460                          *  we continue handling the request here.
461                          */
462                 }
463         } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
464                    (request->reply->code == 0)) {
465                 /*
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.
469                  */
470                 request_reject(request, REQUEST_FAIL_NO_RESPONSE);
471                 goto finished_request;
472         }
473
474         /*
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.
478          */
479         rad_assert(request->magic == REQUEST_MAGIC);
480         if (request->reply->code != 0) {
481                 VALUE_PAIR *vp = NULL;
482
483                 /*
484                  *      Need to copy Proxy-State from request->packet->vps
485                  */
486                 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
487                 if (vp) pairadd(&(request->reply->vps), vp);
488         }
489
490         /*
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.
495          */
496         request->listener->send(request->listener, request);
497
498         /*
499          *  We're done processing the request, set the
500          *  request to be finished, clean up as necessary,
501          *  and forget about the request.
502          */
503
504 finished_request:
505
506         /*
507          *      Don't decode the packet if it's an internal "fake"
508          *      request.  Instead, just skip ahead to processing it.
509          */
510         if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
511                 goto skip_free;
512         }
513
514         /*
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.
520          *
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.
524          *
525          *  Hmm... cleaning them up in the child thread also seems
526          *  to make the server run more efficiently!
527          *
528          *  If we've delayed the REJECT, then do NOT clean up the request,
529          *  as we haven't created the REJECT message yet.
530          */
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;
536                 }
537
538                 /*
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.
542                  */
543                 if (request->reply->code != 0) {
544                         pairfree(&request->reply->vps);
545                 }
546         }
547
548         pairfree(&request->config_items);
549         if (request->proxy) {
550                 pairfree(&request->proxy->vps);
551         }
552         if (request->proxy_reply) {
553                 pairfree(&request->proxy_reply->vps);
554         }
555
556  skip_free:
557         DEBUG2("Finished request %d", request->number);
558         finished = TRUE;
559
560         /*
561          *  Go to the next request, without marking
562          *  the current one as finished.
563          *
564          *  Hmm... this may not be the brightest thing to do.
565          */
566 next_request:
567         DEBUG2("Going to the next request");
568
569 postpone_request:
570         return finished;
571 }