summaryrefslogtreecommitdiff
path: root/src/sp_config_keywords.c
diff options
context:
space:
mode:
authorSebastien Blot2017-09-20 10:11:01 +0200
committerSebastien Blot2017-09-20 10:11:01 +0200
commit868f96c759b6650d88ff9f4fbc5c048302134248 (patch)
treec0de0af318bf77a8959164ef11aeeeb2b7bab294 /src/sp_config_keywords.c
Initial import
Diffstat (limited to 'src/sp_config_keywords.c')
-rw-r--r--src/sp_config_keywords.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c
new file mode 100644
index 0000000..4a6dd3a
--- /dev/null
+++ b/src/sp_config_keywords.c
@@ -0,0 +1,268 @@
1#include "php_snuffleupagus.h"
2
3ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
4
5static int parse_enable(char *line, bool * restrict retval, bool * restrict simulation) {
6 bool enable = false, disable = false;
7 sp_config_functions sp_config_funcs[] = {
8 {parse_empty, SP_TOKEN_ENABLE, &(enable)},
9 {parse_empty, SP_TOKEN_DISABLE, &(disable)},
10 {parse_empty, SP_TOKEN_SIMULATION, simulation},
11 {0}};
12
13 int ret = parse_keywords(sp_config_funcs, line);
14
15 if (0 != ret) {
16 return ret;
17 }
18
19 if (!(enable ^ disable)) {
20 sp_log_err("config", "A rule can't be enabled and disabled.");
21 return -1;
22 }
23
24 *retval = enable;
25
26 return ret;
27}
28
29int parse_random(char *line) {
30 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_random->enable), NULL);
31}
32
33int parse_disable_xxe(char *line) {
34 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL);
35}
36
37int parse_auto_cookie_secure(char *line) {
38 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_auto_cookie_secure->enable), NULL);
39}
40
41int parse_global_strict(char *line) {
42 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_global_strict->enable), NULL);
43}
44
45int parse_unserialize(char *line) {
46 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_unserialize->enable), &(SNUFFLEUPAGUS_G(config).config_unserialize->simulation));
47}
48
49int parse_readonly_exec(char *line) {
50 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_readonly_exec->enable), &(SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation));
51}
52
53int parse_global(char *line) {
54 sp_config_functions sp_config_funcs_encryption_key[] = {
55 {parse_str, SP_TOKEN_ENCRYPTION_KEY,
56 &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)},
57 {0}};
58 return parse_keywords(sp_config_funcs_encryption_key, line);
59}
60
61int parse_cookie_encryption(char *line) {
62 int ret = 0;
63 char *name = NULL;
64
65 sp_config_functions sp_config_funcs_cookie_encryption[] = {
66 {parse_str, SP_TOKEN_NAME, &name},
67 {parse_int, SP_TOKEN_MASK_IPV4,
68 &(SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4)},
69 {parse_int, SP_TOKEN_MASK_IPV6,
70 &(SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6)},
71 {0}};
72
73 ret = parse_keywords(sp_config_funcs_cookie_encryption, line);
74 if (0 != ret) {
75 return ret;
76 }
77
78 if (32 < SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4) {
79 SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4 = 32;
80 }
81 if (128 < SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6) {
82 SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6 = 128;
83 }
84
85 if (name) {
86 zend_hash_str_add_empty_element(
87 SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, name,
88 strlen(name));
89 }
90 return SUCCESS;
91}
92
93int parse_disabled_functions(char *line) {
94 int ret = 0;
95 bool enable = true, disable = false;
96 sp_disabled_function *df = pecalloc(sizeof(*df), 1, 1);
97
98 sp_config_functions sp_config_funcs_disabled_functions[] = {
99 {parse_empty, SP_TOKEN_ENABLE, &(enable)},
100 {parse_empty, SP_TOKEN_DISABLE, &(disable)},
101 {parse_str, SP_TOKEN_ALIAS, &(df->alias)},
102 {parse_empty, SP_TOKEN_SIMULATION, &(df->simulation)},
103 {parse_str, SP_TOKEN_FILENAME, &(df->filename)},
104 {parse_regexp, SP_TOKEN_FILENAME_REGEXP, &(df->r_filename)},
105 {parse_str, SP_TOKEN_FUNCTION, &(df->function)},
106 {parse_regexp, SP_TOKEN_FUNCTION_REGEXP, &(df->r_function)},
107 {parse_str, SP_TOKEN_DUMP, &(df->dump)},
108 {parse_empty, SP_TOKEN_ALLOW, &(df->allow)},
109 {parse_empty, SP_TOKEN_DROP, &(df->drop)},
110 {parse_str, SP_TOKEN_HASH, &(df->hash)},
111 {parse_str, SP_TOKEN_PARAM, &(df->param)},
112 {parse_regexp, SP_TOKEN_VALUE_REGEXP, &(df->regexp)},
113 {parse_str, SP_TOKEN_VALUE, &(df->value)},
114 {parse_regexp, SP_TOKEN_PARAM_REGEXP, &(df->r_param)},
115 {parse_php_type, SP_TOKEN_PARAM_TYPE, &(df->param_type)},
116 {parse_str, SP_TOKEN_RET, &(df->ret)},
117 {parse_cidr, SP_TOKEN_CIDR, &(df->cidr)},
118 {parse_regexp, SP_TOKEN_RET_REGEXP, &(df->r_ret)},
119 {parse_php_type, SP_TOKEN_RET_TYPE, &(df->ret_type)},
120 {parse_str, SP_TOKEN_LOCAL_VAR, &(df->var)},
121 {0}};
122
123 ret = parse_keywords(sp_config_funcs_disabled_functions, line);
124
125 if (0 != ret) {
126 return ret;
127 }
128
129 if (true == disable){
130 df->enable = false;
131 } else {
132 df->enable = true;
133 }
134
135 if (df->value && df->regexp) {
136 sp_log_err("config",
137 "Invalid configuration line: 'sp.disabled_functions%s':"
138 "'.value' and '.regexp' are mutually exclusives.",
139 line);
140 return -1;
141 } else if (df->r_function && df->function) {
142 sp_log_err("config",
143 "Invalid configuration line: 'sp.disabled_functions%s': "
144 "'.r_function' and '.function' are mutually exclusive.",
145 line);
146 return -1;
147 } else if (df->r_filename && df->filename) {
148 sp_log_err("config",
149 "Invalid configuration line: 'sp.disabled_functions%s':"
150 "'.r_filename' and '.filename' are mutually exclusive.",
151 line);
152 return -1;
153 } else if (df->r_param && df->param) {
154 sp_log_err("config",
155 "Invalid configuration line: 'sp.disabled_functions%s':"
156 "'.r_param' and '.param' are mutually exclusive.",
157 line);
158 return -1;
159 } else if (df->r_ret && df->ret) {
160 sp_log_err("config",
161 "Invalid configuration line: 'sp.disabled_functions%s':"
162 "'.r_ret' and '.ret' are mutually exclusive.",
163 line);
164 return -1;
165 } else if ((df->r_ret || df->ret) && (df->r_param || df->param)) {
166 sp_log_err("config",
167 "Invalid configuration line: 'sp.disabled_functions%s':"
168 "`ret` and `param` are mutually exclusives.",
169 line);
170 return -1;
171 } else if (!(df->r_function || df->function)) {
172 sp_log_err("config",
173 "Invalid configuration line: 'sp.disabled_functions%s':"
174 " must take a function name.",
175 line);
176 return -1;
177 } else if (!(df->allow ^ df->drop)) {
178 sp_log_err("config",
179 "Invalid configuration line: 'sp.disabled_functions%s': The "
180 "rule must either be a `drop` or and `allow` one.",
181 line);
182 return -1;
183 }
184
185 if (df->param && strchr(df->param, '[')) { // assume that this is an array
186 df->param_array_keys = sp_new_list();
187 if (0 != array_to_list(&df->param, &df->param_array_keys)) {
188 pefree(df->param_array_keys, 1);
189 return -1;
190 }
191 df->param_is_array = 1;
192 }
193
194 if (df->var && strchr(df->var, '[')) { // assume that this is an array
195 df->var_array_keys = sp_new_list();
196 if (0 != array_to_list(&df->var, &df->var_array_keys)) {
197 pefree(df->var_array_keys, 1);
198 return -1;
199 }
200 df->var_is_array = 1;
201 }
202
203 bool match = false;
204 const char *key[4] = {"include", "include_once", "require", "require_once"};
205 for (size_t i = 0; i < 4; i++) {
206 if (df->r_function && true == is_regexp_matching(df->r_function, key[i])) {
207 match = true;
208 break;
209 } else if (df->function && 0 == strcmp(df->function, key[i])) {
210 match = true;
211 break;
212 }
213 }
214 if (true == match && df->regexp) {
215 sp_list_insert(
216 SNUFFLEUPAGUS_G(config).config_regexp_inclusion->regexp_inclusion,
217 df->regexp);
218 } else if (df->ret || df->r_ret || df->ret_type) {
219 sp_list_insert(
220 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret->disabled_functions,
221 df);
222 } else {
223 sp_list_insert(
224 SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions,
225 df);
226 }
227 return ret;
228}
229
230int parse_upload_validation(char *line) {
231 bool disable = false, enable = false;
232 sp_config_functions sp_config_funcs_upload_validation[] = {
233 {parse_str, SP_TOKEN_UPLOAD_SCRIPT,
234 &(SNUFFLEUPAGUS_G(config).config_upload_validation->script)},
235 {parse_empty, SP_TOKEN_SIMULATION,
236 &(SNUFFLEUPAGUS_G(config).config_upload_validation->simulation)},
237 {parse_empty, SP_TOKEN_ENABLE, &(enable)},
238 {parse_empty, SP_TOKEN_DISABLE, &(disable)},
239 {0}};
240
241 int ret = parse_keywords(sp_config_funcs_upload_validation, line);
242
243 if (0 != ret) {
244 return ret;
245 }
246
247 if (!(enable ^ disable)) {
248 sp_log_err("config", "A rule can't be enabled and disabled.");
249 return -1;
250 }
251 SNUFFLEUPAGUS_G(config).config_upload_validation->enable = enable;
252
253 char const *script = SNUFFLEUPAGUS_G(config).config_upload_validation->script;
254
255 if (!script) {
256 sp_log_err("config", "The `script` directive is mandatory in %s",
257 line);
258 return -1;
259 } else if (-1 == access(script, F_OK)) {
260 sp_log_err("config", "The `script` (%s) doesn't exist.", script);
261 return -1;
262 } else if (-1 == access(script, X_OK)) {
263 sp_log_err("config", "The `script` (%s) isn't executable.", script);
264 return -1;
265 }
266
267 return ret;
268}