Parse literals into VALUE_PAIR_DATA at compile 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         default:
88                 *buffer = '\0';
89                 return 0;
90         }
91
92         if (c->next_op == COND_NONE) {
93                 rad_assert(c->next == NULL);
94                 *p = '\0';
95                 return p - buffer;
96         }
97
98         if (c->next_op == COND_AND) {
99                 strlcpy(p, " && ", end - p);
100                 p += strlen(p);
101
102         } else if (c->next_op == COND_OR) {
103                 strlcpy(p, " || ", end - p);
104                 p += strlen(p);
105
106         } else {
107                 rad_assert(0 == 1);
108         }
109
110         c = c->next;
111         goto next;
112 }
113
114
115 /*
116  *      Cast a literal vpt to a value_pair_data
117  */
118 static int cast_vpt(value_pair_tmpl_t *vpt, DICT_ATTR const *da)
119 {
120         VALUE_PAIR *vp;
121         VALUE_PAIR_DATA *data;
122
123         rad_assert(vpt->type == VPT_TYPE_LITERAL);
124
125         vp = pairalloc(vpt, da);
126         if (!vp) return false;
127
128         if (!pairparsevalue(vp, vpt->name)) {
129                 pairfree(&vp);
130                 return false;
131         }
132
133         vpt->length = vp->length;
134         vpt->vpd = data = talloc(vpt, VALUE_PAIR_DATA);
135         if (!vpt->vpd) return false;
136
137         vpt->type = VPT_TYPE_DATA;
138         vpt->da = da;
139
140         memcpy(data, &vp->data, sizeof(*data));
141         pairfree(&vp);
142
143         return true;
144 }
145
146 static ssize_t condition_tokenize_string(TALLOC_CTX *ctx, char const *start, char **out,
147                                          FR_TOKEN *op, char const **error)
148 {
149         const char *p = start;
150         char *q;
151
152         switch (*p++) {
153         default:
154                 return -1;
155
156         case '"':
157                 *op = T_DOUBLE_QUOTED_STRING;
158                 break;
159
160         case '\'':
161                 *op = T_SINGLE_QUOTED_STRING;
162                 break;
163
164         case '`':
165                 *op = T_BACK_QUOTED_STRING;
166                 break;
167
168         case '/':
169                 *op = T_OP_REG_EQ; /* a bit of a hack. */
170                 break;
171
172         }
173
174         *out = talloc_array(ctx, char, strlen(start) - 1); /* + 2 - 1 */
175         if (!*out) return -1;
176
177         q = *out;
178
179         while (*p) {
180                 if (*p == *start) {
181                         *q = '\0';
182                         p++;
183                         return (p - start);
184                 }
185
186                 if (*p == '\\') {
187                         p++;
188                         if (!*p) {
189                                 *error = "End of string after escape";
190                                 return -(p - start);
191                         }
192
193                         switch (*p) {
194                         case 'r':
195                                 *q++ = '\r';
196                                 break;
197                         case 'n':
198                                 *q++ = '\n';
199                                 break;
200                         case 't':
201                                 *q++ = '\t';
202                                 break;
203                         default:
204                                 *q++ = *p;
205                                 break;
206                         }
207                         p++;
208                         continue;
209                 }
210         
211                 *(q++) = *(p++);
212         }
213
214         *error = "Unterminated string";
215         return -1;
216 }
217
218 static ssize_t condition_tokenize_word(TALLOC_CTX *ctx, char const *start, char **out,
219                                        FR_TOKEN *op, char const **error)
220 {
221         size_t len;
222         char const *p = start;
223
224         if ((*p == '"') || (*p == '\'') || (*p == '`') || (*p == '/')) {
225                 return condition_tokenize_string(ctx, start, out, op, error);
226         }
227
228         *op = T_BARE_WORD;
229         if (*p == '&') p++;     /* special-case &User-Name */
230
231         while (*p) {
232                 /*
233                  *      The LHS should really be limited to only a few
234                  *      things.  For now, we allow pretty much anything.
235                  */
236                 if (*p == '\\') {
237                         *error = "Unexpected escape";
238                         return -(p - start);
239                 }
240
241                 /*
242                  *      ("foo") is valid.
243                  */
244                 if (*p == ')') {
245                         break;
246                 }
247
248                 /*
249                  *      Spaces or special characters delineate the word
250                  */
251                 if (isspace((int) *p) || (*p == '&') || (*p == '|') ||
252                     (*p == '!') || (*p == '=') || (*p == '<') || (*p == '>')) {
253                         break;
254                 }
255
256                 if ((*p == '"') || (*p == '\'') || (*p == '`')) {
257                         *error = "Unexpected start of string";
258                         return -(p - start);
259                 }
260
261                 p++;
262         }
263
264         len = p - start;
265         if (!len) {
266                 *error = "Empty string is invalid";
267                 return 0;
268         }
269
270         *out = talloc_array(ctx, char, len + 1);
271         memcpy(*out, start, len);
272         (*out)[len] = '\0';
273         return len;
274 }
275
276
277 static ssize_t condition_tokenize_cast(char const *start, DICT_ATTR const **pda, char const **error)
278 {
279         char const *p = start;
280         char const *q;
281         PW_TYPE cast;
282
283         while (isspace((int) *p)) p++; /* skip spaces before condition */
284
285         if (*p != '<') return 0;
286         p++;
287
288         q = p;
289         while (*q && *q != '>') q++;
290
291         cast = fr_substr2int(dict_attr_types, p, PW_TYPE_INVALID, q - p);
292         if (cast == PW_TYPE_INVALID) {
293                 *error = "Invalid data type in cast";
294                 return -(p - start);
295         }
296
297         *pda = dict_attrbyvalue(PW_CAST_BASE + cast, 0);
298         if (!*pda) {
299                 *error = "Cannot cast to this data type";
300                 return -(p - start);
301         }
302
303         q++;
304
305         while (isspace((int) *q)) q++; /* skip spaces after cast */
306
307         return q - start;
308 }
309
310 /*
311  *      Less code means less bugs
312  */
313 #define return_P(_x) *error = _x;goto return_p
314 #define return_0(_x) *error = _x;goto return_0
315 #define return_lhs(_x) *error = _x;goto return_lhs
316 #define return_rhs(_x) *error = _x;goto return_rhs
317 #define return_SLEN goto return_slen
318
319
320 /** Tokenize a conditional check
321  *
322  *  @param[in] ctx for talloc
323  *  @param[in] start the start of the string to process.  Should be "(..."
324  *  @param[in] brace look for a closing brace
325  *  @param[out] pcond pointer to the returned condition structure
326  *  @param[out] error the parse error (if any)
327  *  @return length of the string skipped, or when negative, the offset to the offending error
328  */
329 static ssize_t condition_tokenize(TALLOC_CTX *ctx, char const *start, int brace, fr_cond_t **pcond, char const **error)
330 {
331         ssize_t slen;
332         const char *p = start;
333         const char *lhs_p, *rhs_p;
334         fr_cond_t *c;
335         char *lhs, *rhs;
336         FR_TOKEN op, lhs_type, rhs_type;
337
338         c = talloc_zero(ctx, fr_cond_t);
339
340         rad_assert(c != NULL);
341         lhs = rhs = NULL;
342
343         while (isspace((int) *p)) p++; /* skip spaces before condition */
344
345         if (!*p) {
346                 return_P("Empty condition is invalid");
347         }
348
349         /*
350          *      !COND
351          */
352         if (*p == '!') {
353                 p++;
354                 c->negate = true;
355                 while (isspace((int) *p)) p++; /* skip spaces after negation */
356
357                 /*
358                  *  Just for stupidity
359                  */
360                 if (*p == '!') {
361                         return_P("Double negation is invalid");
362                 }
363         }
364
365         /*
366          *      (COND)
367          */
368         if (*p == '(') {
369                 p++;
370
371                 /*
372                  *      We've already eaten one layer of
373                  *      brackets.  Go recurse to get more.
374                  */
375                 c->type = COND_TYPE_CHILD;
376                 slen = condition_tokenize(c, p, true, &c->data.child, error);
377                 if (slen <= 0) {
378                         return_SLEN;
379                 }
380
381                 if (!c->data.child) {
382                         return_P("Empty condition is invalid");
383                 }
384
385                 p += slen;
386                 while (isspace((int) *p)) p++; /* skip spaces after (COND)*/
387
388         } else { /* it's a bare FOO==BAR */
389                 /*
390                  *      We didn't see anything special.  The condition must be one of
391                  *
392                  *      FOO
393                  *      FOO OP BAR
394                  */
395
396                 /*
397                  *      Grab the LHS
398                  */
399                 if (*p == '/') {
400                         return_P("Conditional check cannot begin with a regular expression");
401                 }
402
403                 slen = condition_tokenize_cast(p, &c->cast, error);
404                 if (slen < 0) {
405                         return_SLEN;
406                 }
407                 p += slen;
408
409                 lhs_p = p;
410                 slen = condition_tokenize_word(c, p, &lhs, &lhs_type, error);
411                 if (slen <= 0) {
412                         return_SLEN;
413                 }
414                 p += slen;
415
416                 while (isspace((int)*p)) p++; /* skip spaces after LHS */
417
418                 /*
419                  *      We may (or not) have an operator
420                  */
421
422
423                 /*
424                  *      (FOO)
425                  */
426                 if (*p == ')') {
427                         /*
428                          *      don't skip the brace.  We'll look for it later.
429                          */
430                         goto exists;
431
432                         /*
433                          *      FOO
434                          */
435                 } else if (!*p) {
436                         if (brace) {
437                                 return_P("No closing brace at end of string");
438                         }
439
440                         goto exists;
441
442                         /*
443                          *      FOO && ...
444                          */
445                 } else if (((p[0] == '&') && (p[1] == '&')) ||
446                            ((p[0] == '|') && (p[1] == '|'))) {
447
448                 exists:
449                         if (c->cast) {
450                                 return_0("Cannot do cast for existence check");
451                         }
452
453                         c->type = COND_TYPE_EXISTS;
454                         c->data.vpt = radius_str2tmpl(c, lhs, lhs_type);
455                         if (!c->data.vpt) {
456                                 return_P("Failed creating exists");
457                         }
458
459                 } else { /* it's an operator */
460                         int regex;
461
462                         /*
463                          *      The next thing should now be a comparison operator.
464                          */
465                         regex = false;
466                         c->type = COND_TYPE_MAP;
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                          */
553                         if (*p == '<') {
554                                 return_P("Unexpected cast");
555                         }
556
557                         /*
558                          *      Grab the RHS
559                          */
560                         rhs_p = p;
561                         slen = condition_tokenize_word(c, p, &rhs, &rhs_type, error);
562                         if (slen <= 0) {
563                                 return_SLEN;
564                         }
565
566                         /*
567                          *      Sanity checks for regexes.
568                          */
569                         if (regex) {
570                                 if (*p != '/') {
571                                         return_P("Expected regular expression");
572                                 }
573
574                                 /*
575                                  *      Allow /foo/i
576                                  */
577                                 if (p[slen] == 'i') {
578                                         c->regex_i = true;
579                                         slen++;
580                                 }
581
582                         } else if (!regex && (*p == '/')) {
583                                 return_P("Unexpected regular expression");
584                         }
585
586                         c->data.map = radius_str2map(c, lhs, lhs_type, op, rhs, rhs_type,
587                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST,
588                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST);
589                         if (!c->data.map) {
590                                 return_P("Failed creating check");
591                         }
592
593                         /*
594                          *      foo =* bar is just (foo)
595                          *      foo !* bar is just (!foo)
596                          */
597                         if ((op == T_OP_CMP_TRUE) || (op == T_OP_CMP_FALSE)) {
598                                 value_pair_tmpl_t *vpt;
599
600                                 vpt = talloc_steal(c, c->data.map->dst);
601                                 c->data.map->dst = NULL;
602
603                                 talloc_free(c->data.map);
604                                 c->type = COND_TYPE_EXISTS;
605                                 c->data.vpt = vpt;
606
607                                 /*
608                                  *      Invert the negation bit.
609                                  */
610                                 if (op == T_OP_CMP_FALSE) {
611                                         c->negate = !c->negate;
612                                 }
613
614                                 goto done_cond;
615                         }
616
617                         /*
618                          *      @todo: check LHS and RHS separately, to
619                          *      get better errors
620                          */
621                         if ((c->data.map->src->type == VPT_TYPE_LIST) ||
622                             (c->data.map->dst->type == VPT_TYPE_LIST)) {
623                                 return_0("Cannot use list references in condition");
624                         }
625
626                         /*
627                          *      Check cast type.  We can have the RHS
628                          *      a string if the LHS has a cast.  But
629                          *      if the RHS is an attr, it MUST be the
630                          *      same type as the LHS.
631                          */
632                         if (c->cast) {
633                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
634                                     (c->cast->type != c->data.map->src->da->type)) {
635                                         goto same_type;
636                                 }
637
638                                 if (c->data.map->src->type == VPT_TYPE_REGEX) {
639                                         return_0("Cannot use cast with regex comparison");
640                                 }
641
642                                 /*
643                                  *      The LHS is a literal which has been cast to a data type.
644                                  *      Cast it to the appropriate data type.
645                                  */
646                                 if ((c->data.map->dst->type == VPT_TYPE_LITERAL) &&
647                                     !cast_vpt(c->data.map->dst, c->cast)) {
648                                         *error = "Failed to parse data";
649                                         if (lhs) talloc_free(lhs);
650                                         if (rhs) talloc_free(rhs);
651                                         talloc_free(c);
652                                         return -(lhs_p - start);
653                                 }
654
655                                 /*
656                                  *      Casting to a redundant type means we don't need the cast.
657                                  */
658                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
659                                     (c->cast->type == c->data.map->dst->da->type)) {
660                                         c->cast = NULL;
661                                 }
662
663                         } else {
664                                 /*
665                                  *      Two attributes?  They must be of the same type
666                                  */
667                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
668                                     (c->data.map->dst->type == VPT_TYPE_ATTR) &&
669                                     (c->data.map->dst->da->type != c->data.map->src->da->type)) {
670                                 same_type:
671                                         return_0("Attribute comparisons must be of the same attribute type");
672                                 }
673
674                                 /*
675                                  *      Without a cast, we can't compare "foo" to User-Name,
676                                  *      it has to be done the other way around.
677                                  */
678                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
679                                     (c->data.map->dst->type != VPT_TYPE_ATTR)) {
680                                         *error = "Cannot use attribute reference on right side of condition";
681                                 return_0:
682                                         if (lhs) talloc_free(lhs);
683                                         if (rhs) talloc_free(rhs);
684                                         talloc_free(c);
685                                         return 0;
686                                 }
687
688                                 /*
689                                  *      Invalid: User-Name == bob
690                                  *      Valid:   User-Name == "bob"
691                                  */
692                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
693                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
694                                     (c->data.map->dst->da->type == PW_TYPE_STRING) &&
695                                     (rhs_type == T_BARE_WORD)) {
696                                         return_rhs("Must have string as value for attribute");
697                                 }
698
699                                 /*
700                                  *      Quotes around non-string
701                                  *      attributes mean that it's
702                                  *      either xlat, or an exec.
703                                  */
704                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
705                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
706                                     (c->data.map->dst->da->type != PW_TYPE_STRING) &&
707                                     (c->data.map->dst->da->type != PW_TYPE_OCTETS) &&
708                                     (c->data.map->dst->da->type != PW_TYPE_DATE) &&
709                                     (rhs_type == T_SINGLE_QUOTED_STRING)) {
710                                         *error = "Value must be an unquoted string";
711                                 return_rhs:
712                                         if (lhs) talloc_free(lhs);
713                                         if (rhs) talloc_free(rhs);
714                                         talloc_free(c);
715                                         return -(rhs_p - start);
716                                 }
717
718                                 /*
719                                  *      The LHS has been cast to a data type, and the RHS is a
720                                  *      literal.  Cast the RHS to the type of the cast.
721                                  */
722                                 if (c->cast && (c->data.map->src->type == VPT_TYPE_LITERAL) &&
723                                     !cast_vpt(c->data.map->src, c->cast)) {
724                                         return_rhs("Failed to parse data");
725                                 }
726
727                                 /*
728                                  *      The LHS is an attribute, and the RHS is a literal.  Cast the
729                                  *      RHS to the data type of the LHS.
730                                  */
731                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
732                                     (c->data.map->src->type == VPT_TYPE_LITERAL) &&
733                                     !cast_vpt(c->data.map->src, c->data.map->dst->da)) {
734                                         return_rhs("Failed to parse data");
735                                 }
736                         }
737
738                 done_cond:
739                         p += slen;
740
741                         while (isspace((int) *p)) p++; /* skip spaces after RHS */
742                 } /* parse OP RHS */
743         } /* parse a condition (COND) or FOO OP BAR*/
744
745         /*
746          *      ...COND)
747          */
748         if (*p == ')') {
749                 if (!brace) {
750                         return_P("Unexpected closing brace");
751                 }
752
753                 p++;
754                 while (isspace((int) *p)) p++; /* skip spaces after closing brace */
755                 brace = false;
756                 goto done;
757         }
758
759         /*
760          *      End of string is now allowed.
761          */
762         if (!*p) {
763                 if (brace) {
764                         return_P("No closing brace at end of string");
765                 }
766
767                 goto done;
768         }
769
770         if (!(((p[0] == '&') && (p[1] == '&')) ||
771               ((p[0] == '|') && (p[1] == '|')))) {
772                 *error = "Unexpected text after condition";
773         return_p:
774                 if (lhs) talloc_free(lhs);
775                 if (rhs) talloc_free(rhs);
776                 talloc_free(c);
777                 return -(p - start);
778         }
779
780         /*
781          *      Recurse to parse the next condition.
782          */
783         c->next_op = p[0];
784         p += 2;
785
786         /*
787          *      May still be looking for a closing brace.
788          */
789         slen = condition_tokenize(c, p, brace, &c->next, error);
790         if (slen <= 0) {
791         return_slen:
792                 if (lhs) talloc_free(lhs);
793                 if (rhs) talloc_free(rhs);
794                 talloc_free(c);
795                 return slen - (p - start);
796         }
797         p += slen;
798
799 done:
800         /*
801          *      Normalize it before returning it.
802          */
803
804         /*
805          *      (FOO)     --> FOO
806          *      (FOO) ... --> FOO ...
807          */
808         if ((c->type == COND_TYPE_CHILD) && !c->data.child->next) {
809                 fr_cond_t *child;
810
811                 child = talloc_steal(ctx, c->data.child);
812                 c->data.child = NULL;
813
814                 child->next = talloc_steal(child, c->next);
815                 c->next = NULL;
816
817                 child->next_op = c->next_op;
818
819                 /*
820                  *      Set the negation properly
821                  */
822                 if ((c->negate && !child->negate) ||
823                     (!c->negate && child->negate)) {
824                         child->negate = true;
825                 } else {
826                         child->negate = false;
827                 }
828
829                 talloc_free(c);
830                 c = child;
831         }
832
833         /*
834          *      (FOO ...) --> FOO ...
835          *
836          *      But don't do !(FOO || BAR) --> !FOO || BAR
837          *      Because that's different.
838          */
839         if ((c->type == COND_TYPE_CHILD) &&
840             !c->next && !c->negate) {
841                 fr_cond_t *child;
842
843                 child = talloc_steal(ctx, c->data.child);
844                 c->data.child = NULL;
845
846                 talloc_free(c);
847                 c = child;
848         }
849
850         /*
851          *      Normalize negation.  This doesn't really make any
852          *      difference, but it simplifies the run-time code in
853          *      evaluate.c
854          */
855         if (c->type == COND_TYPE_MAP) {
856                 /*
857                  *      !FOO !~ BAR --> FOO =~ BAR
858                  */
859                 if (c->negate && (c->data.map->op == T_OP_REG_NE)) {
860                         c->negate = false;
861                         c->data.map->op = T_OP_REG_EQ;
862                 }
863
864                 /*
865                  *      FOO !~ BAR --> !FOO =~ BAR
866                  */
867                 if (!c->negate && (c->data.map->op == T_OP_REG_NE)) {
868                         c->negate = true;
869                         c->data.map->op = T_OP_REG_EQ;
870                 }
871
872                 /*
873                  *      !FOO != BAR --> FOO == BAR
874                  */
875                 if (c->negate && (c->data.map->op == T_OP_NE)) {
876                         c->negate = false;
877                         c->data.map->op = T_OP_CMP_EQ;
878                 }
879
880                 /*
881                  *      This next one catches "LDAP-Group != foo",
882                  *      which doesn't really work, but this hack fixes it.
883                  *
884                  *      FOO != BAR --> !FOO == BAR
885                  */
886                 if (!c->negate && (c->data.map->op == T_OP_NE)) {
887                         c->negate = true;
888                         c->data.map->op = T_OP_CMP_EQ;
889                 }
890         }
891
892         if (lhs) talloc_free(lhs);
893         if (rhs) talloc_free(rhs);
894
895         *pcond = c;
896         return p - start;
897 }
898
899 /** Tokenize a conditional check
900  *
901  *  @param[in] ctx for talloc
902  *  @param[in] start the start of the string to process.  Should be "(..."
903  *  @param[out] head the parsed condition structure
904  *  @param[out] error the parse error (if any)
905  *  @return length of the string skipped, or when negative, the offset to the offending error
906  */
907 ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, char const *start, fr_cond_t **head, char const **error)
908 {
909         return condition_tokenize(ctx, start, false, head, error);
910 }