xlat_explode: trim white space
[freeradius.git] / src / modules / rlm_expr / rlm_expr.c
1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or (at
5  *   your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16
17 /**
18  * $Id$
19  * @file rlm_expr.c
20  * @brief Register many xlat expansions including the expr expansion.
21  *
22  * @copyright 2001,2006  The FreeRADIUS server project
23  * @copyright 2002  Alan DeKok <aland@ox.org>
24  */
25 RCSID("$Id$")
26 USES_APPLE_DEPRECATED_API
27
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/md5.h>
30 #include <freeradius-devel/sha1.h>
31 #include <freeradius-devel/base64.h>
32 #include <freeradius-devel/modules.h>
33 #include <freeradius-devel/rad_assert.h>
34
35 #ifdef HAVE_OPENSSL_EVP_H
36 #  include <openssl/evp.h>
37 #endif
38
39 #include <ctype.h>
40
41 #include "rlm_expr.h"
42
43 /*
44  *      Define a structure for our module configuration.
45  */
46 typedef struct rlm_expr_t {
47         char const *xlat_name;
48         char const *allowed_chars;
49 } rlm_expr_t;
50
51 static const CONF_PARSER module_config[] = {
52         { "safe_characters", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_expr_t, allowed_chars), "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" },
53         CONF_PARSER_TERMINATOR
54 };
55
56 /*
57  *      Lookup tables for randstr char classes
58  */
59 static char randstr_punc[] = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
60 static char randstr_salt[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz/.";
61
62 /*
63  *      Characters humans rarely confuse. Reduces char set considerably
64  *      should only be used for things such as one time passwords.
65  */
66 static char randstr_otp[] = "469ACGHJKLMNPQRUVWXYabdfhijkprstuvwxyz";
67
68 static char const hextab[] = "0123456789abcdef";
69
70 /** Calculate powers
71  *
72  * @author Orson Peters
73  * @note Borrowed from the gist here: https://gist.github.com/nightcracker/3551590.
74  *
75  * @param base a 32bit signed integer.
76  * @param exp amount to raise base by.
77  * @return base ^ pow, or 0 on underflow/overflow.
78  */
79 static int64_t fr_pow(int64_t base, int64_t exp)
80 {
81         static const uint8_t highest_bit_set[] = {
82                 0, 1, 2, 2, 3, 3, 3, 3,
83                 4, 4, 4, 4, 4, 4, 4, 4,
84                 5, 5, 5, 5, 5, 5, 5, 5,
85                 5, 5, 5, 5, 5, 5, 5, 5,
86                 6, 6, 6, 6, 6, 6, 6, 6,
87                 6, 6, 6, 6, 6, 6, 6, 6,
88                 6, 6, 6, 6, 6, 6, 6, 6,
89                 6, 6, 6, 6, 6, 6, 6, 6 // anything past 63 is a guaranteed overflow with base > 1
90         };
91
92         int64_t result = 1;
93
94         if (exp > 63) {
95                 if (base == 1) {
96                         return 1;
97                 }
98
99                 if (base == -1) {
100                         return 1 - 2 * (exp & 1);
101                 }
102                 return 0;       /* overflow */
103         }
104
105         switch (highest_bit_set[exp]) {
106         case 6:
107                 if (exp & 1) result *= base;
108                 exp >>= 1;
109                 base *= base;
110         case 5:
111                 if (exp & 1) result *= base;
112                 exp >>= 1;
113                 base *= base;
114         case 4:
115                 if (exp & 1) result *= base;
116                 exp >>= 1;
117                 base *= base;
118         case 3:
119                 if (exp & 1) result *= base;
120                 exp >>= 1;
121                 base *= base;
122         case 2:
123                 if (exp & 1) result *= base;
124                 exp >>= 1;
125                 base *= base;
126         case 1:
127                 if (exp & 1) result *= base;
128         default:
129                 return result;
130         }
131 }
132
133 /*
134  *      Start of expression calculator.
135  */
136 typedef enum expr_token_t {
137         TOKEN_NONE = 0,
138         TOKEN_INTEGER,
139
140         TOKEN_AND,
141         TOKEN_OR,
142
143         TOKEN_LSHIFT,
144         TOKEN_RSHIFT,
145
146         TOKEN_ADD,
147         TOKEN_SUBTRACT,
148
149         TOKEN_DIVIDE,
150         TOKEN_REMAINDER,
151         TOKEN_MULTIPLY,
152
153         TOKEN_POWER,
154         TOKEN_LAST
155 } expr_token_t;
156
157 static int precedence[TOKEN_LAST + 1] = {
158         0, 0, 1, 1,             /* and or */
159         2, 2, 3, 3,             /* shift add */
160         4, 4, 4, 5,             /* mul, pow */
161         0
162 };
163
164 typedef struct expr_map_t {
165         char op;
166         expr_token_t token;
167 } expr_map_t;
168
169 static expr_map_t map[] =
170 {
171         {'+',   TOKEN_ADD },
172         {'-',   TOKEN_SUBTRACT },
173         {'/',   TOKEN_DIVIDE },
174         {'*',   TOKEN_MULTIPLY },
175         {'%',   TOKEN_REMAINDER },
176         {'&',   TOKEN_AND },
177         {'|',   TOKEN_OR },
178         {'^',   TOKEN_POWER },
179         {0,     TOKEN_LAST}
180 };
181
182 static bool get_expression(REQUEST *request, char const **string, int64_t *answer, expr_token_t prev);
183
184 static bool get_number(REQUEST *request, char const **string, int64_t *answer)
185 {
186         int64_t x;
187         bool invert = false;
188         bool negative = false;
189         char const *p = *string;
190
191         /*
192          *      Look for a number.
193          */
194         while (isspace((int) *p)) p++;
195
196         /*
197          *      ~1 == 0xff...ffe
198          */
199         if (*p == '~') {
200                 invert = true;
201                 p++;
202         }
203
204         /*
205          *  No algrebraic operator found, the next thing
206          *  MUST be a number.
207          *
208          *  If it isn't, then we die.
209          */
210         if ((*p == '0') && (p[1] == 'x')) {
211                 char *end;
212
213                 x = strtoul(p, &end, 16);
214                 p = end;
215                 goto done;
216         }
217
218         if (*p == '-') {
219                 negative = true;
220                 p++;
221         }
222
223         /*
224          *      Look for an attribute.
225          */
226         if (*p == '&') {
227                 ssize_t         slen;
228                 VALUE_PAIR      *vp;
229                 vp_tmpl_t       vpt;
230
231                 p += 1;
232
233                 slen = tmpl_from_attr_substr(&vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false);
234                 if (slen <= 0) {
235                         REDEBUG("Failed parsing attribute name '%s': %s", p, fr_strerror());
236                         return false;
237                 }
238
239                 p += slen;
240
241                 if (tmpl_find_vp(&vp, request, &vpt) < 0) {
242                         RWDEBUG("Can't find &%.*s.  Using 0 as operand value", (int)vpt.len, vpt.name);
243                         x = 0;
244                         goto done;
245                 }
246
247                 if (vp->da->type != PW_TYPE_INTEGER64) {
248                         value_data_t    value;
249
250                         if (value_data_cast(vp, &value, PW_TYPE_INTEGER64, NULL, vp->da->type, vp->da, &vp->data, vp->vp_length) < 0) {
251                                 REDEBUG("Failed converting &%.*s to an integer value: %s", (int) vpt.len,
252                                         vpt.name, fr_strerror());
253                                 return false;
254                         }
255                         if (value.integer64 > INT64_MAX) {
256                         overflow:
257                                 REDEBUG("Value of &%.*s (%"PRIu64 ") would overflow a signed 64bit integer "
258                                         "(our internal arithmetic type)", (int)vpt.len, vpt.name, value.integer64);
259                                 return false;
260                         }
261                         x = (int64_t)value.integer64;
262
263                         RINDENT();
264                         RDEBUG3("&%.*s --> %" PRIu64, (int)vpt.len, vpt.name, x);
265                         REXDENT();
266                 } else {
267                         if (vp->vp_integer64 > INT64_MAX) goto overflow;
268                         x = (int64_t)vp->vp_integer64;
269                 }
270
271                 goto done;
272         }
273
274         /*
275          *      Do brackets recursively
276          */
277         if (*p == '(') {
278                 p++;
279                 if (!get_expression(request, &p, &x, TOKEN_NONE)) return false;
280
281                 if (*p != ')') {
282                         RDEBUG("No trailing ')'");
283                         return false;
284                 }
285                 p++;
286                 goto done;
287         }
288
289         if ((*p < '0') || (*p > '9')) {
290                 RDEBUG2("Not a number at \"%s\"", p);
291                 return false;
292         }
293
294         /*
295          *  This is doing it the hard way, but it also allows
296          *  us to increment 'p'.
297          */
298         x = 0;
299         while ((*p >= '0') && (*p <= '9')) {
300                 x *= 10;
301                 x += (*p - '0');
302                 p++;
303         }
304
305 done:
306         if (invert) x = ~x;
307
308         if (negative) x = -x;
309
310         *string = p;
311         *answer = x;
312         return true;
313 }
314
315 static bool calc_result(REQUEST *request, int64_t lhs, expr_token_t op, int64_t rhs, int64_t *answer)
316 {
317         switch (op) {
318         default:
319         case TOKEN_ADD:
320                 *answer = lhs + rhs;
321                 break;
322
323         case TOKEN_SUBTRACT:
324                 *answer = lhs - rhs;
325                 break;
326
327         case TOKEN_DIVIDE:
328                 if (rhs == 0) {
329                         RDEBUG("Division by zero!");
330                         return false;
331                 } else {
332                         *answer = lhs / rhs;
333                 }
334                 break;
335
336         case TOKEN_REMAINDER:
337                 if (rhs == 0) {
338                         RDEBUG("Division by zero!");
339                         return false;
340                 }
341
342                 *answer = lhs % rhs;
343                 break;
344
345         case TOKEN_MULTIPLY:
346                 *answer = lhs * rhs;
347                 break;
348
349         case TOKEN_LSHIFT:
350                 if (rhs > 63) {
351                         RDEBUG("Shift must be less than 63 (was %lld)", (long long int) rhs);
352                         return false;
353                 }
354
355                 *answer = lhs << rhs;
356                 break;
357
358         case TOKEN_RSHIFT:
359                 if (rhs > 63) {
360                         RDEBUG("Shift must be less than 63 (was %lld)", (long long int) rhs);
361                         return false;
362                 }
363
364                 *answer = lhs >> rhs;
365                 break;
366
367         case TOKEN_AND:
368                 *answer = lhs & rhs;
369                 break;
370
371         case TOKEN_OR:
372                 *answer = lhs | rhs;
373                 break;
374
375         case TOKEN_POWER:
376                 if (rhs > 63) {
377                         REDEBUG("Exponent must be between 0-63 (was %lld)", (long long int) rhs);
378                         return false;
379                 }
380
381                 if (lhs > 65535) {
382                         REDEBUG("Base must be between 0-65535 (was %lld)", (long long int) lhs);
383                         return false;
384                 }
385
386                 *answer = fr_pow(lhs, rhs);
387                 break;
388         }
389
390         return true;
391 }
392
393 static bool get_operator(REQUEST *request, char const **string, expr_token_t *op)
394 {
395         int             i;
396         char const      *p = *string;
397
398         /*
399          *      All tokens are one character.
400          */
401         for (i = 0; map[i].token != TOKEN_LAST; i++) {
402                 if (*p == map[i].op) {
403                         *op = map[i].token;
404                         *string = p + 1;
405                         return true;
406                 }
407         }
408
409         if ((p[0] == '<') && (p[1] == '<')) {
410                 *op = TOKEN_LSHIFT;
411                 *string = p + 2;
412                 return true;
413         }
414
415         if ((p[0] == '>') && (p[1] == '>')) {
416                 *op = TOKEN_RSHIFT;
417                 *string = p + 2;
418                 return true;
419         }
420
421         RDEBUG("Expected operator at \"%s\"", p);
422         return false;
423 }
424
425
426 static bool get_expression(REQUEST *request, char const **string, int64_t *answer, expr_token_t prev)
427 {
428         int64_t         lhs, rhs;
429         char const      *p, *op_p;
430         expr_token_t    this;
431
432         p = *string;
433
434         if (!get_number(request, &p, &lhs)) return false;
435
436 redo:
437         while (isspace((int) *p)) p++;
438
439         /*
440          *      A number by itself is OK.
441          */
442         if (!*p || (*p == ')')) {
443                 *answer = lhs;
444                 *string = p;
445                 return true;
446         }
447
448         /*
449          *      Peek at the operator.
450          */
451         op_p = p;
452         if (!get_operator(request, &p, &this)) return false;
453
454         /*
455          *      a + b + c ... = (a + b) + c ...
456          *      a * b + c ... = (a * b) + c ...
457          *
458          *      Feed the current number to the caller, who will take
459          *      care of continuing.
460          */
461         if (precedence[this] <= precedence[prev]) {
462                 *answer = lhs;
463                 *string = op_p;
464                 return true;
465         }
466
467         /*
468          *      a + b * c ... = a + (b * c) ...
469          */
470         if (!get_expression(request, &p, &rhs, this)) return false;
471
472         if (!calc_result(request, lhs, this, rhs, answer)) return false;
473
474         /*
475          *      There may be more to calculate.  The answer we
476          *      calculated here is now the LHS of the lower priority
477          *      operation which follows the current expression.  e.g.
478          *
479          *      a * b + c ... = (a * b) + c ...
480          *                    =       d + c ...
481          */
482         lhs = *answer;
483         goto redo;
484 }
485
486 /*
487  *  Do xlat of strings!
488  */
489 static ssize_t expr_xlat(UNUSED void *instance, REQUEST *request, char const *fmt,
490                          char *out, size_t outlen)
491 {
492         int64_t         result;
493         char const      *p;
494
495         p = fmt;
496
497         if (!get_expression(request, &p, &result, TOKEN_NONE)) {
498                 return -1;
499         }
500
501         if (*p) {
502                 RDEBUG("Invalid text after expression: %s", p);
503                 return -1;
504         }
505
506         snprintf(out, outlen, "%lld", (long long int) result);
507         return strlen(out);
508 }
509
510 /** Generate a random integer value
511  *
512  */
513 static ssize_t rand_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt,
514                          char *out, size_t outlen)
515 {
516         int64_t         result;
517
518         result = atoi(fmt);
519
520         /*
521          *      Too small or too big.
522          */
523         if (result <= 0) {
524                 *out = '\0';
525                 return -1;
526         }
527         if (result >= (1 << 30)) result = (1 << 30);
528
529         result *= fr_rand();    /* 0..2^32-1 */
530         result >>= 32;
531
532         snprintf(out, outlen, "%ld", (long int) result);
533         return strlen(out);
534 }
535
536 /** Generate a string of random chars
537  *
538  *  Build strings of random chars, useful for generating tokens and passcodes
539  *  Format similar to String::Random.
540  */
541 static ssize_t randstr_xlat(UNUSED void *instance, UNUSED REQUEST *request,
542                             char const *fmt, char *out, size_t outlen)
543 {
544         char const      *p;
545         unsigned int    result;
546         unsigned int    number;
547         size_t          freespace = outlen;
548
549         if (outlen <= 1) return 0;
550
551         *out = '\0';
552
553         p = fmt;
554         while (*p && (--freespace > 0)) {
555                 number = 0;
556
557                 /*
558                  *      Modifiers are polite.
559                  *
560                  *      But we limit it to 100, because we don't want
561                  *      utter stupidity.
562                  */
563                 while (isdigit((int) *p)) {
564                         if (number >= 100) {
565                                 p++;
566                                 continue;
567                         }
568
569                         number *= 10;
570                         number += *p - '0';
571                         p++;
572                 }
573
574         redo:
575                 result = fr_rand();
576
577                 switch (*p) {
578                 /*
579                  *  Lowercase letters
580                  */
581                 case 'c':
582                         *out++ = 'a' + (result % 26);
583                         break;
584
585                 /*
586                  *  Uppercase letters
587                  */
588                 case 'C':
589                         *out++ = 'A' + (result % 26);
590                         break;
591
592                 /*
593                  *  Numbers
594                  */
595                 case 'n':
596                         *out++ = '0' + (result % 10);
597                         break;
598
599                 /*
600                  *  Alpha numeric
601                  */
602                 case 'a':
603                         *out++ = randstr_salt[result % (sizeof(randstr_salt) - 3)];
604                         break;
605
606                 /*
607                  *  Punctuation
608                  */
609                 case '!':
610                         *out++ = randstr_punc[result % (sizeof(randstr_punc) - 1)];
611                         break;
612
613                 /*
614                  *  Alpa numeric + punctuation
615                  */
616                 case '.':
617                         *out++ = '!' + (result % 95);
618                         break;
619
620                 /*
621                  *  Alpha numeric + salt chars './'
622                  */
623                 case 's':
624                         *out++ = randstr_salt[result % (sizeof(randstr_salt) - 1)];
625                         break;
626
627                 /*
628                  *  Chars suitable for One Time Password tokens.
629                  *  Alpha numeric with easily confused char pairs removed.
630                  */
631                 case 'o':
632                         *out++ = randstr_otp[result % (sizeof(randstr_otp) - 1)];
633                         break;
634
635                 /*
636                  *  Binary data as hexits (we don't really support
637                  *  non printable chars).
638                  */
639                 case 'h':
640                         if (freespace < 2) {
641                                 break;
642                         }
643
644                         snprintf(out, 3, "%02x", result % 256);
645
646                         /* Already decremented */
647                         freespace -= 1;
648                         out += 2;
649                         break;
650
651                 /*
652                  *  Binary data with uppercase hexits
653                  */
654                 case 'H':
655                         if (freespace < 2) {
656                                 break;
657                         }
658
659                         snprintf(out, 3, "%02X", result % 256);
660
661                         /* Already decremented */
662                         freespace -= 1;
663                         out += 2;
664                         break;
665
666                 default:
667                         ERROR("rlm_expr: invalid character class '%c'", *p);
668
669                         return -1;
670                 }
671
672                 if (number > 0) {
673                         number--;
674                         goto redo;
675                 }
676
677                 p++;
678         }
679
680         *out++ = '\0';
681
682         return outlen - freespace;
683 }
684
685 /** URLencode special characters
686  *
687  * Example: "%{urlquote:http://example.org/}" == "http%3A%47%47example.org%47"
688  */
689 static ssize_t urlquote_xlat(UNUSED void *instance, UNUSED REQUEST *request,
690                              char const *fmt, char *out, size_t outlen)
691 {
692         char const      *p;
693         size_t  freespace = outlen;
694
695         if (outlen <= 1) return 0;
696
697         p = fmt;
698         while (*p && (--freespace > 0)) {
699                 if (isalnum(*p)) {
700                         *out++ = *p++;
701                         continue;
702                 }
703
704                 switch (*p) {
705                 case '-':
706                 case '_':
707                 case '.':
708                 case '~':
709                         *out++ = *p++;
710                         break;
711
712                 default:
713                         if (freespace < 3)
714                                 break;
715
716                         /* MUST be upper case hex to be compliant */
717                         snprintf(out, 4, "%%%02X", (uint8_t) *p++); /* %XX */
718
719                         /* Already decremented */
720                         freespace -= 2;
721                         out += 3;
722                 }
723         }
724
725         *out = '\0';
726
727         return outlen - freespace;
728 }
729
730 /** URLdecode special characters
731  *
732  * Example: "%{urlunquote:http%%3A%%47%%47example.org%%47}" == "http://example.org/"
733  *
734  * Remember to escape % with %% in strings, else xlat will try to parse it.
735  */
736 static ssize_t urlunquote_xlat(UNUSED void *instance, REQUEST *request,
737                                char const *fmt, char *out, size_t outlen)
738 {
739         char const *p;
740         char *c1, *c2;
741         size_t  freespace = outlen;
742
743         if (outlen <= 1) return 0;
744
745         p = fmt;
746         while (*p && (--freespace > 0)) {
747                 if (*p != '%') {
748                         *out++ = *p++;
749                         continue;
750                 }
751                 /* Is a % char */
752
753                 /* Don't need \0 check, as it won't be in the hextab */
754                 if (!(c1 = memchr(hextab, tolower(*++p), 16)) ||
755                     !(c2 = memchr(hextab, tolower(*++p), 16))) {
756                         REMARKER(fmt, p - fmt, "None hex char in % sequence");
757                         return -1;
758                 }
759                 p++;
760                 *out++ = ((c1 - hextab) << 4) + (c2 - hextab);
761         }
762
763         *out = '\0';
764
765         return outlen - freespace;
766 }
767
768 /** Equivalent to the old safe_characters functionality in rlm_sql but with utf8 support
769  *
770  * @verbatim Example: "%{escape:<img>foo.jpg</img>}" == "=60img=62foo.jpg=60/img=62" @endverbatim
771  */
772 static ssize_t escape_xlat(void *instance, UNUSED REQUEST *request,
773                            char const *fmt, char *out, size_t outlen)
774 {
775         rlm_expr_t *inst = instance;
776         char const *p = fmt;
777         size_t freespace = outlen;
778
779         while (p[0]) {
780                 int chr_len = 1;
781                 int ret = 1;    /* -Werror=uninitialized */
782
783                 if (fr_utf8_strchr(&chr_len, inst->allowed_chars, p) == NULL) {
784                         /*
785                          *      '=' 1 + ([hex]{2}) * chr_len)
786                          */
787                         if (freespace <= (size_t)(1 + (chr_len * 3))) break;
788
789                         switch (chr_len) {
790                         case 4:
791                                 ret = snprintf(out, freespace, "=%02X=%02X=%02X=%02X",
792                                                (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]);
793                                 break;
794
795                         case 3:
796                                 ret = snprintf(out, freespace, "=%02X=%02X=%02X",
797                                                (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2]);
798                                 break;
799
800                         case 2:
801                                 ret = snprintf(out, freespace, "=%02X=%02X", (uint8_t)p[0], (uint8_t)p[1]);
802                                 break;
803
804                         case 1:
805                                 ret = snprintf(out, freespace, "=%02X", (uint8_t)p[0]);
806                                 break;
807                         }
808
809                         p += chr_len;
810                         out += ret;
811                         freespace -= ret;
812                         continue;
813                 }
814
815                 /*
816                  *      Only one byte left.
817                  */
818                 if (freespace <= 1) break;
819
820                 /*
821                  *      Allowed character (copy whole mb chars at once)
822                  */
823                 memcpy(out, p, chr_len);
824                 out += chr_len;
825                 p += chr_len;
826                 freespace -= chr_len;
827         }
828         *out = '\0';
829
830         return outlen - freespace;
831 }
832
833 /** Equivalent to the old safe_characters functionality in rlm_sql
834  *
835  * @verbatim Example: "%{unescape:=60img=62foo.jpg=60/img=62}" == "<img>foo.jpg</img>" @endverbatim
836  */
837 static ssize_t unescape_xlat(UNUSED void *instance, UNUSED REQUEST *request,
838                              char const *fmt, char *out, size_t outlen)
839 {
840         char const *p;
841         char *c1, *c2, c3;
842         size_t  freespace = outlen;
843
844         if (outlen <= 1) return 0;
845
846         p = fmt;
847         while (*p && (--freespace > 0)) {
848                 if (*p != '=') {
849                 next:
850
851                         *out++ = *p++;
852                         continue;
853                 }
854
855                 /* Is a = char */
856
857                 if (!(c1 = memchr(hextab, tolower(*(p + 1)), 16)) ||
858                     !(c2 = memchr(hextab, tolower(*(p + 2)), 16))) goto next;
859                 c3 = ((c1 - hextab) << 4) + (c2 - hextab);
860
861                 *out++ = c3;
862                 p += 3;
863         }
864
865         *out = '\0';
866
867         return outlen - freespace;
868 }
869
870 /** Convert a string to lowercase
871  *
872  * Example: "%{tolower:Bar}" == "bar"
873  *
874  * Probably only works for ASCII
875  */
876 static ssize_t lc_xlat(UNUSED void *instance, UNUSED REQUEST *request,
877                        char const *fmt, char *out, size_t outlen)
878 {
879         char *q;
880         char const *p;
881
882         if (outlen <= 1) return 0;
883
884         for (p = fmt, q = out; *p != '\0'; p++, outlen--) {
885                 if (outlen <= 1) break;
886
887                 *(q++) = tolower((int) *p);
888         }
889
890         *q = '\0';
891
892         return strlen(out);
893 }
894
895 /** Convert a string to uppercase
896  *
897  * Example: "%{toupper:Foo}" == "FOO"
898  *
899  * Probably only works for ASCII
900  */
901 static ssize_t uc_xlat(UNUSED void *instance, UNUSED REQUEST *request,
902                        char const *fmt, char *out, size_t outlen)
903 {
904         char *q;
905         char const *p;
906
907         if (outlen <= 1) return 0;
908
909         for (p = fmt, q = out; *p != '\0'; p++, outlen--) {
910                 if (outlen <= 1) break;
911
912                 *(q++) = toupper((int) *p);
913         }
914
915         *q = '\0';
916
917         return strlen(out);
918 }
919
920 /** Calculate the MD5 hash of a string or attribute.
921  *
922  * Example: "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8"
923  */
924 static ssize_t md5_xlat(UNUSED void *instance, REQUEST *request,
925                         char const *fmt, char *out, size_t outlen)
926 {
927         uint8_t digest[16];
928         ssize_t i, len, inlen;
929         uint8_t const *p;
930         FR_MD5_CTX ctx;
931
932         /*
933          *      We need room for at least one octet of output.
934          */
935         if (outlen < 3) {
936                 *out = '\0';
937                 return 0;
938         }
939
940         inlen = xlat_fmt_to_ref(&p, request, fmt);
941         if (inlen < 0) {
942                 return -1;
943         }
944
945         fr_md5_init(&ctx);
946         fr_md5_update(&ctx, p, inlen);
947         fr_md5_final(digest, &ctx);
948
949         /*
950          *      Each digest octet takes two hex digits, plus one for
951          *      the terminating NUL.
952          */
953         len = (outlen / 2) - 1;
954         if (len > 16) len = 16;
955
956         for (i = 0; i < len; i++) {
957                 snprintf(out + i * 2, 3, "%02x", digest[i]);
958         }
959
960         return strlen(out);
961 }
962
963 /** Calculate the SHA1 hash of a string or attribute.
964  *
965  * Example: "%{sha1:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
966  */
967 static ssize_t sha1_xlat(UNUSED void *instance, REQUEST *request,
968                          char const *fmt, char *out, size_t outlen)
969 {
970         uint8_t digest[20];
971         ssize_t i, len, inlen;
972         uint8_t const *p;
973         fr_sha1_ctx ctx;
974
975         /*
976          *      We need room for at least one octet of output.
977          */
978         if (outlen < 3) {
979                 *out = '\0';
980                 return 0;
981         }
982
983         inlen = xlat_fmt_to_ref(&p, request, fmt);
984         if (inlen < 0) {
985                 return -1;
986         }
987
988         fr_sha1_init(&ctx);
989         fr_sha1_update(&ctx, p, inlen);
990         fr_sha1_final(digest, &ctx);
991
992         /*
993          *      Each digest octet takes two hex digits, plus one for
994          *      the terminating NUL. SHA1 is 160 bits (20 bytes)
995          */
996         len = (outlen / 2) - 1;
997         if (len > 20) len = 20;
998
999         for (i = 0; i < len; i++) {
1000                 snprintf(out + i * 2, 3, "%02x", digest[i]);
1001         }
1002
1003         return strlen(out);
1004 }
1005
1006 /** Calculate any digest supported by OpenSSL EVP_MD
1007  *
1008  * Example: "%{sha256:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
1009  */
1010 #ifdef HAVE_OPENSSL_EVP_H
1011 static ssize_t evp_md_xlat(UNUSED void *instance, REQUEST *request,
1012                            char const *fmt, char *out, size_t outlen, EVP_MD const *md)
1013 {
1014         uint8_t digest[EVP_MAX_MD_SIZE];
1015         unsigned int digestlen, i, len;
1016         ssize_t inlen;
1017         uint8_t const *p;
1018
1019         EVP_MD_CTX *ctx;
1020
1021         /*
1022          *      We need room for at least one octet of output.
1023          */
1024         if (outlen < 3) {
1025                 *out = '\0';
1026                 return 0;
1027         }
1028
1029         inlen = xlat_fmt_to_ref(&p, request, fmt);
1030         if (inlen < 0) {
1031                 return -1;
1032         }
1033
1034         ctx = EVP_MD_CTX_create();
1035         EVP_DigestInit_ex(ctx, md, NULL);
1036         EVP_DigestUpdate(ctx, p, inlen);
1037         EVP_DigestFinal_ex(ctx, digest, &digestlen);
1038         EVP_MD_CTX_destroy(ctx);
1039
1040         /*
1041          *      Each digest octet takes two hex digits, plus one for
1042          *      the terminating NUL.
1043          */
1044         len = (outlen / 2) - 1;
1045         if (len > digestlen) len = digestlen;
1046
1047         for (i = 0; i < len; i++) {
1048                 snprintf(out + i * 2, 3, "%02x", digest[i]);
1049         }
1050         return strlen(out);
1051 }
1052
1053 #  define EVP_MD_XLAT(_md) \
1054 static ssize_t _md##_xlat(void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen)\
1055 {\
1056         return evp_md_xlat(instance, request, fmt, out, outlen, EVP_##_md());\
1057 }
1058
1059 EVP_MD_XLAT(sha256)
1060 EVP_MD_XLAT(sha512)
1061 #endif
1062
1063 /** Generate the HMAC-MD5 of a string or attribute
1064  *
1065  * Example: "%{hmacmd5:foo bar}" == "Zm9v"
1066  */
1067 static ssize_t hmac_md5_xlat(UNUSED void *instance, REQUEST *request,
1068                              char const *fmt, char *out, size_t outlen)
1069 {
1070         uint8_t const *data, *key;
1071         char const *p;
1072         ssize_t data_len, key_len;
1073         uint8_t digest[MD5_DIGEST_LENGTH];
1074         char data_ref[256];
1075
1076         if (outlen <= (sizeof(digest) * 2)) {
1077                 REDEBUG("Insufficient space to write digest, needed %zu bytes, have %zu bytes",
1078                         (sizeof(digest) * 2) + 1, outlen);
1079                 return -1;
1080         }
1081
1082         p = strchr(fmt, ' ');
1083         if (!p) {
1084                 REDEBUG("HMAC requires exactly two arguments (&data &key)");
1085                 return -1;
1086         }
1087
1088         if ((size_t)(p - fmt) >= sizeof(data_ref)) {
1089                 REDEBUG("Insufficient space to store HMAC input data, needed %zu bytes, have %zu bytes",
1090                        (p - fmt) + 1, sizeof(data_ref));
1091
1092                 return -1;
1093         }
1094         strlcpy(data_ref, fmt, (p - fmt) + 1);
1095
1096         data_len = xlat_fmt_to_ref(&data, request, data_ref);
1097         if (data_len < 0) return -1;
1098
1099         while (isspace(*p) && p++);
1100
1101         key_len = xlat_fmt_to_ref(&key, request, p);
1102         if (key_len < 0) return -1;
1103
1104         fr_hmac_md5(digest, data, data_len, key, key_len);
1105
1106         return fr_bin2hex(out, digest, sizeof(digest));
1107 }
1108
1109 /** Generate the HMAC-SHA1 of a string or attribute
1110  *
1111  * Example: "%{hmacsha1:foo bar}" == "Zm9v"
1112  */
1113 static ssize_t hmac_sha1_xlat(UNUSED void *instance, REQUEST *request,
1114                               char const *fmt, char *out, size_t outlen)
1115 {
1116         uint8_t const *data, *key;
1117         char const *p;
1118         ssize_t data_len, key_len;
1119         uint8_t digest[SHA1_DIGEST_LENGTH];
1120         char data_ref[256];
1121
1122         if (outlen <= (sizeof(digest) * 2)) {
1123                 REDEBUG("Insufficient space to write digest, needed %zu bytes, have %zu bytes",
1124                         (sizeof(digest) * 2) + 1, outlen);
1125                 return -1;
1126         }
1127
1128         p = strchr(fmt, ' ');
1129         if (!p) {
1130                 REDEBUG("HMAC requires exactly two arguments (&data &key)");
1131                 return -1;
1132         }
1133
1134         if ((size_t)(p - fmt) >= sizeof(data_ref)) {
1135                 REDEBUG("Insufficient space to store HMAC input data, needed %zu bytes, have %zu bytes",
1136                         (p - fmt) + 1, sizeof(data_ref));
1137
1138                 return -1;
1139         }
1140         strlcpy(data_ref, fmt, (p - fmt) + 1);
1141
1142         data_len = xlat_fmt_to_ref(&data, request, data_ref);
1143         if (data_len < 0) return -1;
1144
1145         while (isspace(*p) && p++);
1146
1147         key_len = xlat_fmt_to_ref(&key, request, p);
1148         if (key_len < 0) return -1;
1149
1150         fr_hmac_sha1(digest, data, data_len, key, key_len);
1151
1152         return fr_bin2hex(out, digest, sizeof(digest));
1153 }
1154
1155 /** Encode attributes as a series of string attribute/value pairs
1156  *
1157  * This is intended to serialize one or more attributes as a comma
1158  * delimited string.
1159  *
1160  * Example: "%{pairs:request:}" == "User-Name = 'foo', User-Password = 'bar'"
1161  */
1162 static ssize_t pairs_xlat(UNUSED void *instance, REQUEST *request,
1163                           char const *fmt, char *out, size_t outlen)
1164 {
1165         vp_tmpl_t vpt;
1166         vp_cursor_t cursor;
1167         size_t len, freespace = outlen;
1168         char *p = out;
1169
1170         VALUE_PAIR *vp;
1171
1172         if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
1173                 REDEBUG("%s", fr_strerror());
1174                 return -1;
1175         }
1176
1177         for (vp = tmpl_cursor_init(NULL, &cursor, request, &vpt);
1178              vp;
1179              vp = tmpl_cursor_next(&cursor, &vpt)) {
1180                 FR_TOKEN op = vp->op;
1181
1182                 vp->op = T_OP_EQ;
1183                 len = vp_prints(p, freespace, vp);
1184                 vp->op = op;
1185
1186                 if (is_truncated(len, freespace)) {
1187                 no_space:
1188                         REDEBUG("Insufficient space to store pair string, needed %zu bytes have %zu bytes",
1189                                 (p - out) + len, outlen);
1190                         *out = '\0';
1191                         return -1;
1192                 }
1193                 p += len;
1194                 freespace -= len;
1195
1196                 if (freespace < 2) {
1197                         len = 2;
1198                         goto no_space;
1199                 }
1200
1201                 *p++ = ',';
1202                 *p++ = ' ';
1203                 freespace -= 2;
1204         }
1205
1206         /* Trim the trailing ', ' */
1207         if (p != out) p -= 2;
1208         *p = '\0';
1209
1210         return (p - out);
1211 }
1212
1213 /** Encode string or attribute as base64
1214  *
1215  * Example: "%{base64:foo}" == "Zm9v"
1216  */
1217 static ssize_t base64_xlat(UNUSED void *instance, REQUEST *request,
1218                            char const *fmt, char *out, size_t outlen)
1219 {
1220         ssize_t inlen;
1221         uint8_t const *p;
1222
1223         inlen = xlat_fmt_to_ref(&p, request, fmt);
1224         if (inlen < 0) {
1225                 return -1;
1226         }
1227
1228         /*
1229          *  We can accurately calculate the length of the output string
1230          *  if it's larger than outlen, the output would be useless so abort.
1231          */
1232         if ((inlen < 0) || ((FR_BASE64_ENC_LENGTH(inlen) + 1) > (ssize_t) outlen)) {
1233                 REDEBUG("xlat failed");
1234                 *out = '\0';
1235                 return -1;
1236         }
1237
1238         return fr_base64_encode(out, outlen, p, inlen);
1239 }
1240
1241 /** Convert base64 to hex
1242  *
1243  * Example: "%{base64tohex:Zm9v}" == "666f6f"
1244  */
1245 static ssize_t base64_to_hex_xlat(UNUSED void *instance, REQUEST *request,
1246                                   char const *fmt, char *out, size_t outlen)
1247 {
1248         uint8_t decbuf[1024];
1249
1250         ssize_t declen;
1251         ssize_t len = strlen(fmt);
1252
1253         *out = '\0';
1254
1255         declen = fr_base64_decode(decbuf, sizeof(decbuf), fmt, len);
1256         if (declen < 0) {
1257                 REDEBUG("Base64 string invalid");
1258                 return -1;
1259         }
1260
1261         if ((size_t)((declen * 2) + 1) > outlen) {
1262                 REDEBUG("Base64 conversion failed, output buffer exhausted, needed %zd bytes, have %zd bytes",
1263                         (declen * 2) + 1, outlen);
1264                 return -1;
1265         }
1266
1267         return fr_bin2hex(out, decbuf, declen);
1268 }
1269
1270 /** Split an attribute into multiple new attributes based on a delimiter
1271  *
1272  * @todo should support multibyte delimiter for string types.
1273  *
1274  * Example: "%{explode:&ref <delim>}"
1275  */
1276 static ssize_t explode_xlat(UNUSED void *instance, REQUEST *request,
1277                             char const *fmt, char *out, size_t outlen)
1278 {
1279         vp_tmpl_t vpt;
1280         vp_cursor_t cursor, to_merge;
1281         VALUE_PAIR *vp, *head = NULL;
1282         ssize_t slen;
1283         int count = 0;
1284         char const *p = fmt;
1285         char delim;
1286
1287         /*
1288          *  Trim whitespace
1289          */
1290         while (isspace(*p) && p++);
1291
1292         slen = tmpl_from_attr_substr(&vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false);
1293         if (slen <= 0) {
1294                 REDEBUG("%s", fr_strerror());
1295                 return -1;
1296         }
1297
1298         p += slen;
1299
1300         if (*p++ != ' ') {
1301         arg_error:
1302                 REDEBUG("explode needs exactly two arguments: &ref <delim>");
1303                 return -1;
1304         }
1305
1306         if (*p == '\0') goto arg_error;
1307
1308         delim = *p;
1309
1310         fr_cursor_init(&to_merge, &head);
1311
1312         for (vp = tmpl_cursor_init(NULL, &cursor, request, &vpt);
1313              vp;
1314              vp = tmpl_cursor_next(&cursor, &vpt)) {
1315                 VALUE_PAIR *new;
1316                 char const *end;
1317                 char const *q;
1318
1319                 /*
1320                  *      This can theoretically operate on lists too
1321                  *      so we need to check the type of each attribute.
1322                  */
1323                 switch (vp->da->type) {
1324                 case PW_TYPE_OCTETS:
1325                 case PW_TYPE_STRING:
1326                         break;
1327
1328                 default:
1329                         continue;
1330                 }
1331
1332                 p = vp->data.ptr;
1333                 end = p + vp->vp_length;
1334                 while (p < end) {
1335                         q = memchr(p, delim, end - p);
1336                         if (!q) {
1337                                 /* Delimiter not present in attribute */
1338                                 if (p == vp->data.ptr) goto next;
1339                                 q = end;
1340                         }
1341
1342                         /* Skip zero length */
1343                         if (q == p) {
1344                                 p = q + 1;
1345                                 continue;
1346                         }
1347
1348                         new = fr_pair_afrom_da(talloc_parent(vp), vp->da);
1349                         if (!new) {
1350                                 fr_pair_list_free(&head);
1351                                 return -1;
1352                         }
1353                         new->tag = vp->tag;
1354
1355                         switch (vp->da->type) {
1356                         case PW_TYPE_OCTETS:
1357                         {
1358                                 uint8_t *buff;
1359
1360                                 buff = talloc_array(new, uint8_t, q - p);
1361                                 memcpy(buff, p, q - p);
1362                                 fr_pair_value_memsteal(new, buff);
1363                         }
1364                                 break;
1365
1366                         case PW_TYPE_STRING:
1367                         {
1368                                 char *buff;
1369
1370                                 buff = talloc_array(new, char, (q - p) + 1);
1371                                 memcpy(buff, p, q - p);
1372                                 buff[q - p] = '\0';
1373                                 fr_pair_value_strsteal(new, (char *)buff);
1374                         }
1375                                 break;
1376
1377                         default:
1378                                 rad_assert(0);
1379                         }
1380
1381                         fr_cursor_insert(&to_merge, new);
1382
1383                         p = q + 1;      /* next */
1384
1385                         count++;
1386                 }
1387
1388                 /*
1389                  *      Remove the unexploded version
1390                  */
1391                 vp = fr_cursor_remove(&cursor);
1392                 talloc_free(vp);
1393
1394         next:
1395                 continue;       /* Apparently goto labels aren't allowed at the end of loops? */
1396         }
1397
1398         fr_cursor_merge(&cursor, head);
1399
1400         return snprintf(out, outlen, "%i", count);
1401 }
1402
1403 /** Calculate number of seconds until the next n hour(s), day(s), week(s), year(s).
1404  *
1405  * For example, if it were 16:18 %{nexttime:1h} would expand to 2520.
1406  *
1407  * The envisaged usage for this function is to limit sessions so that they don't
1408  * cross billing periods. The output of the xlat should be combined with %{rand:} to create
1409  * some jitter, unless the desired effect is every subscriber on the network
1410  * re-authenticating at the same time.
1411  */
1412 static ssize_t next_time_xlat(UNUSED void *instance, REQUEST *request,
1413                               char const *fmt, char *out, size_t outlen)
1414 {
1415         long            num;
1416
1417         char const      *p;
1418         char            *q;
1419         time_t          now;
1420         struct tm       *local, local_buff;
1421
1422         now = time(NULL);
1423         local = localtime_r(&now, &local_buff);
1424
1425         p = fmt;
1426
1427         num = strtoul(p, &q, 10);
1428         if (!q || *q == '\0') {
1429                 REDEBUG("nexttime: <int> must be followed by period specifier (h|d|w|m|y)");
1430                 return -1;
1431         }
1432
1433         if (p == q) {
1434                 num = 1;
1435         } else {
1436                 p += q - p;
1437         }
1438
1439         local->tm_sec = 0;
1440         local->tm_min = 0;
1441
1442         switch (*p) {
1443         case 'h':
1444                 local->tm_hour += num;
1445                 break;
1446
1447         case 'd':
1448                 local->tm_hour = 0;
1449                 local->tm_mday += num;
1450                 break;
1451
1452         case 'w':
1453                 local->tm_hour = 0;
1454                 local->tm_mday += (7 - local->tm_wday) + (7 * (num-1));
1455                 break;
1456
1457         case 'm':
1458                 local->tm_hour = 0;
1459                 local->tm_mday = 1;
1460                 local->tm_mon += num;
1461                 break;
1462
1463         case 'y':
1464                 local->tm_hour = 0;
1465                 local->tm_mday = 1;
1466                 local->tm_mon = 0;
1467                 local->tm_year += num;
1468                 break;
1469
1470         default:
1471                 REDEBUG("nexttime: Invalid period specifier '%c', must be h|d|w|m|y", *p);
1472                 return -1;
1473         }
1474
1475         return snprintf(out, outlen, "%" PRIu64, (uint64_t)(mktime(local) - now));
1476 }
1477
1478
1479 /*
1480  *      Parse the 3 arguments to lpad / rpad.
1481  */
1482 static bool parse_pad(REQUEST *request, char const *fmt,
1483                        vp_tmpl_t **pvpt, size_t *plength,
1484                        char *fill)
1485 {
1486         ssize_t slen;
1487         unsigned long length;
1488         char const *p;
1489         char *end;
1490         vp_tmpl_t *vpt;
1491
1492         *fill = ' ';            /* the default */
1493
1494         p = fmt;
1495         while (isspace((int) *p)) p++;
1496
1497         if (*p != '&') {
1498                 RDEBUG("First argument must be an attribute reference");
1499                 return false;
1500         }
1501
1502         vpt = talloc(request, vp_tmpl_t);
1503         if (!vpt) return false;
1504
1505         slen = tmpl_from_attr_substr(vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false);
1506         if (slen <= 0) {
1507                 talloc_free(vpt);
1508                 RDEBUG("Failed expanding string: %s", fr_strerror());
1509                 return false;
1510         }
1511
1512         p = fmt + slen;
1513
1514         while (isspace((int) *p)) p++;
1515
1516         length = strtoul(p, &end, 10);
1517         if ((length == ULONG_MAX) || (length > 8192)) {
1518                 talloc_free(vpt);
1519                 RDEBUG("Invalid length found at: %s", p);
1520                 return false;
1521         }
1522
1523         p += (end - p);
1524
1525         /*
1526          *      The fill character is optional.
1527          *
1528          *      But we must have a space after the previous number,
1529          *      and we must have only ONE fill character.
1530          */
1531         if (*p) {
1532                 if (!isspace(*p)) {
1533                         talloc_free(vpt);
1534                         RDEBUG("Invalid text found at: %s", p);
1535                         return false;
1536                 }
1537
1538                 while (isspace((int) *p)) p++;
1539
1540                 if (p[1] != '\0') {
1541                         talloc_free(vpt);
1542                         RDEBUG("Invalid text found at: %s", p);
1543                         return false;
1544                 }
1545
1546                 *fill = *p;
1547         }
1548
1549         *pvpt = vpt;
1550         *plength = length;
1551
1552         return true;
1553 }
1554
1555
1556 /** left pad a string
1557  *
1558  *  %{lpad:&Attribute-Name length 'x'}
1559  */
1560 static ssize_t lpad_xlat(UNUSED void *instance, REQUEST *request,
1561                          char const *fmt, char *out, size_t outlen)
1562 {
1563         char fill;
1564         size_t pad;
1565         ssize_t len;
1566         vp_tmpl_t *vpt;
1567
1568         *out = '\0';
1569         if (!parse_pad(request, fmt, &vpt, &pad, &fill)) {
1570                 return 0;
1571         }
1572
1573         if (outlen <= pad) {
1574                 RWARN("Output is too short!  Result will be truncated");
1575                 pad = outlen - 1;
1576         }
1577
1578         /*
1579          *      Print the attribute (left justified).  If it's too
1580          *      big, we're done.
1581          */
1582         len = tmpl_expand(NULL, out, pad + 1, request, vpt, NULL, NULL);
1583         if (len <= 0) return 0;
1584
1585         if ((size_t) len >= pad) return pad;
1586
1587         /*
1588          *      We have to shift the string to the right, and pad with
1589          *      "fill" characters.
1590          */
1591         memmove(out + (pad - len), out, len + 1);
1592         memset(out, fill, pad - len);
1593
1594         return pad;
1595 }
1596
1597
1598 /** right pad a string
1599  *
1600  *  %{rpad:&Attribute-Name length 'x'}
1601  */
1602 static ssize_t rpad_xlat(UNUSED void *instance, REQUEST *request,
1603                          char const *fmt, char *out, size_t outlen)
1604 {
1605         char fill;
1606         size_t pad;
1607         ssize_t len;
1608         vp_tmpl_t *vpt;
1609
1610         *out = '\0';
1611
1612         if (!parse_pad(request, fmt, &vpt, &pad, &fill)) {
1613                 return 0;
1614         }
1615
1616         if (outlen <= pad) {
1617                 RWARN("Output is too short!  Result will be truncated");
1618                 pad = outlen - 1;
1619         }
1620
1621         /*
1622          *      Print the attribute (left justified).  If it's too
1623          *      big, we're done.
1624          */
1625         len = tmpl_expand(NULL, out, pad + 1, request, vpt, NULL, NULL);
1626         if (len <= 0) return 0;
1627
1628         if ((size_t) len >= pad) return pad;
1629
1630         /*
1631          *      We have to pad with "fill" characters.
1632          */
1633         memset(out + len, fill, pad - len);
1634         out[pad] = '\0';
1635
1636         return pad;
1637 }
1638
1639
1640 /*
1641  *      Do any per-module initialization that is separate to each
1642  *      configured instance of the module.  e.g. set up connections
1643  *      to external databases, read configuration files, set up
1644  *      dictionary entries, etc.
1645  *
1646  *      If configuration information is given in the config section
1647  *      that must be referenced in later calls, store a handle to it
1648  *      in *instance otherwise put a null pointer there.
1649  */
1650 static int mod_bootstrap(CONF_SECTION *conf, void *instance)
1651 {
1652         rlm_expr_t *inst = instance;
1653
1654         inst->xlat_name = cf_section_name2(conf);
1655         if (!inst->xlat_name) {
1656                 inst->xlat_name = cf_section_name1(conf);
1657         }
1658
1659         xlat_register(inst->xlat_name, expr_xlat, NULL, inst);
1660
1661         xlat_register("rand", rand_xlat, NULL, inst);
1662         xlat_register("randstr", randstr_xlat, NULL, inst);
1663         xlat_register("urlquote", urlquote_xlat, NULL, inst);
1664         xlat_register("urlunquote", urlunquote_xlat, NULL, inst);
1665         xlat_register("escape", escape_xlat, NULL, inst);
1666         xlat_register("unescape", unescape_xlat, NULL, inst);
1667         xlat_register("tolower", lc_xlat, NULL, inst);
1668         xlat_register("toupper", uc_xlat, NULL, inst);
1669         xlat_register("md5", md5_xlat, NULL, inst);
1670         xlat_register("sha1", sha1_xlat, NULL, inst);
1671 #ifdef HAVE_OPENSSL_EVP_H
1672         xlat_register("sha256", sha256_xlat, NULL, inst);
1673         xlat_register("sha512", sha512_xlat, NULL, inst);
1674 #endif
1675         xlat_register("hmacmd5", hmac_md5_xlat, NULL, inst);
1676         xlat_register("hmacsha1", hmac_sha1_xlat, NULL, inst);
1677         xlat_register("pairs", pairs_xlat, NULL, inst);
1678
1679         xlat_register("base64", base64_xlat, NULL, inst);
1680         xlat_register("base64tohex", base64_to_hex_xlat, NULL, inst);
1681
1682         xlat_register("explode", explode_xlat, NULL, inst);
1683
1684         xlat_register("nexttime", next_time_xlat, NULL, inst);
1685         xlat_register("lpad", lpad_xlat, NULL, inst);
1686         xlat_register("rpad", rpad_xlat, NULL, inst);
1687
1688         /*
1689          *      Initialize various paircompare functions
1690          */
1691         pair_builtincompare_add(instance);
1692         return 0;
1693 }
1694
1695 /*
1696  *      The module name should be the only globally exported symbol.
1697  *      That is, everything else should be 'static'.
1698  *
1699  *      If the module needs to temporarily modify it's instantiation
1700  *      data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
1701  *      The server will then take care of ensuring that the module
1702  *      is single-threaded.
1703  */
1704 extern module_t rlm_expr;
1705 module_t rlm_expr = {
1706         .magic          = RLM_MODULE_INIT,
1707         .name           = "expr",
1708         .inst_size      = sizeof(rlm_expr_t),
1709         .config         = module_config,
1710         .bootstrap      = mod_bootstrap,
1711 };