add service_validator support
[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_string(struct dt_state *s, int nargs)
318 {
319 return true;
320 }
321
322 static bool
323 dt_type_ip4addr(struct dt_state *s, int nargs)
324 {
325 struct in6_addr a;
326 return inet_pton(AF_INET, s->value, &a);
327 }
328
329 static bool
330 dt_type_ip6addr(struct dt_state *s, int nargs)
331 {
332 struct in6_addr a;
333 return inet_pton(AF_INET6, s->value, &a);
334 }
335
336 static bool
337 dt_type_ipaddr(struct dt_state *s, int nargs)
338 {
339 return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
340 }
341
342 static bool
343 dt_type_netmask4(struct dt_state *s, int nargs)
344 {
345 int i;
346 struct in_addr a;
347
348 if (!inet_pton(AF_INET, s->value, &a))
349 return false;
350
351 if (a.s_addr == 0)
352 return true;
353
354 a.s_addr = ntohl(a.s_addr);
355
356 for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
357
358 return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
359 }
360
361 static bool
362 dt_type_netmask6(struct dt_state *s, int nargs)
363 {
364 int i;
365 struct in6_addr a;
366
367 if (!inet_pton(AF_INET6, s->value, &a))
368 return false;
369
370 for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
371
372 if (i == 16)
373 return true;
374
375 if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
376 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
377 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
378 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
379 (a.s6_addr[i] != 0))
380 return false;
381
382 for (; (i < 16) && (a.s6_addr[i] == 0); i++);
383
384 return (i == 16);
385 }
386
387 static bool
388 dt_type_cidr4(struct dt_state *s, int nargs)
389 {
390 int n;
391 struct in_addr a;
392 char *p, buf[sizeof("255.255.255.255/32\0")];
393
394 if (strlen(s->value) >= sizeof(buf))
395 return false;
396
397 strcpy(buf, s->value);
398 p = strchr(buf, '/');
399
400 if (p)
401 {
402 *p++ = 0;
403
404 n = strtoul(p, &p, 10);
405
406 if ((*p != 0) || (n > 32))
407 return false;
408 }
409
410 return inet_pton(AF_INET, buf, &a);
411 }
412
413 static bool
414 dt_type_cidr6(struct dt_state *s, int nargs)
415 {
416 int n;
417 struct in6_addr a;
418 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
419
420 if (strlen(s->value) >= sizeof(buf))
421 return false;
422
423 strcpy(buf, s->value);
424 p = strchr(buf, '/');
425
426 if (p)
427 {
428 *p++ = 0;
429
430 n = strtoul(p, &p, 10);
431
432 if ((*p != 0) || (n > 128))
433 return false;
434 }
435
436 return inet_pton(AF_INET6, buf, &a);
437 }
438
439 static bool
440 dt_type_cidr(struct dt_state *s, int nargs)
441 {
442 return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
443 }
444
445 static bool
446 dt_type_ipmask4(struct dt_state *s, int nargs)
447 {
448 bool rv;
449 struct in_addr a;
450 const char *value;
451 char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
452
453 if (strlen(s->value) >= sizeof(buf))
454 return false;
455
456 strcpy(buf, s->value);
457 p = strchr(buf, '/');
458
459 if (p)
460 {
461 *p++ = 0;
462
463 value = s->value;
464 s->value = p;
465 rv = dt_type_netmask4(s, 0);
466 s->value = value;
467
468 if (!rv)
469 return false;
470 }
471
472 return inet_pton(AF_INET, buf, &a);
473 }
474
475 static bool
476 dt_type_ipmask6(struct dt_state *s, int nargs)
477 {
478 bool rv;
479 struct in6_addr a;
480 const char *value;
481 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
482 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
483
484 if (strlen(s->value) >= sizeof(buf))
485 return false;
486
487 strcpy(buf, s->value);
488 p = strchr(buf, '/');
489
490 if (p)
491 {
492 *p++ = 0;
493
494 value = s->value;
495 s->value = p;
496 rv = dt_type_netmask6(s, 0);
497 s->value = value;
498
499 if (!rv)
500 return false;
501 }
502
503 return inet_pton(AF_INET6, buf, &a);
504 }
505
506 static bool
507 dt_type_ipmask(struct dt_state *s, int nargs)
508 {
509 return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
510 }
511
512 static bool
513 dt_type_port(struct dt_state *s, int nargs)
514 {
515 int n;
516 char *e;
517
518 n = strtoul(s->value, &e, 10);
519
520 return (e > s->value && *e == 0 && n <= 65535);
521 }
522
523 static bool
524 dt_type_portrange(struct dt_state *s, int nargs)
525 {
526 int n, m;
527 char *e;
528
529 n = strtoul(s->value, &e, 10);
530
531 if (e == s->value || *e != '-')
532 return false;
533
534 m = strtoul(e + 1, &e, 10);
535
536 return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
537 }
538
539 static bool
540 dt_type_macaddr(struct dt_state *s, int nargs)
541 {
542 return !!ether_aton(s->value);
543 }
544
545 static bool
546 dt_type_uciname(struct dt_state *s, int nargs)
547 {
548 const char *p;
549
550 for (p = s->value;
551 *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
552 (*p >= '0' && *p <= '9') || (*p == '_'));
553 p++);
554
555 return (*p == 0);
556 }
557
558 static bool
559 dt_type_wpakey(struct dt_state *s, int nargs)
560 {
561 int len = strlen(s->value);
562 const char *p = s->value;
563
564 if (len == 64)
565 {
566 while (isxdigit(*p))
567 p++;
568
569 return (*p == 0);
570 }
571
572 return (len >= 8 && len <= 63);
573 }
574
575 static bool
576 dt_type_wepkey(struct dt_state *s, int nargs)
577 {
578 int len = strlen(s->value);
579 const char *p = s->value;
580
581 if (!strncmp(p, "s:", 2))
582 {
583 len -= 2;
584 p += 2;
585 }
586
587 if (len == 10 || len == 26)
588 {
589 while (isxdigit(*p))
590 p++;
591
592 return (*p == 0);
593 }
594
595 return (len == 5 || len == 13);
596 }
597
598 static bool
599 dt_type_hostname(struct dt_state *s, int nargs)
600 {
601 const char *p, *last;
602
603 for (p = last = s->value; *p; p++)
604 {
605 if (*p == '.')
606 {
607 if ((p - last) == 0 || (p - last) > 63)
608 return false;
609
610 last = p + 1;
611 continue;
612 }
613 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
614 (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
615 {
616 continue;
617 }
618
619 return false;
620 }
621
622 return ((p - last) > 0 && (p - last) <= 255);
623 }
624
625 static bool
626 dt_type_host(struct dt_state *s, int nargs)
627 {
628 return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
629 }
630
631 static bool
632 dt_type_network(struct dt_state *s, int nargs)
633 {
634 return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
635 }
636
637 static bool
638 dt_type_phonedigit(struct dt_state *s, int nargs)
639 {
640 const char *p;
641
642 for (p = s->value;
643 *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
644 (*p == '!') || (*p == '.'));
645 p++);
646
647 return (*p == 0);
648 }
649
650 static bool
651 dt_type_directory(struct dt_state *s, int nargs)
652 {
653 struct stat st;
654 return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
655 }
656
657
658 static bool
659 dt_type_device(struct dt_state *s, int nargs)
660 {
661 struct stat st;
662 return (!stat(s->value, &st) &&
663 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
664 }
665
666 static bool
667 dt_type_file(struct dt_state *s, int nargs)
668 {
669 struct stat st;
670 return (!stat(s->value, &st) && S_ISREG(st.st_mode));
671 }
672
673
674 static struct dt_fun dt_types[] = {
675 { "or", dt_type_or },
676 { "and", dt_type_and },
677 { "not", dt_type_not },
678 { "neg", dt_type_neg },
679 { "list", dt_type_list },
680 { "min", dt_type_min },
681 { "max", dt_type_max },
682 { "range", dt_type_range },
683 { "minlength", dt_type_minlen },
684 { "maxlength", dt_type_maxlen },
685 { "rangelength", dt_type_rangelen },
686 { "integer", dt_type_int },
687 { "uinteger", dt_type_uint },
688 { "float", dt_type_float },
689 { "ufloat", dt_type_ufloat },
690 { "bool", dt_type_bool },
691 { "string", dt_type_string },
692 { "ip4addr", dt_type_ip4addr },
693 { "ip6addr", dt_type_ip6addr },
694 { "ipaddr", dt_type_ipaddr },
695 { "cidr4", dt_type_cidr4 },
696 { "cidr6", dt_type_cidr6 },
697 { "cidr", dt_type_cidr },
698 { "netmask4", dt_type_netmask4 },
699 { "netmask6", dt_type_netmask6 },
700 { "ipmask4", dt_type_ipmask4 },
701 { "ipmask6", dt_type_ipmask6 },
702 { "ipmask", dt_type_ipmask },
703 { "port", dt_type_port },
704 { "portrange", dt_type_portrange },
705 { "macaddr", dt_type_macaddr },
706 { "uciname", dt_type_uciname },
707 { "wpakey", dt_type_wpakey },
708 { "wepkey", dt_type_wepkey },
709 { "hostname", dt_type_hostname },
710 { "host", dt_type_host },
711 { "network", dt_type_network },
712 { "phonedigit", dt_type_phonedigit },
713 { "directory", dt_type_directory },
714 { "device", dt_type_device },
715 { "file", dt_type_file },
716
717 { }
718 };
719
720 static struct dt_fun *
721 dt_lookup_function(const char *s, const char *e)
722 {
723 struct dt_fun *fun = dt_types;
724
725 while (fun->name)
726 {
727 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
728 return fun;
729
730 fun++;
731 }
732
733 return NULL;
734 }
735
736 static bool
737 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
738 {
739 char q, *e;
740 const char *p;
741 bool esc;
742 double dval;
743 struct dt_fun *func;
744 struct dt_op *op = &s->stack[s->depth];
745
746 if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
747 {
748 printf("Syntax error, expression too long\n");
749 return false;
750 }
751
752 while (isspace(*label))
753 label++;
754
755 /* test whether label is a float */
756 dval = strtod(label, &e);
757
758 if (e > label)
759 {
760 op->next = e;
761 op->type = OP_NUMBER;
762 op->value.number = dval;
763 op->nextop = ++s->depth;
764
765 return true;
766 }
767 else if ((*label == '"') || (*label == '\''))
768 {
769 for (p = label + 1, q = *label, esc = false; p <= end; p++)
770 {
771 if (esc)
772 {
773 esc = false;
774 continue;
775 }
776 else if (*p == '\\')
777 {
778 esc = true;
779 continue;
780 }
781 else if (*p == q)
782 {
783 op->next = p + 1;
784 op->type = OP_STRING;
785 op->length = (p - label) - 2;
786 op->value.string = label + 1;
787 op->nextop = ++s->depth;
788
789 return true;
790 }
791 }
792
793 printf("Syntax error, unterminated string\n");
794 return false;
795 }
796 else if (*label)
797 {
798 for (p = label;
799 p <= end && ((*p >= 'A' && *p <= 'Z') ||
800 (*p >= 'a' && *p <= 'z') ||
801 (*p >= '0' && *p <= '9') ||
802 (*p == '_'));
803 p++);
804
805 func = dt_lookup_function(label, p);
806
807 if (!func)
808 {
809 printf("Syntax error, unrecognized function\n");
810 return false;
811 }
812
813 op->next = p;
814 op->type = OP_FUNCTION;
815 op->value.function = func;
816 op->nextop = ++s->depth;
817
818 return true;
819 }
820
821 printf("Syntax error, unexpected EOF\n");
822 return false;
823 }
824
825 static bool
826 dt_parse_list(struct dt_state *s, const char *code, const char *end);
827
828 static bool
829 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
830 {
831 struct dt_op *tok;
832
833 if (!dt_parse_atom(s, code, end))
834 return false;
835
836 tok = &s->stack[s->depth - 1];
837
838 while (isspace(*tok->next))
839 tok->next++;
840
841 if (tok->type == OP_FUNCTION)
842 {
843 if (*tok->next == '(')
844 {
845 end--;
846
847 while (isspace(*end) && end > tok->next + 1)
848 end--;
849
850 return dt_parse_list(s, tok->next + 1, end);
851 }
852 else if (tok->next == end)
853 {
854 return dt_parse_list(s, tok->next, tok->next);
855 }
856
857 printf("Syntax error, expected '(' or EOF after function label\n");
858 return false;
859 }
860 else if (tok->next == end)
861 {
862 return true;
863 }
864
865 printf("Syntax error, expected ',' after literal\n");
866 return false;
867 }
868
869 static bool
870 dt_parse_list(struct dt_state *s, const char *code, const char *end)
871 {
872 char c;
873 bool esc;
874 int nest;
875 const char *p, *last;
876 struct dt_op *fptr;
877
878 if (!code)
879 return false;
880
881 fptr = &s->stack[s->depth - 1];
882
883 for (nest = 0, p = last = code, esc = false, c = *p;
884 p <= end;
885 p++, c = (p < end) ? *p : '\0')
886 {
887 if (esc)
888 {
889 esc = false;
890 continue;
891 }
892
893 switch (c)
894 {
895 case '\\':
896 esc = true;
897 break;
898
899 case '(':
900 nest++;
901 break;
902
903 case ')':
904 nest--;
905 break;
906
907 case ',':
908 case '\0':
909 if (nest <= 0)
910 {
911 if (p > last)
912 {
913 if (!dt_parse_expr(last, p, s))
914 return false;
915
916 fptr->length++;
917 }
918
919 last = p + 1;
920 }
921
922 break;
923 }
924 }
925
926 fptr->nextop = s->depth;
927 return true;
928 }
929
930 static bool
931 dt_step(struct dt_state *s)
932 {
933 bool rv;
934 struct dt_op *op = &s->stack[s->pos];
935
936 switch (op->type)
937 {
938 case OP_BOOL:
939 rv = op->value.boolean;
940 break;
941
942 case OP_NUMBER:
943 rv = dt_test_number(op->value.number, s->value);
944 break;
945
946 case OP_STRING:
947 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
948 break;
949
950 case OP_FUNCTION:
951 rv = dt_call(s);
952 break;
953
954 default:
955 rv = false;
956 break;
957 }
958
959 s->pos = op->nextop;
960 return rv;
961 }
962
963 static bool
964 dt_call(struct dt_state *s)
965 {
966 bool rv;
967 struct dt_op *fptr = &s->stack[s->pos];
968 struct dt_fun *func = fptr->value.function;
969
970 s->pos++;
971
972 rv = func->call(s, fptr->length);
973
974 s->pos = fptr->nextop;
975
976 return rv;
977 }
978
979 bool
980 dt_parse(const char *code, const char *value)
981 {
982 struct dt_state s = {
983 .depth = 1,
984 .stack = {
985 {
986 .type = OP_FUNCTION,
987 .value.function = &dt_types[0],
988 .next = code
989 }
990 }
991 };
992
993 if (!value || !*value)
994 return false;
995
996 if (!dt_parse_list(&s, code, code + strlen(code)))
997 return false;
998
999 s.value = value;
1000
1001 return dt_call(&s);
1002 }