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