Remove redundant file from freeradius-abfab list.
[freeradius.git] / src / main / parser.c
1 /*
2  * parser.c     Parse various things
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 2013  Alan DeKok <aland@freeradius.org>
21  */
22
23 RCSID("$Id$")
24
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/parser.h>
27 #include <freeradius-devel/rad_assert.h>
28
29 #include <ctype.h>
30
31 #define PW_CAST_BASE (1850)
32
33 static const FR_NAME_NUMBER allowed_return_codes[] = {
34         { "reject",     1 },
35         { "fail",       1 },
36         { "ok",         1 },
37         { "handled",    1 },
38         { "invalid",    1 },
39         { "userlock",   1 },
40         { "notfound",   1 },
41         { "noop",       1 },
42         { "updated",    1 },
43         { NULL, 0 }
44 };
45
46 /*
47  *      This file shouldn't use any functions from the server core.
48  */
49
50 size_t fr_cond_sprint(char *buffer, size_t bufsize, fr_cond_t const *in)
51 {
52         size_t len;
53         char *p = buffer;
54         char *end = buffer + bufsize - 1;
55         fr_cond_t const *c = in;
56
57         rad_assert(bufsize > 0);
58
59 next:
60         if (!c) {
61                 p[0] = '\0';
62                 return 0;
63         }
64
65         if (c->negate) {
66                 *(p++) = '!';   /* FIXME: only allow for child? */
67         }
68
69         switch (c->type) {
70         case COND_TYPE_EXISTS:
71                 rad_assert(c->data.vpt != NULL);
72                 if (c->cast) {
73                         len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types,
74                                                                       c->cast->type, "??"));
75                         p += len;
76                 }
77
78                 len = tmpl_prints(p, end - p, c->data.vpt, NULL);
79                 p += len;
80                 break;
81
82         case COND_TYPE_MAP:
83                 rad_assert(c->data.map != NULL);
84 #if 0
85                 *(p++) = '[';   /* for extra-clear debugging */
86 #endif
87                 if (c->cast) {
88                         len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types,
89                                                                       c->cast->type, "??"));
90                         p += len;
91                 }
92
93                 len = map_prints(p, end - p, c->data.map);
94                 p += len;
95 #if 0
96                 *(p++) = ']';
97 #endif
98                 break;
99
100         case COND_TYPE_CHILD:
101                 rad_assert(c->data.child != NULL);
102                 *(p++) = '(';
103                 len = fr_cond_sprint(p, end - p, c->data.child);
104                 p += len;
105                 *(p++) = ')';
106                 break;
107
108         case COND_TYPE_TRUE:
109                 strlcpy(buffer, "true", bufsize);
110                 return strlen(buffer);
111
112         case COND_TYPE_FALSE:
113                 strlcpy(buffer, "false", bufsize);
114                 return strlen(buffer);
115
116         default:
117                 *buffer = '\0';
118                 return 0;
119         }
120
121         if (c->next_op == COND_NONE) {
122                 rad_assert(c->next == NULL);
123                 *p = '\0';
124                 return p - buffer;
125         }
126
127         if (c->next_op == COND_AND) {
128                 strlcpy(p, " && ", end - p);
129                 p += strlen(p);
130
131         } else if (c->next_op == COND_OR) {
132                 strlcpy(p, " || ", end - p);
133                 p += strlen(p);
134
135         } else {
136                 rad_assert(0 == 1);
137         }
138
139         c = c->next;
140         goto next;
141 }
142
143
144 static ssize_t condition_tokenize_string(TALLOC_CTX *ctx, char **out,  char const **error, char const *start,
145                                          FR_TOKEN *op)
146 {
147         char const *p = start;
148         char *q;
149
150         switch (*p++) {
151         default:
152                 return -1;
153
154         case '"':
155                 *op = T_DOUBLE_QUOTED_STRING;
156                 break;
157
158         case '\'':
159                 *op = T_SINGLE_QUOTED_STRING;
160                 break;
161
162         case '`':
163                 *op = T_BACK_QUOTED_STRING;
164                 break;
165
166         case '/':
167                 *op = T_OP_REG_EQ; /* a bit of a hack. */
168                 break;
169
170         }
171
172         *out = talloc_array(ctx, char, strlen(start) - 1); /* + 2 - 1 */
173         if (!*out) return -1;
174
175         q = *out;
176
177         while (*p) {
178                 if (*p == *start) {
179                         /*
180                          *      Call the STANDARD parse function to figure out what the string is.
181                          */
182                         if (cf_new_escape) {
183                                 ssize_t slen;
184                                 value_data_t data;
185                                 char quote = *start;
186                                 PW_TYPE src_type = PW_TYPE_STRING;
187
188                                 /*
189                                  *      Regex compilers can handle escapes.  So we don't do it.
190                                  */
191                                 if (quote == '/') quote = '\0';
192
193                                 slen = value_data_from_str(ctx, &data, &src_type, NULL, start + 1, p - (start + 1), quote);
194                                 if (slen < 0) {
195                                         *error = "error parsing string";
196                                         return slen - 1;
197                                 }
198
199                                 talloc_free(*out);
200                                 *out = talloc_steal(ctx, data.ptr);
201                                 data.strvalue = NULL;
202                         } else {
203                                 char *out2;
204
205                                 *(q++) = '\0'; /* terminate the output string */
206
207                                 out2 = talloc_realloc(ctx, *out, char, (q - *out));
208                                 if (!out2) {
209                                         *error = "Out of memory";
210                                         return -1;
211                                 }
212                                 *out = out2;
213                         }
214
215                         p++;
216                         return (p - start);
217                 }
218
219                 if (*p == '\\') {
220                         if (!p[1]) {
221                                 p++;
222                                 *error = "End of string after escape";
223                                 return -(p - start);
224                         }
225
226                         /*
227                          *      Hacks for backwards compatibility
228                          */
229                         if (cf_new_escape) {
230                                 if (p[1] == start[0]) { /* Convert '\'' --> ' */
231                                         p++;
232                                 } else {
233                                         *(q++) = *(p++);
234                                 }
235
236                         } else {
237                                 switch (p[1]) {
238                                 case 'r':
239                                         *q++ = '\r';
240                                         break;
241                                 case 'n':
242                                         *q++ = '\n';
243                                         break;
244                                 case 't':
245                                         *q++ = '\t';
246                                         break;
247                                 default:
248                                         *q++ = p[1];
249                                         break;
250                                 }
251                                 p += 2;
252                                 continue;
253                         }
254
255                 }
256                 *(q++) = *(p++);
257         }
258
259         *error = "Unterminated string";
260         return -1;
261 }
262
263 static ssize_t condition_tokenize_word(TALLOC_CTX *ctx, char const *start, char **out,
264                                        FR_TOKEN *op, char const **error)
265 {
266         size_t len;
267         char const *p = start;
268
269         if ((*p == '"') || (*p == '\'') || (*p == '`') || (*p == '/')) {
270                 return condition_tokenize_string(ctx, out, error, start, op);
271         }
272
273         *op = T_BARE_WORD;
274         if (*p == '&') p++;     /* special-case &User-Name */
275
276         while (*p) {
277                 /*
278                  *      The LHS should really be limited to only a few
279                  *      things.  For now, we allow pretty much anything.
280                  */
281                 if (*p == '\\') {
282                         *error = "Unexpected escape";
283                         return -(p - start);
284                 }
285
286                 /*
287                  *      ("foo") is valid.
288                  */
289                 if (*p == ')') {
290                         break;
291                 }
292
293                 /*
294                  *      Spaces or special characters delineate the word
295                  */
296                 if (isspace((int) *p) || (*p == '&') || (*p == '|') ||
297                     (*p == '!') || (*p == '=') || (*p == '<') || (*p == '>')) {
298                         break;
299                 }
300
301                 if ((*p == '"') || (*p == '\'') || (*p == '`')) {
302                         *error = "Unexpected start of string";
303                         return -(p - start);
304                 }
305
306                 p++;
307         }
308
309         len = p - start;
310         if (!len) {
311                 *error = "Empty string is invalid";
312                 return 0;
313         }
314
315         *out = talloc_array(ctx, char, len + 1);
316         memcpy(*out, start, len);
317         (*out)[len] = '\0';
318         return len;
319 }
320
321
322 static ssize_t condition_tokenize_cast(char const *start, DICT_ATTR const **pda, char const **error)
323 {
324         char const *p = start;
325         char const *q;
326         PW_TYPE cast;
327
328         while (isspace((int) *p)) p++; /* skip spaces before condition */
329
330         if (*p != '<') return 0;
331         p++;
332
333         q = p;
334         while (*q && *q != '>') q++;
335
336         cast = fr_substr2int(dict_attr_types, p, PW_TYPE_INVALID, q - p);
337         if (cast == PW_TYPE_INVALID) {
338                 *error = "Invalid data type in cast";
339                 return -(p - start);
340         }
341
342         /*
343          *      We can only cast to basic data types.  Complex ones
344          *      are forbidden.
345          */
346         switch (cast) {
347 #ifdef WITH_ASCEND_BINARY
348         case PW_TYPE_ABINARY:
349 #endif
350         case PW_TYPE_COMBO_IP_ADDR:
351         case PW_TYPE_TLV:
352         case PW_TYPE_EXTENDED:
353         case PW_TYPE_LONG_EXTENDED:
354         case PW_TYPE_EVS:
355         case PW_TYPE_VSA:
356                 *error = "Forbidden data type in cast";
357                 return -(p - start);
358
359         default:
360                 break;
361         }
362
363         *pda = dict_attrbyvalue(PW_CAST_BASE + cast, 0);
364         if (!*pda) {
365                 *error = "Cannot cast to this data type";
366                 return -(p - start);
367         }
368
369         q++;
370
371         while (isspace((int) *q)) q++; /* skip spaces after cast */
372
373         return q - start;
374 }
375
376 static bool condition_check_types(fr_cond_t *c, PW_TYPE lhs_type)
377 {
378         /*
379          *      SOME integer mismatch is OK.  If the LHS has a large type,
380          *      and the RHS has a small type, it's OK.
381          *
382          *      If the LHS has a small type, and the RHS has a large type,
383          *      then add a cast to the LHS.
384          */
385         if (lhs_type == PW_TYPE_INTEGER64) {
386                 if ((c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER) ||
387                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_SHORT) ||
388                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_BYTE)) {
389                         c->cast = NULL;
390                         return true;
391                 }
392         }
393
394         if (lhs_type == PW_TYPE_INTEGER) {
395                 if ((c->data.map->rhs->tmpl_da->type == PW_TYPE_SHORT) ||
396                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_BYTE)) {
397                         c->cast = NULL;
398                         return true;
399                 }
400
401                 if (c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER64) {
402                         c->cast = c->data.map->rhs->tmpl_da;
403                         return true;
404                 }
405         }
406
407         if (lhs_type == PW_TYPE_SHORT) {
408                 if (c->data.map->rhs->tmpl_da->type == PW_TYPE_BYTE) {
409                         c->cast = NULL;
410                         return true;
411                 }
412
413                 if ((c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER64) ||
414                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER)) {
415                         c->cast = c->data.map->rhs->tmpl_da;
416                         return true;
417                 }
418         }
419
420         if (lhs_type == PW_TYPE_BYTE) {
421                 if ((c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER64) ||
422                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_INTEGER) ||
423                     (c->data.map->rhs->tmpl_da->type == PW_TYPE_SHORT)) {
424                         c->cast = c->data.map->rhs->tmpl_da;
425                         return true;
426                 }
427         }
428
429         if ((lhs_type == PW_TYPE_IPV4_PREFIX) &&
430             (c->data.map->rhs->tmpl_da->type == PW_TYPE_IPV4_ADDR)) {
431                 return true;
432         }
433
434         if ((lhs_type == PW_TYPE_IPV6_PREFIX) &&
435             (c->data.map->rhs->tmpl_da->type == PW_TYPE_IPV6_ADDR)) {
436                 return true;
437         }
438
439         return false;
440 }
441
442
443 /*
444  *      Less code means less bugs
445  */
446 #define return_P(_x) *error = _x;goto return_p
447 #define return_0(_x) *error = _x;goto return_0
448 #define return_lhs(_x) *error = _x;goto return_lhs
449 #define return_rhs(_x) *error = _x;goto return_rhs
450 #define return_SLEN goto return_slen
451
452
453 /** Tokenize a conditional check
454  *
455  *  @param[in] ctx for talloc
456  *  @param[in] ci for CONF_ITEM
457  *  @param[in] start the start of the string to process.  Should be "(..."
458  *  @param[in] brace look for a closing brace
459  *  @param[out] pcond pointer to the returned condition structure
460  *  @param[out] error the parse error (if any)
461  *  @param[in] flags do one/two pass
462  *  @return length of the string skipped, or when negative, the offset to the offending error
463  */
464 static ssize_t condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, bool brace,
465                                   fr_cond_t **pcond, char const **error, int flags)
466 {
467         ssize_t slen, tlen;
468         char const *p = start;
469         char const *lhs_p, *rhs_p;
470         fr_cond_t *c;
471         char *lhs, *rhs;
472         FR_TOKEN op, lhs_type, rhs_type;
473
474         c = talloc_zero(ctx, fr_cond_t);
475
476         rad_assert(c != NULL);
477         lhs = rhs = NULL;
478         lhs_type = rhs_type = T_INVALID;
479
480         while (isspace((int) *p)) p++; /* skip spaces before condition */
481
482         if (!*p) {
483                 return_P("Empty condition is invalid");
484         }
485
486         /*
487          *      !COND
488          */
489         if (*p == '!') {
490                 p++;
491                 c->negate = true;
492                 while (isspace((int) *p)) p++; /* skip spaces after negation */
493
494                 /*
495                  *  Just for stupidity
496                  */
497                 if (*p == '!') {
498                         return_P("Double negation is invalid");
499                 }
500         }
501
502         /*
503          *      (COND)
504          */
505         if (*p == '(') {
506                 p++;
507
508                 /*
509                  *      We've already eaten one layer of
510                  *      brackets.  Go recurse to get more.
511                  */
512                 c->type = COND_TYPE_CHILD;
513                 c->ci = ci;
514                 slen = condition_tokenize(c, ci, p, true, &c->data.child, error, flags);
515                 if (slen <= 0) {
516                         return_SLEN;
517                 }
518
519                 if (!c->data.child) {
520                         return_P("Empty condition is invalid");
521                 }
522
523                 p += slen;
524                 while (isspace((int) *p)) p++; /* skip spaces after (COND)*/
525
526         } else { /* it's a bare FOO==BAR */
527                 /*
528                  *      We didn't see anything special.  The condition must be one of
529                  *
530                  *      FOO
531                  *      FOO OP BAR
532                  */
533
534                 /*
535                  *      Grab the LHS
536                  */
537                 if (*p == '/') {
538                         return_P("Conditional check cannot begin with a regular expression");
539                 }
540
541                 slen = condition_tokenize_cast(p, &c->cast, error);
542                 if (slen < 0) {
543                         return_SLEN;
544                 }
545                 p += slen;
546
547                 lhs_p = p;
548                 slen = condition_tokenize_word(c, p, &lhs, &lhs_type, error);
549                 if (slen <= 0) {
550                         return_SLEN;
551                 }
552                 p += slen;
553
554                 /*
555                  *      If the LHS is 0xabcdef... automatically cast it to octets
556                  */
557                 if (!c->cast && (lhs_type == T_BARE_WORD) &&
558                     (lhs[0] == '0') && (lhs[1] == 'x') &&
559                     ((slen & 0x01) == 0)) {
560                         if (slen == 2) {
561                                 return_P("Empty octet string is invalid");
562                         }
563
564                         c->cast = dict_attrbyvalue(PW_CAST_BASE + PW_TYPE_OCTETS, 0);
565                 }
566
567                 while (isspace((int)*p)) p++; /* skip spaces after LHS */
568
569                 /*
570                  *      We may (or not) have an operator
571                  */
572
573
574                 /*
575                  *      (FOO)
576                  */
577                 if (*p == ')') {
578                         /*
579                          *      don't skip the brace.  We'll look for it later.
580                          */
581                         goto exists;
582
583                         /*
584                          *      FOO
585                          */
586                 } else if (!*p) {
587                         if (brace) {
588                                 return_P("No closing brace at end of string");
589                         }
590
591                         goto exists;
592
593                         /*
594                          *      FOO && ...
595                          */
596                 } else if (((p[0] == '&') && (p[1] == '&')) ||
597                            ((p[0] == '|') && (p[1] == '|'))) {
598
599                 exists:
600                         if (c->cast) {
601                                 return_0("Cannot do cast for existence check");
602                         }
603
604                         c->type = COND_TYPE_EXISTS;
605                         c->ci = ci;
606
607                         tlen = tmpl_afrom_str(c, &c->data.vpt, lhs, talloc_array_length(lhs) - 1,
608                                               lhs_type, REQUEST_CURRENT, PAIR_LIST_REQUEST, false);
609                         if (tlen < 0) {
610                                 p = lhs_p - tlen;
611                                 return_P(fr_strerror());
612                         }
613
614                         rad_assert(c->data.vpt->type != TMPL_TYPE_REGEX);
615
616                         if (c->data.vpt->type == TMPL_TYPE_ATTR_UNDEFINED) {
617                                 c->pass2_fixup = PASS2_FIXUP_ATTR;
618                         }
619
620                 } else { /* it's an operator */
621 #ifdef HAVE_REGEX
622                         bool regex = false;
623                         bool iflag = false;
624                         bool mflag = false;
625 #endif
626                         vp_map_t *map;
627
628                         /*
629                          *      The next thing should now be a comparison operator.
630                          */
631                         c->type = COND_TYPE_MAP;
632                         c->ci = ci;
633
634                         switch (*p) {
635                         default:
636                                 return_P("Invalid text. Expected comparison operator");
637
638                         case '!':
639                                 if (p[1] == '=') {
640                                         op = T_OP_NE;
641                                         p += 2;
642
643 #ifdef HAVE_REGEX
644                                 } else if (p[1] == '~') {
645                                         regex = true;
646
647                                         op = T_OP_REG_NE;
648                                         p += 2;
649 #endif
650
651                                 } else if (p[1] == '*') {
652                                         if (lhs_type != T_BARE_WORD) {
653                                                 return_P("Cannot use !* on a string");
654                                         }
655
656                                         op = T_OP_CMP_FALSE;
657                                         p += 2;
658
659                                 } else {
660                                         goto invalid_operator;
661                                 }
662                                 break;
663
664                         case '=':
665                                 if (p[1] == '=') {
666                                         op = T_OP_CMP_EQ;
667                                         p += 2;
668
669 #ifdef HAVE_REGEX
670                                 } else if (p[1] == '~') {
671                                         regex = true;
672
673                                         op = T_OP_REG_EQ;
674                                         p += 2;
675 #endif
676
677                                 } else if (p[1] == '*') {
678                                         if (lhs_type != T_BARE_WORD) {
679                                                 return_P("Cannot use =* on a string");
680                                         }
681
682                                         op = T_OP_CMP_TRUE;
683                                         p += 2;
684
685                                 } else {
686                                 invalid_operator:
687                                         return_P("Invalid operator");
688                                 }
689
690                                 break;
691
692                         case '<':
693                                 if (p[1] == '=') {
694                                         op = T_OP_LE;
695                                         p += 2;
696
697                                 } else {
698                                         op = T_OP_LT;
699                                         p++;
700                                 }
701                                 break;
702
703                         case '>':
704                                 if (p[1] == '=') {
705                                         op = T_OP_GE;
706                                         p += 2;
707
708                                 } else {
709                                         op = T_OP_GT;
710                                         p++;
711                                 }
712                                 break;
713                         }
714
715                         while (isspace((int) *p)) p++; /* skip spaces after operator */
716
717                         if (!*p) {
718                                 return_P("Expected text after operator");
719                         }
720
721                         /*
722                          *      Cannot have a cast on the RHS.
723                          *      But produce good errors, too.
724                          */
725                         if (*p == '<') {
726                                 DICT_ATTR const *cast_da;
727
728                                 slen = condition_tokenize_cast(p, &cast_da, error);
729                                 if (slen < 0) {
730                                         return_SLEN;
731                                 }
732
733                                 if (!c->cast) {
734                                         return_P("Unexpected cast");
735                                 }
736
737                                 if (c->cast != cast_da) {
738                                         return_P("Cannot cast to a different data type");
739                                 }
740
741                                 return_P("Unnecessary cast");
742                         }
743
744                         /*
745                          *      Grab the RHS
746                          */
747                         rhs_p = p;
748                         slen = condition_tokenize_word(c, p, &rhs, &rhs_type, error);
749                         if (slen <= 0) {
750                                 return_SLEN;
751                         }
752
753 #ifdef HAVE_REGEX
754                         /*
755                          *      Sanity checks for regexes.
756                          */
757                         if (regex) {
758                                 if (*p != '/') {
759                                         return_P("Expected regular expression");
760                                 }
761                                 for (;;) {
762                                         switch (p[slen]) {
763                                         /*
764                                          *      /foo/i
765                                          */
766                                         case 'i':
767                                                 iflag = true;
768                                                 slen++;
769                                                 continue;
770
771                                         /*
772                                          *      /foo/m
773                                          */
774                                         case 'm':
775                                                 mflag = true;
776                                                 slen++;
777                                                 continue;
778
779                                         default:
780                                                 break;
781                                         }
782                                         break;
783                                 }
784                         } else if (!regex && (*p == '/')) {
785                                 return_P("Unexpected regular expression");
786                         }
787
788 #endif
789                         /*
790                          *      Duplicate map_from_fields here, as we
791                          *      want to separate parse errors in the
792                          *      LHS from ones in the RHS.
793                          */
794                         c->data.map = map = talloc_zero(c, vp_map_t);
795
796                         tlen = tmpl_afrom_str(map, &map->lhs, lhs, talloc_array_length(lhs) - 1,
797                                               lhs_type, REQUEST_CURRENT, PAIR_LIST_REQUEST, false);
798                         if (tlen < 0) {
799                                 p = lhs_p - tlen;
800                                 return_P(fr_strerror());
801                         }
802
803                         if (tmpl_define_unknown_attr(map->lhs) < 0) {
804                                 return_lhs("Failed defining attribute");
805                         return_lhs:
806                                 if (lhs) talloc_free(lhs);
807                                 if (rhs) talloc_free(rhs);
808                                 talloc_free(c);
809                                 return -(lhs_p - start);
810                         }
811
812                         map->op = op;
813
814                         /*
815                          *      If the RHS is 0xabcdef... automatically cast it to octets
816                          *      unless the LHS is an attribute of type octets, or an
817                          *      integer type.
818                          */
819                         if (!c->cast && (rhs_type == T_BARE_WORD) &&
820                             (rhs[0] == '0') && (rhs[1] == 'x') &&
821                             ((slen & 0x01) == 0)) {
822                                 if (slen == 2) {
823                                         return_P("Empty octet string is invalid");
824                                 }
825
826                                 if ((map->lhs->type != TMPL_TYPE_ATTR) ||
827                                     !((map->lhs->tmpl_da->type == PW_TYPE_OCTETS) ||
828                                       (map->lhs->tmpl_da->type == PW_TYPE_BYTE) ||
829                                       (map->lhs->tmpl_da->type == PW_TYPE_SHORT) ||
830                                       (map->lhs->tmpl_da->type == PW_TYPE_INTEGER) ||
831                                       (map->lhs->tmpl_da->type == PW_TYPE_INTEGER64))) {
832                                         c->cast = dict_attrbyvalue(PW_CAST_BASE + PW_TYPE_OCTETS, 0);
833                                 }
834                         }
835
836                         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
837                             map->lhs->tmpl_da->flags.is_unknown &&
838                             map_cast_from_hex(map, rhs_type, rhs)) {
839                                 /* do nothing */
840
841                         } else {
842                                 tlen = tmpl_afrom_str(map, &map->rhs, rhs, talloc_array_length(rhs) - 1, rhs_type,
843                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, false);
844                                 if (tlen < 0) {
845                                         p = rhs_p - tlen;
846                                         return_P(fr_strerror());
847                                 }
848
849                                 if (tmpl_define_unknown_attr(map->rhs) < 0) {
850                                         return_rhs("Failed defining attribute");
851                                 }
852                         }
853
854                         /*
855                          *      Unknown attributes get marked up for pass2.
856                          */
857                         if ((c->data.map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) ||
858                             (c->data.map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED)) {
859                                 c->pass2_fixup = PASS2_FIXUP_ATTR;
860                         }
861
862 #ifdef HAVE_REGEX
863                         if (c->data.map->rhs->type == TMPL_TYPE_REGEX) {
864                                 c->data.map->rhs->tmpl_iflag = iflag;
865                                 c->data.map->rhs->tmpl_mflag = mflag;
866                         }
867 #endif
868
869                         /*
870                          *      Save the CONF_ITEM for later.
871                          */
872                         c->data.map->ci = ci;
873
874                         /*
875                          *      @todo: check LHS and RHS separately, to
876                          *      get better errors
877                          */
878                         if ((c->data.map->rhs->type == TMPL_TYPE_LIST) ||
879                             (c->data.map->lhs->type == TMPL_TYPE_LIST)) {
880                                 return_0("Cannot use list references in condition");
881                         }
882
883                         /*
884                          *      Check cast type.  We can have the RHS
885                          *      a string if the LHS has a cast.  But
886                          *      if the RHS is an attr, it MUST be the
887                          *      same type as the LHS.
888                          */
889                         if (c->cast) {
890                                 if ((c->data.map->rhs->type == TMPL_TYPE_ATTR) &&
891                                     (c->cast->type != c->data.map->rhs->tmpl_da->type)) {
892                                         if (condition_check_types(c, c->cast->type)) {
893                                                 goto keep_going;
894                                         }
895
896                                         goto same_type;
897                                 }
898
899 #ifdef HAVE_REGEX
900                                 if (c->data.map->rhs->type == TMPL_TYPE_REGEX) {
901                                         return_0("Cannot use cast with regex comparison");
902                                 }
903 #endif
904
905                                 /*
906                                  *      The LHS is a literal which has been cast to a data type.
907                                  *      Cast it to the appropriate data type.
908                                  */
909                                 if ((c->data.map->lhs->type == TMPL_TYPE_LITERAL) &&
910                                     (tmpl_cast_in_place(c->data.map->lhs, c->cast->type, c->cast) < 0)) {
911                                         *error = "Failed to parse field";
912                                         if (lhs) talloc_free(lhs);
913                                         if (rhs) talloc_free(rhs);
914                                         talloc_free(c);
915                                         return -(lhs_p - start);
916                                 }
917
918                                 /*
919                                  *      The RHS is a literal, and the LHS has been cast to a data
920                                  *      type.
921                                  */
922                                 if ((c->data.map->lhs->type == TMPL_TYPE_DATA) &&
923                                     (c->data.map->rhs->type == TMPL_TYPE_LITERAL) &&
924                                     (tmpl_cast_in_place(c->data.map->rhs, c->cast->type, c->cast) < 0)) {
925                                         return_rhs("Failed to parse field");
926                                 }
927
928                                 /*
929                                  *      We may be casting incompatible
930                                  *      types.  We check this based on
931                                  *      their size.
932                                  */
933                                 if (c->data.map->lhs->type == TMPL_TYPE_ATTR) {
934                                         /*
935                                          *      dst.min == src.min
936                                          *      dst.max == src.max
937                                          */
938                                         if ((dict_attr_sizes[c->cast->type][0] == dict_attr_sizes[c->data.map->lhs->tmpl_da->type][0]) &&
939                                             (dict_attr_sizes[c->cast->type][1] == dict_attr_sizes[c->data.map->lhs->tmpl_da->type][1])) {
940                                                 goto cast_ok;
941                                         }
942
943                                         /*
944                                          *      Run-time parsing of strings.
945                                          *      Run-time copying of octets.
946                                          */
947                                         if ((c->data.map->lhs->tmpl_da->type == PW_TYPE_STRING) ||
948                                             (c->data.map->lhs->tmpl_da->type == PW_TYPE_OCTETS)) {
949                                                 goto cast_ok;
950                                         }
951
952                                         /*
953                                          *      ifid to integer64 is OK
954                                          */
955                                         if ((c->data.map->lhs->tmpl_da->type == PW_TYPE_IFID) &&
956                                             (c->cast->type == PW_TYPE_INTEGER64)) {
957                                                 goto cast_ok;
958                                         }
959
960                                         /*
961                                          *      ipaddr to ipv4prefix is OK
962                                          */
963                                         if ((c->data.map->lhs->tmpl_da->type == PW_TYPE_IPV4_ADDR) &&
964                                             (c->cast->type == PW_TYPE_IPV4_PREFIX)) {
965                                                 goto cast_ok;
966                                         }
967
968                                         /*
969                                          *      ipv6addr to ipv6prefix is OK
970                                          */
971                                         if ((c->data.map->lhs->tmpl_da->type == PW_TYPE_IPV6_ADDR) &&
972                                             (c->cast->type == PW_TYPE_IPV6_PREFIX)) {
973                                                 goto cast_ok;
974                                         }
975
976                                         /*
977                                          *      integer64 to ethernet is OK.
978                                          */
979                                         if ((c->data.map->lhs->tmpl_da->type == PW_TYPE_INTEGER64) &&
980                                             (c->cast->type == PW_TYPE_ETHERNET)) {
981                                                 goto cast_ok;
982                                         }
983
984                                         /*
985                                          *      dst.max < src.min
986                                          *      dst.min > src.max
987                                          */
988                                         if ((dict_attr_sizes[c->cast->type][1] < dict_attr_sizes[c->data.map->lhs->tmpl_da->type][0]) ||
989                                             (dict_attr_sizes[c->cast->type][0] > dict_attr_sizes[c->data.map->lhs->tmpl_da->type][1])) {
990                                                 return_0("Cannot cast to attribute of incompatible size");
991                                         }
992                                 }
993
994                         cast_ok:
995                                 /*
996                                  *      Casting to a redundant type means we don't need the cast.
997                                  *
998                                  *      Do this LAST, as the rest of the code above assumes c->cast
999                                  *      is not NULL.
1000                                  */
1001                                 if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
1002                                     (c->cast->type == c->data.map->lhs->tmpl_da->type)) {
1003                                         c->cast = NULL;
1004                                 }
1005
1006                         } else {
1007                                 vp_tmpl_t *vpt;
1008
1009                                 /*
1010                                  *      Two attributes?  They must be of the same type
1011                                  */
1012                                 if ((c->data.map->rhs->type == TMPL_TYPE_ATTR) &&
1013                                     (c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
1014                                     (c->data.map->lhs->tmpl_da->type != c->data.map->rhs->tmpl_da->type)) {
1015                                         if (condition_check_types(c, c->data.map->lhs->tmpl_da->type)) {
1016                                                 goto keep_going;
1017                                         }
1018
1019                                 same_type:
1020                                         return_0("Attribute comparisons must be of the same data type");
1021                                 }
1022
1023                                 /*
1024                                  *      Without a cast, we can't compare "foo" to User-Name,
1025                                  *      it has to be done the other way around.
1026                                  */
1027                                 if ((c->data.map->rhs->type == TMPL_TYPE_ATTR) &&
1028                                     (c->data.map->lhs->type != TMPL_TYPE_ATTR)) {
1029                                         *error = "Cannot use attribute reference on right side of condition";
1030                                 return_0:
1031                                         if (lhs) talloc_free(lhs);
1032                                         if (rhs) talloc_free(rhs);
1033                                         talloc_free(c);
1034                                         return 0;
1035                                 }
1036
1037                                 /*
1038                                  *      Invalid: User-Name == bob
1039                                  *      Valid:   User-Name == "bob"
1040                                  *
1041                                  *      There's no real reason for
1042                                  *      this, other than consistency.
1043                                  */
1044                                 if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
1045                                     (c->data.map->rhs->type != TMPL_TYPE_ATTR) &&
1046                                     (c->data.map->lhs->tmpl_da->type == PW_TYPE_STRING) &&
1047                                     (c->data.map->op != T_OP_CMP_TRUE) &&
1048                                     (c->data.map->op != T_OP_CMP_FALSE) &&
1049                                     (rhs_type == T_BARE_WORD)) {
1050                                         return_rhs("Must have string as value for attribute");
1051                                 }
1052
1053                                 /*
1054                                  *      Quotes around non-string
1055                                  *      attributes mean that it's
1056                                  *      either xlat, or an exec.
1057                                  */
1058                                 if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
1059                                     (c->data.map->rhs->type != TMPL_TYPE_ATTR) &&
1060                                     (c->data.map->lhs->tmpl_da->type != PW_TYPE_STRING) &&
1061                                     (c->data.map->lhs->tmpl_da->type != PW_TYPE_OCTETS) &&
1062                                     (c->data.map->lhs->tmpl_da->type != PW_TYPE_DATE) &&
1063                                     (rhs_type == T_SINGLE_QUOTED_STRING)) {
1064                                         *error = "Value must be an unquoted string";
1065                                 return_rhs:
1066                                         if (lhs) talloc_free(lhs);
1067                                         if (rhs) talloc_free(rhs);
1068                                         talloc_free(c);
1069                                         return -(rhs_p - start);
1070                                 }
1071
1072                                 /*
1073                                  *      The LHS has been cast to a data type, and the RHS is a
1074                                  *      literal.  Cast the RHS to the type of the cast.
1075                                  */
1076                                 if (c->cast && (c->data.map->rhs->type == TMPL_TYPE_LITERAL) &&
1077                                     (tmpl_cast_in_place(c->data.map->rhs, c->cast->type, c->cast) < 0)) {
1078                                         return_rhs("Failed to parse field");
1079                                 }
1080
1081                                 /*
1082                                  *      The LHS is an attribute, and the RHS is a literal.  Cast the
1083                                  *      RHS to the data type of the LHS.
1084                                  *
1085                                  *      Note: There's a hack in here to always parse RHS as the
1086                                  *      equivalent prefix type if the LHS is an IP address.
1087                                  *
1088                                  *      This allows Framed-IP-Address < 192.168.0.0./24
1089                                  */
1090                                 if ((c->data.map->lhs->type == TMPL_TYPE_ATTR) &&
1091                                     (c->data.map->rhs->type == TMPL_TYPE_LITERAL)) {
1092                                         PW_TYPE type;
1093
1094                                         switch (c->data.map->lhs->tmpl_da->type) {
1095                                         case PW_TYPE_IPV4_ADDR:
1096                                                 type = PW_TYPE_IPV4_PREFIX;
1097                                                 break;
1098
1099                                         case PW_TYPE_IPV6_ADDR:
1100                                                 type = PW_TYPE_IPV6_PREFIX;
1101                                                 break;
1102
1103                                         default:
1104                                                 type = c->data.map->lhs->tmpl_da->type;
1105                                                 break;
1106                                         }
1107
1108                                         if (tmpl_cast_in_place(c->data.map->rhs, type, c->data.map->lhs->tmpl_da) < 0) {
1109                                                 DICT_ATTR const *da = c->data.map->lhs->tmpl_da;
1110
1111                                                 if ((da->vendor == 0) &&
1112                                                     ((da->attr == PW_AUTH_TYPE) ||
1113                                                      (da->attr == PW_AUTZ_TYPE) ||
1114                                                      (da->attr == PW_ACCT_TYPE) ||
1115                                                      (da->attr == PW_SESSION_TYPE) ||
1116                                                      (da->attr == PW_POST_AUTH_TYPE) ||
1117                                                      (da->attr == PW_PRE_PROXY_TYPE) ||
1118                                                      (da->attr == PW_POST_PROXY_TYPE) ||
1119                                                      (da->attr == PW_PRE_ACCT_TYPE) ||
1120                                                      (da->attr == PW_RECV_COA_TYPE) ||
1121                                                      (da->attr == PW_SEND_COA_TYPE))) {
1122                                                         /*
1123                                                          *      The types for these attributes are dynamically allocated
1124                                                          *      by modules.c, so we can't enforce strictness here.
1125                                                          */
1126                                                         c->pass2_fixup = PASS2_FIXUP_TYPE;
1127
1128                                                 } else {
1129                                                         return_rhs("Failed to parse value for attribute");
1130                                                 }
1131                                         }
1132
1133                                         /*
1134                                          *      Stupid WiMAX shit.
1135                                          *      Cast the LHS to the
1136                                          *      type of the RHS.
1137                                          */
1138                                         if (c->data.map->lhs->tmpl_da->type == PW_TYPE_COMBO_IP_ADDR) {
1139                                                 DICT_ATTR const *da;
1140
1141                                                 da = dict_attrbytype(c->data.map->lhs->tmpl_da->attr,
1142                                                                      c->data.map->lhs->tmpl_da->vendor,
1143                                                                      c->data.map->rhs->tmpl_data_type);
1144                                                 if (!da) {
1145                                                         return_rhs("Cannot find type for attribute");
1146                                                 }
1147                                                 c->data.map->lhs->tmpl_da = da;
1148                                         }
1149                                 } /* attr to literal comparison */
1150
1151                                 /*
1152                                  *      If the LHS is a bare word, AND it looks like
1153                                  *      an attribute, try to parse it as such.
1154                                  *
1155                                  *      This allows LDAP-Group and SQL-Group to work.
1156                                  *
1157                                  *      The real fix is to just read the config files,
1158                                  *      and do no parsing until after all of the modules
1159                                  *      are loaded.  But that has issues, too.
1160                                  */
1161                                 if ((c->data.map->lhs->type == TMPL_TYPE_LITERAL) &&
1162                                     (lhs_type == T_BARE_WORD) &&
1163                                     (c->data.map->rhs->type == TMPL_TYPE_LITERAL)) {
1164                                         int hyphens = 0;
1165                                         bool may_be_attr = true;
1166                                         size_t i;
1167                                         ssize_t attr_slen;
1168
1169                                         /*
1170                                          *      Backwards compatibility: Allow Foo-Bar,
1171                                          *      e.g. LDAP-Group and SQL-Group.
1172                                          */
1173                                         for (i = 0; i < c->data.map->lhs->len; i++) {
1174                                                 if (!dict_attr_allowed_chars[(unsigned char) c->data.map->lhs->name[i]]) {
1175                                                         may_be_attr = false;
1176                                                         break;
1177                                                 }
1178
1179                                                 if (c->data.map->lhs->name[i] == '-') {
1180                                                         hyphens++;
1181                                                         if (hyphens > 1) {
1182                                                                 may_be_attr = false;
1183                                                                 break;
1184                                                         }
1185                                                 }
1186                                         }
1187
1188                                         if (!hyphens || (hyphens > 3)) may_be_attr = false;
1189
1190                                         if (may_be_attr) {
1191                                                 attr_slen = tmpl_afrom_attr_str(c->data.map, &vpt, lhs,
1192                                                                                 REQUEST_CURRENT, PAIR_LIST_REQUEST,
1193                                                                                 true, true);
1194                                                 if ((attr_slen > 0) && (vpt->len == c->data.map->lhs->len)) {
1195                                                         talloc_free(c->data.map->lhs);
1196                                                         c->data.map->lhs = vpt;
1197                                                         c->pass2_fixup = PASS2_FIXUP_ATTR;
1198                                                 }
1199                                         }
1200                                 }
1201                         } /* we didn't have a cast */
1202
1203                 keep_going:
1204                         p += slen;
1205
1206                         while (isspace((int) *p)) p++; /* skip spaces after RHS */
1207                 } /* parse OP RHS */
1208         } /* parse a condition (COND) or FOO OP BAR*/
1209
1210         /*
1211          *      ...COND)
1212          */
1213         if (*p == ')') {
1214                 if (!brace) {
1215                         return_P("Unexpected closing brace");
1216                 }
1217
1218                 p++;
1219                 while (isspace((int) *p)) p++; /* skip spaces after closing brace */
1220                 goto done;
1221         }
1222
1223         /*
1224          *      End of string is now allowed.
1225          */
1226         if (!*p) {
1227                 if (brace) {
1228                         return_P("No closing brace at end of string");
1229                 }
1230
1231                 goto done;
1232         }
1233
1234         if (!(((p[0] == '&') && (p[1] == '&')) ||
1235               ((p[0] == '|') && (p[1] == '|')))) {
1236                 *error = "Unexpected text after condition";
1237         return_p:
1238                 if (lhs) talloc_free(lhs);
1239                 if (rhs) talloc_free(rhs);
1240                 talloc_free(c);
1241                 return -(p - start);
1242         }
1243
1244         /*
1245          *      Recurse to parse the next condition.
1246          */
1247         c->next_op = p[0];
1248         p += 2;
1249
1250         /*
1251          *      May still be looking for a closing brace.
1252          */
1253         slen = condition_tokenize(c, ci, p, brace, &c->next, error, flags);
1254         if (slen <= 0) {
1255         return_slen:
1256                 if (lhs) talloc_free(lhs);
1257                 if (rhs) talloc_free(rhs);
1258                 talloc_free(c);
1259                 return slen - (p - start);
1260         }
1261         p += slen;
1262
1263 done:
1264         /*
1265          *      Normalize the condition before returning.
1266          *
1267          *      We collapse multiple levels of braces to one.  Then
1268          *      convert maps to literals.  Then literals to true/false
1269          *      statements.  Then true/false ||/&& followed by other
1270          *      conditions to just conditions.
1271          *
1272          *      Order is important.  The more complex cases are
1273          *      converted to simpler ones, from the most complex cases
1274          *      to the simplest ones.
1275          */
1276
1277         /*
1278          *      (FOO)     --> FOO
1279          *      (FOO) ... --> FOO ...
1280          */
1281         if ((c->type == COND_TYPE_CHILD) && !c->data.child->next) {
1282                 fr_cond_t *child;
1283
1284                 child = talloc_steal(ctx, c->data.child);
1285                 c->data.child = NULL;
1286
1287                 child->next = talloc_steal(child, c->next);
1288                 c->next = NULL;
1289
1290                 child->next_op = c->next_op;
1291
1292                 /*
1293                  *      Set the negation properly
1294                  */
1295                 if ((c->negate && !child->negate) ||
1296                     (!c->negate && child->negate)) {
1297                         child->negate = true;
1298                 } else {
1299                         child->negate = false;
1300                 }
1301
1302                 lhs = rhs = NULL;
1303                 talloc_free(c);
1304                 c = child;
1305         }
1306
1307         /*
1308          *      (FOO ...) --> FOO ...
1309          *
1310          *      But don't do !(FOO || BAR) --> !FOO || BAR
1311          *      Because that's different.
1312          */
1313         if ((c->type == COND_TYPE_CHILD) &&
1314             !c->next && !c->negate) {
1315                 fr_cond_t *child;
1316
1317                 child = talloc_steal(ctx, c->data.child);
1318                 c->data.child = NULL;
1319
1320                 lhs = rhs = NULL;
1321                 talloc_free(c);
1322                 c = child;
1323         }
1324
1325         /*
1326          *      Convert maps to literals.  Convert one form of map to
1327          *      a standardized form.  This doesn't make any
1328          *      theoretical difference, but it does mean that the
1329          *      run-time evaluation has fewer cases to check.
1330          */
1331         if (c->type == COND_TYPE_MAP) do {
1332                 /*
1333                  *      !FOO !~ BAR --> FOO =~ BAR
1334                  */
1335                 if (c->negate && (c->data.map->op == T_OP_REG_NE)) {
1336                         c->negate = false;
1337                         c->data.map->op = T_OP_REG_EQ;
1338                 }
1339
1340                 /*
1341                  *      FOO !~ BAR --> !FOO =~ BAR
1342                  */
1343                 if (!c->negate && (c->data.map->op == T_OP_REG_NE)) {
1344                         c->negate = true;
1345                         c->data.map->op = T_OP_REG_EQ;
1346                 }
1347
1348                 /*
1349                  *      !FOO != BAR --> FOO == BAR
1350                  */
1351                 if (c->negate && (c->data.map->op == T_OP_NE)) {
1352                         c->negate = false;
1353                         c->data.map->op = T_OP_CMP_EQ;
1354                 }
1355
1356                 /*
1357                  *      This next one catches "LDAP-Group != foo",
1358                  *      which doesn't work as-is, but this hack fixes
1359                  *      it.
1360                  *
1361                  *      FOO != BAR --> !FOO == BAR
1362                  */
1363                 if (!c->negate && (c->data.map->op == T_OP_NE)) {
1364                         c->negate = true;
1365                         c->data.map->op = T_OP_CMP_EQ;
1366                 }
1367
1368                 /*
1369                  *      FOO =* BAR --> FOO
1370                  *      FOO !* BAR --> !FOO
1371                  *
1372                  *      FOO may be a string, or a delayed attribute
1373                  *      reference.
1374                  */
1375                 if ((c->data.map->op == T_OP_CMP_TRUE) ||
1376                     (c->data.map->op == T_OP_CMP_FALSE)) {
1377                         vp_tmpl_t *vpt;
1378
1379                         vpt = talloc_steal(c, c->data.map->lhs);
1380                         c->data.map->lhs = NULL;
1381
1382                         /*
1383                          *      Invert the negation bit.
1384                          */
1385                         if (c->data.map->op == T_OP_CMP_FALSE) {
1386                                 c->negate = !c->negate;
1387                         }
1388
1389                         TALLOC_FREE(c->data.map);
1390
1391                         c->type = COND_TYPE_EXISTS;
1392                         c->data.vpt = vpt;
1393                         break;  /* it's no longer a map */
1394                 }
1395
1396                 /*
1397                  *      Both are data (IP address, integer, etc.)
1398                  *
1399                  *      We can do the evaluation here, so that it
1400                  *      doesn't need to be done at run time
1401                  */
1402                 if ((c->data.map->lhs->type == TMPL_TYPE_DATA) &&
1403                     (c->data.map->rhs->type == TMPL_TYPE_DATA)) {
1404                         int rcode;
1405
1406                         rad_assert(c->cast != NULL);
1407
1408                         rcode = radius_evaluate_map(NULL, 0, 0, c);
1409                         TALLOC_FREE(c->data.map);
1410                         c->cast = NULL;
1411                         if (rcode) {
1412                                 c->type = COND_TYPE_TRUE;
1413                         } else {
1414                                 c->type = COND_TYPE_FALSE;
1415                         }
1416
1417                         break;  /* it's no longer a map */
1418                 }
1419
1420                 /*
1421                  *      Both are literal strings.  They're not parsed
1422                  *      as TMPL_TYPE_DATA because there's no cast to an
1423                  *      attribute.
1424                  *
1425                  *      We can do the evaluation here, so that it
1426                  *      doesn't need to be done at run time
1427                  */
1428                 if ((c->data.map->rhs->type == TMPL_TYPE_LITERAL) &&
1429                     (c->data.map->lhs->type == TMPL_TYPE_LITERAL) &&
1430                     !c->pass2_fixup) {
1431                         int rcode;
1432
1433                         rad_assert(c->cast == NULL);
1434
1435                         rcode = radius_evaluate_map(NULL, 0, 0, c);
1436                         if (rcode) {
1437                                 c->type = COND_TYPE_TRUE;
1438                         } else {
1439                                 DEBUG3("OPTIMIZING (%s %s %s) --> FALSE",
1440                                        c->data.map->lhs->name,
1441                                        fr_int2str(fr_tokens, c->data.map->op, "??"),
1442                                        c->data.map->rhs->name);
1443                                 c->type = COND_TYPE_FALSE;
1444                         }
1445
1446                         /*
1447                          *      Free map after using it above.
1448                          */
1449                         TALLOC_FREE(c->data.map);
1450                         break;
1451                 }
1452
1453                 /*
1454                  *      <ipaddr>"foo" CMP &Attribute-Name The cast may
1455                  *      not be necessary, and we can re-write it so
1456                  *      that the attribute reference is on the LHS.
1457                  */
1458                 if (c->cast &&
1459                     (c->data.map->rhs->type == TMPL_TYPE_ATTR) &&
1460                     (c->cast->type == c->data.map->rhs->tmpl_da->type) &&
1461                     (c->data.map->lhs->type != TMPL_TYPE_ATTR)) {
1462                         vp_tmpl_t *tmp;
1463
1464                         tmp = c->data.map->rhs;
1465                         c->data.map->rhs = c->data.map->lhs;
1466                         c->data.map->lhs = tmp;
1467
1468                         c->cast = NULL;
1469
1470                         switch (c->data.map->op) {
1471                         case T_OP_CMP_EQ:
1472                                 /* do nothing */
1473                                 break;
1474
1475                         case T_OP_LE:
1476                                 c->data.map->op = T_OP_GE;
1477                                 break;
1478
1479                         case T_OP_LT:
1480                                 c->data.map->op = T_OP_GT;
1481                                 break;
1482
1483                         case T_OP_GE:
1484                                 c->data.map->op = T_OP_LE;
1485                                 break;
1486
1487                         case T_OP_GT:
1488                                 c->data.map->op = T_OP_LT;
1489                                 break;
1490
1491                         default:
1492                                 return_0("Internal sanity check failed 1");
1493                         }
1494
1495                         /*
1496                          *      This must have been parsed into TMPL_TYPE_DATA.
1497                          */
1498                         rad_assert(c->data.map->rhs->type != TMPL_TYPE_LITERAL);
1499                 }
1500
1501         } while (0);
1502
1503         /*
1504          *      Existence checks.  We short-circuit static strings,
1505          *      too.
1506          *
1507          *      FIXME: the data types should be in the template, too.
1508          *      So that we know where a literal came from.
1509          *
1510          *      "foo" is NOT the same as 'foo' or a bare foo.
1511          */
1512         if (c->type == COND_TYPE_EXISTS) {
1513                 switch (c->data.vpt->type) {
1514                 case TMPL_TYPE_XLAT:
1515                 case TMPL_TYPE_ATTR:
1516                 case TMPL_TYPE_ATTR_UNDEFINED:
1517                 case TMPL_TYPE_LIST:
1518                 case TMPL_TYPE_EXEC:
1519                         break;
1520
1521                         /*
1522                          *      'true' and 'false' are special strings
1523                          *      which mean themselves.
1524                          *
1525                          *      For integers, 0 is false, all other
1526                          *      integers are true.
1527                          *
1528                          *      For strings, '' and "" are false.
1529                          *      'foo' and "foo" are true.
1530                          *
1531                          *      The str2tmpl function takes care of
1532                          *      marking "%{foo}" as TMPL_TYPE_XLAT, so
1533                          *      the strings here are fixed at compile
1534                          *      time.
1535                          *
1536                          *      `exec` and "%{...}" are left alone.
1537                          *
1538                          *      Bare words must be module return
1539                          *      codes.
1540                          */
1541                 case TMPL_TYPE_LITERAL:
1542                         if ((strcmp(c->data.vpt->name, "true") == 0) ||
1543                             (strcmp(c->data.vpt->name, "1") == 0)) {
1544                                 c->type = COND_TYPE_TRUE;
1545                                 TALLOC_FREE(c->data.vpt);
1546
1547                         } else if ((strcmp(c->data.vpt->name, "false") == 0) ||
1548                                    (strcmp(c->data.vpt->name, "0") == 0)) {
1549                                 c->type = COND_TYPE_FALSE;
1550                                 TALLOC_FREE(c->data.vpt);
1551
1552                         } else if (!*c->data.vpt->name) {
1553                                 c->type = COND_TYPE_FALSE;
1554                                 TALLOC_FREE(c->data.vpt);
1555
1556                         } else if ((lhs_type == T_SINGLE_QUOTED_STRING) ||
1557                                    (lhs_type == T_DOUBLE_QUOTED_STRING)) {
1558                                 c->type = COND_TYPE_TRUE;
1559                                 TALLOC_FREE(c->data.vpt);
1560
1561                         } else if (lhs_type == T_BARE_WORD) {
1562                                 int rcode;
1563                                 bool zeros = true;
1564                                 char const *q;
1565
1566                                 for (q = c->data.vpt->name;
1567                                      *q != '\0';
1568                                      q++) {
1569                                         if (!isdigit((int) *q)) {
1570                                                 break;
1571                                         }
1572                                         if (*q != '0') zeros = false;
1573                                 }
1574
1575                                 /*
1576                                  *      It's all digits, and therefore
1577                                  *      'false' if zero, and 'true' otherwise.
1578                                  */
1579                                 if (!*q) {
1580                                         if (zeros) {
1581                                                 c->type = COND_TYPE_FALSE;
1582                                         } else {
1583                                                 c->type = COND_TYPE_TRUE;
1584                                         }
1585                                         TALLOC_FREE(c->data.vpt);
1586                                         break;
1587                                 }
1588
1589                                 /*
1590                                  *      Allow &Foo-Bar where Foo-Bar is an attribute
1591                                  *      defined by a module.
1592                                  */
1593                                 if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
1594                                         break;
1595                                 }
1596
1597                                 rcode = fr_str2int(allowed_return_codes,
1598                                                    c->data.vpt->name, 0);
1599                                 if (!rcode) {
1600                                         return_0("Expected a module return code");
1601                                 }
1602                         }
1603
1604                         /*
1605                          *      Else lhs_type==T_INVALID, and this
1606                          *      node was made by promoting a child
1607                          *      which had already been normalized.
1608                          */
1609                         break;
1610
1611                 case TMPL_TYPE_DATA:
1612                         return_0("Cannot use data here");
1613
1614                 default:
1615                         return_0("Internal sanity check failed 2");
1616                 }
1617         }
1618
1619         /*
1620          *      !TRUE -> FALSE
1621          */
1622         if (c->type == COND_TYPE_TRUE) {
1623                 if (c->negate) {
1624                         c->negate = false;
1625                         c->type = COND_TYPE_FALSE;
1626                 }
1627         }
1628
1629         /*
1630          *      !FALSE -> TRUE
1631          */
1632         if (c->type == COND_TYPE_FALSE) {
1633                 if (c->negate) {
1634                         c->negate = false;
1635                         c->type = COND_TYPE_TRUE;
1636                 }
1637         }
1638
1639         /*
1640          *      true && FOO --> FOO
1641          */
1642         if ((c->type == COND_TYPE_TRUE) &&
1643             (c->next_op == COND_AND)) {
1644                 fr_cond_t *next;
1645
1646                 next = talloc_steal(ctx, c->next);
1647                 c->next = NULL;
1648
1649                 lhs = rhs = NULL;
1650                 talloc_free(c);
1651                 c = next;
1652         }
1653
1654         /*
1655          *      false && FOO --> false
1656          */
1657         if ((c->type == COND_TYPE_FALSE) &&
1658             (c->next_op == COND_AND)) {
1659                 talloc_free(c->next);
1660                 c->next = NULL;
1661                 c->next_op = COND_NONE;
1662         }
1663
1664         /*
1665          *      false || FOO --> FOO
1666          */
1667         if ((c->type == COND_TYPE_FALSE) &&
1668             (c->next_op == COND_OR)) {
1669                 fr_cond_t *next;
1670
1671                 next = talloc_steal(ctx, c->next);
1672                 c->next = NULL;
1673
1674                 lhs = rhs = NULL;
1675                 talloc_free(c);
1676                 c = next;
1677         }
1678
1679         /*
1680          *      true || FOO --> true
1681          */
1682         if ((c->type == COND_TYPE_TRUE) &&
1683             (c->next_op == COND_OR)) {
1684                 talloc_free(c->next);
1685                 c->next = NULL;
1686                 c->next_op = COND_NONE;
1687         }
1688
1689         if (lhs) talloc_free(lhs);
1690         if (rhs) talloc_free(rhs);
1691
1692         *pcond = c;
1693         return p - start;
1694 }
1695
1696 /** Tokenize a conditional check
1697  *
1698  *  @param[in] ctx for talloc
1699  *  @param[in] ci for CONF_ITEM
1700  *  @param[in] start the start of the string to process.  Should be "(..."
1701  *  @param[out] head the parsed condition structure
1702  *  @param[out] error the parse error (if any)
1703  *  @param[in] flags do one/two pass
1704  *  @return length of the string skipped, or when negative, the offset to the offending error
1705  */
1706 ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flags)
1707 {
1708         return condition_tokenize(ctx, ci, start, false, head, error, flags);
1709 }
1710
1711 /*
1712  *      Walk in order.
1713  */
1714 bool fr_condition_walk(fr_cond_t *c, bool (*callback)(void *, fr_cond_t *), void *ctx)
1715 {
1716         while (c) {
1717                 /*
1718                  *      Process this one, exit on error.
1719                  */
1720                 if (!callback(ctx, c)) return false;
1721
1722                 switch (c->type) {
1723                 case COND_TYPE_INVALID:
1724                         return false;
1725
1726                 case COND_TYPE_EXISTS:
1727                 case COND_TYPE_MAP:
1728                 case COND_TYPE_TRUE:
1729                 case COND_TYPE_FALSE:
1730                         break;
1731
1732                 case COND_TYPE_CHILD:
1733                         /*
1734                          *      Walk over the child.
1735                          */
1736                         if (!fr_condition_walk(c->data.child, callback, ctx)) {
1737                                 return false;
1738                         }
1739                 }
1740
1741                 /*
1742                  *      No sibling, stop.
1743                  */
1744                 if (c->next_op == COND_NONE) break;
1745
1746                 /*
1747                  *      process the next sibling
1748                  */
1749                 c = c->next;
1750         }
1751
1752         return true;
1753 }