Expose radius_tmpl_cast() for others to use
[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 *c)
51 {
52         size_t len;
53         char *p = buffer;
54         char *end = buffer + bufsize - 1;
55
56 next:
57         if (c->negate) {
58                 *(p++) = '!';   /* FIXME: only allow for child? */
59         }
60
61         switch (c->type) {
62         case COND_TYPE_EXISTS:
63                 rad_assert(c->data.vpt != NULL);
64                 if (c->cast) {
65                         len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types,
66                                                                       c->cast->type, "??"));
67                         p += len;
68                 }
69
70                 len = radius_tmpl2str(p, end - p, c->data.vpt);
71                 p += len;
72                 break;
73
74         case COND_TYPE_MAP:
75                 rad_assert(c->data.map != NULL);
76 #if 0
77                 *(p++) = '[';   /* for extra-clear debugging */
78 #endif
79                 if (c->cast) {
80                         len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types,
81                                                                       c->cast->type, "??"));
82                         p += len;
83                 }
84
85                 len = radius_map2str(p, end - p, c->data.map);
86                 p += len;
87 #if 0
88                 *(p++) = ']';
89 #endif
90                 break;
91
92         case COND_TYPE_CHILD:
93                 rad_assert(c->data.child != NULL);
94                 *(p++) = '(';
95                 len = fr_cond_sprint(p, end - p, c->data.child);
96                 p += len;
97                 *(p++) = ')';
98                 break;
99
100         case COND_TYPE_TRUE:
101                 strlcpy(buffer, "true", bufsize);
102                 return strlen(buffer);
103
104         case COND_TYPE_FALSE:
105                 strlcpy(buffer, "false", bufsize);
106                 return strlen(buffer);
107
108         default:
109                 *buffer = '\0';
110                 return 0;
111         }
112
113         if (c->next_op == COND_NONE) {
114                 rad_assert(c->next == NULL);
115                 *p = '\0';
116                 return p - buffer;
117         }
118
119         if (c->next_op == COND_AND) {
120                 strlcpy(p, " && ", end - p);
121                 p += strlen(p);
122
123         } else if (c->next_op == COND_OR) {
124                 strlcpy(p, " || ", end - p);
125                 p += strlen(p);
126
127         } else {
128                 rad_assert(0 == 1);
129         }
130
131         c = c->next;
132         goto next;
133 }
134
135
136 static ssize_t condition_tokenize_string(TALLOC_CTX *ctx, char const *start, char **out,
137                                          FR_TOKEN *op, char const **error)
138 {
139         char const *p = start;
140         char *q;
141
142         switch (*p++) {
143         default:
144                 return -1;
145
146         case '"':
147                 *op = T_DOUBLE_QUOTED_STRING;
148                 break;
149
150         case '\'':
151                 *op = T_SINGLE_QUOTED_STRING;
152                 break;
153
154         case '`':
155                 *op = T_BACK_QUOTED_STRING;
156                 break;
157
158         case '/':
159                 *op = T_OP_REG_EQ; /* a bit of a hack. */
160                 break;
161
162         }
163
164         *out = talloc_array(ctx, char, strlen(start) - 1); /* + 2 - 1 */
165         if (!*out) return -1;
166
167         q = *out;
168
169         while (*p) {
170                 if (*p == *start) {
171                         *q = '\0';
172                         p++;
173                         return (p - start);
174                 }
175
176                 if (*p == '\\') {
177                         p++;
178                         if (!*p) {
179                                 *error = "End of string after escape";
180                                 return -(p - start);
181                         }
182
183                         switch (*p) {
184                         case 'r':
185                                 *q++ = '\r';
186                                 break;
187                         case 'n':
188                                 *q++ = '\n';
189                                 break;
190                         case 't':
191                                 *q++ = '\t';
192                                 break;
193                         default:
194                                 *q++ = *p;
195                                 break;
196                         }
197                         p++;
198                         continue;
199                 }
200
201                 *(q++) = *(p++);
202         }
203
204         *error = "Unterminated string";
205         return -1;
206 }
207
208 static ssize_t condition_tokenize_word(TALLOC_CTX *ctx, char const *start, char **out,
209                                        FR_TOKEN *op, char const **error)
210 {
211         size_t len;
212         char const *p = start;
213
214         if ((*p == '"') || (*p == '\'') || (*p == '`') || (*p == '/')) {
215                 return condition_tokenize_string(ctx, start, out, op, error);
216         }
217
218         *op = T_BARE_WORD;
219         if (*p == '&') p++;     /* special-case &User-Name */
220
221         while (*p) {
222                 /*
223                  *      The LHS should really be limited to only a few
224                  *      things.  For now, we allow pretty much anything.
225                  */
226                 if (*p == '\\') {
227                         *error = "Unexpected escape";
228                         return -(p - start);
229                 }
230
231                 /*
232                  *      ("foo") is valid.
233                  */
234                 if (*p == ')') {
235                         break;
236                 }
237
238                 /*
239                  *      Spaces or special characters delineate the word
240                  */
241                 if (isspace((int) *p) || (*p == '&') || (*p == '|') ||
242                     (*p == '!') || (*p == '=') || (*p == '<') || (*p == '>')) {
243                         break;
244                 }
245
246                 if ((*p == '"') || (*p == '\'') || (*p == '`')) {
247                         *error = "Unexpected start of string";
248                         return -(p - start);
249                 }
250
251                 p++;
252         }
253
254         len = p - start;
255         if (!len) {
256                 *error = "Empty string is invalid";
257                 return 0;
258         }
259
260         *out = talloc_array(ctx, char, len + 1);
261         memcpy(*out, start, len);
262         (*out)[len] = '\0';
263         return len;
264 }
265
266
267 static ssize_t condition_tokenize_cast(char const *start, DICT_ATTR const **pda, char const **error)
268 {
269         char const *p = start;
270         char const *q;
271         PW_TYPE cast;
272
273         while (isspace((int) *p)) p++; /* skip spaces before condition */
274
275         if (*p != '<') return 0;
276         p++;
277
278         q = p;
279         while (*q && *q != '>') q++;
280
281         cast = fr_substr2int(dict_attr_types, p, PW_TYPE_INVALID, q - p);
282         if (cast == PW_TYPE_INVALID) {
283                 *error = "Invalid data type in cast";
284                 return -(p - start);
285         }
286
287         *pda = dict_attrbyvalue(PW_CAST_BASE + cast, 0);
288         if (!*pda) {
289                 *error = "Cannot cast to this data type";
290                 return -(p - start);
291         }
292
293         q++;
294
295         while (isspace((int) *q)) q++; /* skip spaces after cast */
296
297         return q - start;
298 }
299
300 /*
301  *      Less code means less bugs
302  */
303 #define return_P(_x) *error = _x;goto return_p
304 #define return_0(_x) *error = _x;goto return_0
305 #define return_lhs(_x) *error = _x;goto return_lhs
306 #define return_rhs(_x) *error = _x;goto return_rhs
307 #define return_SLEN goto return_slen
308
309
310 /** Tokenize a conditional check
311  *
312  *  @param[in] ctx for talloc
313  *  @param[in] ci for CONF_ITEM
314  *  @param[in] start the start of the string to process.  Should be "(..."
315  *  @param[in] brace look for a closing brace
316  *  @param[in] flags do one/two pass
317  *  @param[out] pcond pointer to the returned condition structure
318  *  @param[out] error the parse error (if any)
319  *  @return length of the string skipped, or when negative, the offset to the offending error
320  */
321 static ssize_t condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, int brace, fr_cond_t **pcond, char const **error, int flags)
322 {
323         ssize_t slen;
324         char const *p = start;
325         char const *lhs_p, *rhs_p;
326         fr_cond_t *c;
327         char *lhs, *rhs;
328         FR_TOKEN op, lhs_type, rhs_type;
329
330         c = talloc_zero(ctx, fr_cond_t);
331
332         rad_assert(c != NULL);
333         lhs = rhs = NULL;
334         lhs_type = rhs_type = T_OP_INVALID;
335
336         while (isspace((int) *p)) p++; /* skip spaces before condition */
337
338         if (!*p) {
339                 return_P("Empty condition is invalid");
340         }
341
342         /*
343          *      !COND
344          */
345         if (*p == '!') {
346                 p++;
347                 c->negate = true;
348                 while (isspace((int) *p)) p++; /* skip spaces after negation */
349
350                 /*
351                  *  Just for stupidity
352                  */
353                 if (*p == '!') {
354                         return_P("Double negation is invalid");
355                 }
356         }
357
358         /*
359          *      (COND)
360          */
361         if (*p == '(') {
362                 p++;
363
364                 /*
365                  *      We've already eaten one layer of
366                  *      brackets.  Go recurse to get more.
367                  */
368                 c->type = COND_TYPE_CHILD;
369                 c->ci = ci;
370                 slen = condition_tokenize(c, ci, p, true, &c->data.child, error, flags);
371                 if (slen <= 0) {
372                         return_SLEN;
373                 }
374
375                 if (!c->data.child) {
376                         return_P("Empty condition is invalid");
377                 }
378
379                 p += slen;
380                 while (isspace((int) *p)) p++; /* skip spaces after (COND)*/
381
382         } else { /* it's a bare FOO==BAR */
383                 /*
384                  *      We didn't see anything special.  The condition must be one of
385                  *
386                  *      FOO
387                  *      FOO OP BAR
388                  */
389
390                 /*
391                  *      Grab the LHS
392                  */
393                 if (*p == '/') {
394                         return_P("Conditional check cannot begin with a regular expression");
395                 }
396
397                 slen = condition_tokenize_cast(p, &c->cast, error);
398                 if (slen < 0) {
399                         return_SLEN;
400                 }
401                 p += slen;
402
403                 lhs_p = p;
404                 slen = condition_tokenize_word(c, p, &lhs, &lhs_type, error);
405                 if (slen <= 0) {
406                         return_SLEN;
407                 }
408                 p += slen;
409
410                 while (isspace((int)*p)) p++; /* skip spaces after LHS */
411
412                 /*
413                  *      We may (or not) have an operator
414                  */
415
416
417                 /*
418                  *      (FOO)
419                  */
420                 if (*p == ')') {
421                         /*
422                          *      don't skip the brace.  We'll look for it later.
423                          */
424                         goto exists;
425
426                         /*
427                          *      FOO
428                          */
429                 } else if (!*p) {
430                         if (brace) {
431                                 return_P("No closing brace at end of string");
432                         }
433
434                         goto exists;
435
436                         /*
437                          *      FOO && ...
438                          */
439                 } else if (((p[0] == '&') && (p[1] == '&')) ||
440                            ((p[0] == '|') && (p[1] == '|'))) {
441
442                 exists:
443                         if (c->cast) {
444                                 return_0("Cannot do cast for existence check");
445                         }
446
447                         c->type = COND_TYPE_EXISTS;
448                         c->ci = ci;
449
450                         c->data.vpt = radius_str2tmpl(c, lhs, lhs_type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
451                         if (!c->data.vpt) {
452                                 return_P("Failed creating exists");
453                         }
454
455                         rad_assert(c->data.vpt->type != VPT_TYPE_REGEX);
456
457                 } else { /* it's an operator */
458                         int regex;
459
460                         /*
461                          *      The next thing should now be a comparison operator.
462                          */
463                         regex = false;
464                         c->type = COND_TYPE_MAP;
465                         c->ci = ci;
466
467                         switch (*p) {
468                         default:
469                                 return_P("Invalid text. Expected comparison operator");
470
471                         case '!':
472                                 if (p[1] == '=') {
473                                         op = T_OP_NE;
474                                         p += 2;
475
476                                 } else if (p[1] == '~') {
477                                 regex = true;
478
479                                 op = T_OP_REG_NE;
480                                 p += 2;
481
482                                 } else if (p[1] == '*') {
483                                         if (lhs_type != T_BARE_WORD) {
484                                                 return_P("Cannot use !* on a string");
485                                         }
486
487                                         op = T_OP_CMP_FALSE;
488                                         p += 2;
489
490                                 } else {
491                                         goto invalid_operator;
492                                 }
493                                 break;
494
495                         case '=':
496                                 if (p[1] == '=') {
497                                         op = T_OP_CMP_EQ;
498                                         p += 2;
499
500                                 } else if (p[1] == '~') {
501                                         regex = true;
502
503                                         op = T_OP_REG_EQ;
504                                         p += 2;
505
506                                 } else if (p[1] == '*') {
507                                         if (lhs_type != T_BARE_WORD) {
508                                                 return_P("Cannot use =* on a string");
509                                         }
510
511                                         op = T_OP_CMP_TRUE;
512                                         p += 2;
513
514                                 } else {
515                                 invalid_operator:
516                                         return_P("Invalid operator");
517                                 }
518
519                                 break;
520
521                         case '<':
522                                 if (p[1] == '=') {
523                                         op = T_OP_LE;
524                                         p += 2;
525
526                                 } else {
527                                         op = T_OP_LT;
528                                         p++;
529                                 }
530                                 break;
531
532                         case '>':
533                                 if (p[1] == '=') {
534                                         op = T_OP_GE;
535                                         p += 2;
536
537                                 } else {
538                                         op = T_OP_GT;
539                                         p++;
540                                 }
541                                 break;
542                         }
543
544                         while (isspace((int) *p)) p++; /* skip spaces after operator */
545
546                         if (!*p) {
547                                 return_P("Expected text after operator");
548                         }
549
550                         /*
551                          *      Cannot have a cast on the RHS.
552                          *      But produce good errors, too.
553                          */
554                         if (*p == '<') {
555                                 DICT_ATTR const *cast_da;
556
557                                 slen = condition_tokenize_cast(p, &cast_da, error);
558                                 if (slen < 0) {
559                                         return_SLEN;
560                                 }
561
562                                 if (!c->cast) {
563                                         return_P("Unexpected cast");
564                                 }
565
566                                 if (c->cast != cast_da) {
567                                         return_P("Cannot cast to a different data type");
568                                 }
569
570                                 return_P("Unnecessary cast");
571                         }
572
573                         /*
574                          *      Grab the RHS
575                          */
576                         rhs_p = p;
577                         slen = condition_tokenize_word(c, p, &rhs, &rhs_type, error);
578                         if (slen <= 0) {
579                                 return_SLEN;
580                         }
581
582                         /*
583                          *      Sanity checks for regexes.
584                          */
585                         if (regex) {
586                                 if (*p != '/') {
587                                         return_P("Expected regular expression");
588                                 }
589
590                                 /*
591                                  *      Allow /foo/i
592                                  */
593                                 if (p[slen] == 'i') {
594                                         c->regex_i = true;
595                                         slen++;
596                                 }
597
598                         } else if (!regex && (*p == '/')) {
599                                 return_P("Unexpected regular expression");
600                         }
601
602                         c->data.map = radius_str2map(c, lhs, lhs_type, op, rhs, rhs_type,
603                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST,
604                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST);
605                         if (!c->data.map) {
606                                 if (*lhs == '&') {
607                                         /*
608                                          *      FIXME: In the future,
609                                          *      have str2map above
610                                          *      know whether this is
611                                          *      pass1 or pass2.  If
612                                          *      it's pass2, then an
613                                          *      unknown attribute is a
614                                          *      soft fail.
615                                          */
616                                         return_0("Unknown attribute");
617                                 }
618                                 return_0("Syntax error");
619                         }
620
621                         /*
622                          *      Could have been a reference to an attribute which is registered later.
623                          *      Mark it as being checked in pass2.
624                          */
625                         if ((lhs_type == T_BARE_WORD) &&
626                             (c->data.map->dst->type == VPT_TYPE_LITERAL)) {
627                                 c->pass2_fixup = PASS2_FIXUP_ATTR;
628                         }
629
630                         /*
631                          *      Save the CONF_ITEM for later.
632                          */
633                         c->data.map->ci = ci;
634
635                         /*
636                          *      @todo: check LHS and RHS separately, to
637                          *      get better errors
638                          */
639                         if ((c->data.map->src->type == VPT_TYPE_LIST) ||
640                             (c->data.map->dst->type == VPT_TYPE_LIST)) {
641                                 return_0("Cannot use list references in condition");
642                         }
643
644                         /*
645                          *      Check cast type.  We can have the RHS
646                          *      a string if the LHS has a cast.  But
647                          *      if the RHS is an attr, it MUST be the
648                          *      same type as the LHS.
649                          */
650                         if (c->cast) {
651                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
652                                     (c->cast->type != c->data.map->src->da->type)) {
653                                         goto same_type;
654                                 }
655
656                                 if (c->data.map->src->type == VPT_TYPE_REGEX) {
657                                         return_0("Cannot use cast with regex comparison");
658                                 }
659
660                                 /*
661                                  *      The LHS is a literal which has been cast to a data type.
662                                  *      Cast it to the appropriate data type.
663                                  */
664                                 if ((c->data.map->dst->type == VPT_TYPE_LITERAL) &&
665                                     !radius_cast_tmpl(c->data.map->dst, c->cast)) {
666                                         *error = "Failed to parse field";
667                                         if (lhs) talloc_free(lhs);
668                                         if (rhs) talloc_free(rhs);
669                                         talloc_free(c);
670                                         return -(lhs_p - start);
671                                 }
672
673                                 /*
674                                  *      The RHS is a literal, and the LHS has been cast to a data
675                                  *      type.
676                                  */
677                                 if ((c->data.map->dst->type == VPT_TYPE_DATA) &&
678                                     (c->data.map->src->type == VPT_TYPE_LITERAL) &&
679                                     !radius_cast_tmpl(c->data.map->src, c->data.map->dst->da)) {
680                                         return_rhs("Failed to parse field");
681                                 }
682
683                                 /*
684                                  *      Casting to a redundant type means we don't need the cast.
685                                  *
686                                  *      Do this LAST, as the rest of the code above assumes c->cast
687                                  *      is not NULL.
688                                  */
689                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
690                                     (c->cast->type == c->data.map->dst->da->type)) {
691                                         c->cast = NULL;
692                                 }
693
694                         } else {
695                                 /*
696                                  *      Two attributes?  They must be of the same type
697                                  */
698                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
699                                     (c->data.map->dst->type == VPT_TYPE_ATTR) &&
700                                     (c->data.map->dst->da->type != c->data.map->src->da->type)) {
701                                 same_type:
702                                         return_0("Attribute comparisons must be of the same data type");
703                                 }
704
705                                 /*
706                                  *      Without a cast, we can't compare "foo" to User-Name,
707                                  *      it has to be done the other way around.
708                                  */
709                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
710                                     (c->data.map->dst->type != VPT_TYPE_ATTR)) {
711                                         *error = "Cannot use attribute reference on right side of condition";
712                                 return_0:
713                                         if (lhs) talloc_free(lhs);
714                                         if (rhs) talloc_free(rhs);
715                                         talloc_free(c);
716                                         return 0;
717                                 }
718
719                                 /*
720                                  *      Invalid: User-Name == bob
721                                  *      Valid:   User-Name == "bob"
722                                  *
723                                  *      There's no real reason for
724                                  *      this, other than consistency.
725                                  */
726                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
727                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
728                                     (c->data.map->dst->da->type == PW_TYPE_STRING) &&
729                                     (c->data.map->op != T_OP_CMP_TRUE) &&
730                                     (c->data.map->op != T_OP_CMP_FALSE) &&
731                                     (rhs_type == T_BARE_WORD)) {
732                                         return_rhs("Must have string as value for attribute");
733                                 }
734
735                                 /*
736                                  *      Quotes around non-string
737                                  *      attributes mean that it's
738                                  *      either xlat, or an exec.
739                                  */
740                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
741                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
742                                     (c->data.map->dst->da->type != PW_TYPE_STRING) &&
743                                     (c->data.map->dst->da->type != PW_TYPE_OCTETS) &&
744                                     (c->data.map->dst->da->type != PW_TYPE_DATE) &&
745                                     (rhs_type == T_SINGLE_QUOTED_STRING)) {
746                                         *error = "Value must be an unquoted string";
747                                 return_rhs:
748                                         if (lhs) talloc_free(lhs);
749                                         if (rhs) talloc_free(rhs);
750                                         talloc_free(c);
751                                         return -(rhs_p - start);
752                                 }
753
754                                 /*
755                                  *      The LHS has been cast to a data type, and the RHS is a
756                                  *      literal.  Cast the RHS to the type of the cast.
757                                  */
758                                 if (c->cast && (c->data.map->src->type == VPT_TYPE_LITERAL) &&
759                                     !radius_cast_tmpl(c->data.map->src, c->cast)) {
760                                         return_rhs("Failed to parse field");
761                                 }
762
763                                 /*
764                                  *      The LHS is an attribute, and the RHS is a literal.  Cast the
765                                  *      RHS to the data type of the LHS.
766                                  */
767                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
768                                     (c->data.map->src->type == VPT_TYPE_LITERAL) &&
769                                     !radius_cast_tmpl(c->data.map->src, c->data.map->dst->da)) {
770                                         DICT_ATTR const *da = c->data.map->dst->da;
771
772                                         if ((da->vendor == 0) &&
773                                             ((da->attr == PW_AUTH_TYPE) ||
774                                              (da->attr == PW_AUTZ_TYPE) ||
775                                              (da->attr == PW_ACCT_TYPE) ||
776                                              (da->attr == PW_SESSION_TYPE) ||
777                                              (da->attr == PW_POST_AUTH_TYPE) ||
778                                              (da->attr == PW_PRE_PROXY_TYPE) ||
779                                              (da->attr == PW_POST_PROXY_TYPE) ||
780                                              (da->attr == PW_PRE_ACCT_TYPE) ||
781                                              (da->attr == PW_RECV_COA_TYPE) ||
782                                              (da->attr == PW_SEND_COA_TYPE))) {
783                                                 /*
784                                                  *      The types for these attributes are dynamically allocated
785                                                  *      by modules.c, so we can't enforce strictness here.
786                                                  */
787                                                 c->pass2_fixup = PASS2_FIXUP_TYPE;
788
789                                         } else {
790                                                 return_rhs("Failed to parse value for attribute");
791                                         }
792                                 }
793                         }
794
795                         p += slen;
796
797                         while (isspace((int) *p)) p++; /* skip spaces after RHS */
798                 } /* parse OP RHS */
799         } /* parse a condition (COND) or FOO OP BAR*/
800
801         /*
802          *      ...COND)
803          */
804         if (*p == ')') {
805                 if (!brace) {
806                         return_P("Unexpected closing brace");
807                 }
808
809                 p++;
810                 while (isspace((int) *p)) p++; /* skip spaces after closing brace */
811                 goto done;
812         }
813
814         /*
815          *      End of string is now allowed.
816          */
817         if (!*p) {
818                 if (brace) {
819                         return_P("No closing brace at end of string");
820                 }
821
822                 goto done;
823         }
824
825         if (!(((p[0] == '&') && (p[1] == '&')) ||
826               ((p[0] == '|') && (p[1] == '|')))) {
827                 *error = "Unexpected text after condition";
828         return_p:
829                 if (lhs) talloc_free(lhs);
830                 if (rhs) talloc_free(rhs);
831                 talloc_free(c);
832                 return -(p - start);
833         }
834
835         /*
836          *      Recurse to parse the next condition.
837          */
838         c->next_op = p[0];
839         p += 2;
840
841         /*
842          *      May still be looking for a closing brace.
843          */
844         slen = condition_tokenize(c, ci, p, brace, &c->next, error, flags);
845         if (slen <= 0) {
846         return_slen:
847                 if (lhs) talloc_free(lhs);
848                 if (rhs) talloc_free(rhs);
849                 talloc_free(c);
850                 return slen - (p - start);
851         }
852         p += slen;
853
854 done:
855         /*
856          *      Normalize the condition before returning.
857          *
858          *      We collapse multiple levels of braces to one.  Then
859          *      convert maps to literals.  Then literals to true/false
860          *      statements.  Then true/false ||/&& followed by other
861          *      conditions to just conditions.
862          *
863          *      Order is important.  The more complex cases are
864          *      converted to simpler ones, from the most complex cases
865          *      to the simplest ones.
866          */
867
868         /*
869          *      (FOO)     --> FOO
870          *      (FOO) ... --> FOO ...
871          */
872         if ((c->type == COND_TYPE_CHILD) && !c->data.child->next) {
873                 fr_cond_t *child;
874
875                 child = talloc_steal(ctx, c->data.child);
876                 c->data.child = NULL;
877
878                 child->next = talloc_steal(child, c->next);
879                 c->next = NULL;
880
881                 child->next_op = c->next_op;
882
883                 /*
884                  *      Set the negation properly
885                  */
886                 if ((c->negate && !child->negate) ||
887                     (!c->negate && child->negate)) {
888                         child->negate = true;
889                 } else {
890                         child->negate = false;
891                 }
892
893                 lhs = rhs = NULL;
894                 talloc_free(c);
895                 c = child;
896         }
897
898         /*
899          *      (FOO ...) --> FOO ...
900          *
901          *      But don't do !(FOO || BAR) --> !FOO || BAR
902          *      Because that's different.
903          */
904         if ((c->type == COND_TYPE_CHILD) &&
905             !c->next && !c->negate) {
906                 fr_cond_t *child;
907
908                 child = talloc_steal(ctx, c->data.child);
909                 c->data.child = NULL;
910
911                 lhs = rhs = NULL;
912                 talloc_free(c);
913                 c = child;
914         }
915
916         /*
917          *      Convert maps to literals.  Convert one form of map to
918          *      a standardized form.  This doesn't make any
919          *      theoretical difference, but it does mean that the
920          *      run-time evaluation has fewer cases to check.
921          */
922         if (c->type == COND_TYPE_MAP) do {
923                 /*
924                  *      !FOO !~ BAR --> FOO =~ BAR
925                  */
926                 if (c->negate && (c->data.map->op == T_OP_REG_NE)) {
927                         c->negate = false;
928                         c->data.map->op = T_OP_REG_EQ;
929                 }
930
931                 /*
932                  *      FOO !~ BAR --> !FOO =~ BAR
933                  */
934                 if (!c->negate && (c->data.map->op == T_OP_REG_NE)) {
935                         c->negate = true;
936                         c->data.map->op = T_OP_REG_EQ;
937                 }
938
939                 /*
940                  *      !FOO != BAR --> FOO == BAR
941                  */
942                 if (c->negate && (c->data.map->op == T_OP_NE)) {
943                         c->negate = false;
944                         c->data.map->op = T_OP_CMP_EQ;
945                 }
946
947                 /*
948                  *      This next one catches "LDAP-Group != foo",
949                  *      which doesn't work as-is, but this hack fixes
950                  *      it.
951                  *
952                  *      FOO != BAR --> !FOO == BAR
953                  */
954                 if (!c->negate && (c->data.map->op == T_OP_NE)) {
955                         c->negate = true;
956                         c->data.map->op = T_OP_CMP_EQ;
957                 }
958
959                 /*
960                  *      FOO =* BAR --> FOO
961                  *      FOO !* BAR --> !FOO
962                  */
963                 if ((c->data.map->op == T_OP_CMP_TRUE) ||
964                     (c->data.map->op == T_OP_CMP_FALSE)) {
965                         value_pair_tmpl_t *vpt;
966
967                         vpt = talloc_steal(c, c->data.map->dst);
968                         c->data.map->dst = NULL;
969
970                         /*
971                          *      Invert the negation bit.
972                          */
973                         if (c->data.map->op == T_OP_CMP_FALSE) {
974                                 c->negate = !c->negate;
975                         }
976
977                         TALLOC_FREE(c->data.map);
978
979                         c->type = COND_TYPE_EXISTS;
980                         c->data.vpt = vpt;
981                         break;  /* it's no longer a map */
982                 }
983
984                 /*
985                  *      Both are data (IP address, integer, etc.)
986                  *
987                  *      We can do the evaluation here, so that it
988                  *      doesn't need to be done at run time
989                  */
990                 if ((c->data.map->dst->type == VPT_TYPE_DATA) &&
991                     (c->data.map->src->type == VPT_TYPE_DATA)) {
992                         int rcode;
993
994                         rad_assert(c->cast != NULL);
995
996                         rcode = radius_evaluate_map(NULL, 0, 0, c);
997                         TALLOC_FREE(c->data.map);
998                         c->cast = NULL;
999                         c->regex_i = false;
1000                         if (rcode) {
1001                                 c->type = COND_TYPE_TRUE;
1002                         } else {
1003                                 c->type = COND_TYPE_FALSE;
1004                         }
1005
1006                         break;  /* it's no longer a map */
1007                 }
1008
1009                 /*
1010                  *      Both are literal strings.  They're not parsed
1011                  *      as VPT_TYPE_DATA because there's no cast to an
1012                  *      attribute.
1013                  *
1014                  *      We can do the evaluation here, so that it
1015                  *      doesn't need to be done at run time
1016                  */
1017                 if ((c->data.map->src->type == VPT_TYPE_LITERAL) &&
1018                     (c->data.map->dst->type == VPT_TYPE_LITERAL)) {
1019                         int rcode;
1020
1021                         rad_assert(c->cast == NULL);
1022                         rad_assert(c->regex_i == false);
1023
1024                         rcode = radius_evaluate_map(NULL, 0, 0, c);
1025                         if (rcode) {
1026                                 c->type = COND_TYPE_TRUE;
1027                         } else {
1028                                 c->type = COND_TYPE_FALSE;
1029                         }
1030
1031                         /*
1032                          *      Free map after using it above.
1033                          */
1034                         TALLOC_FREE(c->data.map);
1035                         break;
1036                 }
1037         } while (0);
1038
1039         /*
1040          *      Existence checks.  We short-circuit static strings,
1041          *      too.
1042          */
1043         if (c->type == COND_TYPE_EXISTS) {
1044                 switch (c->data.vpt->type) {
1045                 case VPT_TYPE_XLAT:
1046                 case VPT_TYPE_ATTR:
1047                 case VPT_TYPE_LIST:
1048                 case VPT_TYPE_EXEC:
1049                         break;
1050
1051                         /*
1052                          *      'true' and 'false' are special strings
1053                          *      which mean themselves.
1054                          *
1055                          *      For integers, 0 is false, all other
1056                          *      integers are true.
1057                          *
1058                          *      For strings, '' and "" are false.
1059                          *      'foo' and "foo" are true.
1060                          *
1061                          *      The str2tmpl function takes care of
1062                          *      marking "%{foo}" as VPT_TYPE_XLAT, so
1063                          *      the strings here are fixed at compile
1064                          *      time.
1065                          *
1066                          *      `exec` and "%{...}" are left alone.
1067                          *
1068                          *      Bare words must be module return
1069                          *      codes.
1070                          */
1071                 case VPT_TYPE_LITERAL:
1072                         if ((strcmp(c->data.vpt->name, "true") == 0) ||
1073                             (strcmp(c->data.vpt->name, "1") == 0)) {
1074                                 c->type = COND_TYPE_TRUE;
1075                                 TALLOC_FREE(c->data.vpt);
1076
1077                         } else if ((strcmp(c->data.vpt->name, "false") == 0) ||
1078                                    (strcmp(c->data.vpt->name, "0") == 0)) {
1079                                 c->type = COND_TYPE_FALSE;
1080                                 TALLOC_FREE(c->data.vpt);
1081
1082                         } else if (!*c->data.vpt->name) {
1083                                 c->type = COND_TYPE_FALSE;
1084                                 TALLOC_FREE(c->data.vpt);
1085
1086                         } else if ((lhs_type == T_SINGLE_QUOTED_STRING) ||
1087                                    (lhs_type == T_DOUBLE_QUOTED_STRING)) {
1088                                 c->type = COND_TYPE_TRUE;
1089                                 TALLOC_FREE(c->data.vpt);
1090
1091                         } else if (lhs_type == T_BARE_WORD) {
1092                                 int rcode;
1093                                 char const *q;
1094
1095                                 for (q = c->data.vpt->name;
1096                                      *q != '\0';
1097                                      q++) {
1098                                         if (!isdigit((int) *q)) {
1099                                                 break;
1100                                         }
1101                                 }
1102
1103                                 /*
1104                                  *      It's all digits, and therefore
1105                                  *      'true'.
1106                                  */
1107                                 if (!*q) {
1108                                         c->type = COND_TYPE_TRUE;
1109                                         TALLOC_FREE(c->data.vpt);
1110                                         break;
1111                                 }
1112
1113                                 rcode = fr_str2int(allowed_return_codes,
1114                                                    c->data.vpt->name, 0);
1115                                 if (!rcode) {
1116                                         return_0("Expected a module return code");
1117                                 }
1118                         }
1119
1120                         /*
1121                          *      Else lhs_type==T_OP_INVALID, and this
1122                          *      node was made by promoting a child
1123                          *      which had already been normalized.
1124                          */
1125                         break;
1126
1127                 case VPT_TYPE_DATA:
1128                         return_0("Cannot use data here");
1129
1130                 default:
1131                         return_0("Internal sanity check failed");
1132                 }
1133         }
1134
1135         /*
1136          *      !TRUE -> FALSE
1137          */
1138         if (c->type == COND_TYPE_TRUE) {
1139                 if (c->negate) {
1140                         c->negate = false;
1141                         c->type = COND_TYPE_FALSE;
1142                 }
1143         }
1144
1145         /*
1146          *      !FALSE -> TRUE
1147          */
1148         if (c->type == COND_TYPE_FALSE) {
1149                 if (c->negate) {
1150                         c->negate = false;
1151                         c->type = COND_TYPE_TRUE;
1152                 }
1153         }
1154
1155         /*
1156          *      true && FOO --> FOO
1157          */
1158         if ((c->type == COND_TYPE_TRUE) &&
1159             (c->next_op == COND_AND)) {
1160                 fr_cond_t *next;
1161
1162                 next = talloc_steal(ctx, c->next);
1163                 c->next = NULL;
1164
1165                 lhs = rhs = NULL;
1166                 talloc_free(c);
1167                 c = next;
1168         }
1169
1170         /*
1171          *      false && FOO --> false
1172          */
1173         if ((c->type == COND_TYPE_FALSE) &&
1174             (c->next_op == COND_AND)) {
1175                 talloc_free(c->next);
1176                 c->next = NULL;
1177                 c->next_op = COND_NONE;
1178         }
1179
1180         /*
1181          *      false || FOO --> FOO
1182          */
1183         if ((c->type == COND_TYPE_FALSE) &&
1184             (c->next_op == COND_OR)) {
1185                 fr_cond_t *next;
1186
1187                 next = talloc_steal(ctx, c->next);
1188                 c->next = NULL;
1189
1190                 lhs = rhs = NULL;
1191                 talloc_free(c);
1192                 c = next;
1193         }
1194
1195         /*
1196          *      true || FOO --> true
1197          */
1198         if ((c->type == COND_TYPE_TRUE) &&
1199             (c->next_op == COND_OR)) {
1200                 talloc_free(c->next);
1201                 c->next = NULL;
1202                 c->next_op = COND_NONE;
1203         }
1204
1205         if (lhs) talloc_free(lhs);
1206         if (rhs) talloc_free(rhs);
1207
1208         *pcond = c;
1209         return p - start;
1210 }
1211
1212 /** Tokenize a conditional check
1213  *
1214  *  @param[in] ctx for talloc
1215  *  @param[in] ci for CONF_ITEM
1216  *  @param[in] start the start of the string to process.  Should be "(..."
1217  *  @param[out] head the parsed condition structure
1218  *  @param[out] error the parse error (if any)
1219  *  @param[in] flags do one/two pass
1220  *  @return length of the string skipped, or when negative, the offset to the offending error
1221  */
1222 ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flags)
1223 {
1224         return condition_tokenize(ctx, ci, start, false, head, error, flags);
1225 }
1226
1227 /*
1228  *      Walk in order.
1229  */
1230 bool fr_condition_walk(fr_cond_t *c, bool (*callback)(void *, fr_cond_t *), void *ctx)
1231 {
1232         while (c) {
1233                 /*
1234                  *      Process this one, exit on error.
1235                  */
1236                 if (!callback(ctx, c)) return false;
1237
1238                 switch (c->type) {
1239                 case COND_TYPE_INVALID:
1240                         return false;
1241
1242                 case COND_TYPE_EXISTS:
1243                 case COND_TYPE_MAP:
1244                 case COND_TYPE_TRUE:
1245                 case COND_TYPE_FALSE:
1246                         break;
1247
1248                 case COND_TYPE_CHILD:
1249                         /*
1250                          *      Walk over the child.
1251                          */
1252                         if (!fr_condition_walk(c->data.child, callback, ctx)) {
1253                                 return false;
1254                         }
1255                 }
1256
1257                 /*
1258                  *      No sibling, stop.
1259                  */
1260                 if (c->next_op == COND_NONE) break;
1261
1262                 /*
1263                  *      process the next sibling
1264                  */
1265                 c = c->next;
1266         }
1267
1268         return true;
1269 }