85b69aff74e283877ec52348ccc2240472076f01
[project/procd.git] / validate.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdbool.h>
5 #include <ctype.h>
6
7 #include <arpa/inet.h>
8 #include <netinet/ether.h>
9 #include <sys/stat.h>
10
11 #include "libvalidate.h"
12
13 enum dt_optype {
14 OP_UNKNOWN,
15 OP_BOOL,
16 OP_NUMBER,
17 OP_STRING,
18 OP_FUNCTION
19 };
20
21 struct dt_fun;
22
23 struct dt_op {
24 enum dt_optype type;
25 const char *next;
26 int length;
27 int nextop;
28 union {
29 bool boolean;
30 double number;
31 const char *string;
32 struct dt_fun *function;
33 } value;
34 };
35
36 struct dt_state {
37 int pos;
38 int depth;
39 const char *value;
40 struct dt_op stack[32];
41 };
42
43 struct dt_fun {
44 const char *name;
45 bool (*call)(struct dt_state *s, int nargs);
46 };
47
48 static bool
49 dt_test_number(double number, const char *value)
50 {
51 char *e;
52 double n;
53
54 n = strtod(value, &e);
55
56 return (e > value && *e == 0 && n == number);
57 }
58
59 static bool
60 dt_test_string(const char *s, const char *end, const char *value)
61 {
62 bool esc = false;
63
64 while (*value)
65 {
66 if (s > end)
67 return false;
68
69 if (!esc && *s == '\\')
70 {
71 s++;
72
73 if (s >= end)
74 break;
75
76 esc = true;
77 continue;
78 }
79
80 if (*s != *value)
81 return false;
82
83 esc = false;
84 value++;
85 s++;
86 }
87
88 return (*s == *value || (s > end && *value == 0));
89 }
90
91 static bool
92 dt_step(struct dt_state *s);
93
94 static bool
95 dt_call(struct dt_state *s);
96
97 static bool
98 dt_type_or(struct dt_state *s, int nargs)
99 {
100 while (nargs--)
101 if (dt_step(s))
102 return true;
103
104 return false;
105 }
106
107 static bool
108 dt_type_and(struct dt_state *s, int nargs)
109 {
110 while (nargs--)
111 if (!dt_step(s))
112 return false;
113
114 return true;
115 }
116
117 static bool
118 dt_type_not(struct dt_state *s, int nargs)
119 {
120 if (!nargs)
121 return false;
122
123 return !dt_step(s);
124 }
125
126 static bool
127 dt_type_neg(struct dt_state *s, int nargs)
128 {
129 bool rv;
130 const char *value = s->value;
131
132 if (!nargs)
133 return false;
134
135 if (*s->value == '!')
136 while (isspace(*++s->value));
137
138 rv = dt_step(s);
139 s->value = value;
140
141 return rv;
142 }
143
144 static bool
145 dt_type_list(struct dt_state *s, int nargs)
146 {
147 bool rv = true;
148 int pos = s->pos;
149 char *p, *str = strdup(s->value);
150 const char *value = s->value;
151
152 if (!str || !nargs)
153 return false;
154
155 for (p = strtok(str, " \t"); p; p = strtok(NULL, " \t"))
156 {
157 s->value = p;
158
159 if (!dt_step(s))
160 {
161 rv = false;
162 break;
163 }
164
165 s->pos = pos;
166 }
167
168 s->value = value;
169 free(str);
170
171 return rv;
172 }
173
174 static bool
175 dt_type_min(struct dt_state *s, int nargs)
176 {
177 int n;
178 char *e;
179
180 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
181 {
182 n = strtol(s->value, &e, 0);
183
184 return (e > s->value && *e == 0 &&
185 n >= s->stack[s->pos].value.number);
186 }
187
188 return false;
189 }
190
191 static bool
192 dt_type_max(struct dt_state *s, int nargs)
193 {
194 int n;
195 char *e;
196
197 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
198 {
199 n = strtol(s->value, &e, 0);
200
201 return (e > s->value && *e == 0 &&
202 n <= s->stack[s->pos].value.number);
203 }
204
205 return false;
206 }
207
208 static bool
209 dt_type_range(struct dt_state *s, int nargs)
210 {
211 int n;
212 char *e;
213
214 if (nargs >= 2 &&
215 s->stack[s->pos].type == OP_NUMBER &&
216 s->stack[s->pos + 1].type == OP_NUMBER)
217 {
218 n = strtol(s->value, &e, 0);
219
220 return (e > s->value && *e == 0 &&
221 n >= s->stack[s->pos].value.number &&
222 n <= s->stack[s->pos + 1].value.number);
223 }
224
225 return false;
226 }
227
228 static bool
229 dt_type_minlen(struct dt_state *s, int nargs)
230 {
231 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
232 return (strlen(s->value) >= s->stack[s->pos].value.number);
233
234 return false;
235 }
236
237 static bool
238 dt_type_maxlen(struct dt_state *s, int nargs)
239 {
240 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
241 return (strlen(s->value) <= s->stack[s->pos].value.number);
242
243 return false;
244 }
245
246 static bool
247 dt_type_rangelen(struct dt_state *s, int nargs)
248 {
249 if (nargs >= 2 &&
250 s->stack[s->pos].type == OP_NUMBER &&
251 s->stack[s->pos + 1].type == OP_NUMBER)
252 return (strlen(s->value) >= s->stack[s->pos].value.number &&
253 strlen(s->value) <= s->stack[s->pos + 1].value.number);
254
255 return false;
256 }
257
258 static bool
259 dt_type_int(struct dt_state *s, int nargs)
260 {
261 char *e;
262
263 strtol(s->value, &e, 0);
264
265 return (e > s->value && *e == 0);
266 }
267
268 static bool
269 dt_type_uint(struct dt_state *s, int nargs)
270 {
271 int n;
272 char *e;
273
274 n = strtol(s->value, &e, 0);
275
276 return (e > s->value && *e == 0 && n >= 0);
277 }
278
279 static bool
280 dt_type_float(struct dt_state *s, int nargs)
281 {
282 char *e;
283
284 strtod(s->value, &e);
285
286 return (e > s->value && *e == 0);
287 }
288
289 static bool
290 dt_type_ufloat(struct dt_state *s, int nargs)
291 {
292 int n;
293 char *e;
294
295 n = strtod(s->value, &e);
296
297 return (e > s->value && *e == 0 && n >= 0.0);
298 }
299
300 static bool
301 dt_type_bool(struct dt_state *s, int nargs)
302 {
303 int i;
304 const char *values[] = {
305 "0", "off", "false", "no",
306 "1", "on", "true", "yes"
307 };
308
309 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
310 if (!strcasecmp(values[i], s->value))
311 return true;
312
313 return false;
314 }
315
316 static bool
317 dt_type_ip4addr(struct dt_state *s, int nargs)
318 {
319 struct in6_addr a;
320 return inet_pton(AF_INET, s->value, &a);
321 }
322
323 static bool
324 dt_type_ip6addr(struct dt_state *s, int nargs)
325 {
326 struct in6_addr a;
327 return inet_pton(AF_INET6, s->value, &a);
328 }
329
330 static bool
331 dt_type_ipaddr(struct dt_state *s, int nargs)
332 {
333 return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
334 }
335
336 static bool
337 dt_type_netmask4(struct dt_state *s, int nargs)
338 {
339 int i;
340 struct in_addr a;
341
342 if (!inet_pton(AF_INET, s->value, &a))
343 return false;
344
345 if (a.s_addr == 0)
346 return true;
347
348 a.s_addr = ntohl(a.s_addr);
349
350 for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
351
352 return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
353 }
354
355 static bool
356 dt_type_netmask6(struct dt_state *s, int nargs)
357 {
358 int i;
359 struct in6_addr a;
360
361 if (!inet_pton(AF_INET6, s->value, &a))
362 return false;
363
364 for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
365
366 if (i == 16)
367 return true;
368
369 if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
370 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
371 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
372 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
373 (a.s6_addr[i] != 0))
374 return false;
375
376 for (; (i < 16) && (a.s6_addr[i] == 0); i++);
377
378 return (i == 16);
379 }
380
381 static bool
382 dt_type_cidr4(struct dt_state *s, int nargs)
383 {
384 int n;
385 struct in_addr a;
386 char *p, buf[sizeof("255.255.255.255/32\0")];
387
388 if (strlen(s->value) >= sizeof(buf))
389 return false;
390
391 strcpy(buf, s->value);
392 p = strchr(buf, '/');
393
394 if (p)
395 {
396 *p++ = 0;
397
398 n = strtoul(p, &p, 10);
399
400 if ((*p != 0) || (n > 32))
401 return false;
402 }
403
404 return inet_pton(AF_INET, buf, &a);
405 }
406
407 static bool
408 dt_type_cidr6(struct dt_state *s, int nargs)
409 {
410 int n;
411 struct in6_addr a;
412 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
413
414 if (strlen(s->value) >= sizeof(buf))
415 return false;
416
417 strcpy(buf, s->value);
418 p = strchr(buf, '/');
419
420 if (p)
421 {
422 *p++ = 0;
423
424 n = strtoul(p, &p, 10);
425
426 if ((*p != 0) || (n > 128))
427 return false;
428 }
429
430 return inet_pton(AF_INET6, buf, &a);
431 }
432
433 static bool
434 dt_type_cidr(struct dt_state *s, int nargs)
435 {
436 return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
437 }
438
439 static bool
440 dt_type_ipmask4(struct dt_state *s, int nargs)
441 {
442 bool rv;
443 struct in_addr a;
444 const char *value;
445 char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
446
447 if (strlen(s->value) >= sizeof(buf))
448 return false;
449
450 strcpy(buf, s->value);
451 p = strchr(buf, '/');
452
453 if (p)
454 {
455 *p++ = 0;
456
457 value = s->value;
458 s->value = p;
459 rv = dt_type_netmask4(s, 0);
460 s->value = value;
461
462 if (!rv)
463 return false;
464 }
465
466 return inet_pton(AF_INET, buf, &a);
467 }
468
469 static bool
470 dt_type_ipmask6(struct dt_state *s, int nargs)
471 {
472 bool rv;
473 struct in6_addr a;
474 const char *value;
475 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
476 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
477
478 if (strlen(s->value) >= sizeof(buf))
479 return false;
480
481 strcpy(buf, s->value);
482 p = strchr(buf, '/');
483
484 if (p)
485 {
486 *p++ = 0;
487
488 value = s->value;
489 s->value = p;
490 rv = dt_type_netmask6(s, 0);
491 s->value = value;
492
493 if (!rv)
494 return false;
495 }
496
497 return inet_pton(AF_INET6, buf, &a);
498 }
499
500 static bool
501 dt_type_ipmask(struct dt_state *s, int nargs)
502 {
503 return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
504 }
505
506 static bool
507 dt_type_port(struct dt_state *s, int nargs)
508 {
509 int n;
510 char *e;
511
512 n = strtoul(s->value, &e, 10);
513
514 return (e > s->value && *e == 0 && n <= 65535);
515 }
516
517 static bool
518 dt_type_portrange(struct dt_state *s, int nargs)
519 {
520 int n, m;
521 char *e;
522
523 n = strtoul(s->value, &e, 10);
524
525 if (e == s->value || *e != '-')
526 return false;
527
528 m = strtoul(e + 1, &e, 10);
529
530 return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
531 }
532
533 static bool
534 dt_type_macaddr(struct dt_state *s, int nargs)
535 {
536 return !!ether_aton(s->value);
537 }
538
539 static bool
540 dt_type_uciname(struct dt_state *s, int nargs)
541 {
542 const char *p;
543
544 for (p = s->value;
545 *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
546 (*p >= '0' && *p <= '9') || (*p == '_'));
547 p++);
548
549 return (*p == 0);
550 }
551
552 static bool
553 dt_type_wpakey(struct dt_state *s, int nargs)
554 {
555 int len = strlen(s->value);
556 const char *p = s->value;
557
558 if (len == 64)
559 {
560 while (isxdigit(*p))
561 p++;
562
563 return (*p == 0);
564 }
565
566 return (len >= 8 && len <= 63);
567 }
568
569 static bool
570 dt_type_wepkey(struct dt_state *s, int nargs)
571 {
572 int len = strlen(s->value);
573 const char *p = s->value;
574
575 if (!strncmp(p, "s:", 2))
576 {
577 len -= 2;
578 p += 2;
579 }
580
581 if (len == 10 || len == 26)
582 {
583 while (isxdigit(*p))
584 p++;
585
586 return (*p == 0);
587 }
588
589 return (len == 5 || len == 13);
590 }
591
592 static bool
593 dt_type_hostname(struct dt_state *s, int nargs)
594 {
595 const char *p, *last;
596
597 for (p = last = s->value; *p; p++)
598 {
599 if (*p == '.')
600 {
601 if ((p - last) == 0 || (p - last) > 63)
602 return false;
603
604 last = p + 1;
605 continue;
606 }
607 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
608 (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
609 {
610 continue;
611 }
612
613 return false;
614 }
615
616 return ((p - last) > 0 && (p - last) <= 255);
617 }
618
619 static bool
620 dt_type_host(struct dt_state *s, int nargs)
621 {
622 return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
623 }
624
625 static bool
626 dt_type_network(struct dt_state *s, int nargs)
627 {
628 return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
629 }
630
631 static bool
632 dt_type_phonedigit(struct dt_state *s, int nargs)
633 {
634 const char *p;
635
636 for (p = s->value;
637 *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
638 (*p == '!') || (*p == '.'));
639 p++);
640
641 return (*p == 0);
642 }
643
644 static bool
645 dt_type_directory(struct dt_state *s, int nargs)
646 {
647 struct stat st;
648 return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
649 }
650
651
652 static bool
653 dt_type_device(struct dt_state *s, int nargs)
654 {
655 struct stat st;
656 return (!stat(s->value, &st) &&
657 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
658 }
659
660 static bool
661 dt_type_file(struct dt_state *s, int nargs)
662 {
663 struct stat st;
664 return (!stat(s->value, &st) && S_ISREG(st.st_mode));
665 }
666
667
668 static struct dt_fun dt_types[] = {
669 { "or", dt_type_or },
670 { "and", dt_type_and },
671 { "not", dt_type_not },
672 { "neg", dt_type_neg },
673 { "list", dt_type_list },
674 { "min", dt_type_min },
675 { "max", dt_type_max },
676 { "range", dt_type_range },
677 { "minlength", dt_type_minlen },
678 { "maxlength", dt_type_maxlen },
679 { "rangelength", dt_type_rangelen },
680 { "integer", dt_type_int },
681 { "uinteger", dt_type_uint },
682 { "float", dt_type_float },
683 { "ufloat", dt_type_ufloat },
684 { "bool", dt_type_bool },
685 { "ip4addr", dt_type_ip4addr },
686 { "ip6addr", dt_type_ip6addr },
687 { "ipaddr", dt_type_ipaddr },
688 { "cidr4", dt_type_cidr4 },
689 { "cidr6", dt_type_cidr6 },
690 { "cidr", dt_type_cidr },
691 { "netmask4", dt_type_netmask4 },
692 { "netmask6", dt_type_netmask6 },
693 { "ipmask4", dt_type_ipmask4 },
694 { "ipmask6", dt_type_ipmask6 },
695 { "ipmask", dt_type_ipmask },
696 { "port", dt_type_port },
697 { "portrange", dt_type_portrange },
698 { "macaddr", dt_type_macaddr },
699 { "uciname", dt_type_uciname },
700 { "wpakey", dt_type_wpakey },
701 { "wepkey", dt_type_wepkey },
702 { "hostname", dt_type_hostname },
703 { "host", dt_type_host },
704 { "network", dt_type_network },
705 { "phonedigit", dt_type_phonedigit },
706 { "directory", dt_type_directory },
707 { "device", dt_type_device },
708 { "file", dt_type_file },
709
710 { }
711 };
712
713 static struct dt_fun *
714 dt_lookup_function(const char *s, const char *e)
715 {
716 struct dt_fun *fun = dt_types;
717
718 while (fun->name)
719 {
720 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
721 return fun;
722
723 fun++;
724 }
725
726 return NULL;
727 }
728
729 static bool
730 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
731 {
732 char q, *e;
733 const char *p;
734 bool esc;
735 double dval;
736 struct dt_fun *func;
737 struct dt_op *op = &s->stack[s->depth];
738
739 if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
740 {
741 printf("Syntax error, expression too long\n");
742 return false;
743 }
744
745 while (isspace(*label))
746 label++;
747
748 /* test whether label is a float */
749 dval = strtod(label, &e);
750
751 if (e > label)
752 {
753 op->next = e;
754 op->type = OP_NUMBER;
755 op->value.number = dval;
756 op->nextop = ++s->depth;
757
758 return true;
759 }
760 else if ((*label == '"') || (*label == '\''))
761 {
762 for (p = label + 1, q = *label, esc = false; p <= end; p++)
763 {
764 if (esc)
765 {
766 esc = false;
767 continue;
768 }
769 else if (*p == '\\')
770 {
771 esc = true;
772 continue;
773 }
774 else if (*p == q)
775 {
776 op->next = p + 1;
777 op->type = OP_STRING;
778 op->length = (p - label) - 2;
779 op->value.string = label + 1;
780 op->nextop = ++s->depth;
781
782 return true;
783 }
784 }
785
786 printf("Syntax error, unterminated string\n");
787 return false;
788 }
789 else if (*label)
790 {
791 for (p = label;
792 p <= end && ((*p >= 'A' && *p <= 'Z') ||
793 (*p >= 'a' && *p <= 'z') ||
794 (*p >= '0' && *p <= '9') ||
795 (*p == '_'));
796 p++);
797
798 func = dt_lookup_function(label, p);
799
800 if (!func)
801 {
802 printf("Syntax error, unrecognized function\n");
803 return false;
804 }
805
806 op->next = p;
807 op->type = OP_FUNCTION;
808 op->value.function = func;
809 op->nextop = ++s->depth;
810
811 return true;
812 }
813
814 printf("Syntax error, unexpected EOF\n");
815 return false;
816 }
817
818 static bool
819 dt_parse_list(struct dt_state *s, const char *code, const char *end);
820
821 static bool
822 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
823 {
824 struct dt_op *tok;
825
826 if (!dt_parse_atom(s, code, end))
827 return false;
828
829 tok = &s->stack[s->depth - 1];
830
831 while (isspace(*tok->next))
832 tok->next++;
833
834 if (tok->type == OP_FUNCTION)
835 {
836 if (*tok->next == '(')
837 {
838 end--;
839
840 while (isspace(*end) && end > tok->next + 1)
841 end--;
842
843 return dt_parse_list(s, tok->next + 1, end);
844 }
845 else if (tok->next == end)
846 {
847 return dt_parse_list(s, tok->next, tok->next);
848 }
849
850 printf("Syntax error, expected '(' or EOF after function label\n");
851 return false;
852 }
853 else if (tok->next == end)
854 {
855 return true;
856 }
857
858 printf("Syntax error, expected ',' after literal\n");
859 return false;
860 }
861
862 static bool
863 dt_parse_list(struct dt_state *s, const char *code, const char *end)
864 {
865 char c;
866 bool esc;
867 int nest;
868 const char *p, *last;
869 struct dt_op *fptr;
870
871 if (!code)
872 return false;
873
874 fptr = &s->stack[s->depth - 1];
875
876 for (nest = 0, p = last = code, esc = false, c = *p;
877 p <= end;
878 p++, c = (p < end) ? *p : '\0')
879 {
880 if (esc)
881 {
882 esc = false;
883 continue;
884 }
885
886 switch (c)
887 {
888 case '\\':
889 esc = true;
890 break;
891
892 case '(':
893 nest++;
894 break;
895
896 case ')':
897 nest--;
898 break;
899
900 case ',':
901 case '\0':
902 if (nest <= 0)
903 {
904 if (p > last)
905 {
906 if (!dt_parse_expr(last, p, s))
907 return false;
908
909 fptr->length++;
910 }
911
912 last = p + 1;
913 }
914
915 break;
916 }
917 }
918
919 fptr->nextop = s->depth;
920 return true;
921 }
922
923 static bool
924 dt_step(struct dt_state *s)
925 {
926 bool rv;
927 struct dt_op *op = &s->stack[s->pos];
928
929 switch (op->type)
930 {
931 case OP_BOOL:
932 rv = op->value.boolean;
933 break;
934
935 case OP_NUMBER:
936 rv = dt_test_number(op->value.number, s->value);
937 break;
938
939 case OP_STRING:
940 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
941 break;
942
943 case OP_FUNCTION:
944 rv = dt_call(s);
945 break;
946
947 default:
948 rv = false;
949 break;
950 }
951
952 s->pos = op->nextop;
953 return rv;
954 }
955
956 static bool
957 dt_call(struct dt_state *s)
958 {
959 bool rv;
960 struct dt_op *fptr = &s->stack[s->pos];
961 struct dt_fun *func = fptr->value.function;
962
963 s->pos++;
964
965 rv = func->call(s, fptr->length);
966
967 s->pos = fptr->nextop;
968
969 return rv;
970 }
971
972 bool
973 dt_parse(const char *code, const char *value)
974 {
975 struct dt_state s = {
976 .depth = 1,
977 .stack = {
978 {
979 .type = OP_FUNCTION,
980 .value.function = &dt_types[0],
981 .next = code
982 }
983 }
984 };
985
986 if (!value || !*value)
987 return false;
988
989 if (!dt_parse_list(&s, code, code + strlen(code)))
990 return false;
991
992 s.value = value;
993
994 return dt_call(&s);
995 }