validator.c (3214B)
1 /*
2 * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <sys/types.h>
18
19 #include "kore.h"
20
21 TAILQ_HEAD(, kore_validator) validators;
22
23 void
24 kore_validator_init(void)
25 {
26 TAILQ_INIT(&validators);
27 }
28
29 int
30 kore_validator_add(const char *name, u_int8_t type, const char *arg)
31 {
32 int ret;
33 struct kore_validator *val;
34
35 val = kore_malloc(sizeof(*val));
36 val->type = type;
37
38 switch (val->type) {
39 case KORE_VALIDATOR_TYPE_REGEX:
40 ret = regcomp(&(val->rctx), arg, REG_EXTENDED | REG_NOSUB);
41 if (ret) {
42 kore_free(val);
43 kore_log(LOG_NOTICE,
44 "validator %s has bad regex %s (%d)",
45 name, arg, ret);
46 return (KORE_RESULT_ERROR);
47 }
48 break;
49 case KORE_VALIDATOR_TYPE_FUNCTION:
50 val->rcall = kore_runtime_getcall(arg);
51 if (val->rcall == NULL) {
52 kore_free(val);
53 kore_log(LOG_NOTICE,
54 "validator %s has undefined callback %s",
55 name, arg);
56 return (KORE_RESULT_ERROR);
57 }
58 break;
59 default:
60 kore_free(val);
61 return (KORE_RESULT_ERROR);
62 }
63
64 val->arg = kore_strdup(arg);
65 val->name = kore_strdup(name);
66 TAILQ_INSERT_TAIL(&validators, val, list);
67
68 return (KORE_RESULT_OK);
69 }
70
71 int
72 kore_validator_run(struct http_request *req, const char *name, char *data)
73 {
74 struct kore_validator *val;
75
76 TAILQ_FOREACH(val, &validators, list) {
77 if (strcmp(val->name, name))
78 continue;
79
80 return (kore_validator_check(req, val, data));
81 }
82
83 return (KORE_RESULT_ERROR);
84 }
85
86 int
87 kore_validator_check(struct http_request *req, struct kore_validator *val,
88 const void *data)
89 {
90 int r;
91
92 switch (val->type) {
93 case KORE_VALIDATOR_TYPE_REGEX:
94 if (!regexec(&(val->rctx), data, 0, NULL, 0))
95 r = KORE_RESULT_OK;
96 else
97 r = KORE_RESULT_ERROR;
98 break;
99 case KORE_VALIDATOR_TYPE_FUNCTION:
100 r = kore_runtime_validator(val->rcall, req, data);
101 break;
102 default:
103 r = KORE_RESULT_ERROR;
104 kore_log(LOG_NOTICE, "invalid type %d for validator %s",
105 val->type, val->name);
106 break;
107 }
108
109 return (r);
110 }
111
112 void
113 kore_validator_reload(void)
114 {
115 struct kore_validator *val;
116
117 TAILQ_FOREACH(val, &validators, list) {
118 if (val->type != KORE_VALIDATOR_TYPE_FUNCTION)
119 continue;
120
121 kore_free(val->rcall);
122 val->rcall = kore_runtime_getcall(val->arg);
123 if (val->rcall == NULL)
124 fatal("no function for validator %s found", val->arg);
125 }
126 }
127
128 struct kore_validator *
129 kore_validator_lookup(const char *name)
130 {
131 struct kore_validator *val;
132
133 TAILQ_FOREACH(val, &validators, list) {
134 if (!strcmp(val->name, name))
135 return (val);
136 }
137
138 return (NULL);
139 }