e3378edb5648fcf57d440eb30c37ac0f46fe12bb
[freeradius.git] / src / main / util.c
1 /*
2  * util.c       Various utility functions.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2000  The FreeRADIUS server project
21  */
22
23 static const char rcsid[] = "$Id$";
24
25 #include "autoconf.h"
26 #include "libradius.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <signal.h>
33
34 #include <sys/stat.h>
35 #include <fcntl.h>
36
37 #ifdef HAVE_UNISTD_H
38 #       include <unistd.h>
39 #endif
40
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
43 #endif
44
45 #include "radiusd.h"
46 #include "rad_assert.h"
47
48 /*
49  *      The signal() function in Solaris 2.5.1 sets SA_NODEFER in
50  *      sa_flags, which causes grief if signal() is called in the
51  *      handler before the cause of the signal has been cleared.
52  *      (Infinite recursion).
53  *
54  *      The same problem appears on HPUX, so we avoid it, if we can.
55  *
56  *      Using sigaction() to reset the signal handler fixes the problem,
57  *      so where available, we prefer that solution.
58  */
59 void (*reset_signal(int signo, void (*func)(int)))(int)
60 {
61 #ifdef HAVE_SIGACTION
62         struct sigaction act, oact;
63
64         act.sa_handler = func;
65         sigemptyset(&act.sa_mask);
66         act.sa_flags = 0;
67 #ifdef  SA_INTERRUPT            /* SunOS */
68         act.sa_flags |= SA_INTERRUPT;
69 #endif
70         if (sigaction(signo, &act, &oact) < 0)
71                 return SIG_ERR;
72         return oact.sa_handler;
73 #else
74         
75         /*
76          *      re-set by calling the 'signal' function, which
77          *      may cause infinite recursion and core dumps due to
78          *      stack growth.
79          *
80          *      However, the system is too dumb to implement sigaction(),
81          *      so we don't have a choice.
82          */
83         signal(signo, func);
84 #endif
85 }
86
87 /*
88  *      Per-request data, added by modules...
89  */
90 struct request_data_t {
91         request_data_t  *next;
92         
93         void            *unique_ptr;
94         int             unique_int;
95         void            *opaque;
96         void            (*free_opaque)(void *);
97 };
98
99 /*
100  *      Add opaque data (with a "free" function) to a REQUEST.
101  *
102  *      The unique ptr is meant to be a malloc'd module configuration,
103  *      and the unique integer allows the caller to have multiple
104  *      opaque data associated with a REQUEST.
105  */
106 int request_data_add(REQUEST *request,
107                      void *unique_ptr, int unique_int,
108                      void *opaque, void (*free_opaque)(void *))
109 {
110         request_data_t *this, **last, *next;
111
112         /*
113          *      Some simple sanity checks.
114          */
115         if (!request || !opaque) return -1;
116
117         this = next = NULL;
118         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
119                 if (((*last)->unique_ptr == unique_ptr) &&
120                     ((*last)->unique_int == unique_int)) {
121                         this = *last;
122
123                         next = this->next;
124
125                         if (this->opaque && /* free it, if necessary */
126                             this->free_opaque)
127                                 this->free_opaque(this->opaque);
128                         break;  /* replace the existing entry */
129                 }
130         }
131
132         if (!this) this = rad_malloc(sizeof(*this));
133         memset(this, 0, sizeof(*this));
134
135         this->next = next;
136         this->unique_ptr = unique_ptr;
137         this->unique_int = unique_int;
138         this->opaque = opaque;
139         this->free_opaque = free_opaque;
140
141         *last = this;
142
143         return 0;
144 }
145
146
147 /*
148  *      Get opaque data from a request.
149  */
150 void *request_data_get(REQUEST *request,
151                        void *unique_ptr, int unique_int)
152 {
153         request_data_t **last;
154
155         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
156                 if (((*last)->unique_ptr == unique_ptr) &&
157                     ((*last)->unique_int == unique_int)) {
158                         request_data_t *this = *last;
159                         void *ptr = this->opaque;
160
161                         /*
162                          *      Remove the entry from the list, and free it.
163                          */
164                         *last = this->next;
165                         free(this);
166                         return ptr; /* don't free it, the caller does that */
167                 }
168         }
169
170         return NULL;            /* wasn't found, too bad... */
171 }
172
173
174 /*
175  *      Free a REQUEST struct.
176  */
177 void request_free(REQUEST **request_ptr)
178 {
179         REQUEST *request;
180
181         if (request_ptr == NULL)
182                 return;
183
184         request = *request_ptr;
185
186         /*
187          *      If there's a thread currently active on this request,
188          *      blow up!
189          */
190         rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
191         
192         if (request->packet) 
193                 rad_free(&request->packet);
194
195         if (request->proxy) 
196                 rad_free(&request->proxy);
197
198         if (request->reply) 
199                 rad_free(&request->reply);
200
201         if (request->proxy_reply) 
202                 rad_free(&request->proxy_reply);
203
204         if (request->config_items) 
205                 pairfree(&request->config_items);
206
207         request->username = NULL;
208         request->password = NULL;
209
210         if (request->data) {
211                 request_data_t *this, *next;
212
213                 for (this = request->data; this != NULL; this = next) {
214                         next = this->next;
215                         if (this->opaque && /* free it, if necessary */
216                             this->free_opaque)
217                                 this->free_opaque(this->opaque);
218                         free(this);
219                 }
220                 request->data = NULL;
221         }
222
223 #ifndef NDEBUG
224         request->magic = 0x01020304;    /* set the request to be nonsense */
225         strcpy(request->secret, "REQUEST-DELETED");
226         strcpy(request->proxysecret, "REQUEST-DELETED");
227 #endif
228         free(request);
229
230         *request_ptr = NULL;
231 }
232
233 /*
234  *      Check a filename for sanity.
235  *
236  *      Allow only uppercase/lowercase letters, numbers, and '-_/.'
237  */
238 int rad_checkfilename(const char *filename)
239 {
240         if (strspn(filename, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/.") == strlen(filename)) {
241                 return 0;
242         }
243
244         return -1;
245 }
246
247 /*
248  *      Create possibly many directories.
249  *
250  *      Note that the input directory name is NOT a constant!
251  *      This is so that IF an error is returned, the 'directory' ptr
252  *      points to the name of the file which caused the error.
253  */
254 int rad_mkdir(char *directory, int mode)
255 {
256         int rcode;
257         char *p;
258         struct stat st;
259
260         /*
261          *      If the directory exists, don't do anything.
262          */
263         if (stat(directory, &st) == 0) {
264                 return 0;
265         }
266
267         /*
268          *      Look for the LAST directory name.  Try to create that,
269          *      failing on any error.
270          */
271         p = strrchr(directory, '/');
272         if (p != NULL) {
273                 *p = '\0';
274                 rcode = rad_mkdir(directory, mode);
275
276                 /*
277                  *      On error, we leave the directory name as the
278                  *      one which caused the error.
279                  */
280                 if (rcode < 0) {
281                         return rcode;
282                 }
283
284                 /*
285                  *      Reset the directory delimiter, and go ask
286                  *      the system to make the directory.
287                  */
288                 *p = '/';
289         } else {
290                 return 0;
291         }
292
293         /*
294          *      Having done everything successfully, we do the
295          *      system call to actually go create the directory.
296          */
297         return mkdir(directory, mode);
298 }
299
300
301 /*
302  *      Module malloc() call, which does stuff if the malloc fails.
303  *
304  *      This call ALWAYS succeeds!
305  */
306 void *rad_malloc(size_t size)
307 {
308         void *ptr = malloc(size);
309         
310         if (ptr == NULL) {
311                 radlog(L_ERR|L_CONS, "no memory");
312                 exit(1);
313         }
314
315         return ptr;
316 }
317
318 void xfree(const char *ptr)
319 {
320         free((char *)ptr);
321 }
322
323 /*
324  *      Logs an error message and aborts the program
325  *
326  */
327
328 void rad_assert_fail (const char *file, unsigned int line)
329 {
330         radlog(L_ERR|L_CONS, "Assertion failed in %s, line %u", file, line);
331         abort();
332 }
333
334
335 /*
336  *      Create a new REQUEST data structure.
337  */
338 REQUEST *request_alloc(void)
339 {
340         REQUEST *request;
341
342         request = rad_malloc(sizeof(REQUEST));
343         memset(request, 0, sizeof(REQUEST));
344 #ifndef NDEBUG
345         request->magic = REQUEST_MAGIC;
346 #endif
347         request->proxy = NULL;
348         request->reply = NULL;
349         request->proxy_reply = NULL;
350         request->config_items = NULL;
351         request->username = NULL;
352         request->password = NULL;
353         request->timestamp = time(NULL);
354         request->child_pid = NO_SUCH_CHILD_PID;
355         request->container = NULL;
356         request->options = RAD_REQUEST_OPTION_NONE;
357
358         return request;
359 }
360
361
362 /*
363  *      Create a new REQUEST, based on an old one.
364  *
365  *      This function allows modules to inject fake requests
366  *      into the server, for tunneled protocols like TTLS & PEAP.
367  */
368 REQUEST *request_alloc_fake(REQUEST *oldreq)
369 {
370   REQUEST *request;
371
372   request = request_alloc();
373
374   request->number = oldreq->number;
375   request->child_pid = NO_SUCH_CHILD_PID;
376   request->options = RAD_REQUEST_OPTION_FAKE_REQUEST;
377
378   request->packet = rad_alloc(0);
379   rad_assert(request->packet != NULL);
380
381   request->reply = rad_alloc(0);
382   rad_assert(request->reply != NULL);
383
384   /*
385    *    Fill in the fake request packet.
386    */
387   request->packet->sockfd = -1;
388   request->packet->src_ipaddr = htonl(INADDR_LOOPBACK);
389   request->packet->dst_ipaddr = htonl(INADDR_LOOPBACK);
390   request->packet->src_port = request->number >> 8;
391   request->packet->dst_port = 0;
392
393   /*
394    *    This isn't STRICTLY required, as the fake request SHOULD NEVER
395    *    be put into the request list.  However, it's still reasonable
396    *    practice.
397    */
398   request->packet->id = request->number & 0xff;
399   request->packet->code = oldreq->packet->code;
400   request->timestamp = oldreq->timestamp;
401
402   /*
403    *    Fill in the fake reply, based on the fake request.
404    */
405   request->reply->sockfd = request->packet->sockfd;
406   request->reply->dst_ipaddr = request->packet->src_ipaddr;
407   request->reply->dst_port = request->packet->src_port;
408   request->reply->id = request->packet->id;
409   request->reply->code = 0; /* UNKNOWN code */
410
411   return request;
412 }
413
414
415 /*
416  *  Perform any RFC specified cleaning of outgoing replies
417  */
418 void rfc_clean(RADIUS_PACKET *packet)
419 {
420         VALUE_PAIR *vps = NULL;
421
422         switch (packet->code) {
423                 /*
424                  *      In the default case, we just move all of the
425                  *      attributes over.
426                  */
427         default:
428                 vps = packet->vps;
429                 packet->vps = NULL;
430                 break;
431                 
432                 /*
433                  *      Accounting responses can only contain
434                  *      Proxy-State and VSA's.  Note that we do NOT
435                  *      move the Proxy-State attributes over, as the
436                  *      Proxy-State attributes in this packet are NOT
437                  *      the right ones to use.  The reply function
438                  *      takes care of copying those attributes from
439                  *      the original request, which ARE the right ones
440                  *      to use.
441                  */
442         case PW_ACCOUNTING_RESPONSE:
443                 pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
444                 break;
445
446                 /*
447                  *      Authentication REJECT's can have only
448                  *      EAP-Message, Message-Authenticator
449                  *      Reply-Message and Proxy-State.
450                  *
451                  *      We delete everything other than these.
452                  *      Proxy-State is added below, just before the
453                  *      reply is sent.
454                  */
455         case PW_AUTHENTICATION_REJECT:
456                 pairmove2(&vps, &(packet->vps), PW_EAP_MESSAGE);
457                 pairmove2(&vps, &(packet->vps), PW_MESSAGE_AUTHENTICATOR);
458                 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
459                 pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
460                 break;
461         }
462
463         /*
464          *      Move the newly cleaned attributes over.
465          */
466         pairfree(&packet->vps);
467         packet->vps = vps;
468
469         /*
470          *      FIXME: Perform other, more generic sanity checks.
471          */
472 }
473
474
475 /*
476  *  Reject a request, by sending a trivial reply packet.
477  */
478  void request_reject(REQUEST *request)
479 {
480         VALUE_PAIR *vps;
481
482         /*
483          *      Already rejected.  Don't do anything.
484          */
485         if (request->options & RAD_REQUEST_OPTION_REJECTED) {
486                 return;
487         }
488         
489         DEBUG2("Server rejecting request %d.", request->number);
490         switch (request->packet->code) {
491                 /*
492                  *  Accounting requests, etc. get dropped on the floor.
493                  */
494                 default:
495                 case PW_ACCOUNTING_REQUEST:
496                 case PW_STATUS_SERVER:
497                         break;
498
499                 /*
500                  *  Authentication requests get their Proxy-State
501                  *  attributes copied over, and an otherwise blank
502                  *  reject message sent.
503                  */
504                 case PW_AUTHENTICATION_REQUEST:
505                         request->reply->code = PW_AUTHENTICATION_REJECT; 
506
507                         /*
508                          *  Perform RFC limitations on outgoing replies.
509                          */
510                         rfc_clean(request->reply);
511
512                         /*
513                          *  Need to copy Proxy-State from request->packet->vps
514                          */
515                         vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
516                         if (vps != NULL)
517                                 pairadd(&(request->reply->vps), vps);
518                         break;
519         }
520         
521         /*
522          *  If a reply exists, send it.
523          */
524         if (request->reply->code != 0) {
525                 /*
526                  *      If we're not delaying authentication rejects,
527                  *      then send the response immediately.  Otherwise,
528                  *      mark the request as delayed, and do NOT send a
529                  *      response.
530                  */
531                 if (mainconfig.reject_delay == 0) {
532                         rad_send(request->reply, request->packet,
533                                  request->secret);
534                 } else {
535                         request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
536                 }
537         }
538
539         /*
540          *      Remember that it was rejected.
541          */
542         request->options |= RAD_REQUEST_OPTION_REJECTED;
543 }