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