summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Fuhrmannek2022-02-05 12:23:37 +0100
committerBen Fuhrmannek2022-02-05 12:23:37 +0100
commitc38df1077a6c1dfbca1baca049214d053e2e7684 (patch)
treed29872cb01e3f905f26c11abc01e39b81607553e /src
parent4d4ae75f0b843e06c666ea192a912316a9e1497c (diff)
added config dump/export for use with other tools
Diffstat (limited to 'src')
-rw-r--r--src/snuffleupagus.c260
1 files changed, 249 insertions, 11 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c
index caa6ba3..e8f3664 100644
--- a/src/snuffleupagus.c
+++ b/src/snuffleupagus.c
@@ -4,6 +4,8 @@
4#include <glob.h> 4#include <glob.h>
5#endif 5#endif
6 6
7#include "zend_smart_str.h"
8
7#include "php_snuffleupagus.h" 9#include "php_snuffleupagus.h"
8 10
9#ifndef ZEND_EXT_API 11#ifndef ZEND_EXT_API
@@ -38,19 +40,10 @@ static inline void sp_op_array_handler(zend_op_array *const op) {
38 40
39ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) 41ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
40 42
41static PHP_INI_MH(StrictMode) {
42 TSRMLS_FETCH();
43
44 SPG(allow_broken_configuration) = false;
45 if (new_value && zend_string_equals_literal(new_value, "1")) {
46 SPG(allow_broken_configuration) = true;
47 }
48 return SUCCESS;
49}
50
51PHP_INI_BEGIN() 43PHP_INI_BEGIN()
52PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, OnUpdateConfiguration) 44PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, OnUpdateConfiguration)
53PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode) 45STD_PHP_INI_BOOLEAN("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_broken_configuration, zend_snuffleupagus_globals, snuffleupagus_globals)
46
54PHP_INI_END() 47PHP_INI_END()
55 48
56ZEND_DLEXPORT zend_extension zend_extension_entry = { 49ZEND_DLEXPORT zend_extension zend_extension_entry = {
@@ -266,6 +259,237 @@ PHP_MINFO_FUNCTION(snuffleupagus) {
266 DISPLAY_INI_ENTRIES(); 259 DISPLAY_INI_ENTRIES();
267} 260}
268 261
262#define ADD_ASSOC_ZSTR(arr, key, zstr) if (zstr) { add_assoc_str(arr, key, zstr); } else { add_assoc_null(arr, key); }
263#define ADD_ASSOC_REGEXP(arr, key, regexp) if (regexp && regexp->pattern) { add_assoc_str(arr, key, regexp->pattern); } else { add_assoc_null(arr, key); }
264
265static void add_df_to_arr(zval *arr, sp_disabled_function *df) {
266 zval arr_df;
267 array_init(&arr_df);
268
269 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_FILENAME, df->filename);
270 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_FILENAME_REGEXP, df->r_filename);
271 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_FUNCTION, df->function);
272 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_FUNCTION_REGEXP, df->r_function);
273 if (df->functions_list && df->functions_list->data) {
274 zval arr_fl;
275 array_init(&arr_fl);
276 for (sp_list_node *p = df->functions_list; p; p = p->next) { add_next_index_str(&arr_fl, p->data); }
277 add_assoc_zval(&arr_df, "function_list", &arr_fl);
278 } else {
279 add_assoc_null(&arr_df, "function_list");
280 }
281 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_HASH, df->hash);
282 add_assoc_bool(&arr_df, SP_TOKEN_SIM, df->simulation);
283 if (df->param && df->param->value) {
284 add_assoc_string(&arr_df, SP_TOKEN_PARAM, df->param->value);
285 } else {
286 add_assoc_null(&arr_df, SP_TOKEN_PARAM);
287 }
288 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_PARAM_REGEXP, df->r_param);
289 add_assoc_long(&arr_df, SP_TOKEN_PARAM_TYPE, df->param_type);
290 add_assoc_long(&arr_df, SP_TOKEN_VALUE_ARG_POS, df->pos);
291 add_assoc_long(&arr_df, SP_TOKEN_LINE_NUMBER, df->line);
292 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_RET, df->ret);
293 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_RET_REGEXP, df->r_ret);
294 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_VALUE, df->value);
295 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_VALUE_REGEXP, df->r_value);
296 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_KEY, df->key);
297 ADD_ASSOC_REGEXP(&arr_df, SP_TOKEN_KEY_REGEXP, df->r_key);
298 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_DUMP, df->dump);
299 ADD_ASSOC_ZSTR(&arr_df, SP_TOKEN_ALIAS, df->alias);
300 add_assoc_bool(&arr_df, "param_is_array", df->param_is_array);
301 add_assoc_bool(&arr_df, "var_is_array", df->var_is_array);
302 add_assoc_bool(&arr_df, "allow", df->allow);
303 // todo: properly traverse tree for .var() and .param()
304 // sp_tree *tr = df->var;
305 // for (; tr; tr = tr->next) {
306 // sp_log_debug("tree: %s", tr->value);
307 // }
308
309 if (df->var && df->var->value) {
310 add_assoc_string(&arr_df, SP_TOKEN_LOCAL_VAR, df->var->value);
311 } else {
312 add_assoc_null(&arr_df, SP_TOKEN_LOCAL_VAR);
313 }
314 if (df->param && df->param->value) {
315 add_assoc_string(&arr_df, SP_TOKEN_PARAM, df->param->value);
316 } else {
317 add_assoc_null(&arr_df, SP_TOKEN_PARAM);
318 }
319
320 if (df->cidr) {
321 char cidrstr[INET6_ADDRSTRLEN+5];
322 if (!get_ip_str(cidrstr, sizeof(cidrstr), df->cidr)) {
323 add_assoc_null(&arr_df, SP_TOKEN_CIDR);
324 } else {
325 add_assoc_string(&arr_df, SP_TOKEN_CIDR, cidrstr);
326 }
327 } else {
328 add_assoc_null(&arr_df, SP_TOKEN_CIDR);
329 }
330
331 add_next_index_zval(arr, &arr_df);
332}
333
334static void dump_config() {
335 zval arr;
336 php_serialize_data_t var_hash;
337 smart_str buf = {0};
338
339 array_init(&arr);
340 add_assoc_string(&arr, "version", PHP_SNUFFLEUPAGUS_VERSION);
341
342 add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_ENABLE, SPCFG(unserialize).enable);
343 add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_SIM, SPCFG(unserialize).simulation);
344 ADD_ASSOC_ZSTR(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_DUMP, SPCFG(unserialize).dump);
345
346 add_assoc_bool(&arr, SP_TOKEN_HARDEN_RANDOM "." SP_TOKEN_ENABLE, SPCFG(random).enable);
347
348 add_assoc_bool(&arr, "readonly_exec.enable", SPCFG(readonly_exec).enable);
349 add_assoc_bool(&arr, "readonly_exec.sim", SPCFG(readonly_exec).simulation);
350 ADD_ASSOC_ZSTR(&arr, SP_TOKEN_READONLY_EXEC "." SP_TOKEN_DUMP, SPCFG(readonly_exec).dump);
351
352 add_assoc_bool(&arr, "global_strict.enable", SPCFG(global_strict).enable);
353
354 add_assoc_bool(&arr, "upload_validation.enable", SPCFG(upload_validation).enable);
355 add_assoc_bool(&arr, "upload_validation.sim", SPCFG(upload_validation).simulation);
356 ADD_ASSOC_ZSTR(&arr, SP_TOKEN_UPLOAD_VALIDATION "." SP_TOKEN_UPLOAD_SCRIPT, SPCFG(upload_validation).script);
357
358 // global
359 add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_ENCRYPTION_KEY, SPCFG(encryption_key) && ZSTR_LEN(SPCFG(encryption_key)));
360 ADD_ASSOC_ZSTR(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_ENV_VAR, SPCFG(cookies_env_var));
361 add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_LOG_MEDIA, SPCFG(log_media));
362 add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_MAX_EXECUTION_DEPTH, SPCFG(max_execution_depth));
363 add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_SERVER_ENCODE, SPCFG(server_encode));
364 add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_SERVER_STRIP, SPCFG(server_strip));
365 add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_SHOW_OLD_PHP_WARNING, SPCFG(show_old_php_warning));
366
367 add_assoc_bool(&arr, SP_TOKEN_AUTO_COOKIE_SECURE, SPCFG(auto_cookie_secure).enable);
368 add_assoc_bool(&arr, SP_TOKEN_XXE_PROTECTION, SPCFG(xxe_protection).enable);
369
370 add_assoc_bool(&arr, SP_TOKEN_EVAL_BLACKLIST "." SP_TOKEN_SIM, SPCFG(eval).simulation);
371 ADD_ASSOC_ZSTR(&arr, SP_TOKEN_EVAL_BLACKLIST "." SP_TOKEN_DUMP, SPCFG(eval).dump);
372#define ADD_ASSOC_SPLIST(arr, key, splist) \
373 if (splist) { \
374 zval arr_sp; \
375 array_init(&arr_sp); \
376 for (sp_list_node *p = splist; p; p = p->next) { add_next_index_str(&arr_sp, p->data); } \
377 add_assoc_zval(arr, key, &arr_sp); \
378 } else { add_assoc_null(arr, key); }
379
380 ADD_ASSOC_SPLIST(&arr, SP_TOKEN_EVAL_BLACKLIST "." SP_TOKEN_LIST, SPCFG(eval).blacklist);
381 ADD_ASSOC_SPLIST(&arr, SP_TOKEN_EVAL_WHITELIST "." SP_TOKEN_LIST, SPCFG(eval).whitelist)
382
383 add_assoc_bool(&arr, SP_TOKEN_SESSION_ENCRYPTION "." SP_TOKEN_ENCRYPT, SPCFG(session).encrypt);
384 add_assoc_bool(&arr, SP_TOKEN_SESSION_ENCRYPTION "." SP_TOKEN_SIM, SPCFG(session).simulation);
385
386 add_assoc_long(&arr, SP_TOKEN_SESSION_ENCRYPTION "." SP_TOKEN_SID_MIN_LENGTH, SPCFG(session).sid_min_length);
387 add_assoc_long(&arr, SP_TOKEN_SESSION_ENCRYPTION "." SP_TOKEN_SID_MAX_LENGTH, SPCFG(session).sid_max_length);
388 add_assoc_bool(&arr, SP_TOKEN_SLOPPY_COMPARISON "." SP_TOKEN_ENABLE, SPCFG(sloppy).enable);
389
390 ADD_ASSOC_SPLIST(&arr, SP_TOKEN_ALLOW_WRAPPERS, SPCFG(wrapper).whitelist);
391
392 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." SP_TOKEN_ENABLE, SPCFG(ini).enable);
393 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." SP_TOKEN_SIM, SPCFG(ini).simulation);
394 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." "policy_ro", SPCFG(ini).policy_readonly);
395 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." "policy_silent_ro", SPCFG(ini).policy_silent_ro);
396 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." "policy_silent_fail", SPCFG(ini).policy_silent_fail);
397 add_assoc_bool(&arr, SP_TOKEN_INI_PROTECTION "." "policy_drop", SPCFG(ini).policy_drop);
398
399 if (SPCFG(ini).entries && zend_hash_num_elements(SPCFG(ini).entries) > 0) {
400 zval arr_ini;
401 array_init(&arr_ini);
402
403 sp_ini_entry *sp_entry;
404 ZEND_HASH_FOREACH_PTR(SPCFG(ini).entries, sp_entry)
405 zval arr_ini_entry;
406 array_init(&arr_ini_entry);
407 add_assoc_bool(&arr_ini_entry, SP_TOKEN_SIM, sp_entry->simulation);
408 ADD_ASSOC_ZSTR(&arr_ini_entry, SP_TOKEN_KEY, sp_entry->key);
409 ADD_ASSOC_ZSTR(&arr_ini_entry, "msg", sp_entry->msg);
410 ADD_ASSOC_ZSTR(&arr_ini_entry, "set", sp_entry->set);
411 ADD_ASSOC_ZSTR(&arr_ini_entry, "min", sp_entry->min);
412 ADD_ASSOC_ZSTR(&arr_ini_entry, "max", sp_entry->max);
413 add_assoc_long(&arr_ini_entry, "access", sp_entry->access);
414 add_assoc_bool(&arr_ini_entry, "drop", sp_entry->drop);
415 add_assoc_bool(&arr_ini_entry, "allow_null", sp_entry->allow_null);
416 ADD_ASSOC_REGEXP(&arr_ini_entry, "regexp", sp_entry->regexp);
417 add_next_index_zval(&arr_ini, &arr_ini_entry);
418 ZEND_HASH_FOREACH_END();
419 add_assoc_zval(&arr, SP_TOKEN_INI, &arr_ini);
420 } else {
421 add_assoc_null(&arr, SP_TOKEN_INI);
422 }
423
424 if (SPCFG(cookie).cookies && SPCFG(cookie).cookies->data) {
425 zval arr_cookies;
426 array_init(&arr_cookies);
427
428 sp_cookie *cookie;
429 sp_list_node *p = SPCFG(cookie).cookies;
430 for (; p; p = p->next) {
431 zval arr_cookie;
432 array_init(&arr_cookie);
433 cookie = (sp_cookie*)p->data;
434
435 add_assoc_long(&arr_cookie, SP_TOKEN_SAMESITE, cookie->samesite);
436 add_assoc_bool(&arr_cookie, SP_TOKEN_ENCRYPT, cookie->encrypt);
437 ADD_ASSOC_ZSTR(&arr_cookie, SP_TOKEN_NAME, cookie->name);
438 ADD_ASSOC_REGEXP(&arr_cookie, SP_TOKEN_NAME_REGEXP, cookie->name_r);
439 add_assoc_bool(&arr_cookie, SP_TOKEN_SIM, cookie->simulation);
440
441 add_next_index_zval(&arr_cookies, &arr_cookie);
442 }
443
444 add_assoc_zval(&arr, SP_TOKEN_COOKIE_ENCRYPTION, &arr_cookies);
445 } else {
446 add_assoc_null(&arr, SP_TOKEN_COOKIE_ENCRYPTION);
447 }
448
449 // disabled_functions
450 zval arr_dfs;
451 array_init(&arr_dfs);
452 size_t num_df = 0;
453 sp_list_node *dflist, *dfp;
454 ZEND_HASH_FOREACH_PTR(SPCFG(disabled_functions), dflist)
455 for (dfp = dflist; dfp; dfp = dfp->next) {
456 add_df_to_arr(&arr_dfs, dfp->data);
457 num_df++;
458 }
459 ZEND_HASH_FOREACH_END();
460 ZEND_HASH_FOREACH_PTR(SPCFG(disabled_functions_ret), dflist)
461 for (dfp = dflist; dfp; dfp = dfp->next) {
462 add_df_to_arr(&arr_dfs, dfp->data);
463 num_df++;
464 }
465 ZEND_HASH_FOREACH_END();
466 for (dfp = SPCFG(disabled_functions_reg).disabled_functions; dfp; dfp = dfp->next) {
467 add_df_to_arr(&arr_dfs, dfp->data);
468 num_df++;
469 }
470 for (dfp = SPCFG(disabled_functions_reg_ret).disabled_functions; dfp; dfp = dfp->next) {
471 add_df_to_arr(&arr_dfs, dfp->data);
472 num_df++;
473 }
474
475 if (num_df) {
476 add_assoc_zval(&arr, SP_TOKEN_DISABLE_FUNC, &arr_dfs);
477 } else {
478 add_assoc_null(&arr, SP_TOKEN_DISABLE_FUNC);
479 }
480
481 // serialize and print array
482 PHP_VAR_SERIALIZE_INIT(var_hash);
483 php_var_serialize(&buf, &arr, &var_hash);
484 PHP_VAR_SERIALIZE_DESTROY(var_hash);
485
486 printf("%s", ZSTR_VAL(buf.s));
487 sp_log_debug("--");
488
489 smart_str_free(&buf);
490
491}
492
269static PHP_INI_MH(OnUpdateConfiguration) { 493static PHP_INI_MH(OnUpdateConfiguration) {
270 sp_log_debug("(OnUpdateConfiguration)"); 494 sp_log_debug("(OnUpdateConfiguration)");
271 495
@@ -304,6 +528,20 @@ static PHP_INI_MH(OnUpdateConfiguration) {
304 528
305 SPG(is_config_valid) = SP_CONFIG_VALID; 529 SPG(is_config_valid) = SP_CONFIG_VALID;
306 530
531 // dump config
532 sp_log_debug("module name? %s", sapi_module.name);
533 if (getenv("SP_DUMP_CONFIG")) {
534 sp_log_debug("env? %s", getenv("SP_DUMP_CONFIG"));
535 }
536
537 if (strcmp(sapi_module.name, "cli") == 0 && getenv("SP_DUMP_CONFIG")) {
538 dump_config();
539 return SUCCESS;
540 }
541
542
543 // start hooks
544
307 if (SPCFG(sloppy).enable) { 545 if (SPCFG(sloppy).enable) {
308 hook_sloppy(); 546 hook_sloppy();
309 } 547 }