diff options
| author | Ben Fuhrmannek | 2022-02-05 12:23:37 +0100 |
|---|---|---|
| committer | Ben Fuhrmannek | 2022-02-05 12:23:37 +0100 |
| commit | c38df1077a6c1dfbca1baca049214d053e2e7684 (patch) | |
| tree | d29872cb01e3f905f26c11abc01e39b81607553e | |
| parent | 4d4ae75f0b843e06c666ea192a912316a9e1497c (diff) | |
added config dump/export for use with other tools
| -rw-r--r-- | src/snuffleupagus.c | 260 |
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 | ||
| 39 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | 41 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) |
| 40 | 42 | ||
| 41 | static 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 | |||
| 51 | PHP_INI_BEGIN() | 43 | PHP_INI_BEGIN() |
| 52 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, OnUpdateConfiguration) | 44 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, OnUpdateConfiguration) |
| 53 | PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode) | 45 | STD_PHP_INI_BOOLEAN("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_broken_configuration, zend_snuffleupagus_globals, snuffleupagus_globals) |
| 46 | |||
| 54 | PHP_INI_END() | 47 | PHP_INI_END() |
| 55 | 48 | ||
| 56 | ZEND_DLEXPORT zend_extension zend_extension_entry = { | 49 | ZEND_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 | |||
| 265 | static 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 | |||
| 334 | static 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 | |||
| 269 | static PHP_INI_MH(OnUpdateConfiguration) { | 493 | static 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 | } |
