a5777d3d160b7e605191c845b0235b75a02bd589
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/rad_assert.h>
28
29 #include <ctype.h>
30 #include <signal.h>
31
32 #include <sys/stat.h>
33 #include <fcntl.h>
34
35 /*
36  *      The signal() function in Solaris 2.5.1 sets SA_NODEFER in
37  *      sa_flags, which causes grief if signal() is called in the
38  *      handler before the cause of the signal has been cleared.
39  *      (Infinite recursion).
40  *
41  *      The same problem appears on HPUX, so we avoid it, if we can.
42  *
43  *      Using sigaction() to reset the signal handler fixes the problem,
44  *      so where available, we prefer that solution.
45  */
46
47 void (*reset_signal(int signo, void (*func)(int)))(int)
48 {
49 #ifdef HAVE_SIGACTION
50         struct sigaction act, oact;
51
52         memset(&act, 0, sizeof(act));
53         act.sa_handler = func;
54         sigemptyset(&act.sa_mask);
55         act.sa_flags = 0;
56 #ifdef  SA_INTERRUPT            /* SunOS */
57         act.sa_flags |= SA_INTERRUPT;
58 #endif
59         if (sigaction(signo, &act, &oact) < 0)
60                 return SIG_ERR;
61         return oact.sa_handler;
62 #else
63
64         /*
65          *      re-set by calling the 'signal' function, which
66          *      may cause infinite recursion and core dumps due to
67          *      stack growth.
68          *
69          *      However, the system is too dumb to implement sigaction(),
70          *      so we don't have a choice.
71          */
72         signal(signo, func);
73
74         return NULL;
75 #endif
76 }
77
78 /*
79  *      Per-request data, added by modules...
80  */
81 struct request_data_t {
82         request_data_t  *next;
83
84         void            *unique_ptr;
85         int             unique_int;
86         void            *opaque;
87         void            (*free_opaque)(void *);
88 };
89
90 /*
91  *      Add opaque data (with a "free" function) to a REQUEST.
92  *
93  *      The unique ptr is meant to be a malloc'd module configuration,
94  *      and the unique integer allows the caller to have multiple
95  *      opaque data associated with a REQUEST.
96  */
97 int request_data_add(REQUEST *request,
98                      void *unique_ptr, int unique_int,
99                      void *opaque, void (*free_opaque)(void *))
100 {
101         request_data_t *this, **last, *next;
102
103         /*
104          *      Some simple sanity checks.
105          */
106         if (!request || !opaque) return -1;
107
108         this = next = NULL;
109         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
110                 if (((*last)->unique_ptr == unique_ptr) &&
111                     ((*last)->unique_int == unique_int)) {
112                         this = *last;
113
114                         next = this->next;
115
116                         if (this->opaque && /* free it, if necessary */
117                             this->free_opaque)
118                                 this->free_opaque(this->opaque);
119                         break;  /* replace the existing entry */
120                 }
121         }
122
123         if (!this) this = rad_malloc(sizeof(*this));
124         memset(this, 0, sizeof(*this));
125
126         this->next = next;
127         this->unique_ptr = unique_ptr;
128         this->unique_int = unique_int;
129         this->opaque = opaque;
130         this->free_opaque = free_opaque;
131
132         *last = this;
133
134         return 0;
135 }
136
137
138 /*
139  *      Get opaque data from a request.
140  */
141 void *request_data_get(REQUEST *request,
142                        void *unique_ptr, int unique_int)
143 {
144         request_data_t **last;
145
146         if (!request) return NULL;
147
148         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
149                 if (((*last)->unique_ptr == unique_ptr) &&
150                     ((*last)->unique_int == unique_int)) {
151                         request_data_t *this = *last;
152                         void *ptr = this->opaque;
153
154                         /*
155                          *      Remove the entry from the list, and free it.
156                          */
157                         *last = this->next;
158                         free(this);
159                         return ptr; /* don't free it, the caller does that */
160                 }
161         }
162
163         return NULL;            /* wasn't found, too bad... */
164 }
165
166
167 /*
168  *      Get opaque data from a request without removing it.
169  */
170 void *request_data_reference(REQUEST *request,
171                        void *unique_ptr, int unique_int)
172 {
173         request_data_t **last;
174
175         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
176                 if (((*last)->unique_ptr == unique_ptr) &&
177                     ((*last)->unique_int == unique_int)) {
178                         request_data_t *this = *last;
179                         void *ptr = this->opaque;
180
181                         return ptr;
182                 }
183         }
184
185         return NULL;            /* wasn't found, too bad... */
186 }
187
188
189 /*
190  *      Free a REQUEST struct.
191  */
192 void request_free(REQUEST **request_ptr)
193 {
194         REQUEST *request;
195
196         if (!request_ptr || !*request_ptr) {
197                 return;
198         }
199
200         request = *request_ptr;
201
202         rad_assert(!request->in_request_hash);
203 #ifdef WITH_PROXY
204         rad_assert(!request->in_proxy_hash);
205 #endif
206         rad_assert(!request->ev);
207
208         if (request->packet)
209                 rad_free(&request->packet);
210
211 #ifdef WITH_PROXY
212         if (request->proxy)
213                 rad_free(&request->proxy);
214 #endif
215
216         if (request->reply)
217                 rad_free(&request->reply);
218
219 #ifdef WITH_PROXY
220         if (request->proxy_reply)
221                 rad_free(&request->proxy_reply);
222 #endif
223
224         if (request->config_items)
225                 pairfree(&request->config_items);
226
227         request->username = NULL;
228         request->password = NULL;
229
230         if (request->data) {
231                 request_data_t *this, *next;
232
233                 for (this = request->data; this != NULL; this = next) {
234                         next = this->next;
235                         if (this->opaque && /* free it, if necessary */
236                             this->free_opaque)
237                                 this->free_opaque(this->opaque);
238                         free(this);
239                 }
240                 request->data = NULL;
241         }
242
243         if (request->root &&
244             (request->root->refcount > 0)) {
245                 request->root->refcount--;
246                 request->root = NULL;
247         }
248
249 #ifdef WITH_COA
250         if (request->coa) {
251                 request->coa->parent = NULL;
252                 rad_assert(request->coa->ev == NULL);
253                 request_free(&request->coa);
254         }
255
256         if (request->parent && (request->parent->coa == request)) {
257                 request->parent->coa = NULL;
258         }
259 #endif
260
261 #ifndef NDEBUG
262         request->magic = 0x01020304;    /* set the request to be nonsense */
263 #endif
264         request->client = NULL;
265 #ifdef WITH_PROXY
266         request->home_server = NULL;
267 #endif
268         talloc_free(request);
269         *request_ptr = NULL;
270 }
271
272 /*
273  *      Check a filename for sanity.
274  *
275  *      Allow only uppercase/lowercase letters, numbers, and '-_/.'
276  */
277 int rad_checkfilename(const char *filename)
278 {
279         if (strspn(filename, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/.") == strlen(filename)) {
280                 return 0;
281         }
282
283         return -1;
284 }
285
286 /*
287  *      Create possibly many directories.
288  *
289  *      Note that the input directory name is NOT a constant!
290  *      This is so that IF an error is returned, the 'directory' ptr
291  *      points to the name of the file which caused the error.
292  */
293 int rad_mkdir(char *directory, mode_t mode)
294 {
295         int rcode;
296         char *p;
297         struct stat st;
298
299         /*
300          *      If the directory exists, don't do anything.
301          */
302         if (stat(directory, &st) == 0) {
303                 return 0;
304         }
305
306         /*
307          *      Look for the LAST directory name.  Try to create that,
308          *      failing on any error.
309          */
310         p = strrchr(directory, FR_DIR_SEP);
311         if (p != NULL) {
312                 *p = '\0';
313                 rcode = rad_mkdir(directory, mode);
314
315                 /*
316                  *      On error, we leave the directory name as the
317                  *      one which caused the error.
318                  */
319                 if (rcode < 0) {
320                         if (errno == EEXIST) return 0;
321                         return rcode;
322                 }
323
324                 /*
325                  *      Reset the directory delimiter, and go ask
326                  *      the system to make the directory.
327                  */
328                 *p = FR_DIR_SEP;
329         } else {
330                 return 0;
331         }
332
333         /*
334          *      Having done everything successfully, we do the
335          *      system call to actually go create the directory.
336          */
337         rcode = mkdir(directory, mode & 0777);
338         if (rcode < 0) {
339                 return rcode;
340         }
341         
342         /*
343          *      Set things like sticky bits that aren't supported by
344          *      mkdir.
345          */
346         if (mode & ~0777) {
347                 rcode = chmod(directory, mode);
348         }
349         
350         return rcode;
351 }
352
353
354 /*
355  *      Module malloc() call, which does stuff if the malloc fails.
356  *
357  *      This call ALWAYS succeeds!
358  */
359 void *rad_malloc(size_t size)
360 {
361         void *ptr = malloc(size);
362
363         if (ptr == NULL) {
364                 radlog(L_ERR, "no memory");
365                 exit(1);
366         }
367
368         return ptr;
369 }
370
371
372 void *rad_calloc(size_t size)
373 {
374         void *ptr = rad_malloc(size);
375         memset(ptr, 0, size);
376         return ptr;
377 }
378
379 void rad_const_free(const void *ptr)
380 {
381         void *tmp;
382         if (!ptr) return;
383
384         memcpy(&tmp, &ptr, sizeof(tmp));
385         talloc_free(tmp);
386 }
387
388
389 /*
390  *      Signature for free is dumb, and raises errors when we try
391  *      to free const ptrs.
392  */
393 void rad_cfree(const void *ptr)
394 {
395         void *tmp;
396         if (!ptr) return;
397
398         memcpy(&tmp, &ptr, sizeof(tmp));
399         free(tmp);
400 }
401
402 /*
403  *      Logs an error message and aborts the program
404  *
405  */
406
407 void NEVER_RETURNS rad_assert_fail (const char *file, unsigned int line,
408                                     const char *expr)
409 {
410         radlog(L_ERR, "ASSERT FAILED %s[%u]: %s", file, line, expr);
411         abort();
412 }
413
414
415 /*
416  *      Create a new REQUEST data structure.
417  */
418 REQUEST *request_alloc(void)
419 {
420         REQUEST *request;
421
422         request = talloc_zero(NULL, REQUEST);
423 #ifndef NDEBUG
424         request->magic = REQUEST_MAGIC;
425 #endif
426 #ifdef WITH_PROXY
427         request->proxy = NULL;
428 #endif
429         request->reply = NULL;
430 #ifdef WITH_PROXY
431         request->proxy_reply = NULL;
432 #endif
433         request->config_items = NULL;
434         request->username = NULL;
435         request->password = NULL;
436         request->timestamp = time(NULL);
437         request->options = debug_flag; /* Default to global debug level */
438
439         request->module = "";
440         request->component = "<core>";
441         if (debug_flag) request->radlog = radlog_request;
442
443         return request;
444 }
445
446
447 /*
448  *      Create a new REQUEST, based on an old one.
449  *
450  *      This function allows modules to inject fake requests
451  *      into the server, for tunneled protocols like TTLS & PEAP.
452  */
453 REQUEST *request_alloc_fake(REQUEST *request)
454 {
455   REQUEST *fake;
456
457   fake = request_alloc();
458
459   fake->number = request->number;
460 #ifdef HAVE_PTHREAD_H
461   fake->child_pid = request->child_pid;
462 #endif
463   fake->parent = request;
464   fake->root = request->root;
465   fake->client = request->client;
466
467   /*
468    *    For new server support.
469    *
470    *    FIXME: Key instead off of a "virtual server" data structure.
471    *
472    *    FIXME: Permit different servers for inner && outer sessions?
473    */
474   fake->server = request->server;
475
476   fake->packet = rad_alloc(request, 1);
477   if (!fake->packet) {
478           request_free(&fake);
479           return NULL;
480   }
481
482   fake->reply = rad_alloc(request, 0);
483   if (!fake->reply) {
484           request_free(&fake);
485           return NULL;
486   }
487
488   fake->master_state = REQUEST_ACTIVE;
489   fake->child_state = REQUEST_RUNNING;
490
491   /*
492    *    Fill in the fake request.
493    */
494   fake->packet->sockfd = -1;
495   fake->packet->src_ipaddr = request->packet->src_ipaddr;
496   fake->packet->src_port = request->packet->src_port;
497   fake->packet->dst_ipaddr = request->packet->dst_ipaddr;
498   fake->packet->dst_port = 0;
499
500   /*
501    *    This isn't STRICTLY required, as the fake request MUST NEVER
502    *    be put into the request list.  However, it's still reasonable
503    *    practice.
504    */
505   fake->packet->id = fake->number & 0xff;
506   fake->packet->code = request->packet->code;
507   fake->timestamp = request->timestamp;
508  
509   /*
510    *    Required for new identity support
511    */
512   fake->listener = request->listener;
513
514   /*
515    *    Fill in the fake reply, based on the fake request.
516    */
517   fake->reply->sockfd = fake->packet->sockfd;
518   fake->reply->src_ipaddr = fake->packet->dst_ipaddr;
519   fake->reply->src_port = fake->packet->dst_port;
520   fake->reply->dst_ipaddr = fake->packet->src_ipaddr;
521   fake->reply->dst_port = fake->packet->src_port;
522   fake->reply->id = fake->packet->id;
523   fake->reply->code = 0; /* UNKNOWN code */
524
525   /*
526    *    Copy debug information.
527    */
528   fake->options = request->options;
529   fake->radlog = request->radlog;
530
531   return fake;
532 }
533
534 #ifdef WITH_COA
535 REQUEST *request_alloc_coa(REQUEST *request)
536 {
537         if (!request || request->coa) return NULL;
538
539         /*
540          *      Originate CoA requests only when necessary.
541          */
542         if ((request->packet->code != PW_AUTHENTICATION_REQUEST) &&
543             (request->packet->code != PW_ACCOUNTING_REQUEST)) return NULL;
544
545         request->coa = request_alloc_fake(request);
546         if (!request->coa) return NULL;
547
548         request->coa->packet->code = 0; /* unknown, as of yet */
549         request->coa->child_state = REQUEST_RUNNING;
550         request->coa->proxy = rad_alloc(request->coa, 0);
551         if (!request->coa->proxy) {
552                 request_free(&request->coa);
553                 return NULL;
554         }
555
556         return request->coa;
557 }
558 #endif
559
560 /*
561  *      Copy a quoted string.
562  */
563 int rad_copy_string(char *to, const char *from)
564 {
565         int length = 0;
566         char quote = *from;
567
568         do {
569                 if (*from == '\\') {
570                         *(to++) = *(from++);
571                         length++;
572                 }
573                 *(to++) = *(from++);
574                 length++;
575         } while (*from && (*from != quote));
576
577         if (*from != quote) return -1; /* not properly quoted */
578
579         *(to++) = quote;
580         length++;
581         *to = '\0';
582
583         return length;
584 }
585
586
587 /*
588  *      Copy a %{} string.
589  */
590 int rad_copy_variable(char *to, const char *from)
591 {
592         int length = 0;
593         int sublen;
594
595         *(to++) = *(from++);
596         length++;
597
598         while (*from) {
599                 switch (*from) {
600                 case '"':
601                 case '\'':
602                         sublen = rad_copy_string(to, from);
603                         if (sublen < 0) return sublen;
604                         from += sublen;
605                         to += sublen;
606                         length += sublen;
607                         break;
608
609                 case '}':       /* end of variable expansion */
610                         *(to++) = *(from++);
611                         *to = '\0';
612                         length++;
613                         return length; /* proper end of variable */
614
615                 case '\\':
616                         *(to++) = *(from++);
617                         *(to++) = *(from++);
618                         length += 2;
619                         break;
620
621                 case '%':       /* start of variable expansion */
622                         if (from[1] == '{') {
623                                 *(to++) = *(from++);
624                                 length++;
625
626                                 sublen = rad_copy_variable(to, from);
627                                 if (sublen < 0) return sublen;
628                                 from += sublen;
629                                 to += sublen;
630                                 length += sublen;
631                                 break;
632                         } /* else FIXME: catch %%{ ?*/
633
634                         /* FALL-THROUGH */
635                 default:
636                         *(to++) = *(from++);
637                         length++;
638                         break;
639                 }
640         } /* loop over the input string */
641
642         /*
643          *      We ended the string before a trailing '}'
644          */
645
646         return -1;
647 }
648
649 #ifndef USEC
650 #define USEC 1000000
651 #endif
652
653 int rad_pps(int *past, int *present, time_t *then, struct timeval *now)
654 {
655         int pps;
656
657         if (*then != now->tv_sec) {
658                 *then = now->tv_sec;
659                 *past = *present;
660                 *present = 0;
661         }
662
663         /*
664          *      Bootstrap PPS by looking at a percentage of
665          *      the previous PPS.  This lets us take a moving
666          *      count, without doing a moving average.  If
667          *      we're a fraction "f" (0..1) into the current
668          *      second, we can get a good guess for PPS by
669          *      doing:
670          *
671          *      PPS = pps_now + pps_old * (1 - f)
672          *
673          *      It's an instantaneous measurement, rather than
674          *      a moving average.  This will hopefully let it
675          *      respond better to sudden spikes.
676          *
677          *      Doing the calculations by thousands allows us
678          *      to not overflow 2^32, AND to not underflow
679          *      when we divide by USEC.
680          */
681         pps = USEC - now->tv_usec; /* useconds left in previous second */
682         pps /= 1000;               /* scale to milliseconds */
683         pps *= *past;              /* multiply by past count to get fraction */
684         pps /= 1000;               /* scale to usec again */
685         pps += *present;           /* add in current count */
686
687         return pps;
688 }