More descriptive error messages for casts
[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] ci for CONF_ITEM
338  *  @param[in] start the start of the string to process.  Should be "(..."
339  *  @param[in] brace look for a closing brace
340  *  @param[in] flags do one/two pass
341  *  @param[out] pcond pointer to the returned condition structure
342  *  @param[out] error the parse error (if any)
343  *  @return length of the string skipped, or when negative, the offset to the offending error
344  */
345 static ssize_t condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, int brace, fr_cond_t **pcond, char const **error, int flags)
346 {
347         ssize_t slen;
348         char const *p = start;
349         char const *lhs_p, *rhs_p;
350         fr_cond_t *c;
351         char *lhs, *rhs;
352         FR_TOKEN op, lhs_type, rhs_type;
353
354         c = talloc_zero(ctx, fr_cond_t);
355
356         rad_assert(c != NULL);
357         lhs = rhs = NULL;
358
359         while (isspace((int) *p)) p++; /* skip spaces before condition */
360
361         if (!*p) {
362                 return_P("Empty condition is invalid");
363         }
364
365         /*
366          *      !COND
367          */
368         if (*p == '!') {
369                 p++;
370                 c->negate = true;
371                 while (isspace((int) *p)) p++; /* skip spaces after negation */
372
373                 /*
374                  *  Just for stupidity
375                  */
376                 if (*p == '!') {
377                         return_P("Double negation is invalid");
378                 }
379         }
380
381         /*
382          *      (COND)
383          */
384         if (*p == '(') {
385                 p++;
386
387                 /*
388                  *      We've already eaten one layer of
389                  *      brackets.  Go recurse to get more.
390                  */
391                 c->type = COND_TYPE_CHILD;
392                 slen = condition_tokenize(c, ci, p, true, &c->data.child, error, flags);
393                 if (slen <= 0) {
394                         return_SLEN;
395                 }
396
397                 if (!c->data.child) {
398                         return_P("Empty condition is invalid");
399                 }
400
401                 p += slen;
402                 while (isspace((int) *p)) p++; /* skip spaces after (COND)*/
403
404         } else { /* it's a bare FOO==BAR */
405                 /*
406                  *      We didn't see anything special.  The condition must be one of
407                  *
408                  *      FOO
409                  *      FOO OP BAR
410                  */
411
412                 /*
413                  *      Grab the LHS
414                  */
415                 if (*p == '/') {
416                         return_P("Conditional check cannot begin with a regular expression");
417                 }
418
419                 slen = condition_tokenize_cast(p, &c->cast, error);
420                 if (slen < 0) {
421                         return_SLEN;
422                 }
423                 p += slen;
424
425                 lhs_p = p;
426                 slen = condition_tokenize_word(c, p, &lhs, &lhs_type, error);
427                 if (slen <= 0) {
428                         return_SLEN;
429                 }
430                 p += slen;
431
432                 while (isspace((int)*p)) p++; /* skip spaces after LHS */
433
434                 /*
435                  *      We may (or not) have an operator
436                  */
437
438
439                 /*
440                  *      (FOO)
441                  */
442                 if (*p == ')') {
443                         /*
444                          *      don't skip the brace.  We'll look for it later.
445                          */
446                         goto exists;
447
448                         /*
449                          *      FOO
450                          */
451                 } else if (!*p) {
452                         if (brace) {
453                                 return_P("No closing brace at end of string");
454                         }
455
456                         goto exists;
457
458                         /*
459                          *      FOO && ...
460                          */
461                 } else if (((p[0] == '&') && (p[1] == '&')) ||
462                            ((p[0] == '|') && (p[1] == '|'))) {
463
464                 exists:
465                         if (c->cast) {
466                                 return_0("Cannot do cast for existence check");
467                         }
468
469                         if (lhs_type == T_BARE_WORD) {
470                                 if ((strcmp(lhs, "true") == 0) ||
471                                     ((lhs[0] == '1') && !lhs[1])) {
472                                         c->type = COND_TYPE_TRUE;
473
474                                 } else if ((strcmp(lhs, "false") == 0) ||
475                                            ((lhs[0] == '0') && !lhs[1])) {
476                                         c->type = COND_TYPE_FALSE;
477
478                                 } else {
479                                         goto create_exists;
480                                 }
481
482                         } else {
483                         create_exists:
484                                 c->type = COND_TYPE_EXISTS;
485                                 c->data.vpt = radius_str2tmpl(c, lhs, lhs_type);
486                                 if (!c->data.vpt) {
487                                         return_P("Failed creating exists");
488                                 }
489                         }
490
491                 } else { /* it's an operator */
492                         int regex;
493
494                         /*
495                          *      The next thing should now be a comparison operator.
496                          */
497                         regex = false;
498                         c->type = COND_TYPE_MAP;
499                         switch (*p) {
500                         default:
501                                 return_P("Invalid text. Expected comparison operator");
502
503                         case '!':
504                                 if (p[1] == '=') {
505                                         op = T_OP_NE;
506                                         p += 2;
507
508                                 } else if (p[1] == '~') {
509                                 regex = true;
510
511                                 op = T_OP_REG_NE;
512                                 p += 2;
513
514                                 } else if (p[1] == '*') {
515                                         if (lhs_type != T_BARE_WORD) {
516                                                 return_P("Cannot use !* on a string");
517                                         }
518
519                                         op = T_OP_CMP_FALSE;
520                                         p += 2;
521
522                                 } else {
523                                         goto invalid_operator;
524                                 }
525                                 break;
526
527                         case '=':
528                                 if (p[1] == '=') {
529                                         op = T_OP_CMP_EQ;
530                                         p += 2;
531
532                                 } else if (p[1] == '~') {
533                                         regex = true;
534
535                                         op = T_OP_REG_EQ;
536                                         p += 2;
537
538                                 } else if (p[1] == '*') {
539                                         if (lhs_type != T_BARE_WORD) {
540                                                 return_P("Cannot use =* on a string");
541                                         }
542
543                                         op = T_OP_CMP_TRUE;
544                                         p += 2;
545
546                                 } else {
547                                 invalid_operator:
548                                         return_P("Invalid operator");
549                                 }
550
551                                 break;
552
553                         case '<':
554                                 if (p[1] == '=') {
555                                         op = T_OP_LE;
556                                         p += 2;
557
558                                 } else {
559                                         op = T_OP_LT;
560                                         p++;
561                                 }
562                                 break;
563
564                         case '>':
565                                 if (p[1] == '=') {
566                                         op = T_OP_GE;
567                                         p += 2;
568
569                                 } else {
570                                         op = T_OP_GT;
571                                         p++;
572                                 }
573                                 break;
574                         }
575
576                         while (isspace((int) *p)) p++; /* skip spaces after operator */
577
578                         if (!*p) {
579                                 return_P("Expected text after operator");
580                         }
581
582                         /*
583                          *      Cannot have a cast on the RHS.
584                          *      But produce good errors, too.
585                          */
586                         if (*p == '<') {
587                                 DICT_ATTR const *cast_da;
588
589                                 slen = condition_tokenize_cast(p, &cast_da, error);
590                                 if (slen < 0) {
591                                         return_SLEN;
592                                 }
593
594                                 if (!c->cast) {
595                                         return_P("Unexpected cast");
596                                 }
597
598                                 if (c->cast != cast_da) {
599                                         return_P("Cannot cast to a different data type");
600                                 }
601
602                                 return_P("Unnecessary cast");
603                         }
604
605                         /*
606                          *      Grab the RHS
607                          */
608                         rhs_p = p;
609                         slen = condition_tokenize_word(c, p, &rhs, &rhs_type, error);
610                         if (slen <= 0) {
611                                 return_SLEN;
612                         }
613
614                         /*
615                          *      Sanity checks for regexes.
616                          */
617                         if (regex) {
618                                 if (*p != '/') {
619                                         return_P("Expected regular expression");
620                                 }
621
622                                 /*
623                                  *      Allow /foo/i
624                                  */
625                                 if (p[slen] == 'i') {
626                                         c->regex_i = true;
627                                         slen++;
628                                 }
629
630                         } else if (!regex && (*p == '/')) {
631                                 return_P("Unexpected regular expression");
632                         }
633
634                         c->data.map = radius_str2map(c, lhs, lhs_type, op, rhs, rhs_type,
635                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST,
636                                                      REQUEST_CURRENT, PAIR_LIST_REQUEST);
637
638                         if (!c->data.map) {
639                                 return_0("Syntax error");
640                         }
641
642                         /*
643                          *      Could have been a reference to an attribute which is registered later.
644                          *      Mark it as being checked in pass2.
645                          */
646                         if ((lhs_type == T_BARE_WORD) &&
647                             (c->data.map->dst->type == VPT_TYPE_LITERAL)) {
648                                 c->pass2_fixup = PASS2_FIXUP_ATTR;
649                         }
650
651                         /*
652                          *      Save the CONF_ITEM for later.
653                          */
654                         c->data.map->ci = ci;
655
656                         /*
657                          *      foo =* bar is just (foo)
658                          *      foo !* bar is just (!foo)
659                          */
660                         if ((op == T_OP_CMP_TRUE) || (op == T_OP_CMP_FALSE)) {
661                                 value_pair_tmpl_t *vpt;
662
663                                 vpt = talloc_steal(c, c->data.map->dst);
664                                 c->data.map->dst = NULL;
665
666                                 talloc_free(c->data.map);
667                                 c->type = COND_TYPE_EXISTS;
668                                 c->data.vpt = vpt;
669
670                                 /*
671                                  *      Invert the negation bit.
672                                  */
673                                 if (op == T_OP_CMP_FALSE) {
674                                         c->negate = !c->negate;
675                                 }
676
677                                 goto done_cond;
678                         }
679
680                         /*
681                          *      @todo: check LHS and RHS separately, to
682                          *      get better errors
683                          */
684                         if ((c->data.map->src->type == VPT_TYPE_LIST) ||
685                             (c->data.map->dst->type == VPT_TYPE_LIST)) {
686                                 return_0("Cannot use list references in condition");
687                         }
688
689                         /*
690                          *      Check cast type.  We can have the RHS
691                          *      a string if the LHS has a cast.  But
692                          *      if the RHS is an attr, it MUST be the
693                          *      same type as the LHS.
694                          */
695                         if (c->cast) {
696                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
697                                     (c->cast->type != c->data.map->src->da->type)) {
698                                         goto same_type;
699                                 }
700
701                                 if (c->data.map->src->type == VPT_TYPE_REGEX) {
702                                         return_0("Cannot use cast with regex comparison");
703                                 }
704
705                                 /*
706                                  *      The LHS is a literal which has been cast to a data type.
707                                  *      Cast it to the appropriate data type.
708                                  */
709                                 if ((c->data.map->dst->type == VPT_TYPE_LITERAL) &&
710                                     !cast_vpt(c->data.map->dst, c->cast)) {
711                                         *error = "Failed to parse field";
712                                         if (lhs) talloc_free(lhs);
713                                         if (rhs) talloc_free(rhs);
714                                         talloc_free(c);
715                                         return -(lhs_p - start);
716                                 }
717
718                                 /*
719                                  *      The RHS is a literal, and the LHS has been cast to a data
720                                  *      type.
721                                  */
722                                 if ((c->data.map->dst->type == VPT_TYPE_DATA) &&
723                                     (c->data.map->src->type == VPT_TYPE_LITERAL) &&
724                                     !cast_vpt(c->data.map->src, c->data.map->dst->da)) {
725                                         return_rhs("Failed to parse field");
726                                 }
727
728                                 /*
729                                  *      Casting to a redundant type means we don't need the cast.
730                                  *
731                                  *      Do this LAST, as the rest of the code above assumes c->cast
732                                  *      is not NULL.
733                                  */
734                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
735                                     (c->cast->type == c->data.map->dst->da->type)) {
736                                         c->cast = NULL;
737                                 }
738
739                         } else {
740                                 /*
741                                  *      Two attributes?  They must be of the same type
742                                  */
743                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
744                                     (c->data.map->dst->type == VPT_TYPE_ATTR) &&
745                                     (c->data.map->dst->da->type != c->data.map->src->da->type)) {
746                                 same_type:
747                                         return_0("Attribute comparisons must be of the same attribute type");
748                                 }
749
750                                 /*
751                                  *      Without a cast, we can't compare "foo" to User-Name,
752                                  *      it has to be done the other way around.
753                                  */
754                                 if ((c->data.map->src->type == VPT_TYPE_ATTR) &&
755                                     (c->data.map->dst->type != VPT_TYPE_ATTR)) {
756                                         *error = "Cannot use attribute reference on right side of condition";
757                                 return_0:
758                                         if (lhs) talloc_free(lhs);
759                                         if (rhs) talloc_free(rhs);
760                                         talloc_free(c);
761                                         return 0;
762                                 }
763
764                                 /*
765                                  *      Invalid: User-Name == bob
766                                  *      Valid:   User-Name == "bob"
767                                  */
768                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
769                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
770                                     (c->data.map->dst->da->type == PW_TYPE_STRING) &&
771                                     (rhs_type == T_BARE_WORD)) {
772                                         return_rhs("Must have string as value for attribute");
773                                 }
774
775                                 /*
776                                  *      Quotes around non-string
777                                  *      attributes mean that it's
778                                  *      either xlat, or an exec.
779                                  */
780                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
781                                     (c->data.map->src->type != VPT_TYPE_ATTR) &&
782                                     (c->data.map->dst->da->type != PW_TYPE_STRING) &&
783                                     (c->data.map->dst->da->type != PW_TYPE_OCTETS) &&
784                                     (c->data.map->dst->da->type != PW_TYPE_DATE) &&
785                                     (rhs_type == T_SINGLE_QUOTED_STRING)) {
786                                         *error = "Value must be an unquoted string";
787                                 return_rhs:
788                                         if (lhs) talloc_free(lhs);
789                                         if (rhs) talloc_free(rhs);
790                                         talloc_free(c);
791                                         return -(rhs_p - start);
792                                 }
793
794                                 /*
795                                  *      The LHS has been cast to a data type, and the RHS is a
796                                  *      literal.  Cast the RHS to the type of the cast.
797                                  */
798                                 if (c->cast && (c->data.map->src->type == VPT_TYPE_LITERAL) &&
799                                     !cast_vpt(c->data.map->src, c->cast)) {
800                                         return_rhs("Failed to parse field");
801                                 }
802
803                                 /*
804                                  *      The LHS is an attribute, and the RHS is a literal.  Cast the
805                                  *      RHS to the data type of the LHS.
806                                  */
807                                 if ((c->data.map->dst->type == VPT_TYPE_ATTR) &&
808                                     (c->data.map->src->type == VPT_TYPE_LITERAL) &&
809                                     !cast_vpt(c->data.map->src, c->data.map->dst->da)) {
810                                         DICT_ATTR const *da = c->data.map->dst->da;
811
812                                         if ((da->vendor == 0) &&
813                                             ((da->attr == PW_AUTH_TYPE) ||
814                                              (da->attr == PW_AUTZ_TYPE) ||
815                                              (da->attr == PW_ACCT_TYPE) ||
816                                              (da->attr == PW_SESSION_TYPE) ||
817                                              (da->attr == PW_POST_AUTH_TYPE) ||
818                                              (da->attr == PW_PRE_PROXY_TYPE) ||
819                                              (da->attr == PW_POST_PROXY_TYPE) ||
820                                              (da->attr == PW_PRE_ACCT_TYPE) ||
821                                              (da->attr == PW_RECV_COA_TYPE) ||
822                                              (da->attr == PW_SEND_COA_TYPE))) {
823                                                 /*
824                                                  *      The types for these attributes are dynamically allocated
825                                                  *      by modules.c, so we can't enforce strictness here.
826                                                  */
827                                                 c->pass2_fixup = PASS2_FIXUP_TYPE;
828
829                                         } else {
830                                                 return_rhs("Failed to parse value for attribute");
831                                         }
832                                 }
833                         }
834
835                 done_cond:
836                         p += slen;
837
838                         while (isspace((int) *p)) p++; /* skip spaces after RHS */
839                 } /* parse OP RHS */
840         } /* parse a condition (COND) or FOO OP BAR*/
841
842         /*
843          *      ...COND)
844          */
845         if (*p == ')') {
846                 if (!brace) {
847                         return_P("Unexpected closing brace");
848                 }
849
850                 p++;
851                 while (isspace((int) *p)) p++; /* skip spaces after closing brace */
852                 brace = false;
853                 goto done;
854         }
855
856         /*
857          *      End of string is now allowed.
858          */
859         if (!*p) {
860                 if (brace) {
861                         return_P("No closing brace at end of string");
862                 }
863
864                 goto done;
865         }
866
867         if (!(((p[0] == '&') && (p[1] == '&')) ||
868               ((p[0] == '|') && (p[1] == '|')))) {
869                 *error = "Unexpected text after condition";
870         return_p:
871                 if (lhs) talloc_free(lhs);
872                 if (rhs) talloc_free(rhs);
873                 talloc_free(c);
874                 return -(p - start);
875         }
876
877         /*
878          *      Recurse to parse the next condition.
879          */
880         c->next_op = p[0];
881         p += 2;
882
883         /*
884          *      May still be looking for a closing brace.
885          */
886         slen = condition_tokenize(c, ci, p, brace, &c->next, error, flags);
887         if (slen <= 0) {
888         return_slen:
889                 if (lhs) talloc_free(lhs);
890                 if (rhs) talloc_free(rhs);
891                 talloc_free(c);
892                 return slen - (p - start);
893         }
894         p += slen;
895
896 done:
897         /*
898          *      Normalize it before returning it.
899          */
900
901         /*
902          *      (FOO)     --> FOO
903          *      (FOO) ... --> FOO ...
904          */
905         if ((c->type == COND_TYPE_CHILD) && !c->data.child->next) {
906                 fr_cond_t *child;
907
908                 child = talloc_steal(ctx, c->data.child);
909                 c->data.child = NULL;
910
911                 child->next = talloc_steal(child, c->next);
912                 c->next = NULL;
913
914                 child->next_op = c->next_op;
915
916                 /*
917                  *      Set the negation properly
918                  */
919                 if ((c->negate && !child->negate) ||
920                     (!c->negate && child->negate)) {
921                         child->negate = true;
922                 } else {
923                         child->negate = false;
924                 }
925
926                 lhs = rhs = NULL;
927                 talloc_free(c);
928                 c = child;
929         }
930
931         /*
932          *      (FOO ...) --> FOO ...
933          *
934          *      But don't do !(FOO || BAR) --> !FOO || BAR
935          *      Because that's different.
936          */
937         if ((c->type == COND_TYPE_CHILD) &&
938             !c->next && !c->negate) {
939                 fr_cond_t *child;
940
941                 child = talloc_steal(ctx, c->data.child);
942                 c->data.child = NULL;
943
944                 lhs = rhs = NULL;
945                 talloc_free(c);
946                 c = child;
947         }
948
949         /*
950          *      Normalize negation.  This doesn't really make any
951          *      difference, but it simplifies the run-time code in
952          *      evaluate.c
953          */
954         if (c->type == COND_TYPE_MAP) {
955                 /*
956                  *      !FOO !~ BAR --> FOO =~ BAR
957                  */
958                 if (c->negate && (c->data.map->op == T_OP_REG_NE)) {
959                         c->negate = false;
960                         c->data.map->op = T_OP_REG_EQ;
961                 }
962
963                 /*
964                  *      FOO !~ BAR --> !FOO =~ BAR
965                  */
966                 if (!c->negate && (c->data.map->op == T_OP_REG_NE)) {
967                         c->negate = true;
968                         c->data.map->op = T_OP_REG_EQ;
969                 }
970
971                 /*
972                  *      !FOO != BAR --> FOO == BAR
973                  */
974                 if (c->negate && (c->data.map->op == T_OP_NE)) {
975                         c->negate = false;
976                         c->data.map->op = T_OP_CMP_EQ;
977                 }
978
979                 /*
980                  *      This next one catches "LDAP-Group != foo",
981                  *      which doesn't really work, but this hack fixes it.
982                  *
983                  *      FOO != BAR --> !FOO == BAR
984                  */
985                 if (!c->negate && (c->data.map->op == T_OP_NE)) {
986                         c->negate = true;
987                         c->data.map->op = T_OP_CMP_EQ;
988                 }
989
990                 if ((c->data.map->dst->type == VPT_TYPE_DATA) &&
991                     (c->data.map->src->type == VPT_TYPE_DATA)) {
992                         int rcode;
993
994                         rad_assert(c->cast != NULL);
995
996                         rcode = radius_evaluate_map(NULL, 0, 0, c);
997                         talloc_free(c->data.map);
998                         c->data.map = NULL;
999                         c->cast = NULL;
1000                         c->regex_i = false;
1001                         if (rcode) {
1002                                 c->type = COND_TYPE_TRUE;
1003                         } else {
1004                                 c->type = COND_TYPE_FALSE;
1005                         }
1006                 }
1007         }
1008
1009         if (c->type == COND_TYPE_TRUE) {
1010                 if (c->negate) {
1011                         c->negate = false;
1012                         c->type = COND_TYPE_FALSE;
1013                 }
1014         }
1015
1016         if (c->type == COND_TYPE_FALSE) {
1017                 if (c->negate) {
1018                         c->negate = false;
1019                         c->type = COND_TYPE_TRUE;
1020                 }
1021         }
1022
1023         /*
1024          *      true && FOO --> FOO
1025          */
1026         if ((c->type == COND_TYPE_TRUE) &&
1027             (c->next_op == COND_AND)) {
1028                 fr_cond_t *next;
1029
1030                 next = talloc_steal(ctx, c->next);
1031                 c->next = NULL;
1032
1033                 lhs = rhs = NULL;
1034                 talloc_free(c);
1035                 c = next;
1036         }
1037
1038         /*
1039          *      false && FOO --> false
1040          */
1041         if ((c->type == COND_TYPE_FALSE) &&
1042             (c->next_op == COND_AND)) {
1043                 talloc_free(c->next);
1044                 c->next = NULL;
1045                 c->next_op = COND_NONE;
1046         }
1047
1048         /*
1049          *      false || FOO --> FOO
1050          */
1051         if ((c->type == COND_TYPE_FALSE) &&
1052             (c->next_op == COND_OR)) {
1053                 fr_cond_t *next;
1054
1055                 next = talloc_steal(ctx, c->next);
1056                 c->next = NULL;
1057
1058                 lhs = rhs = NULL;
1059                 talloc_free(c);
1060                 c = next;
1061         }
1062
1063         /*
1064          *      true || FOO --> true
1065          */
1066         if ((c->type == COND_TYPE_TRUE) &&
1067             (c->next_op == COND_OR)) {
1068                 talloc_free(c->next);
1069                 c->next = NULL;
1070                 c->next_op = COND_NONE;
1071         }
1072
1073         if (lhs) talloc_free(lhs);
1074         if (rhs) talloc_free(rhs);
1075
1076         *pcond = c;
1077         return p - start;
1078 }
1079
1080 /** Tokenize a conditional check
1081  *
1082  *  @param[in] ctx for talloc
1083  *  @param[in] ci for CONF_ITEM
1084  *  @param[in] start the start of the string to process.  Should be "(..."
1085  *  @param[out] head the parsed condition structure
1086  *  @param[out] error the parse error (if any)
1087  *  @param[in] flags do one/two pass
1088  *  @return length of the string skipped, or when negative, the offset to the offending error
1089  */
1090 ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flags)
1091 {
1092         return condition_tokenize(ctx, ci, start, false, head, error, flags);
1093 }
1094
1095 /*
1096  *      Walk in order.
1097  */
1098 bool fr_condition_walk(fr_cond_t *c, bool (*callback)(void *, fr_cond_t *), void *ctx)
1099 {
1100         while (c) {
1101                 /*
1102                  *      Process this one, exit on error.
1103                  */
1104                 if (!callback(ctx, c)) return false;
1105
1106                 switch (c->type) {
1107                 case COND_TYPE_INVALID:
1108                         return false;
1109
1110                 case COND_TYPE_EXISTS:
1111                 case COND_TYPE_MAP:
1112                 case COND_TYPE_TRUE:
1113                 case COND_TYPE_FALSE:
1114                         break;
1115
1116                 case COND_TYPE_CHILD:
1117                         /*
1118                          *      Walk over the child.
1119                          */
1120                         if (!fr_condition_walk(c->data.child, callback, ctx)) {
1121                                 return false;
1122                         }
1123                 }
1124
1125                 /*
1126                  *      No sibling, stop.
1127                  */
1128                 if (c->next_op == COND_NONE) break;
1129
1130                 /*
1131                  *      process the next sibling
1132                  */
1133                 c = c->next;
1134         }
1135
1136         return true;
1137 }