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