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