fake->packet has parent fake, not request
[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 RCSID("$Id$")
24
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/rad_assert.h>
27
28 #include <ctype.h>
29
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 /*
34  *      The signal() function in Solaris 2.5.1 sets SA_NODEFER in
35  *      sa_flags, which causes grief if signal() is called in the
36  *      handler before the cause of the signal has been cleared.
37  *      (Infinite recursion).
38  *
39  *      The same problem appears on HPUX, so we avoid it, if we can.
40  *
41  *      Using sigaction() to reset the signal handler fixes the problem,
42  *      so where available, we prefer that solution.
43  */
44
45 void (*reset_signal(int signo, void (*func)(int)))(int)
46 {
47 #ifdef HAVE_SIGACTION
48         struct sigaction act, oact;
49
50         memset(&act, 0, sizeof(act));
51         act.sa_handler = func;
52         sigemptyset(&act.sa_mask);
53         act.sa_flags = 0;
54 #ifdef  SA_INTERRUPT            /* SunOS */
55         act.sa_flags |= SA_INTERRUPT;
56 #endif
57         if (sigaction(signo, &act, &oact) < 0)
58                 return SIG_ERR;
59         return oact.sa_handler;
60 #else
61
62         /*
63          *      re-set by calling the 'signal' function, which
64          *      may cause infinite recursion and core dumps due to
65          *      stack growth.
66          *
67          *      However, the system is too dumb to implement sigaction(),
68          *      so we don't have a choice.
69          */
70         signal(signo, func);
71
72         return NULL;
73 #endif
74 }
75
76 /*
77  *      Per-request data, added by modules...
78  */
79 struct request_data_t {
80         request_data_t  *next;
81
82         void            *unique_ptr;
83         int             unique_int;
84         void            *opaque;
85         bool            free_opaque;
86 };
87
88 /*
89  *      Add opaque data (with a "free" function) to a REQUEST.
90  *
91  *      The unique ptr is meant to be a module configuration,
92  *      and the unique integer allows the caller to have multiple
93  *      opaque data associated with a REQUEST.
94  */
95 int request_data_add(REQUEST *request,
96                      void *unique_ptr, int unique_int,
97                      void *opaque, bool free_opaque)
98 {
99         request_data_t *this, **last, *next;
100
101         /*
102          *      Some simple sanity checks.
103          */
104         if (!request || !opaque) return -1;
105
106         this = next = NULL;
107         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
108                 if (((*last)->unique_ptr == unique_ptr) &&
109                     ((*last)->unique_int == unique_int)) {
110                         this = *last;
111
112                         next = this->next;
113
114                         /*
115                          *      If caller requires custom behaviour on free
116                          *      they must set a destructor.
117                          */
118                         if (this->opaque && this->free_opaque) {
119                                 talloc_free(this->opaque);
120                         }
121                         break;                          /* replace the existing entry */
122                 }
123         }
124
125         if (!this) this = talloc_zero(request, request_data_t);
126
127         this->next = next;
128         this->unique_ptr = unique_ptr;
129         this->unique_int = unique_int;
130         this->opaque = opaque;
131         if (free_opaque) {
132                 this->free_opaque = free_opaque;
133         }
134
135         *last = this;
136
137         return 0;
138 }
139
140
141 /*
142  *      Get opaque data from a request.
143  */
144 void *request_data_get(REQUEST *request,
145                        void *unique_ptr, int unique_int)
146 {
147         request_data_t **last;
148
149         if (!request) return NULL;
150
151         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
152                 if (((*last)->unique_ptr == unique_ptr) &&
153                     ((*last)->unique_int == unique_int)) {
154                         request_data_t *this = *last;
155                         void *ptr = this->opaque;
156
157                         /*
158                          *      Remove the entry from the list, and free it.
159                          */
160                         *last = this->next;
161                         talloc_free(this);
162                         return ptr;             /* don't free it, the caller does that */
163                 }
164         }
165
166         return NULL;            /* wasn't found, too bad... */
167 }
168
169
170 /*
171  *      Get opaque data from a request without removing it.
172  */
173 void *request_data_reference(REQUEST *request,
174                        void *unique_ptr, int unique_int)
175 {
176         request_data_t **last;
177
178         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
179                 if (((*last)->unique_ptr == unique_ptr) &&
180                     ((*last)->unique_int == unique_int)) {
181                         request_data_t *this = *last;
182                         void *ptr = this->opaque;
183
184                         return ptr;
185                 }
186         }
187
188         return NULL;            /* wasn't found, too bad... */
189 }
190
191 /*
192  *      Free a REQUEST struct.
193  */
194 void request_free(REQUEST **request_ptr)
195 {
196         REQUEST *request;
197
198         if (!request_ptr || !*request_ptr) {
199                 return;
200         }
201
202         request = *request_ptr;
203
204         rad_assert(!request->in_request_hash);
205 #ifdef WITH_PROXY
206         rad_assert(!request->in_proxy_hash);
207 #endif
208         rad_assert(!request->ev);
209
210 #ifdef WITH_COA
211         if (request->coa) {
212                 request->coa->parent = NULL;
213                 request_free(&request->coa);
214         }
215
216         if (request->parent && (request->parent->coa == request)) {
217                 request->parent->coa = NULL;
218         }
219 #endif
220
221 #ifndef NDEBUG
222         request->magic = 0x01020304;    /* set the request to be nonsense */
223 #endif
224         request->client = NULL;
225 #ifdef WITH_PROXY
226         request->home_server = NULL;
227 #endif
228         talloc_free(request);
229         *request_ptr = NULL;
230
231         VERIFY_ALL_TALLOC;
232 }
233
234 /*
235  *      Free a request.
236  */
237 int request_opaque_free(REQUEST *request)
238 {
239         request_free(&request);
240
241         return 0;
242 }
243
244 /*
245  *      Check a filename for sanity.
246  *
247  *      Allow only uppercase/lowercase letters, numbers, and '-_/.'
248  */
249 int rad_checkfilename(char const *filename)
250 {
251         if (strspn(filename, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/.") == strlen(filename)) {
252                 return 0;
253         }
254
255         return -1;
256 }
257
258 /** Check if file exists
259  *
260  * @param filename to check.
261  * @return 0 if the file does not exist, 1 if the file exists, -1 if the file
262  *      exists but there was an error opening it. errno value should be usable
263  *      for error messages.
264  */
265 int rad_file_exists(char const *filename)
266 {
267         int des;
268         int ret = 1;
269
270         if ((des = open(filename, O_RDONLY)) == -1) {
271                 if (errno == ENOENT) {
272                         ret = 0;
273                 } else {
274                         ret = -1;
275                 }
276         } else {
277                 close(des);
278         }
279
280         return ret;
281 }
282
283 /*
284  *      Create possibly many directories.
285  *
286  *      Note that the input directory name is NOT a constant!
287  *      This is so that IF an error is returned, the 'directory' ptr
288  *      points to the name of the file which caused the error.
289  */
290 int rad_mkdir(char *directory, mode_t mode)
291 {
292         int rcode;
293         char *p;
294         struct stat st;
295
296         /*
297          *      If the directory exists, don't do anything.
298          */
299         if (stat(directory, &st) == 0) {
300                 return 0;
301         }
302
303         /*
304          *      Look for the LAST directory name.  Try to create that,
305          *      failing on any error.
306          */
307         p = strrchr(directory, FR_DIR_SEP);
308         if (p != NULL) {
309                 *p = '\0';
310                 rcode = rad_mkdir(directory, mode);
311
312                 /*
313                  *      On error, we leave the directory name as the
314                  *      one which caused the error.
315                  */
316                 if (rcode < 0) {
317                         if (errno == EEXIST) return 0;
318                         return rcode;
319                 }
320
321                 /*
322                  *      Reset the directory delimiter, and go ask
323                  *      the system to make the directory.
324                  */
325                 *p = FR_DIR_SEP;
326         } else {
327                 return 0;
328         }
329
330         /*
331          *      Having done everything successfully, we do the
332          *      system call to actually go create the directory.
333          */
334         rcode = mkdir(directory, mode & 0777);
335         if (rcode < 0) {
336                 return rcode;
337         }
338
339         /*
340          *      Set things like sticky bits that aren't supported by
341          *      mkdir.
342          */
343         if (mode & ~0777) {
344                 rcode = chmod(directory, mode);
345         }
346
347         return rcode;
348 }
349
350
351 /*
352  *      Allocate memory, or exit.
353  *
354  *      This call ALWAYS succeeds!
355  */
356 void *rad_malloc(size_t size)
357 {
358         void *ptr = malloc(size);
359
360         if (ptr == NULL) {
361                 ERROR("no memory");
362                 fr_exit(1);
363         }
364
365         return ptr;
366 }
367
368
369 void *rad_calloc(size_t size)
370 {
371         void *ptr = rad_malloc(size);
372         memset(ptr, 0, size);
373         return ptr;
374 }
375
376 void rad_const_free(void const *ptr)
377 {
378         void *tmp;
379         if (!ptr) return;
380
381         memcpy(&tmp, &ptr, sizeof(tmp));
382         talloc_free(tmp);
383 }
384
385
386 /*
387  *      Logs an error message and aborts the program
388  *
389  */
390
391 void NEVER_RETURNS rad_assert_fail(char const *file, unsigned int line, char const *expr)
392 {
393         ERROR("ASSERT FAILED %s[%u]: %s", file, line, expr);
394         abort();
395 }
396
397
398 /*
399  *      Create a new REQUEST data structure.
400  */
401 REQUEST *request_alloc(TALLOC_CTX *ctx)
402 {
403         REQUEST *request;
404
405         request = talloc_zero(ctx, REQUEST);
406 #ifndef NDEBUG
407         request->magic = REQUEST_MAGIC;
408 #endif
409 #ifdef WITH_PROXY
410         request->proxy = NULL;
411 #endif
412         request->reply = NULL;
413 #ifdef WITH_PROXY
414         request->proxy_reply = NULL;
415 #endif
416         request->config_items = NULL;
417         request->username = NULL;
418         request->password = NULL;
419         request->timestamp = time(NULL);
420         request->options = debug_flag; /* Default to global debug level */
421
422         request->module = "";
423         request->component = "<core>";
424         request->radlog = vradlog_request;
425
426         return request;
427 }
428
429
430 /*
431  *      Create a new REQUEST, based on an old one.
432  *
433  *      This function allows modules to inject fake requests
434  *      into the server, for tunneled protocols like TTLS & PEAP.
435  */
436 REQUEST *request_alloc_fake(REQUEST *request)
437 {
438         REQUEST *fake;
439
440         fake = request_alloc(request);
441
442         fake->number = request->number;
443 #ifdef HAVE_PTHREAD_H
444         fake->child_pid = request->child_pid;
445 #endif
446         fake->parent = request;
447         fake->root = request->root;
448         fake->client = request->client;
449
450         /*
451          *      For new server support.
452          *
453          *      FIXME: Key instead off of a "virtual server" data structure.
454          *
455          *      FIXME: Permit different servers for inner && outer sessions?
456          */
457         fake->server = request->server;
458
459         fake->packet = rad_alloc(fake, 1);
460         if (!fake->packet) {
461                 request_free(&fake);
462                 return NULL;
463         }
464
465         fake->reply = rad_alloc(fake, 0);
466         if (!fake->reply) {
467                 request_free(&fake);
468                 return NULL;
469         }
470
471         fake->master_state = REQUEST_ACTIVE;
472         fake->child_state = REQUEST_RUNNING;
473
474         /*
475          *      Fill in the fake request.
476          */
477         fake->packet->sockfd = -1;
478         fake->packet->src_ipaddr = request->packet->src_ipaddr;
479         fake->packet->src_port = request->packet->src_port;
480         fake->packet->dst_ipaddr = request->packet->dst_ipaddr;
481         fake->packet->dst_port = 0;
482
483         /*
484          *      This isn't STRICTLY required, as the fake request MUST NEVER
485          *      be put into the request list.  However, it's still reasonable
486          *      practice.
487          */
488         fake->packet->id = fake->number & 0xff;
489         fake->packet->code = request->packet->code;
490         fake->timestamp = request->timestamp;
491         fake->packet->timestamp = request->packet->timestamp;
492
493         /*
494          *      Required for new identity support
495          */
496         fake->listener = request->listener;
497
498         /*
499          *      Fill in the fake reply, based on the fake request.
500          */
501         fake->reply->sockfd = fake->packet->sockfd;
502         fake->reply->src_ipaddr = fake->packet->dst_ipaddr;
503         fake->reply->src_port = fake->packet->dst_port;
504         fake->reply->dst_ipaddr = fake->packet->src_ipaddr;
505         fake->reply->dst_port = fake->packet->src_port;
506         fake->reply->id = fake->packet->id;
507         fake->reply->code = 0; /* UNKNOWN code */
508
509         /*
510          *      Copy debug information.
511          */
512         fake->options = request->options;
513         fake->radlog = request->radlog;
514
515         return fake;
516 }
517
518 #ifdef WITH_COA
519 REQUEST *request_alloc_coa(REQUEST *request)
520 {
521         if (!request || request->coa) return NULL;
522
523         /*
524          *      Originate CoA requests only when necessary.
525          */
526         if ((request->packet->code != PW_CODE_AUTHENTICATION_REQUEST) &&
527             (request->packet->code != PW_CODE_ACCOUNTING_REQUEST)) return NULL;
528
529         request->coa = request_alloc_fake(request);
530         if (!request->coa) return NULL;
531
532         request->coa->packet->code = 0; /* unknown, as of yet */
533         request->coa->child_state = REQUEST_RUNNING;
534         request->coa->proxy = rad_alloc(request->coa, 0);
535         if (!request->coa->proxy) {
536                 request_free(&request->coa);
537                 return NULL;
538         }
539
540         return request->coa;
541 }
542 #endif
543
544 /*
545  *      Copy a quoted string.
546  */
547 int rad_copy_string(char *to, char const *from)
548 {
549         int length = 0;
550         char quote = *from;
551
552         do {
553                 if (*from == '\\') {
554                         *(to++) = *(from++);
555                         length++;
556                 }
557                 *(to++) = *(from++);
558                 length++;
559         } while (*from && (*from != quote));
560
561         if (*from != quote) return -1; /* not properly quoted */
562
563         *(to++) = quote;
564         length++;
565         *to = '\0';
566
567         return length;
568 }
569
570 /*
571  *      Copy a quoted string but without the quotes. The length
572  *      returned is the number of chars written; the number of
573  *      characters consumed is 2 more than this.
574  */
575 int rad_copy_string_bare(char *to, char const *from)
576 {
577         int length = 0;
578         char quote = *from;
579
580         from++;
581         while (*from && (*from != quote)) {
582                 if (*from == '\\') {
583                         *(to++) = *(from++);
584                         length++;
585                 }
586                 *(to++) = *(from++);
587                 length++;
588         }
589
590         if (*from != quote) return -1; /* not properly quoted */
591
592         *to = '\0';
593
594         return length;
595 }
596
597
598 /*
599  *      Copy a %{} string.
600  */
601 int rad_copy_variable(char *to, char const *from)
602 {
603         int length = 0;
604         int sublen;
605
606         *(to++) = *(from++);
607         length++;
608
609         while (*from) {
610                 switch (*from) {
611                 case '"':
612                 case '\'':
613                         sublen = rad_copy_string(to, from);
614                         if (sublen < 0) return sublen;
615                         from += sublen;
616                         to += sublen;
617                         length += sublen;
618                         break;
619
620                 case '}':       /* end of variable expansion */
621                         *(to++) = *(from++);
622                         *to = '\0';
623                         length++;
624                         return length; /* proper end of variable */
625
626                 case '\\':
627                         *(to++) = *(from++);
628                         *(to++) = *(from++);
629                         length += 2;
630                         break;
631
632                 case '%':       /* start of variable expansion */
633                         if (from[1] == '{') {
634                                 *(to++) = *(from++);
635                                 length++;
636
637                                 sublen = rad_copy_variable(to, from);
638                                 if (sublen < 0) return sublen;
639                                 from += sublen;
640                                 to += sublen;
641                                 length += sublen;
642                                 break;
643                         } /* else FIXME: catch %%{ ?*/
644
645                         /* FALL-THROUGH */
646                 default:
647                         *(to++) = *(from++);
648                         length++;
649                         break;
650                 }
651         } /* loop over the input string */
652
653         /*
654          *      We ended the string before a trailing '}'
655          */
656
657         return -1;
658 }
659
660 #ifndef USEC
661 #define USEC 1000000
662 #endif
663
664 int rad_pps(int *past, int *present, time_t *then, struct timeval *now)
665 {
666         int pps;
667
668         if (*then != now->tv_sec) {
669                 *then = now->tv_sec;
670                 *past = *present;
671                 *present = 0;
672         }
673
674         /*
675          *      Bootstrap PPS by looking at a percentage of
676          *      the previous PPS.  This lets us take a moving
677          *      count, without doing a moving average.  If
678          *      we're a fraction "f" (0..1) into the current
679          *      second, we can get a good guess for PPS by
680          *      doing:
681          *
682          *      PPS = pps_now + pps_old * (1 - f)
683          *
684          *      It's an instantaneous measurement, rather than
685          *      a moving average.  This will hopefully let it
686          *      respond better to sudden spikes.
687          *
688          *      Doing the calculations by thousands allows us
689          *      to not overflow 2^32, AND to not underflow
690          *      when we divide by USEC.
691          */
692         pps = USEC - now->tv_usec; /* useconds left in previous second */
693         pps /= 1000;               /* scale to milliseconds */
694         pps *= *past;              /* multiply by past count to get fraction */
695         pps /= 1000;               /* scale to usec again */
696         pps += *present;           /* add in current count */
697
698         return pps;
699 }
700
701 /** Split string into words and expand each one
702  *
703  * @param request Current request.
704  * @param cmd string to split.
705  * @param max_argc the maximum number of arguments to split into.
706  * @param argv Where to write the pointers into argv_buf.
707  * @param can_fail If false, stop processing if any of the xlat expansions fail.
708  * @param argv_buflen size of argv_buf.
709  * @param argv_buf temporary buffer we used to mangle/expand cmd.
710  *      Pointers to offsets of this buffer will be written to argv.
711  * @return argc or -1 on failure.
712  */
713
714 int rad_expand_xlat(REQUEST *request, char const *cmd,
715                     int max_argc, char *argv[], bool can_fail,
716                     size_t argv_buflen, char *argv_buf)
717 {
718         char const *from;
719         char *to;
720         int argc = -1;
721         int i;
722         int left;
723
724         if (strlen(cmd) > (argv_buflen - 1)) {
725                 ERROR("rad_expand_xlat: Command line is too long");
726                 return -1;
727         }
728
729         /*
730          *      Check for bad escapes.
731          */
732         if (cmd[strlen(cmd) - 1] == '\\') {
733                 ERROR("rad_expand_xlat: Command line has final backslash, without a following character");
734                 return -1;
735         }
736
737         strlcpy(argv_buf, cmd, argv_buflen);
738
739         /*
740          *      Split the string into argv's BEFORE doing radius_xlat...
741          */
742         from = cmd;
743         to = argv_buf;
744         argc = 0;
745         while (*from) {
746                 int length;
747
748                 /*
749                  *      Skip spaces.
750                  */
751                 if ((*from == ' ') || (*from == '\t')) {
752                         from++;
753                         continue;
754                 }
755
756                 argv[argc] = to;
757                 argc++;
758
759                 if (argc >= (max_argc - 1)) break;
760
761                 /*
762                  *      Copy the argv over to our buffer.
763                  */
764                 while (*from && (*from != ' ') && (*from != '\t')) {
765                         if (to >= argv_buf + argv_buflen - 1) {
766                                 ERROR("rad_expand_xlat: Ran out of space in command line");
767                                 return -1;
768                         }
769
770                         switch (*from) {
771                         case '"':
772                         case '\'':
773                                 length = rad_copy_string_bare(to, from);
774                                 if (length < 0) {
775                                         ERROR("rad_expand_xlat: Invalid string passed as argument");
776                                         return -1;
777                                 }
778                                 from += length+2;
779                                 to += length;
780                                 break;
781
782                         case '%':
783                                 if (from[1] == '{') {
784                                         *(to++) = *(from++);
785
786                                         length = rad_copy_variable(to, from);
787                                         if (length < 0) {
788                                                 ERROR("rad_expand_xlat: Invalid variable expansion passed as argument");
789                                                 return -1;
790                                         }
791                                         from += length;
792                                         to += length;
793                                 } else { /* FIXME: catch %%{ ? */
794                                         *(to++) = *(from++);
795                                 }
796                                 break;
797
798                         case '\\':
799                                 if (from[1] == ' ') from++;
800                                 /* FALL-THROUGH */
801
802                         default:
803                                 *(to++) = *(from++);
804                         }
805                 } /* end of string, or found a space */
806
807                 *(to++) = '\0'; /* terminate the string */
808         }
809
810         /*
811          *      We have to have SOMETHING, at least.
812          */
813         if (argc <= 0) {
814                 ERROR("rad_expand_xlat: Empty command line.");
815                 return -1;
816         }
817
818         /*
819          *      Expand each string, as appropriate.
820          */
821         left = argv_buf + argv_buflen - to;
822         for (i = 0; i < argc; i++) {
823                 int sublen;
824
825                 /*
826                  *      Don't touch argv's which won't be translated.
827                  */
828                 if (strchr(argv[i], '%') == NULL) continue;
829
830                 if (!request) continue;
831
832                 sublen = radius_xlat(to, left - 1, request, argv[i], NULL, NULL);
833                 if (sublen <= 0) {
834                         if (can_fail) {
835                                 /*
836                                  *      Fail to be backwards compatible.
837                                  *
838                                  *      It's yucky, but it won't break anything,
839                                  *      and it won't cause security problems.
840                                  */
841                                 sublen = 0;
842                         } else {
843                                 ERROR("rad_expand_xlat: xlat failed");
844                                 return -1;
845                         }
846                 }
847
848                 argv[i] = to;
849                 to += sublen;
850                 *(to++) = '\0';
851                 left -= sublen;
852                 left--;
853
854                 if (left <= 0) {
855                         ERROR("rad_expand_xlat: Ran out of space while expanding arguments.");
856                         return -1;
857                 }
858         }
859         argv[argc] = NULL;
860
861         return argc;
862 }
863
864 const FR_NAME_NUMBER pair_lists[] = {
865         { "request",            PAIR_LIST_REQUEST },
866         { "reply",              PAIR_LIST_REPLY },
867         { "config",             PAIR_LIST_CONTROL },
868         { "control",            PAIR_LIST_CONTROL },
869 #ifdef WITH_PROXY
870         { "proxy-request",      PAIR_LIST_PROXY_REQUEST },
871         { "proxy-reply",        PAIR_LIST_PROXY_REPLY },
872 #endif
873 #ifdef WITH_COA
874         { "coa",                PAIR_LIST_COA },
875         { "coa-reply",          PAIR_LIST_COA_REPLY },
876         { "disconnect",         PAIR_LIST_DM },
877         { "disconnect-reply",   PAIR_LIST_DM_REPLY },
878 #endif
879         {  NULL , -1 }
880 };
881
882 const FR_NAME_NUMBER request_refs[] = {
883         { "outer",              REQUEST_OUTER },
884         { "current",            REQUEST_CURRENT },
885         { "parent",             REQUEST_PARENT },
886         {  NULL , -1 }
887 };
888
889
890 /** Resolve attribute name to a list.
891  *
892  * Check the name string for qualifiers that specify a list and return
893  * an pair_lists_t value for that list. This value may be passed to
894  * radius_list, along with the current request, to get a pointer to the
895  * actual list in the request.
896  *
897  * If qualifiers were consumed, write a new pointer into name to the
898  * char after the last qualifier to be consumed.
899  *
900  * radius_list_name should be called before passing a name string that
901  * may contain qualifiers to dict_attrbyname.
902  *
903  * @see dict_attrbyname
904  *
905  * @param[in,out] name of attribute.
906  * @param[in] default_list the list to return if no qualifiers were found.
907  * @return PAIR_LIST_UNKOWN if qualifiers couldn't be resolved to a list.
908  */
909 pair_lists_t radius_list_name(char const **name, pair_lists_t default_list)
910 {
911         char const *p = *name;
912         char const *q;
913         pair_lists_t output;
914
915         /* This should never be a NULL pointer or zero length string */
916         rad_assert(name && *name);
917
918         /*
919          *      Unfortunately, ':' isn't a definitive separator for
920          *      the list name.  We may have numeric tags, too.
921          */
922         q = strchr(p, ':');
923         if (q) {
924                 /*
925                  *      Check for tagged attributes.  They have
926                  *      "name:tag", where tag is a decimal number.
927                  *      Valid tags are invalid attributes, so that's
928                  *      OK.
929                  *
930                  *      Also allow "name:tag[#]" as a tag.
931                  *
932                  *      However, "request:" is allowed, too, and
933                  *      shouldn't be interpreted as a tag.
934                  *
935                  *      We do this check first rather than just
936                  *      looking up the request name, because this
937                  *      check is cheap, and looking up the request
938                  *      name is expensive.
939                  */
940                 if (isdigit((int) q[1])) {
941                         char const *d = q + 1;
942
943                         while (isdigit((int) *d)) {
944                                 d++;
945                         }
946
947                         /*
948                          *      Return the DEFAULT list as supplied by
949                          *      the caller.  This is usually
950                          *      PAIRLIST_REQUEST.
951                          */
952                         if (!*d || (*d == '[')) {
953                                 return default_list;
954                         }
955                 }
956
957                 /*
958                  *      If the first part is a list name, then treat
959                  *      it as a list.  This means that we CANNOT have
960                  *      an attribute which is named "request",
961                  *      "reply", etc.  Allowing a tagged attribute
962                  *      "request:3" would just be insane.
963                  */
964                 output = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
965                 if (output != PAIR_LIST_UNKNOWN) {
966                         *name = (q + 1);        /* Consume the list and delimiter */
967                         return output;
968                 }
969
970                 /*
971                  *      It's not a known list, say so.
972                  */
973                 return PAIR_LIST_UNKNOWN;
974         }
975
976         /*
977          *      The input string may be just a list name,
978          *      e.g. "request".  Check for that.
979          */
980         q = (p + strlen(p));
981         output = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
982         if (output != PAIR_LIST_UNKNOWN) {
983                 *name = q;
984                 return output;
985         }
986
987         /*
988          *      It's just an attribute name.  Return the default list
989          *      as supplied by the caller.
990          */
991         return default_list;
992 }
993
994
995 /** Resolve attribute name to a request.
996  *
997  * Check the name string for qualifiers that reference a parent request and
998  * write the pointer to this request to 'request'.
999  *
1000  * If qualifiers were consumed, write a new pointer into name to the
1001  * char after the last qualifier to be consumed.
1002  *
1003  * radius_ref_request should be called before radius_list_name.
1004  *
1005  * @see radius_list_name
1006  * @param[in,out] name of attribute.
1007  * @param[in] def default request ref to return if no request qualifier is present.
1008  * @return one of the REQUEST_* definitions or REQUEST_UNKOWN
1009  */
1010 request_refs_t radius_request_name(char const **name, request_refs_t def)
1011 {
1012         char *p;
1013         int request;
1014
1015         p = strchr(*name, '.');
1016         if (!p) {
1017                 return def;
1018         }
1019
1020         /*
1021          *      We may get passed "127.0.0.1".
1022          */
1023         request = fr_substr2int(request_refs, *name, REQUEST_UNKNOWN,
1024                                 p - *name);
1025
1026         /*
1027          *      If we get a valid name, skip it.
1028          */
1029         if (request != REQUEST_UNKNOWN) {
1030                 *name = p + 1;
1031                 return request;
1032         }
1033
1034         /*
1035          *      Otherwise leave it alone, and return the caller's
1036          *      default.
1037          */
1038         return def;
1039 }
1040
1041 /** Resolve request to a request.
1042  *
1043  * Resolve name to a current request.
1044  *
1045  * @see radius_list
1046  * @param[in,out] context Base context to use, and to write the result back to.
1047  * @param[in] name (request) to resolve to.
1048  * @return 0 if request is valid in this context, else -1.
1049  */
1050 int radius_request(REQUEST **context, request_refs_t name)
1051 {
1052         REQUEST *request = *context;
1053
1054         switch (name) {
1055                 case REQUEST_CURRENT:
1056                         return 0;
1057
1058                 case REQUEST_PARENT:    /* for future use in request chaining */
1059                 case REQUEST_OUTER:
1060                         if (!request->parent) {
1061                                 return -1;
1062                         }
1063                         *context = request->parent;
1064                         break;
1065
1066                 case REQUEST_UNKNOWN:
1067                 default:
1068                         rad_assert(0);
1069                         return -1;
1070         }
1071
1072         return 0;
1073 }
1074
1075 /** Adds subcapture values to request data
1076  *
1077  * Allows use of %{n} expansions.
1078  *
1079  * @param request Current request.
1080  * @param compare Result returned by regexec.
1081  * @param value The original value.
1082  * @param rxmatch Pointers into value.
1083  */
1084 void rad_regcapture(REQUEST *request, int compare, char const *value, regmatch_t rxmatch[])
1085 {
1086         int i;
1087         char *p;
1088         size_t len;
1089
1090         if (compare == REG_NOMATCH) {
1091                 return;
1092         }
1093
1094         /*
1095          *      Add new %{0}, %{1}, etc.
1096          */
1097         for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
1098                 /*
1099                  *      Didn't match: delete old match, if it existed.
1100                  */
1101                 if (rxmatch[i].rm_so == -1) {
1102                         p = request_data_get(request, request, REQUEST_DATA_REGEX | i);
1103                         if (p) {
1104                                 RDEBUG4("%%{%i}: Clearing old value \"%s\"", i, p);
1105                                 talloc_free(p);
1106                         } else {
1107                                 RDEBUG4("%%{%i}: Was empty", i);
1108                         }
1109
1110                         continue;
1111                 }
1112
1113                 len = rxmatch[i].rm_eo - rxmatch[i].rm_so;
1114                 p = talloc_array(request, char, len + 1);
1115                 if (!p) {
1116                         ERROR("Out of memory");
1117                         return;
1118                 }
1119
1120                 memcpy(p, value + rxmatch[i].rm_so, len);
1121                 p[len] = '\0';
1122
1123                 RDEBUG4("%%{%i}: Inserting new value \"%s\"", i, p);
1124                 /*
1125                  *      Copy substring, and add it to
1126                  *      the request.
1127                  *
1128                  *      Note that we don't check
1129                  *      for out of memory, which is
1130                  *      the only error we can get...
1131                  */
1132                 request_data_add(request, request, REQUEST_DATA_REGEX | i, p, true);
1133         }
1134 }
1135