From 868f96c759b6650d88ff9f4fbc5c048302134248 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Wed, 20 Sep 2017 10:11:01 +0200 Subject: Initial import --- src/bench/bench.php | 422 +++++++++++ src/bench/micro_bench.php | 358 +++++++++ src/config.m4 | 35 + src/config.w32 | 13 + src/php_snuffleupagus.h | 71 ++ src/snuffleupagus.c | 222 ++++++ src/snuffleupagus.php | 21 + src/sp_compile.c | 53 ++ src/sp_compile.h | 6 + src/sp_config.c | 193 +++++ src/sp_config.h | 206 +++++ src/sp_config_keywords.c | 268 +++++++ src/sp_config_keywords.h | 16 + src/sp_config_utils.c | 211 ++++++ src/sp_config_utils.h | 8 + src/sp_cookie_encryption.c | 216 ++++++ src/sp_cookie_encryption.h | 17 + src/sp_disable_xxe.c | 25 + src/sp_disable_xxe.h | 6 + src/sp_disabled_functions.c | 356 +++++++++ src/sp_disabled_functions.h | 11 + src/sp_execute.c | 100 +++ src/sp_execute.h | 6 + src/sp_harden_rand.c | 77 ++ src/sp_harden_rand.h | 10 + src/sp_list.c | 37 + src/sp_list.h | 15 + src/sp_network_utils.c | 159 ++++ src/sp_network_utils.h | 8 + src/sp_unserialize.c | 111 +++ src/sp_unserialize.h | 9 + src/sp_upload_validation.c | 92 +++ src/sp_upload_validation.h | 9 + src/sp_utils.c | 425 +++++++++++ src/sp_utils.h | 68 ++ src/tests/broken_conf.phpt | 10 + src/tests/broken_conf2.phpt | 9 + src/tests/broken_conf_config_regexp.phpt | 10 + src/tests/broken_conf_enable_disable.phpt | 9 + src/tests/broken_conf_expecting_bool.phpt | 9 + src/tests/broken_conf_expecting_int.phpt | 9 + src/tests/broken_conf_invalid_cidr.phpt | 9 + src/tests/broken_conf_invalid_cidr6.phpt | 9 + src/tests/broken_conf_invalid_cidr6_no_slash.phpt | 9 + src/tests/broken_conf_invalid_cidr6_too_big.phpt | 9 + src/tests/broken_conf_invalid_cidr_value.phpt | 11 + src/tests/broken_conf_invalid_type.phpt | 9 + src/tests/broken_conf_line_empty_string.phpt | 9 + src/tests/broken_conf_line_no_closing.phpt | 9 + src/tests/broken_conf_line_too_long.phpt | 10 + src/tests/broken_conf_lots_of_quotes.phpt | 9 + src/tests/broken_conf_mutually_exclusive.phpt | 9 + src/tests/broken_conf_mutually_exclusive2.phpt | 9 + src/tests/broken_conf_mutually_exclusive3.phpt | 9 + src/tests/broken_conf_mutually_exclusive4.phpt | 9 + src/tests/broken_conf_mutually_exclusive5.phpt | 9 + src/tests/broken_conf_mutually_exclusive6.phpt | 9 + src/tests/broken_conf_mutually_exclusive7.phpt | 9 + src/tests/broken_conf_mutually_exclusive8.phpt | 9 + src/tests/broken_conf_no_closing_misc.phpt | 10 + src/tests/broken_conf_weird_keyword.phpt | 9 + src/tests/broken_conf_wrong_quotes.phpt | 9 + src/tests/broken_conf_wrong_type.phpt | 9 + src/tests/broken_regexp.phpt | 9 + src/tests/config/borken_conf_enable_disable.ini | 1 + src/tests/config/broken_conf.ini | 1 + src/tests/config/broken_conf2.ini | 1 + src/tests/config/broken_conf_expecting_bool.ini | 5 + src/tests/config/broken_conf_expecting_int.ini | 2 + src/tests/config/broken_conf_invalid_cidr.ini | 1 + src/tests/config/broken_conf_invalid_cidr6.ini | 1 + .../config/broken_conf_invalid_cidr6_no_slash.ini | 1 + .../config/broken_conf_invalid_cidr6_too_big.ini | 1 + .../config/broken_conf_invalid_cidr_value.ini | 1 + src/tests/config/broken_conf_invalid_type.ini | 1 + src/tests/config/broken_conf_line_empty_string.ini | 1 + src/tests/config/broken_conf_line_no_closing.ini | 1 + src/tests/config/broken_conf_line_too_long.ini | 1 + src/tests/config/broken_conf_lots_of_quotes.ini | 1 + .../config/broken_conf_mutually_exclusive.ini | 1 + .../config/broken_conf_mutually_exclusive2.ini | 1 + .../config/broken_conf_mutually_exclusive3.ini | 1 + .../config/broken_conf_mutually_exclusive4.ini | 1 + .../config/broken_conf_mutually_exclusive5.ini | 1 + .../config/broken_conf_mutually_exclusive6.ini | 1 + .../config/broken_conf_mutually_exclusive7.ini | 1 + .../config/broken_conf_mutually_exclusive8.ini | 1 + src/tests/config/broken_conf_no_closing_misc.ini | 1 + src/tests/config/broken_conf_to_few_args.ini | 1 + src/tests/config/broken_conf_weird_keyword.ini | 1 + src/tests/config/broken_conf_wrong_quotes.ini | 1 + src/tests/config/broken_conf_wrong_type.ini | 5 + src/tests/config/broken_config_regexp.ini | 1 + src/tests/config/broken_regexp.ini | 1 + src/tests/config/config_disable_writable.ini | 1 + .../config/config_disable_writable_disabled.ini | 1 + .../config/config_disable_writable_simulation.ini | 1 + .../config_disabled_functions_filename_r.ini | 2 + .../config/config_disabled_functions_method.ini | 3 + .../config/config_disabled_functions_name_r.ini | 2 + .../config/config_disabled_functions_name_type.ini | 1 + .../config/config_disabled_functions_namespace.ini | 2 + .../config/config_disabled_functions_nul_byte.ini | 1 + .../config/config_disabled_functions_param.ini | 6 + .../config_disabled_functions_param_alias.ini | 2 + .../config_disabled_functions_param_allow.ini | 3 + .../config_disabled_functions_param_array.ini | 4 + .../config/config_disabled_functions_param_int.ini | 2 + .../config/config_disabled_functions_param_r.ini | 1 + .../config_disabled_functions_param_runtime.ini | 1 + ...disabled_functions_param_str_representation.ini | 1 + .../config/config_disabled_functions_require.ini | 1 + .../config/config_disabled_functions_ret_allow.ini | 2 + .../config_disabled_functions_ret_allow_value.ini | 1 + .../config_disabled_functions_ret_right_hash.ini | 4 + .../config_disabled_functions_ret_simulation.ini | 3 + .../config_disabled_functions_right_hash.ini | 3 + .../config/config_disabled_user_functions.ini | 1 + src/tests/config/config_encrypted_cookies.ini | 3 + .../config/config_noncore_function_hooking.ini | 1 + src/tests/config/config_rand_harden_disabled.ini | 1 + src/tests/config/config_serialize.ini | 2 + src/tests/config/config_serialize_sim.ini | 2 + src/tests/config/disable_xxe.ini | 1 + src/tests/config/disable_xxe_disable.ini | 1 + src/tests/config/disabled_function_local_var.ini | 2 + .../config/disabled_function_super_global_var.ini | 1 + src/tests/config/disabled_functions.ini | 7 + src/tests/config/disabled_functions_cidr.ini | 4 + src/tests/config/disabled_functions_mb.ini | 2 + src/tests/config/disabled_functions_ret.ini | 5 + src/tests/config/disabled_functions_ret_type.ini | 1 + .../config/disabled_functions_ret_type_double.ini | 1 + .../config/disabled_functions_ret_type_long.ini | 1 + .../disabled_functions_ret_type_resource.ini | 1 + .../config/disabled_functions_ret_type_str.ini | 1 + .../config/disabled_functions_ret_type_true.ini | 1 + src/tests/config/disabled_functions_retval.ini | 1 + src/tests/config/disabled_functions_retval_rx.ini | 1 + src/tests/config/disabled_functions_zero_cidr.ini | 1 + src/tests/config/dump_request.ini | 1 + src/tests/config/dump_request_invalid_folder.ini | 1 + src/tests/config/empty.ini | 0 src/tests/config/empty_conf.ini | 0 src/tests/config/encryption_key_only.ini | 1 + src/tests/config/global_strict.ini | 1 + src/tests/config/global_strict_disabled.ini | 1 + src/tests/config/harden_rand.ini | 1 + src/tests/config/upload_validation.ini | 2 + src/tests/config/upload_validation_invalid.ini | 1 + src/tests/config/upload_validation_ko.ini | 1 + .../config/upload_validation_ko_simulation.ini | 1 + src/tests/config/upload_validation_no_exist.ini | 1 + src/tests/config/upload_validation_non_exec.ini | 1 + src/tests/config/upload_validation_ok.ini | 1 + src/tests/data/upload_invalid.sh | 1 + src/tests/data/upload_ko.sh | 2 + src/tests/data/upload_no_exec.sh | 2 + src/tests/data/upload_ok.sh | 2 + src/tests/deny_writable_execution.phpt | 44 ++ src/tests/deny_writable_execution_disabled.phpt | 32 + src/tests/deny_writable_execution_simulation.phpt | 45 ++ src/tests/disable_xxe_dom.phpt | 71 ++ src/tests/disable_xxe_dom_disabled.phpt | 56 ++ src/tests/disable_xxe_simplexml.phpt | 52 ++ src/tests/disable_xxe_simplexml_oop.phpt | 52 ++ src/tests/disable_xxe_xml_parse.phpt | 104 +++ src/tests/disabled_function_local_var.phpt | 24 + src/tests/disabled_function_super_global_var.phpt | 20 + src/tests/disabled_functions.phpt | 21 + src/tests/disabled_functions_cidr.phpt | 18 + src/tests/disabled_functions_cidr_6.phpt | 18 + src/tests/disabled_functions_filename_r.phpt | 14 + src/tests/disabled_functions_mb.phpt | 12 + src/tests/disabled_functions_method.phpt | 29 + src/tests/disabled_functions_name_r.phpt | 15 + src/tests/disabled_functions_name_type.phpt | 14 + src/tests/disabled_functions_namespace.phpt | 31 + src/tests/disabled_functions_noconf.phpt | 12 + src/tests/disabled_functions_nul_byte.phpt | 15 + src/tests/disabled_functions_param.phpt | 24 + src/tests/disabled_functions_param_alias.phpt | 14 + src/tests/disabled_functions_param_allow.phpt | 14 + src/tests/disabled_functions_param_array.phpt | 37 + src/tests/disabled_functions_param_int.phpt | 25 + src/tests/disabled_functions_param_r.phpt | 14 + ...isabled_functions_param_str_representation.phpt | 25 + src/tests/disabled_functions_parse_class.phpt | 22 + src/tests/disabled_functions_require.phpt | 25 + src/tests/disabled_functions_ret.phpt | 13 + src/tests/disabled_functions_ret2.phpt | 12 + src/tests/disabled_functions_ret3.phpt | 22 + src/tests/disabled_functions_ret_allow.phpt | 13 + src/tests/disabled_functions_ret_allow_value.phpt | 12 + src/tests/disabled_functions_ret_right_hash.phpt | 12 + src/tests/disabled_functions_ret_simulation.phpt | 18 + src/tests/disabled_functions_ret_type.phpt | 16 + src/tests/disabled_functions_ret_type_double.phpt | 12 + src/tests/disabled_functions_ret_type_long.phpt | 12 + .../disabled_functions_ret_type_resource.phpt | 12 + src/tests/disabled_functions_ret_type_str.phpt | 12 + src/tests/disabled_functions_ret_type_true.phpt | 16 + src/tests/disabled_functions_ret_val.phpt | 14 + src/tests/disabled_functions_ret_val_rx.phpt | 14 + src/tests/disabled_functions_right_hash.phpt | 12 + src/tests/disabled_functions_runtime.phpt | 31 + src/tests/disabled_functions_zero_cidr.phpt | 18 + src/tests/disabled_option.phpt | 16 + src/tests/disabled_user_functions.phpt | 15 + src/tests/dump_request.phpt | 39 + src/tests/dump_request_invalid_folder.phpt | 25 + src/tests/dump_request_too_big.phpt | 42 + src/tests/empty_conf.phpt | 8 + src/tests/encrypt_cookies.phpt | 22 + src/tests/encrypt_cookies2.phpt | 23 + src/tests/encrypt_cookies3.phpt | 23 + src/tests/encrypt_cookies4.phpt | 23 + src/tests/encrypt_cookies_invalid_decryption.phpt | 23 + src/tests/encrypt_cookies_invalid_decryption2.phpt | 23 + src/tests/encrypt_cookies_invalid_decryption3.phpt | 21 + src/tests/encryption_key_only.phpt | 13 + src/tests/example_configuration.phpt | 12 + src/tests/global_strict.phpt | 16 + src/tests/global_strict_disabled.phpt | 14 + src/tests/harden_mt_rand.phpt | 22 + src/tests/harden_rand.phpt | 24 + src/tests/harden_rand_noargs.phpt | 62 ++ src/tests/inexistent_conf_file.phpt | 10 + src/tests/loading.phpt | 10 + src/tests/noncore_function_hooking.phpt | 15 + src/tests/phpinfo_presence.phpt | 19 + src/tests/serialize.phpt | 13 + src/tests/setcookie.phpt | 35 + src/tests/shipped_configuration.phpt | 12 + src/tests/unserialize.phpt | 13 + src/tests/unserialize_fail.phpt | 23 + src/tests/unserialize_sim.phpt | 17 + src/tests/upload_validation.phpt | 16 + src/tests/upload_validation_invalid.phpt | 17 + src/tests/upload_validation_ko.phpt | 14 + src/tests/upload_validation_no_exec.phpt | 32 + src/tests/upload_validation_nocrash.phpt | 12 + src/tests/upload_validation_ok.phpt | 17 + src/tweetnacl.c | 842 +++++++++++++++++++++ src/tweetnacl.h | 277 +++++++ 245 files changed, 7307 insertions(+) create mode 100644 src/bench/bench.php create mode 100644 src/bench/micro_bench.php create mode 100644 src/config.m4 create mode 100644 src/config.w32 create mode 100644 src/php_snuffleupagus.h create mode 100644 src/snuffleupagus.c create mode 100644 src/snuffleupagus.php create mode 100644 src/sp_compile.c create mode 100644 src/sp_compile.h create mode 100644 src/sp_config.c create mode 100644 src/sp_config.h create mode 100644 src/sp_config_keywords.c create mode 100644 src/sp_config_keywords.h create mode 100644 src/sp_config_utils.c create mode 100644 src/sp_config_utils.h create mode 100644 src/sp_cookie_encryption.c create mode 100644 src/sp_cookie_encryption.h create mode 100644 src/sp_disable_xxe.c create mode 100644 src/sp_disable_xxe.h create mode 100644 src/sp_disabled_functions.c create mode 100644 src/sp_disabled_functions.h create mode 100644 src/sp_execute.c create mode 100644 src/sp_execute.h create mode 100644 src/sp_harden_rand.c create mode 100644 src/sp_harden_rand.h create mode 100644 src/sp_list.c create mode 100644 src/sp_list.h create mode 100644 src/sp_network_utils.c create mode 100644 src/sp_network_utils.h create mode 100644 src/sp_unserialize.c create mode 100644 src/sp_unserialize.h create mode 100644 src/sp_upload_validation.c create mode 100644 src/sp_upload_validation.h create mode 100644 src/sp_utils.c create mode 100644 src/sp_utils.h create mode 100644 src/tests/broken_conf.phpt create mode 100644 src/tests/broken_conf2.phpt create mode 100644 src/tests/broken_conf_config_regexp.phpt create mode 100644 src/tests/broken_conf_enable_disable.phpt create mode 100644 src/tests/broken_conf_expecting_bool.phpt create mode 100644 src/tests/broken_conf_expecting_int.phpt create mode 100644 src/tests/broken_conf_invalid_cidr.phpt create mode 100644 src/tests/broken_conf_invalid_cidr6.phpt create mode 100644 src/tests/broken_conf_invalid_cidr6_no_slash.phpt create mode 100644 src/tests/broken_conf_invalid_cidr6_too_big.phpt create mode 100644 src/tests/broken_conf_invalid_cidr_value.phpt create mode 100644 src/tests/broken_conf_invalid_type.phpt create mode 100644 src/tests/broken_conf_line_empty_string.phpt create mode 100644 src/tests/broken_conf_line_no_closing.phpt create mode 100644 src/tests/broken_conf_line_too_long.phpt create mode 100644 src/tests/broken_conf_lots_of_quotes.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive2.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive3.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive4.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive5.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive6.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive7.phpt create mode 100644 src/tests/broken_conf_mutually_exclusive8.phpt create mode 100644 src/tests/broken_conf_no_closing_misc.phpt create mode 100644 src/tests/broken_conf_weird_keyword.phpt create mode 100644 src/tests/broken_conf_wrong_quotes.phpt create mode 100644 src/tests/broken_conf_wrong_type.phpt create mode 100644 src/tests/broken_regexp.phpt create mode 100644 src/tests/config/borken_conf_enable_disable.ini create mode 100644 src/tests/config/broken_conf.ini create mode 100644 src/tests/config/broken_conf2.ini create mode 100644 src/tests/config/broken_conf_expecting_bool.ini create mode 100644 src/tests/config/broken_conf_expecting_int.ini create mode 100644 src/tests/config/broken_conf_invalid_cidr.ini create mode 100644 src/tests/config/broken_conf_invalid_cidr6.ini create mode 100644 src/tests/config/broken_conf_invalid_cidr6_no_slash.ini create mode 100644 src/tests/config/broken_conf_invalid_cidr6_too_big.ini create mode 100644 src/tests/config/broken_conf_invalid_cidr_value.ini create mode 100644 src/tests/config/broken_conf_invalid_type.ini create mode 100644 src/tests/config/broken_conf_line_empty_string.ini create mode 100644 src/tests/config/broken_conf_line_no_closing.ini create mode 100644 src/tests/config/broken_conf_line_too_long.ini create mode 100644 src/tests/config/broken_conf_lots_of_quotes.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive2.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive3.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive4.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive5.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive6.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive7.ini create mode 100644 src/tests/config/broken_conf_mutually_exclusive8.ini create mode 100644 src/tests/config/broken_conf_no_closing_misc.ini create mode 100644 src/tests/config/broken_conf_to_few_args.ini create mode 100644 src/tests/config/broken_conf_weird_keyword.ini create mode 100644 src/tests/config/broken_conf_wrong_quotes.ini create mode 100644 src/tests/config/broken_conf_wrong_type.ini create mode 100644 src/tests/config/broken_config_regexp.ini create mode 100644 src/tests/config/broken_regexp.ini create mode 100644 src/tests/config/config_disable_writable.ini create mode 100644 src/tests/config/config_disable_writable_disabled.ini create mode 100644 src/tests/config/config_disable_writable_simulation.ini create mode 100644 src/tests/config/config_disabled_functions_filename_r.ini create mode 100644 src/tests/config/config_disabled_functions_method.ini create mode 100644 src/tests/config/config_disabled_functions_name_r.ini create mode 100644 src/tests/config/config_disabled_functions_name_type.ini create mode 100644 src/tests/config/config_disabled_functions_namespace.ini create mode 100644 src/tests/config/config_disabled_functions_nul_byte.ini create mode 100644 src/tests/config/config_disabled_functions_param.ini create mode 100644 src/tests/config/config_disabled_functions_param_alias.ini create mode 100644 src/tests/config/config_disabled_functions_param_allow.ini create mode 100644 src/tests/config/config_disabled_functions_param_array.ini create mode 100644 src/tests/config/config_disabled_functions_param_int.ini create mode 100644 src/tests/config/config_disabled_functions_param_r.ini create mode 100644 src/tests/config/config_disabled_functions_param_runtime.ini create mode 100644 src/tests/config/config_disabled_functions_param_str_representation.ini create mode 100644 src/tests/config/config_disabled_functions_require.ini create mode 100644 src/tests/config/config_disabled_functions_ret_allow.ini create mode 100644 src/tests/config/config_disabled_functions_ret_allow_value.ini create mode 100644 src/tests/config/config_disabled_functions_ret_right_hash.ini create mode 100644 src/tests/config/config_disabled_functions_ret_simulation.ini create mode 100644 src/tests/config/config_disabled_functions_right_hash.ini create mode 100644 src/tests/config/config_disabled_user_functions.ini create mode 100644 src/tests/config/config_encrypted_cookies.ini create mode 100644 src/tests/config/config_noncore_function_hooking.ini create mode 100644 src/tests/config/config_rand_harden_disabled.ini create mode 100644 src/tests/config/config_serialize.ini create mode 100644 src/tests/config/config_serialize_sim.ini create mode 100644 src/tests/config/disable_xxe.ini create mode 100644 src/tests/config/disable_xxe_disable.ini create mode 100644 src/tests/config/disabled_function_local_var.ini create mode 100644 src/tests/config/disabled_function_super_global_var.ini create mode 100644 src/tests/config/disabled_functions.ini create mode 100644 src/tests/config/disabled_functions_cidr.ini create mode 100644 src/tests/config/disabled_functions_mb.ini create mode 100644 src/tests/config/disabled_functions_ret.ini create mode 100644 src/tests/config/disabled_functions_ret_type.ini create mode 100644 src/tests/config/disabled_functions_ret_type_double.ini create mode 100644 src/tests/config/disabled_functions_ret_type_long.ini create mode 100644 src/tests/config/disabled_functions_ret_type_resource.ini create mode 100644 src/tests/config/disabled_functions_ret_type_str.ini create mode 100644 src/tests/config/disabled_functions_ret_type_true.ini create mode 100644 src/tests/config/disabled_functions_retval.ini create mode 100644 src/tests/config/disabled_functions_retval_rx.ini create mode 100644 src/tests/config/disabled_functions_zero_cidr.ini create mode 100644 src/tests/config/dump_request.ini create mode 100644 src/tests/config/dump_request_invalid_folder.ini create mode 100644 src/tests/config/empty.ini create mode 100644 src/tests/config/empty_conf.ini create mode 100644 src/tests/config/encryption_key_only.ini create mode 100644 src/tests/config/global_strict.ini create mode 100644 src/tests/config/global_strict_disabled.ini create mode 100644 src/tests/config/harden_rand.ini create mode 100644 src/tests/config/upload_validation.ini create mode 100644 src/tests/config/upload_validation_invalid.ini create mode 100644 src/tests/config/upload_validation_ko.ini create mode 100644 src/tests/config/upload_validation_ko_simulation.ini create mode 100644 src/tests/config/upload_validation_no_exist.ini create mode 100644 src/tests/config/upload_validation_non_exec.ini create mode 100644 src/tests/config/upload_validation_ok.ini create mode 100755 src/tests/data/upload_invalid.sh create mode 100755 src/tests/data/upload_ko.sh create mode 100644 src/tests/data/upload_no_exec.sh create mode 100755 src/tests/data/upload_ok.sh create mode 100644 src/tests/deny_writable_execution.phpt create mode 100644 src/tests/deny_writable_execution_disabled.phpt create mode 100644 src/tests/deny_writable_execution_simulation.phpt create mode 100644 src/tests/disable_xxe_dom.phpt create mode 100644 src/tests/disable_xxe_dom_disabled.phpt create mode 100644 src/tests/disable_xxe_simplexml.phpt create mode 100644 src/tests/disable_xxe_simplexml_oop.phpt create mode 100644 src/tests/disable_xxe_xml_parse.phpt create mode 100644 src/tests/disabled_function_local_var.phpt create mode 100644 src/tests/disabled_function_super_global_var.phpt create mode 100644 src/tests/disabled_functions.phpt create mode 100644 src/tests/disabled_functions_cidr.phpt create mode 100644 src/tests/disabled_functions_cidr_6.phpt create mode 100644 src/tests/disabled_functions_filename_r.phpt create mode 100644 src/tests/disabled_functions_mb.phpt create mode 100644 src/tests/disabled_functions_method.phpt create mode 100644 src/tests/disabled_functions_name_r.phpt create mode 100644 src/tests/disabled_functions_name_type.phpt create mode 100644 src/tests/disabled_functions_namespace.phpt create mode 100644 src/tests/disabled_functions_noconf.phpt create mode 100644 src/tests/disabled_functions_nul_byte.phpt create mode 100644 src/tests/disabled_functions_param.phpt create mode 100644 src/tests/disabled_functions_param_alias.phpt create mode 100644 src/tests/disabled_functions_param_allow.phpt create mode 100644 src/tests/disabled_functions_param_array.phpt create mode 100644 src/tests/disabled_functions_param_int.phpt create mode 100644 src/tests/disabled_functions_param_r.phpt create mode 100644 src/tests/disabled_functions_param_str_representation.phpt create mode 100644 src/tests/disabled_functions_parse_class.phpt create mode 100644 src/tests/disabled_functions_require.phpt create mode 100644 src/tests/disabled_functions_ret.phpt create mode 100644 src/tests/disabled_functions_ret2.phpt create mode 100644 src/tests/disabled_functions_ret3.phpt create mode 100644 src/tests/disabled_functions_ret_allow.phpt create mode 100644 src/tests/disabled_functions_ret_allow_value.phpt create mode 100644 src/tests/disabled_functions_ret_right_hash.phpt create mode 100644 src/tests/disabled_functions_ret_simulation.phpt create mode 100644 src/tests/disabled_functions_ret_type.phpt create mode 100644 src/tests/disabled_functions_ret_type_double.phpt create mode 100644 src/tests/disabled_functions_ret_type_long.phpt create mode 100644 src/tests/disabled_functions_ret_type_resource.phpt create mode 100644 src/tests/disabled_functions_ret_type_str.phpt create mode 100644 src/tests/disabled_functions_ret_type_true.phpt create mode 100644 src/tests/disabled_functions_ret_val.phpt create mode 100644 src/tests/disabled_functions_ret_val_rx.phpt create mode 100644 src/tests/disabled_functions_right_hash.phpt create mode 100644 src/tests/disabled_functions_runtime.phpt create mode 100644 src/tests/disabled_functions_zero_cidr.phpt create mode 100644 src/tests/disabled_option.phpt create mode 100644 src/tests/disabled_user_functions.phpt create mode 100644 src/tests/dump_request.phpt create mode 100644 src/tests/dump_request_invalid_folder.phpt create mode 100644 src/tests/dump_request_too_big.phpt create mode 100644 src/tests/empty_conf.phpt create mode 100644 src/tests/encrypt_cookies.phpt create mode 100644 src/tests/encrypt_cookies2.phpt create mode 100644 src/tests/encrypt_cookies3.phpt create mode 100644 src/tests/encrypt_cookies4.phpt create mode 100644 src/tests/encrypt_cookies_invalid_decryption.phpt create mode 100644 src/tests/encrypt_cookies_invalid_decryption2.phpt create mode 100644 src/tests/encrypt_cookies_invalid_decryption3.phpt create mode 100644 src/tests/encryption_key_only.phpt create mode 100644 src/tests/example_configuration.phpt create mode 100644 src/tests/global_strict.phpt create mode 100644 src/tests/global_strict_disabled.phpt create mode 100644 src/tests/harden_mt_rand.phpt create mode 100644 src/tests/harden_rand.phpt create mode 100644 src/tests/harden_rand_noargs.phpt create mode 100644 src/tests/inexistent_conf_file.phpt create mode 100644 src/tests/loading.phpt create mode 100644 src/tests/noncore_function_hooking.phpt create mode 100644 src/tests/phpinfo_presence.phpt create mode 100644 src/tests/serialize.phpt create mode 100644 src/tests/setcookie.phpt create mode 100644 src/tests/shipped_configuration.phpt create mode 100644 src/tests/unserialize.phpt create mode 100644 src/tests/unserialize_fail.phpt create mode 100644 src/tests/unserialize_sim.phpt create mode 100644 src/tests/upload_validation.phpt create mode 100644 src/tests/upload_validation_invalid.phpt create mode 100644 src/tests/upload_validation_ko.phpt create mode 100644 src/tests/upload_validation_no_exec.phpt create mode 100644 src/tests/upload_validation_nocrash.phpt create mode 100644 src/tests/upload_validation_ok.phpt create mode 100644 src/tweetnacl.c create mode 100644 src/tweetnacl.h (limited to 'src') diff --git a/src/bench/bench.php b/src/bench/bench.php new file mode 100644 index 0000000..5f77180 --- /dev/null +++ b/src/bench/bench.php @@ -0,0 +1,422 @@ +0)) { + $im=$re*$im*2+$imc; + $re=$re2-$im2+$rec; + $re2=$re*$re; + $im2=$im*$im; + $color=$color-1; + } + if ( $color==0 ) { + print "_"; + } else { + print "#"; + } + } + print "
"; + flush(); + } +} + +/****/ + +function mandel2() { + $b = " .:,;!/>)|&IH%*#"; + //float r, i, z, Z, t, c, C; + for ($y=30; printf("\n"), $C = $y*0.1 - 1.5, $y--;){ + for ($x=0; $c = $x*0.04 - 2, $z=0, $Z=0, $x++ < 75;){ + for ($r=$c, $i=$C, $k=0; $t = $z*$z - $Z*$Z + $r, $Z = 2*$z*$Z + $i, $z=$t, $k<5000; $k++) + if ($z*$z + $Z*$Z > 500000) break; + echo $b[$k%16]; + } + } +} + +/****/ + +function Ack($m, $n){ + if($m == 0) return $n+1; + if($n == 0) return Ack($m-1, 1); + return Ack($m - 1, Ack($m, ($n - 1))); +} + +function ackermann($n) { + $r = Ack(3,$n); + print "Ack(3,$n): $r\n"; +} + +/****/ + +function ary($n) { + for ($i=0; $i<$n; $i++) { + $X[$i] = $i; + } + for ($i=$n-1; $i>=0; $i--) { + $Y[$i] = $X[$i]; + } + $last = $n-1; + print "$Y[$last]\n"; +} + +/****/ + +function ary2($n) { + for ($i=0; $i<$n;) { + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + } + for ($i=$n-1; $i>=0;) { + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + } + $last = $n-1; + print "$Y[$last]\n"; +} + +/****/ + +function ary3($n) { + for ($i=0; $i<$n; $i++) { + $X[$i] = $i + 1; + $Y[$i] = 0; + } + for ($k=0; $k<1000; $k++) { + for ($i=$n-1; $i>=0; $i--) { + $Y[$i] += $X[$i]; + } + } + $last = $n-1; + print "$Y[0] $Y[$last]\n"; +} + +/****/ + +function fibo_r($n){ + return(($n < 2) ? 1 : fibo_r($n - 2) + fibo_r($n - 1)); +} + +function fibo($n) { + $r = fibo_r($n); + print "$r\n"; +} + +/****/ + +function hash1($n) { + for ($i = 1; $i <= $n; $i++) { + $X[dechex($i)] = $i; + } + $c = 0; + for ($i = $n; $i > 0; $i--) { + if ($X[dechex($i)]) { $c++; } + } + print "$c\n"; +} + +/****/ + +function hash2($n) { + for ($i = 0; $i < $n; $i++) { + $hash1["foo_$i"] = $i; + $hash2["foo_$i"] = 0; + } + for ($i = $n; $i > 0; $i--) { + foreach($hash1 as $key => $value) $hash2[$key] += $value; + } + $first = "foo_0"; + $last = "foo_".($n-1); + print "$hash1[$first] $hash1[$last] $hash2[$first] $hash2[$last]\n"; +} + +/****/ + +function gen_random ($n) { + global $LAST; + return( ($n * ($LAST = ($LAST * IA + IC) % IM)) / IM ); +} + +function heapsort_r($n, &$ra) { + $l = ($n >> 1) + 1; + $ir = $n; + + while (1) { + if ($l > 1) { + $rra = $ra[--$l]; + } else { + $rra = $ra[$ir]; + $ra[$ir] = $ra[1]; + if (--$ir == 1) { + $ra[1] = $rra; + return; + } + } + $i = $l; + $j = $l << 1; + while ($j <= $ir) { + if (($j < $ir) && ($ra[$j] < $ra[$j+1])) { + $j++; + } + if ($rra < $ra[$j]) { + $ra[$i] = $ra[$j]; + $j += ($i = $j); + } else { + $j = $ir + 1; + } + } + $ra[$i] = $rra; + } +} + +function heapsort($N) { + global $LAST; + + define("IM", 139968); + define("IA", 3877); + define("IC", 29573); + + $LAST = 42; + for ($i=1; $i<=$N; $i++) { + $ary[$i] = gen_random(1); + } + heapsort_r($N, $ary); + printf("%.10f\n", $ary[$N]); +} + +/****/ + +function mkmatrix ($rows, $cols) { + $count = 1; + $mx = array(); + for ($i=0; $i<$rows; $i++) { + for ($j=0; $j<$cols; $j++) { + $mx[$i][$j] = $count++; + } + } + return($mx); +} + +function mmult ($rows, $cols, $m1, $m2) { + $m3 = array(); + for ($i=0; $i<$rows; $i++) { + for ($j=0; $j<$cols; $j++) { + $x = 0; + for ($k=0; $k<$cols; $k++) { + $x += $m1[$i][$k] * $m2[$k][$j]; + } + $m3[$i][$j] = $x; + } + } + return($m3); +} + +function matrix($n) { + $SIZE = 30; + $m1 = mkmatrix($SIZE, $SIZE); + $m2 = mkmatrix($SIZE, $SIZE); + while ($n--) { + $mm = mmult($SIZE, $SIZE, $m1, $m2); + } + print "{$mm[0][0]} {$mm[2][3]} {$mm[3][2]} {$mm[4][4]}\n"; +} + +/****/ + +function nestedloop($n) { + $x = 0; + for ($a=0; $a<$n; $a++) + for ($b=0; $b<$n; $b++) + for ($c=0; $c<$n; $c++) + for ($d=0; $d<$n; $d++) + for ($e=0; $e<$n; $e++) + for ($f=0; $f<$n; $f++) + $x++; + print "$x\n"; +} + +/****/ + +function sieve($n) { + $count = 0; + while ($n-- > 0) { + $count = 0; + $flags = range (0,8192); + for ($i=2; $i<8193; $i++) { + if ($flags[$i] > 0) { + for ($k=$i+$i; $k <= 8192; $k+=$i) { + $flags[$k] = 0; + } + $count++; + } + } + } + print "Count: $count\n"; +} + +/****/ + +function strcat($n) { + $str = ""; + while ($n-- > 0) { + $str .= "hello\n"; + } + $len = strlen($str); + print "$len\n"; +} + +/*****/ + +function getmicrotime() +{ + $t = gettimeofday(); + return ($t['sec'] + $t['usec'] / 1000000); +} + +function start_test() +{ + ob_start(); + return getmicrotime(); +} + +function end_test($start, $name) +{ + global $total; + $end = getmicrotime(); + ob_end_clean(); + $total += $end-$start; + $num = number_format($end-$start,3); + $pad = str_repeat(" ", 24-strlen($name)-strlen($num)); + + echo $name.$pad.$num."\n"; + ob_start(); + return getmicrotime(); +} + +function total() +{ + global $total; + $pad = str_repeat("-", 24); + echo $pad."\n"; + $num = number_format($total,3); + $pad = str_repeat(" ", 24-strlen("Total")-strlen($num)); + echo "Total".$pad.$num."\n"; +} + +$t0 = $t = start_test(); +simple(); +$t = end_test($t, "simple"); +simplecall(); +$t = end_test($t, "simplecall"); +simpleucall(); +$t = end_test($t, "simpleucall"); +simpleudcall(); +$t = end_test($t, "simpleudcall"); +mandel(); +$t = end_test($t, "mandel"); +mandel2(); +$t = end_test($t, "mandel2"); +ackermann(7); +$t = end_test($t, "ackermann(7)"); +ary(50000); +$t = end_test($t, "ary(50000)"); +ary2(50000); +$t = end_test($t, "ary2(50000)"); +ary3(2000); +$t = end_test($t, "ary3(2000)"); +fibo(30); +$t = end_test($t, "fibo(30)"); +hash1(50000); +$t = end_test($t, "hash1(50000)"); +hash2(500); +$t = end_test($t, "hash2(500)"); +heapsort(20000); +$t = end_test($t, "heapsort(20000)"); +matrix(20); +$t = end_test($t, "matrix(20)"); +nestedloop(12); +$t = end_test($t, "nestedloop(12)"); +sieve(30); +$t = end_test($t, "sieve(30)"); +strcat(200000); +$t = end_test($t, "strcat(200000)"); +total($t0, "Total"); +?> diff --git a/src/bench/micro_bench.php b/src/bench/micro_bench.php new file mode 100644 index 0000000..7052588 --- /dev/null +++ b/src/bench/micro_bench.php @@ -0,0 +1,358 @@ +b; + } + } + + function write_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $this->b = 0; + } + } + + function assign_add_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $this->b += 2; + } + } + + function pre_inc_prop($n) { + for ($i = 0; $i < $n; ++$i) { + ++$this->b; + } + } + + function pre_dec_prop($n) { + for ($i = 0; $i < $n; ++$i) { + --$this->b; + } + } + + function post_inc_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $this->b++; + } + } + + function post_dec_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $this->b--; + } + } + + function isset_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $x = isset($this->b); + } + } + + function empty_prop($n) { + for ($i = 0; $i < $n; ++$i) { + $x = empty($this->b); + } + } + + function g() { + } + + function call($n) { + for ($i = 0; $i < $n; ++$i) { + $this->g(); + } + } + + function read_const($n) { + for ($i = 0; $i < $n; ++$i) { + $x = $this::TEST; + } + } + +} + +function read_static($n) { + for ($i = 0; $i < $n; ++$i) { + $x = Foo::$a; + } +} + +function write_static($n) { + for ($i = 0; $i < $n; ++$i) { + Foo::$a = 0; + } +} + +function isset_static($n) { + for ($i = 0; $i < $n; ++$i) { + $x = isset(Foo::$a); + } +} + +function empty_static($n) { + for ($i = 0; $i < $n; ++$i) { + $x = empty(Foo::$a); + } +} + +function call_static($n) { + for ($i = 0; $i < $n; ++$i) { + Foo::f(); + } +} + +function create_object($n) { + for ($i = 0; $i < $n; ++$i) { + $x = new Foo(); + } +} + +define('TEST', null); + +function read_const($n) { + for ($i = 0; $i < $n; ++$i) { + $x = TEST; + } +} + +function read_auto_global($n) { + for ($i = 0; $i < $n; ++$i) { + $x = $_GET; + } +} + +$g_var = 0; + +function read_global_var($n) { + for ($i = 0; $i < $n; ++$i) { + $x = $GLOBALS['g_var']; + } +} + +function read_hash($n) { + $hash = array('test' => 0); + for ($i = 0; $i < $n; ++$i) { + $x = $hash['test']; + } +} + +function read_str_offset($n) { + $str = "test"; + for ($i = 0; $i < $n; ++$i) { + $x = $str[1]; + } +} + +function issetor($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + for ($i = 0; $i < $n; ++$i) { + $x = $val ?: null; + } +} + +function issetor2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ?: $j + 1; + } +} + +function ternary($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + $f = false; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? null : $val; + } +} + +function ternary2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? $f : $j + 1; + } +} + +/*****/ + +function empty_loop($n) { + for ($i = 0; $i < $n; ++$i) { + } +} + +function getmicrotime() +{ + $t = gettimeofday(); + return ($t['sec'] + $t['usec'] / 1000000); +} + +function start_test() +{ + ob_start(); + return getmicrotime(); +} + +function end_test($start, $name, $overhead = null) +{ + global $total; + global $last_time; + $end = getmicrotime(); + ob_end_clean(); + $last_time = $end-$start; + $total += $last_time; + $num = number_format($last_time,3); + $pad = str_repeat(" ", 24-strlen($name)-strlen($num)); + if (is_null($overhead)) { + echo $name.$pad.$num."\n"; + } else { + $num2 = number_format($last_time - $overhead,3); + echo $name.$pad.$num." ".$num2."\n"; + } + ob_start(); + return getmicrotime(); +} + +function total() +{ + global $total; + $pad = str_repeat("-", 24); + echo $pad."\n"; + $num = number_format($total,3); + $pad = str_repeat(" ", 24-strlen("Total")-strlen($num)); + echo "Total".$pad.$num."\n"; +} + +const N = 5000000; + +$t0 = $t = start_test(); +empty_loop(N); +$t = end_test($t, 'empty_loop'); +$overhead = $last_time; +simpleucall(N); +$t = end_test($t, 'func()', $overhead); +simpleudcall(N); +$t = end_test($t, 'undef_func()', $overhead); +simpleicall(N); +$t = end_test($t, 'int_func()', $overhead); +Foo::read_static(N); +$t = end_test($t, '$x = self::$x', $overhead); +Foo::write_static(N); +$t = end_test($t, 'self::$x = 0', $overhead); +Foo::isset_static(N); +$t = end_test($t, 'isset(self::$x)', $overhead); +Foo::empty_static(N); +$t = end_test($t, 'empty(self::$x)', $overhead); +read_static(N); +$t = end_test($t, '$x = Foo::$x', $overhead); +write_static(N); +$t = end_test($t, 'Foo::$x = 0', $overhead); +isset_static(N); +$t = end_test($t, 'isset(Foo::$x)', $overhead); +empty_static(N); +$t = end_test($t, 'empty(Foo::$x)', $overhead); +Foo::call_static(N); +$t = end_test($t, 'self::f()', $overhead); +call_static(N); +$t = end_test($t, 'Foo::f()', $overhead); +$x = new Foo(); +$x->read_prop(N); +$t = end_test($t, '$x = $this->x', $overhead); +$x->write_prop(N); +$t = end_test($t, '$this->x = 0', $overhead); +$x->assign_add_prop(N); +$t = end_test($t, '$this->x += 2', $overhead); +$x->pre_inc_prop(N); +$t = end_test($t, '++$this->x', $overhead); +$x->pre_dec_prop(N); +$t = end_test($t, '--$this->x', $overhead); +$x->post_inc_prop(N); +$t = end_test($t, '$this->x++', $overhead); +$x->post_dec_prop(N); +$t = end_test($t, '$this->x--', $overhead); +$x->isset_prop(N); +$t = end_test($t, 'isset($this->x)', $overhead); +$x->empty_prop(N); +$t = end_test($t, 'empty($this->x)', $overhead); +$x->call(N); +$t = end_test($t, '$this->f()', $overhead); +$x->read_const(N); +$t = end_test($t, '$x = Foo::TEST', $overhead); +create_object(N); +$t = end_test($t, 'new Foo()', $overhead); +read_const(N); +$t = end_test($t, '$x = TEST', $overhead); +read_auto_global(N); +$t = end_test($t, '$x = $_GET', $overhead); +read_global_var(N); +$t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead); +read_hash(N); +$t = end_test($t, '$x = $hash[\'v\']', $overhead); +read_str_offset(N); +$t = end_test($t, '$x = $str[0]', $overhead); +issetor(N); +$t = end_test($t, '$x = $a ?: null', $overhead); +issetor2(N); +$t = end_test($t, '$x = $f ?: tmp', $overhead); +ternary(N); +$t = end_test($t, '$x = $f ? $f : $a', $overhead); +ternary2(N); +$t = end_test($t, '$x = $f ? $f : tmp', $overhead); +total($t0, "Total"); diff --git a/src/config.m4 b/src/config.m4 new file mode 100644 index 0000000..aba355c --- /dev/null +++ b/src/config.m4 @@ -0,0 +1,35 @@ +dnl $Id$ +dnl config.m4 for extension snuffleupagus + +sources="snuffleupagus.c sp_config.c sp_config_utils.c sp_harden_rand.c" +sources="$sources sp_unserialize.c sp_utils.c sp_disable_xxe.c sp_list.c" +sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" +sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" +sources="$sources sp_config_keywords.c sp_compile.c" + +PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, +[ --enable-snuffleupagus Enable snuffleupagus support]) + +PHP_ARG_ENABLE(coverage, whether to enable coverage support, +[ --enable-coverage Enable coverage support]) + +PHP_ARG_ENABLE(debug, whether to enable debug messages, +[ --enable-debug Enable debug messages]) + +CFLAGS="$CFLAGS -lpcre" +CFLAGS="$CFLAGS -D_DEFAULT_SOURCE=1 -std=c99" +CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-parameter" + +if test "$PHP_DEBUG" = "yes"; then + AC_DEFINE(SP_DEBUG, 1, [Wether you want to enable debug messages]) +fi + +if test "$PHP_SNUFFLEUPAGUS" != "no"; then + if test "$PHP_COVERAGE" != "no"; then + CFLAGS="$CFLAGS --coverage -fprofile-arcs -ftest-coverage" + LDFLAGS="$LDFLAGS --coverage" + PHP_NEW_EXTENSION(snuffleupagus, $sources, $ext_shared,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -g -fprofile-arcs -ftest-coverage -lgcov) + else + PHP_NEW_EXTENSION(snuffleupagus, $sources, $ext_shared,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + fi +fi diff --git a/src/config.w32 b/src/config.w32 new file mode 100644 index 0000000..a0197c1 --- /dev/null +++ b/src/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("snuffleupagus", "for snuffleupagus support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("snuffleupagus", "enable snuffleupagus support", "no"); + +if (PHP_SNUFFLEUPAGUS != "no") { + EXTENSION("snuffleupagus", "snuffleupagus.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); +} + diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h new file mode 100644 index 0000000..e7a3d59 --- /dev/null +++ b/src/php_snuffleupagus.h @@ -0,0 +1,71 @@ +#ifndef PHP_SNUFFLEUPAGUS_H +#define PHP_SNUFFLEUPAGUS_H + +#define PHP_SNUFFLEUPAGUS_VERSION "0.1" +#define PHP_SNUFFLEUPAGUS_EXTNAME "snuffleupagus" +#define PHP_SNUFFLEUPAGUS_AUTHOR "NBS System" +#define PHP_SNUFFLEUPAGUS_URL "https://github.com/nbs-system/snuffleupagus" +#define PHP_SNUFFLEUPAGUS_COPYRIGHT "LGPLv2" + +#include +#include + +#include +#include +#include + +#include "SAPI.h" +#include "ext/standard/info.h" +#include "php.h" +#include "php_ini.h" +#include "zend_hash.h" +#include "zend_string.h" +#include "zend_extensions.h" + +#include "sp_list.h" +#include "sp_compile.h" +#include "sp_config.h" +#include "sp_config_utils.h" +#include "sp_config_keywords.h" +#include "sp_cookie_encryption.h" +#include "sp_disable_xxe.h" +#include "sp_disabled_functions.h" +#include "sp_execute.h" +#include "sp_harden_rand.h" +#include "sp_network_utils.h" +#include "sp_unserialize.h" +#include "sp_upload_validation.h" +#include "sp_utils.h" + +extern zend_module_entry snuffleupagus_module_entry; +#define phpext_snuffleupagus_ptr &snuffleupagus_module_entry + +#ifdef PHP_WIN32 +#define PHP_SNUFFLEUPAGUS_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define PHP_SNUFFLEUPAGUS_API __attribute__((visibility("default"))) +#else +#define PHP_SNUFFLEUPAGUS_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +ZEND_BEGIN_MODULE_GLOBALS(snuffleupagus) +sp_config config; +HashTable *disabled_functions_hook; +HashTable *sp_internal_functions_hook; +ZEND_END_MODULE_GLOBALS(snuffleupagus) + +#define SNUFFLEUPAGUS_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(snuffleupagus, v) + +#if defined(ZTS) && defined(COMPILE_DL_SNUFFLEUPAGUS) +ZEND_TSRMLS_CACHE_EXTERN() +#endif + +PHP_FUNCTION(check_disabled_function); + +static inline void sp_terminate() { zend_bailout(); } + +#endif /* PHP_SNUFFLEUPAGUS_H */ diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c new file mode 100644 index 0000000..52b975e --- /dev/null +++ b/src/snuffleupagus.c @@ -0,0 +1,222 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_snuffleupagus.h" + +#ifndef ZEND_EXT_API +#define ZEND_EXT_API ZEND_DLEXPORT +#endif + +static PHP_INI_MH(OnUpdateConfiguration); +static inline int zend_auto_start(zend_extension *extension); +static inline void sp_op_array_handler(zend_op_array *op); + +ZEND_EXTENSION(); + +ZEND_DLEXPORT int sp_zend_startup(zend_extension *extension) { + return zend_startup_module(&snuffleupagus_module_entry); +} + +static inline void sp_op_array_handler(zend_op_array *op) { + if (NULL == op->filename) { + return; + } else { + op->fn_flags |= ZEND_ACC_STRICT_TYPES; + } +} + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +PHP_INI_BEGIN() +PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, + OnUpdateConfiguration) +PHP_INI_END() + +ZEND_DLEXPORT zend_extension zend_extension_entry = { + PHP_SNUFFLEUPAGUS_EXTNAME, + PHP_SNUFFLEUPAGUS_VERSION, + PHP_SNUFFLEUPAGUS_AUTHOR, + PHP_SNUFFLEUPAGUS_URL, + PHP_SNUFFLEUPAGUS_COPYRIGHT, + sp_zend_startup, + NULL, + NULL, /* activate_func_t */ + NULL, /* deactivate_func_t */ + NULL, /* message_handler_func_t */ + sp_op_array_handler,//zend_global_strict, /* op_array_handler_func_t */ + NULL, /* statement_handler_func_t */ + NULL, /* fcall_begin_handler_func_t */ + NULL, /* fcall_end_handler_func_t */ + NULL, /* op_array_ctor_func_t */ + NULL, /* op_array_dtor_func_t */ + STANDARD_ZEND_EXTENSION_PROPERTIES}; + +/* Uncomment this function if you have INI entries +static void php_snuffleupagus_init_globals(zend_snuffleupagus_globals +*snuffleupagus_globals) +{ + snuffleupagus_globals->global_value = 0; + snuffleupagus_globals->global_string = NULL; +} +*/ + +PHP_GINIT_FUNCTION(snuffleupagus) { +#define SP_INIT(F) F = pecalloc(sizeof(*F), 1, 1); +#define SP_INIT_HT(F) \ + F = pemalloc(sizeof(*F), 1); \ + zend_hash_init(F, 10, NULL, NULL, 1); + + SP_INIT_HT(snuffleupagus_globals->disabled_functions_hook); + SP_INIT_HT(snuffleupagus_globals->sp_internal_functions_hook); + + SP_INIT(snuffleupagus_globals->config.config_unserialize); + SP_INIT(snuffleupagus_globals->config.config_random); + SP_INIT(snuffleupagus_globals->config.config_readonly_exec); + SP_INIT(snuffleupagus_globals->config.config_global_strict); + SP_INIT(snuffleupagus_globals->config.config_auto_cookie_secure); + SP_INIT(snuffleupagus_globals->config.config_snuffleupagus); + SP_INIT(snuffleupagus_globals->config.config_disable_xxe); + SP_INIT(snuffleupagus_globals->config.config_upload_validation); + SP_INIT(snuffleupagus_globals->config.config_disabled_functions); + SP_INIT(snuffleupagus_globals->config.config_disabled_functions_ret); + SP_INIT(snuffleupagus_globals->config.config_cookie_encryption); + SP_INIT(snuffleupagus_globals->config.config_regexp_inclusion); + + snuffleupagus_globals->config.config_regexp_inclusion->regexp_inclusion = sp_new_list(); + snuffleupagus_globals->config.config_disabled_functions->disabled_functions = sp_new_list(); + snuffleupagus_globals->config.config_disabled_functions_ret->disabled_functions = sp_new_list(); + + SP_INIT_HT(snuffleupagus_globals->config.config_cookie_encryption->names); + +#undef SP_INIT +#undef SP_INIT_HT +} + +PHP_MINIT_FUNCTION(snuffleupagus) { + REGISTER_INI_ENTRIES(); + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { +#define FREE_HT(F) \ + zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ + pefree(SNUFFLEUPAGUS_G(F), 1); + + FREE_HT(disabled_functions_hook); + FREE_HT(config.config_cookie_encryption->names); + +#undef FREE_HT + + pefree(SNUFFLEUPAGUS_G(config.config_unserialize), 1); + pefree(SNUFFLEUPAGUS_G(config.config_random), 1); + pefree(SNUFFLEUPAGUS_G(config.config_readonly_exec), 1); + pefree(SNUFFLEUPAGUS_G(config.config_global_strict), 1); + pefree(SNUFFLEUPAGUS_G(config.config_auto_cookie_secure), 1); + pefree(SNUFFLEUPAGUS_G(config.config_snuffleupagus), 1); + pefree(SNUFFLEUPAGUS_G(config.config_disable_xxe), 1); + pefree(SNUFFLEUPAGUS_G(config.config_upload_validation), 1); + pefree(SNUFFLEUPAGUS_G(config.config_cookie_encryption), 1); + + sp_list_free(SNUFFLEUPAGUS_G(config.config_disabled_functions->disabled_functions)); + pefree(SNUFFLEUPAGUS_G(config.config_disabled_functions), 1); + sp_list_free(SNUFFLEUPAGUS_G(config.config_disabled_functions_ret->disabled_functions)); + pefree(SNUFFLEUPAGUS_G(config.config_disabled_functions_ret), 1); + + UNREGISTER_INI_ENTRIES(); + + return SUCCESS; +} + +PHP_RINIT_FUNCTION(snuffleupagus) { +#if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { + if (NULL != SNUFFLEUPAGUS_G(config).config_cookie_encryption->names) { + zend_hash_apply_with_arguments( + Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]), decrypt_cookie, 0); + } + } + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(snuffleupagus) { return SUCCESS; } + +PHP_MINFO_FUNCTION(snuffleupagus) { + php_info_print_table_start(); + php_info_print_table_header(2, "snuffleupagus support", "enabled"); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} + +static PHP_INI_MH(OnUpdateConfiguration) { + TSRMLS_FETCH(); + + if (!new_value || !new_value->len) { + return FAILURE; + } + + if (sp_parse_config(new_value->val) != SUCCESS) { + return FAILURE; + } + + if (SNUFFLEUPAGUS_G(config).config_random->enable) { + hook_rand(); + } + if (SNUFFLEUPAGUS_G(config).config_upload_validation->enable) { + hook_upload(); + } + if (SNUFFLEUPAGUS_G(config).config_disable_xxe->enable == 0) { + hook_libxml_disable_entity_loader(); + } + hook_disabled_functions(); + hook_execute(); + + if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { + if (SNUFFLEUPAGUS_G(config).config_unserialize->enable) { + hook_serialize(); + } + hook_cookies(); + } + + if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { + if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { + zend_extension_entry.startup = NULL; + zend_register_extension(&zend_extension_entry, NULL); + } + // This is needed to implement the global strict mode + CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; + } + + return SUCCESS; +} + +const zend_function_entry snuffleupagus_functions[] = {PHP_FE_END}; + +zend_module_entry snuffleupagus_module_entry = + {STANDARD_MODULE_HEADER, + PHP_SNUFFLEUPAGUS_EXTNAME, + snuffleupagus_functions, + PHP_MINIT(snuffleupagus), + PHP_MSHUTDOWN(snuffleupagus), + PHP_RINIT(snuffleupagus), + PHP_RSHUTDOWN(snuffleupagus), + PHP_MINFO(snuffleupagus), + PHP_SNUFFLEUPAGUS_VERSION, + PHP_MODULE_GLOBALS(snuffleupagus), + PHP_GINIT(snuffleupagus), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX}; + +#ifdef COMPILE_DL_SNUFFLEUPAGUS +#ifdef ZTS +ZEND_TSRMLS_CACHE_DEFINE() +#endif +ZEND_GET_MODULE(snuffleupagus) +#endif diff --git a/src/snuffleupagus.php b/src/snuffleupagus.php new file mode 100644 index 0000000..b373a53 --- /dev/null +++ b/src/snuffleupagus.php @@ -0,0 +1,21 @@ +"; + +if(!extension_loaded('snuffleupagus')) { + dl('snuffleupagus.' . PHP_SHLIB_SUFFIX); +} +$module = 'snuffleupagus'; +$functions = get_extension_funcs($module); +echo "Functions available in the test extension:$br\n"; +foreach($functions as $func) { + echo $func."$br\n"; +} +echo "$br\n"; +$function = 'confirm_' . $module . '_compiled'; +if (extension_loaded($module)) { + $str = $function($module); +} else { + $str = "Module $module is not compiled into PHP"; +} +echo "$str\n"; +?> diff --git a/src/sp_compile.c b/src/sp_compile.c new file mode 100644 index 0000000..2902377 --- /dev/null +++ b/src/sp_compile.c @@ -0,0 +1,53 @@ +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +static zend_op_array *(*orig_compile_file)(zend_file_handle *, int); +static zend_op_array *(*orig_compile_string)(zval *, char *); + +zend_op_array *sp_compile_file(zend_file_handle *file_handle, int type) { + zend_op_array *ret = orig_compile_file(file_handle, type); + + const sp_node_t* config = SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions; + + while (config && config->data) { + const char* function_name = ((sp_disabled_function*)config->data)->function; + const pcre* function_name_regexp = ((sp_disabled_function*)config->data)->r_function; + + sp_log_err("checking for %s", function_name); + // EG(function_table)->arData[count - 1].val.value.func->internal_function.handler = PHP_FN(check_disabled_function); + + if (function_name) { + if (HOOK_FUNCTION(function_name, disabled_functions_hook, PHP_FN(check_disabled_function), true) == SUCCESS) { + sp_log_err("Successfully hooked %s", function_name); + } + break; + } else if (function_name_regexp) { + sp_log_err("error", "We'll hook regard later."); + } + config = config->next; + } + + return ret; +} + +zend_op_array *sp_compile_string(zval *source_string, char *filename) { + zend_op_array *ret = orig_compile_string(source_string, filename); + sp_log_err("in compile_string : filename is :%s", filename); + return ret; +} + + +int hook_compile(void) { + TSRMLS_FETCH(); + + /* zend_compile_file is used to compile php file */ + orig_compile_file = zend_compile_file; + zend_compile_file = sp_compile_file; + + /* zend_compile_string is used to compile php string */ + orig_compile_string = zend_compile_string; + zend_compile_string = sp_compile_string; + + return SUCCESS; +} \ No newline at end of file diff --git a/src/sp_compile.h b/src/sp_compile.h new file mode 100644 index 0000000..538ff52 --- /dev/null +++ b/src/sp_compile.h @@ -0,0 +1,6 @@ +#ifndef SP_COMPILE_H +#define SP_COMPILE_H + +int hook_compile(void); + +#endif /* SP_COMPILE_H */ \ No newline at end of file diff --git a/src/sp_config.c b/src/sp_config.c new file mode 100644 index 0000000..f73347d --- /dev/null +++ b/src/sp_config.c @@ -0,0 +1,193 @@ +#include +#include +#include + +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +sp_config_tokens const sp_func[] = { + {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, + {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, + {.func = parse_disabled_functions, .token = SP_TOKEN_DISABLE_FUNC}, + {.func = parse_readonly_exec, .token = SP_TOKEN_READONLY_EXEC}, + {.func = parse_global_strict, .token = SP_TOKEN_GLOBAL_STRICT}, + {.func = parse_upload_validation, .token = SP_TOKEN_UPLOAD_VALIDATION}, + {.func = parse_cookie_encryption, .token = SP_TOKEN_COOKIE_ENCRYPTION}, + {.func = parse_global, .token = SP_TOKEN_GLOBAL}, + {.func = parse_auto_cookie_secure, .token = SP_TOKEN_AUTO_COOKIE_SECURE}, + {.func = parse_disable_xxe, .token = SP_TOKEN_DISABLE_XXE}, + {NULL, NULL}}; + +/* Top level keyword parsing */ + +static int parse_line(char *line) { + char *ptr = line; + + while (*ptr == ' ' || *ptr == '\t') { + ++ptr; + } + + if (!*ptr || *ptr == '#' || *ptr == ';') { + return 0; + } + + if (strncmp(ptr, SP_TOKEN_BASE, strlen(SP_TOKEN_BASE))) { + sp_log_err("config", "Invalid configuration prefix for '%s'.", line); + return -1; + } + ptr += strlen(SP_TOKEN_BASE); + + for (size_t i = 0; sp_func[i].func; i++) { + if (!strncmp(sp_func[i].token, ptr, strlen(sp_func[i].token))) { + return sp_func[i].func(ptr + strlen(sp_func[i].token)); + } + } + sp_log_err("config", "Invalid configuration section '%s'.", line); + return -1; +} + +/* keyword parsing */ +int parse_empty(char *restrict line, char *restrict keyword, void *retval) { + *(bool *)retval = true; + return 0; +} + +int parse_int(char *restrict line, char *restrict keyword, void *retval) { + size_t consumed = 0; + char *value = get_param(&consumed, line, SP_TYPE_INT, keyword); + if (value) { + sscanf(value, "%ud", (uint32_t *)retval); + pefree(value, 1); + return consumed; + } else { + sp_log_err("error", "%s) is expecting a valid integer.", keyword); + return -1; + } +} + +int parse_php_type(char *restrict line, char *restrict keyword, void *retval) { + size_t consumed = 0; + char *value = get_param(&consumed, line, SP_TYPE_STR, keyword); + if (value) { + if (0 == strcasecmp("undef", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_UNDEF; + } else if (0 == strcasecmp("null", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_NULL; + } else if (0 == strcasecmp("true", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_TRUE; + } else if (0 == strcasecmp("false", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_FALSE; + } else if (0 == strcasecmp("long", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_LONG; + } else if (0 == strcasecmp("double", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_DOUBLE; + } else if (0 == strcasecmp("string", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_STRING; + } else if (0 == strcasecmp("array", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_ARRAY; + } else if (0 == strcasecmp("object", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_OBJECT; + } else if (0 == strcasecmp("resource", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_RESOURCE; + } else if (0 == strcasecmp("reference", value)) { + *(sp_php_type*)retval = SP_PHP_TYPE_REFERENCE; + } else { + pefree(value, 1); + sp_log_err("error", "%s) is expecting a valid php type ('false', 'true'," + " 'array'. 'object', 'long', 'double', 'null', 'resource', 'reference'," + " 'undef').", keyword); + return -1; + } + pefree(value, 1); + return consumed; + } else { + return -1; + } +} + +int parse_str(char *restrict line, char *restrict keyword, void *retval) { + char *value = NULL; + + size_t consumed = 0; + value = get_param(&consumed, line, SP_TYPE_STR, keyword); + if (value) { + *(char **)retval = value; + return consumed; + } + return -1; +} + +int parse_cidr(char *restrict line, char *restrict keyword, void *retval) { + size_t consumed = 0; + char *value = get_param(&consumed, line, SP_TYPE_STR, keyword); + sp_cidr *cidr = pecalloc(sizeof(sp_cidr), 1, 1); + + if (value) { + if (-1 == get_ip_and_cidr(value, cidr)) { + return -1; + } + *(sp_cidr **)retval = cidr; + return consumed; + } else { + sp_log_err("config", "%s doesn't contain a valid cidr.", line); + return -1; + } +} + +int parse_regexp(char *restrict line, char *restrict keyword, void *retval) { + /* TODO: Do we want to use pcre_study? + * (http://www.pcre.org/original/doc/html/pcre_study.html) + * maybe not: http://sljit.sourceforge.net/pcre.html*/ + size_t consumed = 0; + char *value = get_param(&consumed, line, SP_TYPE_STR, keyword); + + if (value) { + const char *pcre_error; + int pcre_error_offset; + pcre *compiled_re = pcre_compile(value, PCRE_CASELESS, &pcre_error, + &pcre_error_offset, NULL); + if (NULL == compiled_re) { + sp_log_err("config", "Failed to compile '%s': %s.", value, pcre_error); + } else { + *(pcre **)retval = compiled_re; + return consumed; + } + } + char *closing_paren = strchr(line, ')'); + if (NULL != closing_paren) { + closing_paren[0] = '\0'; + } + sp_log_err("config", "'%s)' is expecting a valid regexp, and not '%s'.", + keyword, line); + return -1; +} + +int sp_parse_config(const char *conf_file) { + FILE *fd = fopen(conf_file, "r"); + char *lineptr = NULL; + size_t n = 0; + + if (fd == NULL) { + sp_log_err("config", "Could not open configuration file %s : %s", conf_file, + strerror(errno)); + return FAILURE; + } + + while (getline(&lineptr, &n, fd) > 0) { + /* We trash the terminal `\n`. This simplify the display of logs. */ + if (lineptr[strlen(lineptr) - 1] == '\n') { + lineptr[strlen(lineptr) - 1] = '\0'; + } + if (parse_line(lineptr) == -1) { + fclose(fd); + free(lineptr); + return FAILURE; + } + free(lineptr); + lineptr = NULL; + n = 0; + } + fclose(fd); + return SUCCESS; +} diff --git a/src/sp_config.h b/src/sp_config.h new file mode 100644 index 0000000..54ec2cc --- /dev/null +++ b/src/sp_config.h @@ -0,0 +1,206 @@ +#ifndef SP_CONFIG_H +#define SP_CONFIG_H + +#include +#include +#include + +typedef enum { + SP_TYPE_STR = 0, + SP_TYPE_REGEXP, + SP_TYPE_INT, + SP_TYPE_EMPTY +} sp_type; + +typedef enum { + SP_PHP_TYPE_UNDEF = IS_UNDEF, + SP_PHP_TYPE_NULL = IS_NULL, + SP_PHP_TYPE_FALSE = IS_FALSE, + SP_PHP_TYPE_TRUE = IS_TRUE, + SP_PHP_TYPE_LONG = IS_LONG, + SP_PHP_TYPE_DOUBLE = IS_DOUBLE, + SP_PHP_TYPE_STRING = IS_STRING, + SP_PHP_TYPE_ARRAY = IS_ARRAY, + SP_PHP_TYPE_OBJECT = IS_OBJECT, + SP_PHP_TYPE_RESOURCE = IS_RESOURCE, + SP_PHP_TYPE_REFERENCE = IS_REFERENCE +} sp_php_type; + +typedef struct { + int ip_version; + union { + struct in_addr ipv4; + struct in6_addr ipv6; + } ip; + uint8_t mask; +} sp_cidr; + +typedef struct { char *encryption_key; } sp_config_encryption_key; + +typedef struct { + bool enable; + bool simulation; +} sp_config_readonly_exec; + +typedef struct { bool enable; } sp_config_global_strict; + +typedef struct { bool enable; } sp_config_random; + +typedef struct { bool enable; } sp_config_auto_cookie_secure; + +typedef struct { bool enable; } sp_config_disable_xxe; + +typedef struct { + HashTable *names; + uint32_t mask_ipv4; + uint32_t mask_ipv6; +} sp_config_cookie_encryption; + +typedef struct { + bool enable; + bool simulation; +} sp_config_unserialize; + +typedef struct { + char *filename; + pcre *r_filename; + + char *function; + pcre *r_function; + + char *hash; + int simulation; + bool enable; + + char *param; + pcre *r_param; + sp_php_type param_type; + + char *ret; + pcre *r_ret; + sp_php_type ret_type; + + pcre *regexp; + char *value; + + char *dump; + char *alias; + bool param_is_array; + bool var_is_array; + sp_node_t *param_array_keys; + sp_node_t *var_array_keys; + + bool allow; + bool drop; + + char *var; + + sp_cidr *cidr; +} sp_disabled_function; + +typedef struct { + sp_node_t *disabled_functions; // list of sp_disabled_function +} sp_config_disabled_functions; + +typedef struct { + sp_node_t *regexp_inclusion; // list of regexp for inclusion +} sp_config_regexp_inclusion; + +typedef struct { + char *script; + bool simulation; + bool enable; +} sp_config_upload_validation; + +typedef struct { + sp_config_random *config_random; + sp_config_unserialize *config_unserialize; + sp_config_disabled_functions *config_disabled_functions; + sp_config_disabled_functions *config_disabled_functions_ret; + sp_config_readonly_exec *config_readonly_exec; + sp_config_upload_validation *config_upload_validation; + sp_config_cookie_encryption *config_cookie_encryption; + sp_config_encryption_key *config_snuffleupagus; + sp_config_auto_cookie_secure *config_auto_cookie_secure; + sp_config_global_strict *config_global_strict; + sp_config_disable_xxe *config_disable_xxe; + sp_config_regexp_inclusion *config_regexp_inclusion; +} sp_config; + +typedef struct { + int (*func)(char *, char *, void *); + char *token; + void *retval; +} sp_config_functions; + +typedef struct { + int (*func)(char *); + char *token; +} sp_config_tokens; + +#define SP_TOKEN_BASE "sp" + +#define SP_TOKEN_AUTO_COOKIE_SECURE ".auto_cookie_secure" +#define SP_TOKEN_COOKIE_ENCRYPTION ".cookie_encryption" +#define SP_TOKEN_DISABLE_FUNC ".disable_functions" +#define SP_TOKEN_GLOBAL ".global" +#define SP_TOKEN_GLOBAL_STRICT ".global_strict" +#define SP_TOKEN_HARDEN_RANDOM ".harden_random" +#define SP_TOKEN_READONLY_EXEC ".readonly_exec" +#define SP_TOKEN_UNSERIALIZE_HMAC ".unserialize_hmac" +#define SP_TOKEN_UPLOAD_VALIDATION ".upload_validation" +#define SP_TOKEN_DISABLE_XXE ".disable_xxe" + +// common tokens +#define SP_TOKEN_ENABLE ".enable(" +#define SP_TOKEN_DISABLE ".disable(" +#define SP_TOKEN_SIMULATION ".simulation(" +#define SP_TOKEN_TRUE "1" +#define SP_TOKEN_FALSE "0" +#define SP_TOKEN_DUMP ".dump(" +#define SP_TOKEN_ALIAS ".alias(" +#define SP_TOKEN_ALLOW ".allow(" +#define SP_TOKEN_DROP ".drop(" + +#define SP_TOKEN_END_PARAM ')' + +// disable_function +#define SP_TOKEN_CIDR ".cidr(" +#define SP_TOKEN_FILENAME ".filename(" +#define SP_TOKEN_FILENAME_REGEXP ".filename_r(" +#define SP_TOKEN_FUNCTION ".function(" +#define SP_TOKEN_FUNCTION_REGEXP ".function_r(" +#define SP_TOKEN_HASH ".hash(" +#define SP_TOKEN_LOCAL_VAR ".var(" +#define SP_TOKEN_PARAM ".param(" +#define SP_TOKEN_PARAM_REGEXP ".param_r(" +#define SP_TOKEN_PARAM_TYPE ".param_type(" +#define SP_TOKEN_RET ".ret(" +#define SP_TOKEN_RET_REGEXP ".ret_r(" +#define SP_TOKEN_RET_TYPE ".ret_type(" +#define SP_TOKEN_VALUE ".value(" +#define SP_TOKEN_VALUE_REGEXP ".value_r(" + +// cookies encryption +#define SP_TOKEN_NAME ".cookie(" +#define SP_TOKEN_MASK_IPV4 ".mask_ipv4(" +#define SP_TOKEN_MASK_IPV6 ".mask_ipv6(" + +// Global configuration options +#define SP_TOKEN_ENCRYPTION_KEY ".secret_key(" + +// upload_validator +#define SP_TOKEN_UPLOAD_SCRIPT ".script(" + +int sp_parse_config(const char *); +int parse_array(sp_disabled_function *); + +int parse_str(char *restrict, char *restrict, void *); +int parse_regexp(char *restrict, char *restrict, void *); +int parse_empty(char *restrict, char *restrict, void *); +int parse_int(char *restrict, char *restrict, void *); +int parse_cidr(char *restrict, char *restrict, void *); +int parse_php_type(char *restrict, char *restrict, void *); + + +#endif /* SP_CONFIG_H */ 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 @@ +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +static int parse_enable(char *line, bool * restrict retval, bool * restrict simulation) { + bool enable = false, disable = false; + sp_config_functions sp_config_funcs[] = { + {parse_empty, SP_TOKEN_ENABLE, &(enable)}, + {parse_empty, SP_TOKEN_DISABLE, &(disable)}, + {parse_empty, SP_TOKEN_SIMULATION, simulation}, + {0}}; + + int ret = parse_keywords(sp_config_funcs, line); + + if (0 != ret) { + return ret; + } + + if (!(enable ^ disable)) { + sp_log_err("config", "A rule can't be enabled and disabled."); + return -1; + } + + *retval = enable; + + return ret; +} + +int parse_random(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_random->enable), NULL); +} + +int parse_disable_xxe(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL); +} + +int parse_auto_cookie_secure(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_auto_cookie_secure->enable), NULL); +} + +int parse_global_strict(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_global_strict->enable), NULL); +} + +int parse_unserialize(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_unserialize->enable), &(SNUFFLEUPAGUS_G(config).config_unserialize->simulation)); +} + +int parse_readonly_exec(char *line) { + return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_readonly_exec->enable), &(SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation)); +} + +int parse_global(char *line) { + sp_config_functions sp_config_funcs_encryption_key[] = { + {parse_str, SP_TOKEN_ENCRYPTION_KEY, + &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)}, + {0}}; + return parse_keywords(sp_config_funcs_encryption_key, line); +} + +int parse_cookie_encryption(char *line) { + int ret = 0; + char *name = NULL; + + sp_config_functions sp_config_funcs_cookie_encryption[] = { + {parse_str, SP_TOKEN_NAME, &name}, + {parse_int, SP_TOKEN_MASK_IPV4, + &(SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4)}, + {parse_int, SP_TOKEN_MASK_IPV6, + &(SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6)}, + {0}}; + + ret = parse_keywords(sp_config_funcs_cookie_encryption, line); + if (0 != ret) { + return ret; + } + + if (32 < SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4) { + SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4 = 32; + } + if (128 < SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6) { + SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6 = 128; + } + + if (name) { + zend_hash_str_add_empty_element( + SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, name, + strlen(name)); + } + return SUCCESS; +} + +int parse_disabled_functions(char *line) { + int ret = 0; + bool enable = true, disable = false; + sp_disabled_function *df = pecalloc(sizeof(*df), 1, 1); + + sp_config_functions sp_config_funcs_disabled_functions[] = { + {parse_empty, SP_TOKEN_ENABLE, &(enable)}, + {parse_empty, SP_TOKEN_DISABLE, &(disable)}, + {parse_str, SP_TOKEN_ALIAS, &(df->alias)}, + {parse_empty, SP_TOKEN_SIMULATION, &(df->simulation)}, + {parse_str, SP_TOKEN_FILENAME, &(df->filename)}, + {parse_regexp, SP_TOKEN_FILENAME_REGEXP, &(df->r_filename)}, + {parse_str, SP_TOKEN_FUNCTION, &(df->function)}, + {parse_regexp, SP_TOKEN_FUNCTION_REGEXP, &(df->r_function)}, + {parse_str, SP_TOKEN_DUMP, &(df->dump)}, + {parse_empty, SP_TOKEN_ALLOW, &(df->allow)}, + {parse_empty, SP_TOKEN_DROP, &(df->drop)}, + {parse_str, SP_TOKEN_HASH, &(df->hash)}, + {parse_str, SP_TOKEN_PARAM, &(df->param)}, + {parse_regexp, SP_TOKEN_VALUE_REGEXP, &(df->regexp)}, + {parse_str, SP_TOKEN_VALUE, &(df->value)}, + {parse_regexp, SP_TOKEN_PARAM_REGEXP, &(df->r_param)}, + {parse_php_type, SP_TOKEN_PARAM_TYPE, &(df->param_type)}, + {parse_str, SP_TOKEN_RET, &(df->ret)}, + {parse_cidr, SP_TOKEN_CIDR, &(df->cidr)}, + {parse_regexp, SP_TOKEN_RET_REGEXP, &(df->r_ret)}, + {parse_php_type, SP_TOKEN_RET_TYPE, &(df->ret_type)}, + {parse_str, SP_TOKEN_LOCAL_VAR, &(df->var)}, + {0}}; + + ret = parse_keywords(sp_config_funcs_disabled_functions, line); + + if (0 != ret) { + return ret; + } + + if (true == disable){ + df->enable = false; + } else { + df->enable = true; + } + + if (df->value && df->regexp) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + "'.value' and '.regexp' are mutually exclusives.", + line); + return -1; + } else if (df->r_function && df->function) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s': " + "'.r_function' and '.function' are mutually exclusive.", + line); + return -1; + } else if (df->r_filename && df->filename) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + "'.r_filename' and '.filename' are mutually exclusive.", + line); + return -1; + } else if (df->r_param && df->param) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + "'.r_param' and '.param' are mutually exclusive.", + line); + return -1; + } else if (df->r_ret && df->ret) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + "'.r_ret' and '.ret' are mutually exclusive.", + line); + return -1; + } else if ((df->r_ret || df->ret) && (df->r_param || df->param)) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + "`ret` and `param` are mutually exclusives.", + line); + return -1; + } else if (!(df->r_function || df->function)) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s':" + " must take a function name.", + line); + return -1; + } else if (!(df->allow ^ df->drop)) { + sp_log_err("config", + "Invalid configuration line: 'sp.disabled_functions%s': The " + "rule must either be a `drop` or and `allow` one.", + line); + return -1; + } + + if (df->param && strchr(df->param, '[')) { // assume that this is an array + df->param_array_keys = sp_new_list(); + if (0 != array_to_list(&df->param, &df->param_array_keys)) { + pefree(df->param_array_keys, 1); + return -1; + } + df->param_is_array = 1; + } + + if (df->var && strchr(df->var, '[')) { // assume that this is an array + df->var_array_keys = sp_new_list(); + if (0 != array_to_list(&df->var, &df->var_array_keys)) { + pefree(df->var_array_keys, 1); + return -1; + } + df->var_is_array = 1; + } + + bool match = false; + const char *key[4] = {"include", "include_once", "require", "require_once"}; + for (size_t i = 0; i < 4; i++) { + if (df->r_function && true == is_regexp_matching(df->r_function, key[i])) { + match = true; + break; + } else if (df->function && 0 == strcmp(df->function, key[i])) { + match = true; + break; + } + } + if (true == match && df->regexp) { + sp_list_insert( + SNUFFLEUPAGUS_G(config).config_regexp_inclusion->regexp_inclusion, + df->regexp); + } else if (df->ret || df->r_ret || df->ret_type) { + sp_list_insert( + SNUFFLEUPAGUS_G(config).config_disabled_functions_ret->disabled_functions, + df); + } else { + sp_list_insert( + SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions, + df); + } + return ret; +} + +int parse_upload_validation(char *line) { + bool disable = false, enable = false; + sp_config_functions sp_config_funcs_upload_validation[] = { + {parse_str, SP_TOKEN_UPLOAD_SCRIPT, + &(SNUFFLEUPAGUS_G(config).config_upload_validation->script)}, + {parse_empty, SP_TOKEN_SIMULATION, + &(SNUFFLEUPAGUS_G(config).config_upload_validation->simulation)}, + {parse_empty, SP_TOKEN_ENABLE, &(enable)}, + {parse_empty, SP_TOKEN_DISABLE, &(disable)}, + {0}}; + + int ret = parse_keywords(sp_config_funcs_upload_validation, line); + + if (0 != ret) { + return ret; + } + + if (!(enable ^ disable)) { + sp_log_err("config", "A rule can't be enabled and disabled."); + return -1; + } + SNUFFLEUPAGUS_G(config).config_upload_validation->enable = enable; + + char const *script = SNUFFLEUPAGUS_G(config).config_upload_validation->script; + + if (!script) { + sp_log_err("config", "The `script` directive is mandatory in %s", + line); + return -1; + } else if (-1 == access(script, F_OK)) { + sp_log_err("config", "The `script` (%s) doesn't exist.", script); + return -1; + } else if (-1 == access(script, X_OK)) { + sp_log_err("config", "The `script` (%s) isn't executable.", script); + return -1; + } + + return ret; +} diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h new file mode 100644 index 0000000..40fac47 --- /dev/null +++ b/src/sp_config_keywords.h @@ -0,0 +1,16 @@ +#ifndef SP_CONFIG_KEYWORDS_H +#define SP_CONFIG_KEYWORDS_H +#include "php_snuffleupagus.h" + +int parse_random(char *line); +int parse_disable_xxe(char *line); +int parse_auto_cookie_secure(char *line); +int parse_global_strict(char *line); +int parse_global(char *line) ; +int parse_cookie_encryption(char *line); +int parse_unserialize(char *line) ; +int parse_readonly_exec(char *line); +int parse_disabled_functions(char *line) ; +int parse_upload_validation(char *line); + +#endif // __SP_CONFIG_KEYWORDS_H \ No newline at end of file diff --git a/src/sp_config_utils.c b/src/sp_config_utils.c new file mode 100644 index 0000000..e05e95e --- /dev/null +++ b/src/sp_config_utils.c @@ -0,0 +1,211 @@ +#include "php_snuffleupagus.h" + +static int validate_int(const char *value); +static int validate_str(const char *value); + +static sp_pure int validate_int(const char *value) { + for (size_t i = 0; i < strlen(value); i++) { + if (!isdigit(value[i])) { + return -1; + } + } + return 0; +} + +static sp_pure int validate_str(const char *value) { + int balance = 0; // ghetto [] validation + + if (!strchr(value, '[')) { + return 0; + } + + for (size_t i = 0; i < strlen(value); i++) { + if (value[i] == '[') { + balance++; + } else if (value[i] == ']') { + balance--; + } + if (balance < 0) { + return -1; + } + } + return balance != 0; +} + +int parse_keywords(sp_config_functions *funcs, char *line) { + int value_len = 0; + const char *original_line = line; + for (size_t i = 0; funcs[i].func; i++) { + if (!strncmp(funcs[i].token, line, strlen(funcs[i].token))) { + line += strlen(funcs[i].token); + value_len = funcs[i].func(line, funcs[i].token, funcs[i].retval) + 1; + if (value_len == 0) { // bad parameter + return -1; + } + line += value_len; + i = -1; // we start the loop again + } + } + while (*line == ';' || *line == '\t' || *line == ' ') { + line++; + } + + if (*line == '#') { + return 0; + } + + if (*line) { + sp_log_err("config", "Trailing chars '%s' at the end of '%s'.", line, + original_line); + return -1; + } + return 0; +} + +static char *get_string(size_t *consumed, char *restrict line, + const char *restrict keyword) { + enum { IN_ESCAPE, NONE } state = NONE; + char *original_line = line; + size_t j = 0; + + char *ret = NULL; + if (NULL == line) { + goto err; + } + + ret = pecalloc(sizeof(char), strlen(original_line) + 1, 1); + + /* The first char of a string is always '"', since they MUST be quoted. */ + if ('"' == *line) { + line++; + } else { + goto err; + } + + for (size_t i = 0; line[i] && j < strlen(original_line) - 2; i++) { + switch (line[i]) { + case '"': + /* A double quote at this point is either: + - at the very end of the string. + - escaped + */ + if ((state == NONE) && (line[i + 1] == SP_TOKEN_END_PARAM)) { + /* The `+2` if for + 1. the terminal double-quote + 2. the SP_TOKEN_END_PARAM + */ + *consumed = i + 2; + return ret; + } else if (state == IN_ESCAPE) { + break; // we're on an escped double quote + } else { + goto err; + } + case '\\': + if (state == NONE) { + state = IN_ESCAPE; + continue; + } + default: + break; + } + if (state == IN_ESCAPE) { + state = NONE; + } + ret[j++] = line[i]; + } +err: + sp_log_err("error", + "There is an issue with the parsing of '%s': it doesn't look like a valid string.", + original_line ? original_line : "NULL"); + line = NULL; + return NULL; +} + +static char *get_misc(char *restrict line, const char *restrict keyword) { + size_t i = 0; + char *ret = pecalloc(sizeof(char), 1024, 1); + + while (i < 1024 - 1 && line[i] && line[i] != SP_TOKEN_END_PARAM) { + ret[i] = line[i]; + i++; + } + + if (line[i] != SP_TOKEN_END_PARAM) { + if (i >= 1024 - 1) { + sp_log_err("config", "The following line is too long: %s.", line); + } else { + sp_log_err("config", "Missing closing %c in line %s.", SP_TOKEN_END_PARAM, + line); + } + return NULL; + } else if (i == 0) { + sp_log_err("config", "The keyword %s%c is expecting a parameter.", + keyword, SP_TOKEN_END_PARAM); + return NULL; + } + return ret; +} + +char *get_param(size_t *consumed, char *restrict line, sp_type type, + const char *restrict keyword) { + char *retval = NULL; + if (type == SP_TYPE_STR) { + retval = get_string(consumed, line, keyword); + } else { + retval = get_misc(line, keyword); + *consumed = retval ? strlen(retval) : 0; + } + + if (retval) { + if (type == SP_TYPE_STR && 0 == validate_str(retval)) { + return retval; + } else if (type == SP_TYPE_INT && 0 == validate_int(retval)) { + return retval; + } + } + return NULL; +} + +// FIXME this is leaking like hell @blotus +int array_to_list(char **name_ptr, sp_node_t **keys) { + int in_key = 0; + size_t i = 0; + char *name = *name_ptr; + char *key_name = ecalloc(strlen(name) + 1, 1); // im way too lazy for + // now + char *tmp = ecalloc(strlen(name) + 1, 1); + + for (i = 0; name[i] != '['; i++) { + tmp[i] = name[i]; + } + tmp[i] = 0; + + for (size_t j = 0; name[i]; i++) { + const char c = name[i]; + if (c == '[') { + if (in_key == 0) { + in_key = 1; + } else { + efree(key_name); + return -1; + } + } else if (c == ']') { + if (in_key == 0) { + efree(key_name); + return -1; + } else { + in_key = 0; + j = 0; + sp_list_insert(*keys, pestrdup(key_name, 1)); + memset(key_name, 0, strlen(name) + 1); + } + } else if (in_key == 1) { + key_name[j] = c; + j++; + } + } + efree(key_name); + *name_ptr = pestrdup(tmp, 1); + return in_key; +} diff --git a/src/sp_config_utils.h b/src/sp_config_utils.h new file mode 100644 index 0000000..f2f8fce --- /dev/null +++ b/src/sp_config_utils.h @@ -0,0 +1,8 @@ +#ifndef SP_CONFIG_UTILS +#define SP_CONFIG_UTILS + +int parse_keywords(sp_config_functions *, char *); +char *get_param(size_t *, char *restrict, sp_type, const char *restrict); +int array_to_list(char **, sp_node_t **); + +#endif /* SP_CONFIG_UTILS */ diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c new file mode 100644 index 0000000..5248486 --- /dev/null +++ b/src/sp_cookie_encryption.c @@ -0,0 +1,216 @@ +#include "php_snuffleupagus.h" + +#include "ext/standard/url.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +static unsigned int nonce_d = 0; + +static inline void generate_key(unsigned char *key) { + PHP_SHA256_CTX ctx; + const char *user_agent = sp_getenv("HTTP_USER_AGENT"); + const char *remote_addr = sp_getenv("REMOTE_ADDR"); + const char *encryption_key = + SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key; + + /* 32 is the size of a SHA256. */ + assert(32 == crypto_secretbox_KEYBYTES); + + PHP_SHA256Init(&ctx); + + if (user_agent) { + PHP_SHA256Update(&ctx, (unsigned char *)user_agent, strlen(user_agent)); + } + + if (remote_addr) { + char out[128]; + apply_mask_on_ip(out, remote_addr); + PHP_SHA256Update(&ctx, (unsigned char*)out, sizeof(out)); + } + + if (encryption_key) { + PHP_SHA256Update(&ctx, (const unsigned char *)encryption_key, + strlen(encryption_key)); + } + + PHP_SHA256Final((unsigned char *)key, &ctx); +} + +int decrypt_cookie(zval *pDest, int num_args, va_list args, + zend_hash_key *hash_key) { + unsigned char key[crypto_secretbox_KEYBYTES] = {0}; + size_t value_len; + zend_string *debase64; + unsigned char *decrypted; + int ret = 0; + + /* If the cookie isn't in the conf, it shouldn't be encrypted. */ + if (0 == + zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, + hash_key->key)) { + return ZEND_HASH_APPLY_KEEP; + } + + generate_key(key); + + value_len = php_url_decode(Z_STRVAL_P(pDest), Z_STRLEN_P(pDest)); + + if (value_len == 0) { + return ZEND_HASH_APPLY_KEEP; + } + + debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), value_len); + + if (value_len < + crypto_secretbox_NONCEBYTES + crypto_secretbox_ZEROBYTES) { + sp_log_msg("cookie_encryption", LOG_DROP, + "Buffer underflow tentative detected in cookie encryption handling."); + return ZEND_HASH_APPLY_REMOVE; + } + + decrypted = pecalloc(value_len, 1, 0); + + ret = crypto_secretbox_open( + decrypted, + (unsigned char *)(ZSTR_VAL(debase64) + crypto_secretbox_NONCEBYTES), + ZSTR_LEN(debase64) - crypto_secretbox_NONCEBYTES, + (unsigned char *)ZSTR_VAL(debase64), key); + + if (ret == -1) { + sp_log_msg("cookie_encryption", LOG_DROP, + "Something went wrong with the decryption of %s.", + ZSTR_VAL(hash_key->key)); + return ZEND_HASH_APPLY_REMOVE; + } + + ZVAL_STRINGL(pDest, (char *)(decrypted + crypto_secretbox_ZEROBYTES), + ZSTR_LEN(debase64) - crypto_secretbox_NONCEBYTES - 1 - + crypto_secretbox_ZEROBYTES); + + return ZEND_HASH_APPLY_KEEP; +} + +/** + This function will return the `data` of length `data_len` encrypted in the + form + base64(nonce | encrypted_data) (with `|` being the concatenation + operation). + + The `nonce` is time-based. +*/ +static zend_string *encrypt_data(char *data, unsigned long long data_len) { + const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; + const size_t emsg_and_nonce_len = encrypted_msg_len + crypto_secretbox_NONCEBYTES; + + unsigned char key[crypto_secretbox_KEYBYTES] = {0}; + unsigned char nonce[crypto_secretbox_NONCEBYTES] = {0}; + unsigned char *data_to_encrypt = pecalloc(encrypted_msg_len, 1, 0); + unsigned char *encrypted_data = pecalloc(emsg_and_nonce_len, 1, 1); + + generate_key(key); + + /* tweetnacl's API requires the message to be padded with + crypto_secretbox_ZEROBYTES zeroes. */ + memcpy(data_to_encrypt + crypto_secretbox_ZEROBYTES, data, data_len); + + assert(sizeof(size_t) <= crypto_secretbox_NONCEBYTES); + + nonce_d++; + sscanf((char*)nonce, "%ud", &nonce_d); + + memcpy(encrypted_data, nonce, crypto_secretbox_NONCEBYTES); + crypto_secretbox(encrypted_data + crypto_secretbox_NONCEBYTES, + data_to_encrypt, encrypted_msg_len, nonce, key); + + zend_string *z = php_base64_encode(encrypted_data, emsg_and_nonce_len); + sp_log_debug("cookie_encryption", "Cookie value:%s:", z->val); + return z; +} + +PHP_FUNCTION(sp_setcookie) { + zval params[7] = { 0 }; + zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL; + zend_long expires = 0; + zend_bool secure = 0, httponly = 0; + zval ret_val; + zval func_name; + + ZEND_PARSE_PARAMETERS_START(1, 7) + Z_PARAM_STR(name) + Z_PARAM_OPTIONAL + Z_PARAM_STR(value) + Z_PARAM_LONG(expires) + Z_PARAM_STR(path) + Z_PARAM_STR(domain) + Z_PARAM_BOOL(secure) + Z_PARAM_BOOL(httponly) + ZEND_PARSE_PARAMETERS_END(); + + /* If the request was issued over HTTPS, the cookie should be "secure" */ + if (SNUFFLEUPAGUS_G(config).config_auto_cookie_secure) { + const zval server_vars = PG(http_globals)[TRACK_VARS_SERVER]; + if (Z_TYPE(server_vars) == IS_ARRAY) { + const zval *is_https = + zend_hash_str_find(Z_ARRVAL(server_vars), "HTTPS", strlen("HTTPS")); + if (NULL != is_https) { + secure = 1; + } + } + } + + /* If the cookie's value is encrypted, it won't be usable by + * javascript anyway. + */ + if (zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, + name) > 0) { + httponly = 1; + } + + /* Shall we encrypt the cookie's value? */ + if (zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, + name) > 0 && value) { + zend_string *encrypted_data = encrypt_data(value->val, value->len); + ZVAL_STR_COPY(¶ms[1], encrypted_data); + zend_string_release(encrypted_data); + } else if (value) { + ZVAL_STR_COPY(¶ms[1], value); + } + + ZVAL_STRING(&func_name, "setcookie"); + ZVAL_STR_COPY(¶ms[0], name); + ZVAL_LONG(¶ms[2], expires); + if (path) { + ZVAL_STR_COPY(¶ms[3], path); + } + if (domain) { + ZVAL_STR_COPY(¶ms[4], domain); + } + if (secure) { + ZVAL_LONG(¶ms[5], secure); + } + if (httponly) { + ZVAL_LONG(¶ms[6], httponly); + } + + /* This is the _fun_ part: because PHP is utterly idiotic and nonsensical, + the `call_user_function` macro will __discard__ (yes) its first argument + (the hashtable), effectively calling functions from `CG(function_table)`. + This is why were replacing our hook with the original function, calling + the function, and then re-hooking it. */ + void (*handler)(INTERNAL_FUNCTION_PARAMETERS); + handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), "setcookie", + strlen("setcookie")); + zend_internal_function *func = zend_hash_str_find_ptr( + CG(function_table), "setcookie", strlen("setcookie")); + func->handler = handler; + + call_user_function(CG(function_table), NULL, &func_name, &ret_val, 7, params); + + func->handler = PHP_FN(sp_setcookie); +} + +int hook_cookies() { + HOOK_FUNCTION("setcookie", sp_internal_functions_hook, PHP_FN(sp_setcookie), false); + + return SUCCESS; +} diff --git a/src/sp_cookie_encryption.h b/src/sp_cookie_encryption.h new file mode 100644 index 0000000..9904738 --- /dev/null +++ b/src/sp_cookie_encryption.h @@ -0,0 +1,17 @@ + +#ifndef __SP_COOKIE_ENCRYPTION +#define __SP_COOKIE_ENCRYPTION + +#include "SAPI.h" +#include "tweetnacl.h" + +#include "sp_utils.h" + +#include "ext/hash/php_hash.h" +#include "ext/hash/php_hash_sha.h" +#include "ext/standard/base64.h" + +int hook_cookies(); +int decrypt_cookie(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key); + +#endif /* __SP_COOKIE_ENCRYPTION */ diff --git a/src/sp_disable_xxe.c b/src/sp_disable_xxe.c new file mode 100644 index 0000000..d11b3d0 --- /dev/null +++ b/src/sp_disable_xxe.c @@ -0,0 +1,25 @@ +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +PHP_FUNCTION(sp_libxml_disable_entity_loader) { RETURN_TRUE; } + +int hook_libxml_disable_entity_loader() { + zval func_name; + zval hmac; + zval params[1]; + + TSRMLS_FETCH(); + + /* Call the php function here instead of re-implementing it is a bit + * ugly, but we do not want to introduce compile-time dependencies against + * libxml. */ + ZVAL_STRING(&func_name, "libxml_disable_entity_loader"); + ZVAL_STRING(¶ms[0], "true"); + call_user_function(CG(function_table), NULL, &func_name, &hmac, 1, params); + + HOOK_FUNCTION("libxml_disable_entity_loader", sp_internal_functions_hook, + PHP_FN(sp_libxml_disable_entity_loader), false); + + return SUCCESS; +} diff --git a/src/sp_disable_xxe.h b/src/sp_disable_xxe.h new file mode 100644 index 0000000..274c169 --- /dev/null +++ b/src/sp_disable_xxe.h @@ -0,0 +1,6 @@ +#ifndef __SP_DISABLE_XXE_H +#define __SP_DISABLE_XXE_H + +int hook_libxml_disable_entity_loader(); + +#endif /* __SP_DISABLE_XXE_H */ diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c new file mode 100644 index 0000000..55d782b --- /dev/null +++ b/src/sp_disabled_functions.c @@ -0,0 +1,356 @@ +#include "php_snuffleupagus.h" + +#include "zend_execute.h" +#include "zend_hash.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +ZEND_COLD static zend_always_inline bool is_hash_matching( + const char* current_filename, + sp_disabled_function const* const config_node) { + char current_file_hash[SHA256_SIZE * 2]; + compute_hash(current_filename, current_file_hash); + return (0 == strncmp(current_file_hash, config_node->hash, SHA256_SIZE)); +} + +static zend_always_inline char* get_complete_function_path( + zend_execute_data const* const execute_data) { + char const* class_name; + char const* const function_name = + ZSTR_VAL(execute_data->func->common.function_name); + char* complete_path_function = NULL; + + class_name = get_active_class_name(NULL); + if (*class_name) { + const size_t len = strlen(class_name) + 2 + strlen(function_name) + 1; + complete_path_function = emalloc(len); + snprintf(complete_path_function, len, "%s::%s", class_name, function_name); + } else { + complete_path_function = estrdup(function_name); + } + return complete_path_function; +} + +static bool is_local_var_matching(zend_execute_data *execute_data, const sp_disabled_function *const config_node) { + zend_execute_data *orig_execute_data = execute_data; + + /*because execute_data points to hooked function data, + which we dont care about */ + zend_execute_data *current = execute_data->prev_execute_data; + zval *value = NULL; + + while (current) { + zend_string *key = NULL; + EG(current_execute_data) = current; + zend_array *symtable = zend_rebuild_symbol_table(); + ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { + if (0 == strcmp(config_node->var, key->val)) { // is the var name right? + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (Z_TYPE_P(value) != IS_ARRAY) { + char *var_value_str = sp_convert_to_string(value); + if (true == sp_match_value(var_value_str, config_node->value, config_node->regexp)) { + efree(var_value_str); + EG(current_execute_data) = orig_execute_data; + return true; + } + efree(var_value_str); + } + else { + EG(current_execute_data) = orig_execute_data; + return sp_match_array_key_recurse(value, config_node->var_array_keys, config_node->value, NULL); + } + } + } + ZEND_HASH_FOREACH_END(); + current = current->prev_execute_data; + } + + EG(current_execute_data) = orig_execute_data; + return false; +} + +bool should_disable(zend_execute_data* execute_data) { + const char* current_filename = zend_get_executed_filename(TSRMLS_C); + const sp_node_t* config = + SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions; + const char* function_name = + ZSTR_VAL(execute_data->func->common.function_name); + char* complete_path_function; + char const* client_ip = sp_getenv("REMOTE_ADDR"); + + if (!function_name) { + return false; + } + + if (!config || !config->data) { + return false; + } + + complete_path_function = get_complete_function_path(execute_data); + + while (config) { + sp_disabled_function const* const config_node = + (sp_disabled_function*)(config->data); + const char* arg_name = NULL; + const char* arg_value_str = NULL; + + if (false == config_node->enable) { + goto next; + } + + if (config_node->function) { /* Litteral match against the function name. */ + if (0 != strcmp(config_node->function, complete_path_function)) { + goto next; + } + } else if (config_node->r_function) { + if (false == + is_regexp_matching(config_node->r_function, complete_path_function)) { + goto next; + } + } + if (config_node->var) { + if (false == is_local_var_matching(execute_data, config_node)) { + goto next; + } + } + + if (config_node->filename) { /* Check the current file name. */ + if (0 != strcmp(current_filename, config_node->filename)) { + goto next; + } + } else if (config_node->r_filename) { + if (false == + is_regexp_matching(config_node->r_filename, current_filename)) { + goto next; + } + } + + if (config_node->hash) { + if (false == is_hash_matching(current_filename, config_node)) { + goto next; + } + } + + if (client_ip && config_node->cidr && + (false == cidr_match(client_ip, config_node->cidr))) { + goto next; + } + + /* Check if we filter on parameter value*/ + if (config_node->param || config_node->r_param) { + const unsigned int nb_param = execute_data->func->common.num_args; + bool arg_matched = false; + + for (unsigned int i = 0; i < nb_param; i++) { + arg_matched = false; + if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency + arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); + } else { + arg_name = execute_data->func->internal_function.arg_info[i].name; + } + + const bool arg_matching = + config_node->param && (0 == strcmp(arg_name, config_node->param)); + const bool pcre_matching = + config_node->r_param && + (true == is_regexp_matching(config_node->r_param, arg_name)); + + /* This is the parameter name we're looking for. */ + if (true == arg_matching || true == pcre_matching) { + zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i); + + if (config_node->param_type) { // Are we matching on the `type`? + if (config_node->param_type == Z_TYPE_P(arg_value)) { + arg_matched = true; + break; + } + } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { + arg_value_str = estrdup("Array"); + // match on arr -> match on all key content, if a key is an array, + // ignore it + // match on arr[foo] -> match only on key foo, if the key is an + // array, match on all keys content + if (config_node->param_is_array == true) { + if (true == sp_match_array_key_recurse( + arg_value, config_node->param_array_keys, + config_node->value, config_node->regexp)) { + arg_matched = true; + break; + } + } else { // match on all keys, but don't go into subarray + if (true == sp_match_array_key(arg_value, config_node->value, + config_node->regexp)) { + arg_matched = true; + break; + } + } + } else { + arg_value_str = sp_convert_to_string(arg_value); + if (true == sp_match_value(arg_value_str, config_node->value, + config_node->regexp)) { + arg_matched = true; + break; + } + } + } + } + if (false == arg_matched) { + goto next; + } + } + + /* Everything matched.*/ + + if (true == config_node->allow) { + goto allow; + } + + sp_log_disable(complete_path_function, arg_name, arg_value_str, + config_node); + if (true == config_node->simulation) { + goto next; + } else { // We've got a match, the function won't be executed + efree(complete_path_function); + return true; + } +next: +config = config->next; + } +allow: + efree(complete_path_function); + return false; +} + +static bool should_drop_on_ret(zval* return_value, + const zend_execute_data* const execute_data) { + const sp_node_t* config = + SNUFFLEUPAGUS_G(config).config_disabled_functions_ret->disabled_functions; + char* complete_path_function = get_complete_function_path(execute_data); + const char* current_filename = zend_get_executed_filename(TSRMLS_C); + + if (!config || !config->data) { + return false; + } + + while (config) { + char* ret_value_str = NULL; + sp_disabled_function const* const config_node = + (sp_disabled_function*)(config->data); + + if (false == config_node->enable) { + goto next; + } + + if (config_node->function) { + if (0 != strcmp(config_node->function, complete_path_function)) { + goto next; + } + } else if (config_node->r_function) { + if (false == + is_regexp_matching(config_node->r_function, complete_path_function)) { + goto next; + } + } + + if (config_node->filename) { /* Check the current file name. */ + if (0 != strcmp(current_filename, config_node->filename)) { + goto next; + } + } else if (config_node->r_filename) { + if (false == + is_regexp_matching(config_node->r_filename, current_filename)) { + goto next; + } + } + + if (config_node->hash) { + if (false == is_hash_matching(current_filename, config_node)) { + goto next; + } + } + + ret_value_str = sp_convert_to_string(return_value); // FIXME memleak + + bool match_type = (config_node->ret_type) && + (config_node->ret_type == Z_TYPE_P(return_value)); + bool match_value = (config_node->ret || config_node->r_ret) && + (true == sp_match_value(ret_value_str, config_node->ret, + config_node->r_ret)); + + if (true == match_type || match_value) { + if (true == config_node->allow) { + efree(complete_path_function); + return false; + } + sp_log_disable_ret(complete_path_function, ret_value_str, config_node); + if (false == config_node->simulation) { + efree(complete_path_function); + return true; + } + } + next: + config = config->next; + } + efree(complete_path_function); + return false; +} + +ZEND_FUNCTION(check_disabled_function) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + const char* current_function_name = get_active_function_name(TSRMLS_C); + + if (true == should_disable(execute_data)) { + return; + } + + if ((orig_handler = zend_hash_str_find_ptr( + SNUFFLEUPAGUS_G(disabled_functions_hook), current_function_name, + strlen(current_function_name)))) { + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (true == should_drop_on_ret(return_value, execute_data)) { + zend_bailout(); + } + } else { + sp_log_err( + "disabled_functions", + "Unable to find the pointer to the original function '%s' in the " + "hashtable.\n", + current_function_name); + } +} + +static int hook_functions(const sp_node_t* config) { + while (config && config->data) { + const char* function_name = ((sp_disabled_function*)config->data)->function; + const pcre* function_name_regexp = + ((sp_disabled_function*)config->data)->r_function; + + if (NULL != function_name) { // hook function by name + HOOK_FUNCTION(function_name, disabled_functions_hook, + PHP_FN(check_disabled_function), false); + } else if (NULL != function_name_regexp) { // hook function by regexp + HOOK_FUNCTION_BY_REGEXP(function_name_regexp, disabled_functions_hook, + PHP_FN(check_disabled_function), false); + } else { + return FAILURE; + } + + config = config->next; + } + return SUCCESS; +} + +int hook_disabled_functions(void) { + TSRMLS_FETCH(); + + int ret = SUCCESS; + + ret |= hook_functions( + SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions); + ret |= hook_functions(SNUFFLEUPAGUS_G(config) + .config_disabled_functions_ret->disabled_functions); + + return ret; +} diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h new file mode 100644 index 0000000..680eabb --- /dev/null +++ b/src/sp_disabled_functions.h @@ -0,0 +1,11 @@ +#ifndef __SP_DISABLE_FUNCTIONS_H +#define __SP_DISABLE_FUNCTIONS_H + +#include "ext/hash/php_hash.h" +#include "ext/hash/php_hash_sha.h" +#include "ext/standard/md5.h" + +int hook_disabled_functions(); +bool should_disable(zend_execute_data* function_name); + +#endif /* __SP_DISABLE_FUNCTIONS_H */ diff --git a/src/sp_execute.c b/src/sp_execute.c new file mode 100644 index 0000000..faf126c --- /dev/null +++ b/src/sp_execute.c @@ -0,0 +1,100 @@ +#include "php_snuffleupagus.h" + +#include +#include + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +static void (*orig_execute_ex)(zend_execute_data *execute_data); +static int (*orig_zend_stream_open)(const char *filename, + zend_file_handle *handle); + +// FIXME handle symlink +ZEND_COLD static inline void terminate_if_writable(const char *filename) { + if (0 == access(filename, W_OK)) { + if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation) { + sp_log_msg("readonly_exec", LOG_NOTICE, + "Attempted execution of a writable file (%s).", filename); + } else { + sp_log_msg("readonly_exec", LOG_DROP, + "Attempted execution of a writable file (%s).", filename); + sp_terminate(); + } + } else { + if (EACCES != errno) { + sp_log_err("Writable execution", "Error while accessing %s: %s", filename, + strerror(errno)); + } + } +} + +static void check_inclusion_regexp(const char * const filename) { + if (SNUFFLEUPAGUS_G(config).config_regexp_inclusion->regexp_inclusion) { + const sp_node_t* config = SNUFFLEUPAGUS_G(config).config_regexp_inclusion->regexp_inclusion; + if (!config || !config->data) { + return; + } + while (config) { + pcre *config_node = (pcre*)(config->data); + if (false == is_regexp_matching(config_node, filename)) { + sp_log_msg("include", LOG_DROP, "Inclusion of a forbidden file (%s).", filename); + sp_terminate(); + } + config = config->next; + } + } +} + +static void sp_execute_ex(zend_execute_data *execute_data) { + if (NULL == execute_data->func->common.function_name) { + goto execute; + } + + if (true == should_disable(execute_data)) { + return; + } + + if (execute_data->func->op_array.type == ZEND_EVAL_CODE) { + sp_log_debug("Currently in an eval\n"); + } + + if (NULL != execute_data->func->op_array.filename) { + if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { + terminate_if_writable(ZSTR_VAL(execute_data->func->op_array.filename)); + } +} + +execute: + orig_execute_ex(execute_data); +} + +static int sp_stream_open(const char *filename, + zend_file_handle *handle) { + const zend_execute_data *data = EG(current_execute_data); + + if ((NULL != data) && (NULL != data->opline) && + (ZEND_INCLUDE_OR_EVAL == data->opline->opcode)) { + if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { + terminate_if_writable(filename); + } + check_inclusion_regexp(filename); + } + return orig_zend_stream_open(filename, handle); +} + +int hook_execute(void) { + TSRMLS_FETCH(); + + /* zend_execute_ex is used for "classic" function calls */ + orig_execute_ex = zend_execute_ex; + zend_execute_ex = sp_execute_ex; + + /* zend_stream_open_function is used FIXME */ + orig_zend_stream_open = zend_stream_open_function; + zend_stream_open_function = sp_stream_open; + + /* zend_execute_internal is used for "indirect" functions call, + * like array_map or call_user_func. */ + + return SUCCESS; +} diff --git a/src/sp_execute.h b/src/sp_execute.h new file mode 100644 index 0000000..8345736 --- /dev/null +++ b/src/sp_execute.h @@ -0,0 +1,6 @@ +#ifndef SP_EXECUTE_H +#define SP_EXECUTE_H + +int hook_execute(void); + +#endif /* SP_EXECUTE_H */ diff --git a/src/sp_harden_rand.c b/src/sp_harden_rand.c new file mode 100644 index 0000000..e0e35ff --- /dev/null +++ b/src/sp_harden_rand.c @@ -0,0 +1,77 @@ +#include "php_snuffleupagus.h" + +extern ZEND_API zend_class_entry *zend_ce_error; + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +/* This function is needed because `rand` and `mt_rand` parameters + * are optional, while the ones from `random_int` aren't. */ +static void random_int_wrapper(INTERNAL_FUNCTION_PARAMETERS) { + zend_long min, max, result; + + switch (EX_NUM_ARGS()) { + case 0: + min = 0; + max = PHP_MT_RAND_MAX; + break; + case 1: + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1); + Z_PARAM_LONG(min); + ZEND_PARSE_PARAMETERS_END(); + max = PHP_MT_RAND_MAX; + break; + case 2: + default: + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 0, 2); + Z_PARAM_LONG(min); + Z_PARAM_LONG(max); + ZEND_PARSE_PARAMETERS_END(); + } + + if (min > max) { + if (php_random_int_throw(max, min, &result) == FAILURE) { + return; + } + } else { + if (php_random_int_throw(min, max, &result) == FAILURE) { + return; + } + } + + RETURN_LONG(result); +} + +PHP_FUNCTION(sp_rand) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + + if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), "rand", + strlen("rand")))) { + /* call the original `rand` function, + * since we might no be the only ones to hook it*/ + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } + + random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +PHP_FUNCTION(sp_mt_rand) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + + if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), + "mt_rand", strlen("mt_rand")))) { + /* call the original `mt_rand` function, + * since we might no be the only ones to hook it*/ + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } + + random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +int hook_rand() { + TSRMLS_FETCH(); + + HOOK_FUNCTION("rand", sp_internal_functions_hook, PHP_FN(sp_rand), false); + HOOK_FUNCTION("mt_rand", sp_internal_functions_hook, PHP_FN(sp_mt_rand), false); + + return SUCCESS; +} diff --git a/src/sp_harden_rand.h b/src/sp_harden_rand.h new file mode 100644 index 0000000..53ebdd0 --- /dev/null +++ b/src/sp_harden_rand.h @@ -0,0 +1,10 @@ +#ifndef __SP_HARDEN_RAND_H +#define __SP_HARDEN_RAND_H + +#include "ext/standard/php_rand.h" +#include "ext/standard/php_random.h" +#include "zend_exceptions.h" + +int hook_rand(); + +#endif /* __SP_HARDEN_RAND_H */ diff --git a/src/sp_list.c b/src/sp_list.c new file mode 100644 index 0000000..04154b7 --- /dev/null +++ b/src/sp_list.c @@ -0,0 +1,37 @@ +#include "sp_list.h" +#include +#include +#include "php_snuffleupagus.h" + +void sp_list_free(sp_node_t *node) { + while(node) { + sp_node_t *tmp = node->next; + pefree(node, 1); + node = tmp; + } +} + +sp_node_t *sp_new_list() { + sp_node_t *new = pecalloc(sizeof(*new), 1, 1); + new->next = new->data = new->head = NULL; + return new; +} + +void sp_list_insert(sp_node_t *list, void *data) { + if (list->head == NULL) { + list->data = data; + list->next = NULL; + list->head = list; + } else { + sp_node_t *new = pecalloc(sizeof(*new), 1, 1); + + new->data = data; + new->next = NULL; + new->head = list; + + while (list->next) { + list = list->next; + } + list->next = new; + } +} diff --git a/src/sp_list.h b/src/sp_list.h new file mode 100644 index 0000000..48b11f6 --- /dev/null +++ b/src/sp_list.h @@ -0,0 +1,15 @@ +#ifndef SP_LIST_H +#define SP_LIST_H + +typedef struct sp_node_s { + struct sp_node_s *next; + struct sp_node_s *head; + void *data; + +} sp_node_t; + +sp_node_t *sp_new_list(); +void sp_list_insert(sp_node_t *, void *); +void sp_list_free(sp_node_t *); + +#endif diff --git a/src/sp_network_utils.c b/src/sp_network_utils.c new file mode 100644 index 0000000..28bc324 --- /dev/null +++ b/src/sp_network_utils.c @@ -0,0 +1,159 @@ +#include +#include +#include + +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +static inline bool cidr4_match(const struct in_addr addr, + const struct in_addr net, uint8_t bits); +static inline bool cidr6_match(const struct in6_addr address, + const struct in6_addr network, uint8_t bits); +static inline int get_ip_version(const char *ip); + +void apply_mask_on_ip(char *out, const char *const remote_addr) { + uint8_t mask4 = SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv4; + uint8_t mask6 = SNUFFLEUPAGUS_G(config).config_cookie_encryption->mask_ipv6; + const int ip_version = get_ip_version(remote_addr); + + memset(out, 0, 128); + + if (ip_version == AF_INET) { + struct in_addr out4; + inet_pton(AF_INET, remote_addr, &out4); + const long n = out4.s_addr & htonl(0xFFFFFFFFu << (32 - mask4)); + out[0] = (n >> 24) & 0xFF; + out[1] = (n >> 16) & 0xFF; + out[2] = (n >> 8) & 0xFF; + out[3] = (n >> 0) & 0xFF; + } else if (ip_version == AF_INET6) { + inet_pton(AF_INET6, remote_addr, out); + uint32_t *p_ip = (uint32_t *)out; + while (32 < mask6) { + *p_ip = 0xFFFFFFFFu; + p_ip++; + mask6 -= 32; + } + if (0 != mask6) { + *p_ip = htonl(0xFFFFFFFFu << (32 - mask6)); + } + } else { + sp_log_err("ip_mask", "It seems that %s isn't a valid ip.", remote_addr); + } +} + +/* http://fxr.watson.org/fxr/source/include/net/xfrm.h?v=linux-2.6#L840 */ +static inline bool cidr4_match(const struct in_addr addr, + const struct in_addr net, uint8_t bits) { + if (bits == 0) { // C99 6.5.7 (3): u32 << 32 is undefined behaviour + return true; + } + return !((addr.s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits))); +} + +static inline bool cidr6_match(const struct in6_addr address, + const struct in6_addr network, uint8_t bits) { + //#ifdef LINUX + const uint32_t *a = address.s6_addr32; + const uint32_t *n = network.s6_addr32; + /* +#else + const uint32_t *a = address.__u6_addr.__u6_addr32; + const uint32_t *n = network.__u6_addr.__u6_addr32; +#endif +*/ + int bits_whole, bits_incomplete; + bits_whole = bits >> 5; // number of whole u32 + bits_incomplete = bits & 0x1F; // number of bits in incomplete u32 + if (bits_whole) { + if (memcmp(a, n, bits_whole << 2)) { + return false; + } + } + if (bits_incomplete) { + uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete)); + if ((a[bits_whole] ^ n[bits_whole]) & mask) { + return false; + } + } + return true; +} + +static inline int get_ip_version(const char *ip) { + struct in_addr out4; + struct in6_addr out6; + int res = inet_pton(AF_INET, ip, &out4); + if (0 == res) { + if (1 == inet_pton(AF_INET6, ip, &out6)) { + return AF_INET6; + } else { + return -1; + } + } else if (1 == res) { + return AF_INET; + } else { + return -1; + } +} + +// TODO factorise a bit this function +bool cidr_match(const char *ip, const sp_cidr *cidr) { + struct in_addr out4; + struct in6_addr out6; + + switch (get_ip_version(ip)) { + case AF_INET: + if (AF_INET != cidr->ip_version) { + return false; + } + inet_pton(AF_INET, ip, &out4); + return cidr4_match(out4, cidr->ip.ipv4, cidr->mask); + case AF_INET6: + if (AF_INET6 != cidr->ip_version) { + return false; + } + inet_pton(AF_INET6, ip, &out6); + return cidr6_match(out6, cidr->ip.ipv6, cidr->mask); + default: + sp_log_err("cidr_match", "Weird ip (%s) family", ip); + break; + } + return false; +} + +int get_ip_and_cidr(char *ip, sp_cidr *cidr) { + errno = 0; + char *mask = strchr(ip, '/'); + + if (NULL == mask) { + sp_log_err("config", + "'%s' isn't a valid network mask, it seems that you forgot a '/'.", + ip); + return -1; + } + + if (sscanf(mask + 1, "%hhu", &(cidr->mask)) != 1) { + sp_log_err("config", "'%s' isn't a valid network mask.", mask + 1); + return -1; + } + + ip[mask - ip] = '\0'; // NULL the '/' char + + cidr->ip_version = get_ip_version(ip); + + if (AF_INET == cidr->ip_version) { + if (cidr->mask > 32) { + sp_log_err("config", "'%d' isn't a valid ipv4 mask.", cidr->mask); + return -1; + } + inet_pton(AF_INET, ip, &(cidr->ip.ipv4)); + } else if (AF_INET6 == cidr->ip_version) { + inet_pton(AF_INET6, ip, &(cidr->ip.ipv6)); + } else { + return -1; + } + + ip[mask - ip] = '/'; + return 0; +} diff --git a/src/sp_network_utils.h b/src/sp_network_utils.h new file mode 100644 index 0000000..6b6ce92 --- /dev/null +++ b/src/sp_network_utils.h @@ -0,0 +1,8 @@ +#ifndef SP_NETWORK_UTILS_H +#define SP_NETWORK_UTILS_H + +int get_ip_and_cidr(char *, sp_cidr *); +bool cidr_match(const char *, const sp_cidr *); +void apply_mask_on_ip(char *, const char * const); + +#endif /*SP_NETWORK_UTILS_H*/ diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c new file mode 100644 index 0000000..b5b67b4 --- /dev/null +++ b/src/sp_unserialize.c @@ -0,0 +1,111 @@ +#include "php_snuffleupagus.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +PHP_FUNCTION(sp_serialize) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + + /* Call the original `serialize` function. */ + if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), + "serialize", 9))) { + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } else { + sp_log_err("disabled_functions", + "Unable to find the pointer to the original function 'serialize' in " + "the hashtable.\n"); + } + + /* Compute the HMAC of the textual representation of the serialized data*/ + zval func_name; + zval hmac; + zval params[3]; + + ZVAL_STRING(&func_name, "hash_hmac"); + ZVAL_STRING(¶ms[0], "sha256"); + params[1] = *return_value; + ZVAL_STRING(¶ms[2], + SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key); + call_user_function(CG(function_table), NULL, &func_name, &hmac, 3, params); + + size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac); + zend_string *res = zend_string_alloc(len, 0); + + memcpy(ZSTR_VAL(res), Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); + memcpy(ZSTR_VAL(res) + Z_STRLEN_P(return_value), Z_STRVAL(hmac), + Z_STRLEN(hmac)); + ZSTR_VAL(res)[len] = '\0'; + + /* Append the computed HMAC to the serialized data. */ + return_value->value.str = res; + return; +} + +PHP_FUNCTION(sp_unserialize) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + + char *buf = NULL; + char *serialized_str = NULL; + char *hmac = NULL; + zval expected_hmac; + size_t buf_len = 0; + zval *opts = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) == + FAILURE) { + RETURN_FALSE; + } + + /* 64 is the length of HMAC-256 */ + if (buf_len < 64) { + sp_log_msg("unserialize", LOG_DROP, "The serialized object is too small."); + RETURN_FALSE; + } + + hmac = buf + buf_len - 64; + serialized_str = ecalloc(sizeof(*serialized_str) * (buf_len - 64 + 1), 1); + memcpy(serialized_str, buf, buf_len - 64); + + zval func_name; + ZVAL_STRING(&func_name, "hash_hmac"); + + zval params[3]; + ZVAL_STRING(¶ms[0], "sha256"); + ZVAL_STRING(¶ms[1], serialized_str); + ZVAL_STRING(¶ms[2], + SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key); + call_user_function(CG(function_table), NULL, &func_name, &expected_hmac, 3, + params); + + unsigned int status = 0; + for (uint8_t i = 0; i < 64; i++) { + status |= (hmac[i] ^ (Z_STRVAL(expected_hmac))[i]); + } + + if (0 == status) { + if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), + "unserialize", 11))) { + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } + } else { + if ( true == SNUFFLEUPAGUS_G(config).config_unserialize->simulation) { + sp_log_msg("unserialize", LOG_NOTICE, "Invalid HMAC for %s", serialized_str); + if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), + "unserialize", 11))) { + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } + } else { + sp_log_msg("unserialize", LOG_DROP, "Invalid HMAC for %s", serialized_str); + } + } + efree(serialized_str); + return; +} + +int hook_serialize(void) { + TSRMLS_FETCH(); + + HOOK_FUNCTION("serialize", sp_internal_functions_hook, PHP_FN(sp_serialize), false); + HOOK_FUNCTION("unserialize", sp_internal_functions_hook, PHP_FN(sp_unserialize), false); + + return SUCCESS; +} diff --git a/src/sp_unserialize.h b/src/sp_unserialize.h new file mode 100644 index 0000000..557c60c --- /dev/null +++ b/src/sp_unserialize.h @@ -0,0 +1,9 @@ +#ifndef SP_UNSERIALIZE_H +#define SP_UNSERIALIZE_H + +int hook_serialize(void); + +PHP_FUNCTION(sp_serialize); +PHP_FUNCTION(sp_unserialize); + +#endif /* SP_UNSERIALIZE_H */ diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c new file mode 100644 index 0000000..bbd7eae --- /dev/null +++ b/src/sp_upload_validation.c @@ -0,0 +1,92 @@ +#include "php_snuffleupagus.h" +#include "rfc1867.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +#define EFREE_3(env) \ + for (size_t i = 0; i < 4; i++) { \ + efree(env[i]); \ + } + +void hook_upload() { + sp_rfc1867_orig_callback = php_rfc1867_callback; + php_rfc1867_callback = sp_rfc1867_callback; +} + +int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) { + int retval = SUCCESS; + + if (sp_rfc1867_orig_callback) { + retval = sp_rfc1867_orig_callback(event, event_data, extra); + } + + if (event == MULTIPART_EVENT_END) { + zend_string *file_key __attribute__((unused)) = NULL; + zval *file; + pid_t pid; + + sp_log_debug( + "Got %d files", + zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]))); + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]), + file_key, file) { // for each uploaded file + + char *filename = + Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "name", 4)); + char *tmp_name = + Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "tmp_name", 8)); + size_t filesize = + Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "size", 4)); + char *cmd[3] = {0}; + char *env[5] = {0}; + + sp_log_debug("Filename: %s\nTmpname: %s\nSize: %d\nError: %d\nScript: %s", + filename, tmp_name, filesize, + Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "error", 5)), + SNUFFLEUPAGUS_G(config).config_upload_validation->script); + + cmd[0] = SNUFFLEUPAGUS_G(config).config_upload_validation->script; + cmd[1] = tmp_name; + cmd[2] = NULL; + + spprintf(&env[0], 0, "SP_FILENAME=%s", filename); + spprintf(&env[1], 0, "SP_REMOTE_ADDR=%s", sp_getenv("REMOTE_ADDR")); + spprintf(&env[2], 0, "SP_CURRENT_FILE=%s", + zend_get_executed_filename(TSRMLS_C)); + spprintf(&env[3], 0, "SP_FILESIZE=%zu", filesize); + env[4] = NULL; + + if ((pid = fork()) == 0) { + if (execve(SNUFFLEUPAGUS_G(config).config_upload_validation->script, + cmd, env) == -1) { + sp_log_err("upload_validation", "Could not call '%s' : %s", + SNUFFLEUPAGUS_G(config).config_upload_validation->script, + strerror(errno)); + EFREE_3(env); + exit(1); + } + } else if (pid == -1) { + sp_log_err("upload_validation", "Could not fork process : %s\n", + strerror(errno)); + EFREE_3(env); + continue; + } + + EFREE_3(env); + int waitstatus; + wait(&waitstatus); + if (WEXITSTATUS(waitstatus) != 0) { // Nope + char *uri = sp_getenv("REQUEST_URI"); + int sim = SNUFFLEUPAGUS_G(config).config_upload_validation->simulation; + sp_log_msg("upload_valiation", sim?LOG_NOTICE:LOG_DROP, + "The upload of %s on %s was rejected.", filename, uri?uri:"?"); + if (!SNUFFLEUPAGUS_G(config).config_upload_validation->simulation) { + zend_bailout(); + } + } + } + ZEND_HASH_FOREACH_END(); + } + return retval; +} diff --git a/src/sp_upload_validation.h b/src/sp_upload_validation.h new file mode 100644 index 0000000..3d59527 --- /dev/null +++ b/src/sp_upload_validation.h @@ -0,0 +1,9 @@ +#ifndef __SP_UPLOAD_VALIDATION_H__ +#define __SP_UPLOAD_VALIDATION_H__ + +void hook_upload(); + +int (*sp_rfc1867_orig_callback)(unsigned int event, void *event_data, void **extra); +int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra); + +#endif diff --git a/src/sp_utils.c b/src/sp_utils.c new file mode 100644 index 0000000..087f431 --- /dev/null +++ b/src/sp_utils.c @@ -0,0 +1,425 @@ +#include "php_snuffleupagus.h" + +#include +#include +#include +#include +#include + +static inline void _sp_log_err(const char* fmt, ...) { + char* msg; + va_list args; + + va_start(args, fmt); + vspprintf(&msg, 0, fmt, args); + va_end(args); + php_log_err(msg); +} + +void sp_log_msg(char const *feature, char const *level, const char* fmt, ...) { + char* msg; + va_list args; + + va_start(args, fmt); + vspprintf(&msg, 0, fmt, args); + va_end(args); + + char const * const client_ip = sp_getenv("REMOTE_ADDR"); + _sp_log_err("[snuffleupagus][%s][%s][%s] %s", client_ip?client_ip:"0.0.0.0", + feature, level, msg); +} + +int compute_hash(const char* const filename, char* file_hash) { + unsigned char buf[1024]; + unsigned char digest[SHA256_SIZE]; + PHP_SHA256_CTX context; + size_t n; + + php_stream* stream = + php_stream_open_wrapper(filename, "rb", REPORT_ERRORS, NULL); + if (!stream) { + sp_log_err("hash_computation", "Can not open the file %s to compute its hash.\n", filename); + return -1; + } + + PHP_SHA256Init(&context); + while ((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) { + PHP_SHA256Update(&context, buf, n); + } + PHP_SHA256Final(digest, &context); + php_stream_close(stream); + make_digest_ex(file_hash, digest, SHA256_SIZE); + return 0; +} + +static void construct_filename(char* filename, const char* folder) { + time_t t = time(NULL); + struct tm* tm = localtime(&t); // FIXME use `localtime_r` instead + struct timeval tval; + struct stat st = {0}; + + if (-1 == stat(folder, &st)) { + mkdir(folder, 0700); + } + + memcpy(filename, folder, strlen(folder)); + strcat(filename, "sp_dump_"); + strftime(filename + strlen(filename), 27, "%F_%T:", tm); + gettimeofday(&tval, NULL); + sprintf(filename + strlen(filename), "%04ld", tval.tv_usec); + strcat(filename, "_"); + + char* remote_addr = getenv("REMOTE_ADDR"); + if (remote_addr) { + strcat(filename, remote_addr); + } else { + strcat(filename, "0.0.0.0"); + } + strcat(filename, ".dump"); +} + +int sp_log_request(const char* folder) { + FILE* file; + const char* current_filename = zend_get_executed_filename(TSRMLS_C); + const int current_line = zend_get_executed_lineno(TSRMLS_C); + char filename[MAX_FOLDER_LEN] = {0}; + const struct { + const char* str; + const int key; + } zones[] = {{"GET", TRACK_VARS_GET}, {"POST", TRACK_VARS_POST}, + {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER}, + {"ENV", TRACK_VARS_ENV}, {NULL, 0}}; + + construct_filename(filename, folder); + if (NULL == (file = fopen(filename, "a"))) { + sp_log_err("request_logging", "Unable to open %s", filename); + return -1; + } + + fprintf(file, "%s:%d\n", current_filename, current_line); + for (size_t i = 0; i < (sizeof(zones) / sizeof(zones[0])) - 1; i++) { + zval* variable_value; + zend_string* variable_key; + size_t params_len = strlen(zones[i].str) + 1; + char* param; + size_t size_max = 2048; + + if (Z_TYPE(PG(http_globals)[zones[i].key]) == IS_UNDEF) { + continue; + } + + const HashTable* ht = Z_ARRVAL(PG(http_globals)[zones[i].key]); + + // Compute the size of the allocation + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, variable_key, variable_value) { + params_len += snprintf(NULL, 0, "%s=%s&", ZSTR_VAL(variable_key), + Z_STRVAL_P(variable_value)); + } + ZEND_HASH_FOREACH_END(); + + params_len = params_len>size_max?size_max:params_len; + +#define NCAT_AND_DEC(a, b, c) strncat(a, b, c); c -= strlen(b); + + // Allocate and copy the data + // FIXME Why are we even allocating? + param = pecalloc(params_len, 1, 0); + NCAT_AND_DEC(param, zones[i].str, params_len); + NCAT_AND_DEC(param, ":", params_len); + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, variable_key, variable_value) { + NCAT_AND_DEC(param, ZSTR_VAL(variable_key), params_len); + NCAT_AND_DEC(param, "=", params_len); + NCAT_AND_DEC(param, Z_STRVAL_P(variable_value), params_len); + NCAT_AND_DEC(param, "&", params_len); + } + ZEND_HASH_FOREACH_END(); + + param[strlen(param) - 1] = '\0'; + + fputs(param, file); + fputs("\n", file); + } + fclose(file); + +#undef CAT_AND_DEC + return 0; +} + +static char *zv_str_to_char(zval *zv) { + zval copy; + char *ret; + + + ZVAL_ZVAL(©, zv, 1, 0); + // str = zend_string_dup(Z_STR_P(zv), 0); + for (size_t i = 0; i < Z_STRLEN(copy); i++) { + if (Z_STRVAL(copy)[i] == '\0') { + Z_STRVAL(copy)[i] = '0'; + } + } + ret = estrdup(Z_STRVAL(copy)); + // zend_string_release(str); + return ret; +} + + +char* sp_convert_to_string(zval* zv) { + switch (Z_TYPE_P(zv)) { + case IS_FALSE: + return estrdup("FALSE"); + case IS_TRUE: + return estrdup("TRUE"); + case IS_NULL: + return estrdup("NULL"); + case IS_LONG: { + char *msg; + spprintf(&msg, 0, ZEND_LONG_FMT, Z_LVAL_P(zv)); + return msg; + } + case IS_DOUBLE: { + char *msg; + spprintf(&msg, 0, "%f", Z_DVAL_P(zv)); + return msg; + } + case IS_STRING:{ + return zv_str_to_char(zv); + } + case IS_OBJECT: + return estrdup("OBJECT"); + case IS_ARRAY: + return estrdup("ARRAY"); + case IS_RESOURCE: + return estrdup("RESOURCE"); + } + return estrdup(""); +} + +bool sp_match_value(const char* value, const char* to_match, const pcre* rx) { + if (to_match) { + if (0 == strcmp(value, to_match)) { + return true; + } + } else if (rx) { + int substrvec[30]; + int ret = pcre_exec(rx, NULL, value, strlen(value), 0, 0, substrvec, 30); + + if (ret < 0) { + if (ret != PCRE_ERROR_NOMATCH) { + sp_log_err("regexp", "Something went wrong with a regexp."); + return false; + } + return false; + } + return true; + } + return false; +} + +void sp_log_disable(const char* restrict path, const char* restrict arg_name, + const char* restrict arg_value, + const sp_disabled_function* config_node) { + const char* dump = config_node->dump; + const char* alias = config_node->alias; + const int sim = config_node->simulation; + if (arg_name) { + if (alias) { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The call to the function '%s' in %s:%d has been disabled, " + "because its argument '%s' content (%s) matched the rule '%s'.", + path, zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C), arg_name, arg_value?arg_value:"?", + alias); + } else { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The call to the function '%s' in %s:%d has been disabled, " + "because its argument '%s' content (%s) matched a rule.", + path, zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C), arg_name, + arg_value?arg_value:"?"); + } + } else { + if (alias) { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The call to the function '%s' in %s:%d has been disabled, " + "because of the the rule '%s'.",path, + zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C), alias); + } else { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The call to the function '%s' in %s:%d has been disabled.", + path, zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C)); + } + } + if (dump) { + sp_log_request(config_node->dump); + } +} + +void sp_log_disable_ret(const char* restrict path, + const char* restrict ret_value, + const sp_disabled_function* config_node) { + const char* dump = config_node->dump; + const char* alias = config_node->alias; + const int sim = config_node->simulation; + if (alias) { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The execution has been aborted in %s:%d, " + "because the function '%s' returned '%s', which matched the rule '%s'.", + zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C), path, ret_value?ret_value:"?", alias); + } else { + sp_log_msg("disabled_function", sim?LOG_NOTICE:LOG_DROP, + "The execution has been aborted in %s:%d, " + "because the return value (%s) of the function '%s' matched a rule.", + zend_get_executed_filename(TSRMLS_C), + zend_get_executed_lineno(TSRMLS_C), ret_value?ret_value:"?", path); + } + if (dump) { + sp_log_request(dump); + } +} + +int sp_match_array_key(const zval* zv, const char* to_match, const pcre* rx) { + zend_string* key; + zval* value; + char* arg_value_str; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zv), key, value) { + if (Z_TYPE_P(value) == IS_ARRAY) { + continue; + } + arg_value_str = sp_convert_to_string(value); + if (!sp_match_value(arg_value_str, to_match, rx)) { + efree(arg_value_str); + continue; + } else { + efree(arg_value_str); + return 1; + } + } + ZEND_HASH_FOREACH_END(); + + (void)key; // silence a compiler warning + + return 0; +} + +int sp_match_array_key_recurse(const zval* arr, sp_node_t* keys, + const char* to_match, const pcre* rx) { + zend_string* key; + zval* value; + sp_node_t* current = keys; + if (current == NULL) { + return 0; + } + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arr), key, value) { + if (Z_TYPE_P(value) == IS_ARRAY && !strcmp(ZSTR_VAL(key), current->data)) { + return sp_match_array_key_recurse(value, current->next, to_match, rx); + } + if (!strcmp(ZSTR_VAL(key), current->data) && current->next == NULL) { + if (!to_match && !rx) { + return 1; + } + if (Z_TYPE_P(value) == IS_ARRAY) { + return sp_match_array_key(value, to_match, rx); + } else { + char *value_str = sp_convert_to_string(value); + if (sp_match_value(value_str, to_match, rx)) { + efree(value_str); + return 1; + } else { + efree (value_str); + return 0; + } + } + } + } + ZEND_HASH_FOREACH_END(); + return 0; +} + +zend_always_inline char* sp_getenv(char* var) { + if (sapi_module.getenv) { + return sapi_module.getenv(ZEND_STRL(var)); + } else { + return getenv(var); + } +} + +zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) { + int vec[30]; + int ret = pcre_exec(regexp, NULL, str, strlen(str), 0, 0, vec, sizeof(vec)); + if (ret < 0) { + if (ret != PCRE_ERROR_NOMATCH) { + sp_log_err("regexp", "Something went wrong with a regexp."); + } + return false; + } + return true; +} + +int hook_function(const char* original_name, HashTable* hook_table, + void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), + bool hook_execution_table) { + zend_internal_function* func; + HashTable *ht = hook_execution_table==true?EG(function_table):CG(function_table); + + /* The `mb` module likes to hook functions, like strlen->mb_strlen, + * so we have to hook both of them. */ + if (0 == strncmp(original_name, "mb_", 3)) { + CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; + if (zend_hash_str_find(ht, + VAR_AND_LEN(original_name + 3))) { + hook_function(original_name + 3, hook_table, new_function, hook_execution_table); + } + } else { // TODO this can be moved somewhere else to gain some marginal perfs + CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; + char* mb_name = pecalloc(strlen(original_name) + 3 + 1, 1, 0); + memcpy(mb_name, "mb_", 3); + memcpy(mb_name + 3, VAR_AND_LEN(original_name)); + if (zend_hash_str_find(CG(function_table), VAR_AND_LEN(mb_name))) { + hook_function(mb_name, hook_table, new_function, hook_execution_table); + } + } + + if ((func = zend_hash_str_find_ptr(CG(function_table), + VAR_AND_LEN(original_name)))) { + if (func->handler == new_function) { + /* Success !*/ + } else if (zend_hash_str_add_new_ptr((hook_table), + VAR_AND_LEN(original_name), + func->handler) == NULL) { + sp_log_err("function_pointer_saving", + "Could not save function pointer for %s", original_name); + return FAILURE; + } else { + func->handler = new_function; + } + } + return SUCCESS; +} + +int hook_regexp(const pcre* regexp, HashTable* hook_table, + void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), + bool hook_execution_table) { + zend_string* key; + HashTable *ht = hook_execution_table==true?EG(function_table):CG(function_table); + + ZEND_HASH_FOREACH_STR_KEY(ht, key) { + if (key) { + int vec[30]; + int ret = pcre_exec(regexp, NULL, key->val, key->len, 0, 0, vec, 30); + if (ret < 0) { /* Error or no match*/ + if (PCRE_ERROR_NOMATCH != ret) { + sp_log_err("pcre", "Runtime error with pcre, error code: %d", ret); + return FAILURE; + } + continue; + } + hook_function(key->val, hook_table, new_function, hook_execution_table); + } + } + ZEND_HASH_FOREACH_END(); + return SUCCESS; +} diff --git a/src/sp_utils.h b/src/sp_utils.h new file mode 100644 index 0000000..37dd2c0 --- /dev/null +++ b/src/sp_utils.h @@ -0,0 +1,68 @@ +#ifndef SP_UTILS_H +#define SP_UTILS_H + +#include "sp_config.h" +#include "sp_list.h" + +#if defined(__GNUC__) +# if __GNUC__ >= 3 +# define sp_pure __attribute__((pure)) +# define sp_const __attribute__((const)) +# else +# define sp_pure +# define sp_const +# endif +#endif +/* The dump filename are of the form + * `sp_dump_DATE_IPADDR.dump`, with: + * - DATE being the output of asctime, 26 chars long + * - IP_ADDR being an IP adress, with a maximum size of 15 + * + * We keep one char for the terminal \0, and one for the leading slash. + */ + +#define MAX_FOLDER_LEN \ + PATH_MAX - 1 - sizeof("sp_dump_") - 26 - sizeof("_") - 15 - \ + sizeof(".dump") - 1 + +#define VAR_AND_LEN(var) var, strlen(var) + +#define SHA256_SIZE 32 + +#define HOOK_FUNCTION(original_name, hook_table, new_function, execution) \ + hook_function(original_name, SNUFFLEUPAGUS_G(hook_table), new_function, execution) + +#define HOOK_FUNCTION_BY_REGEXP(regexp, hook_table, new_function, execution) \ + hook_regexp(regexp, SNUFFLEUPAGUS_G(hook_table), new_function, execution) + +#define LOG_NOTICE "notice" +#define LOG_DROP "drop" +#define LOG_DEBUG "debug" +#define LOG_ERROR "error" + +#define sp_log_err(feature, ...) sp_log_msg(feature, LOG_ERROR, __VA_ARGS__) +#ifdef SP_DEBUG + #define sp_log_debug(...) sp_log_msg("DEBUG", LOG_DEBUG, __VA_ARGS__) +#else + #define sp_log_debug(...) +#endif + +void sp_log_msg(char const *feature, char const *level, const char* fmt, ...); +int compute_hash(const char *const filename, char *file_hash); +char *sp_convert_to_string(zval *); +bool sp_match_value(const char *, const char *, const pcre *); +int sp_match_array_key(const zval *, const char *, const pcre *); +int sp_match_array_key_recurse(const zval *, sp_node_t *, const char *, + const pcre *); +void sp_log_disable(const char *restrict, const char *restrict, + const char *restrict, const sp_disabled_function *); +void sp_log_disable_ret(const char *restrict, const char *restrict, + const sp_disabled_function *); +char *sp_getenv(char *); +int is_regexp_matching(const pcre *, const char *); +int hook_function(const char *, HashTable *, + void (*)(INTERNAL_FUNCTION_PARAMETERS), bool); +int hook_regexp(const pcre *, HashTable *, + void (*)(INTERNAL_FUNCTION_PARAMETERS), bool); + +#endif /* SP_UTILS_H */ diff --git a/src/tests/broken_conf.phpt b/src/tests/broken_conf.phpt new file mode 100644 index 0000000..ae0ef6e --- /dev/null +++ b/src/tests/broken_conf.phpt @@ -0,0 +1,10 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration prefix for 'this is a broken line'. + diff --git a/src/tests/broken_conf2.phpt b/src/tests/broken_conf2.phpt new file mode 100644 index 0000000..88a2232 --- /dev/null +++ b/src/tests/broken_conf2.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf2.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration section 'sp.wrong'. diff --git a/src/tests/broken_conf_config_regexp.phpt b/src/tests/broken_conf_config_regexp.phpt new file mode 100644 index 0000000..75bc603 --- /dev/null +++ b/src/tests/broken_conf_config_regexp.phpt @@ -0,0 +1,10 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_config_regexp.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Failed to compile '*.': nothing to repeat. +[snuffleupagus][0.0.0.0][config][error] '.filename_r()' is expecting a valid regexp, and not '"*."'. diff --git a/src/tests/broken_conf_enable_disable.phpt b/src/tests/broken_conf_enable_disable.phpt new file mode 100644 index 0000000..2f3fe19 --- /dev/null +++ b/src/tests/broken_conf_enable_disable.phpt @@ -0,0 +1,9 @@ +--TEST-- +Global strict mode +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/borken_conf_enable_disable.ini +--FILE-- +--EXPECTF-- +[snuffleupagus][0.0.0.0][config][error] A rule can't be enabled and disabled. diff --git a/src/tests/broken_conf_expecting_bool.phpt b/src/tests/broken_conf_expecting_bool.phpt new file mode 100644 index 0000000..80e1b61 --- /dev/null +++ b/src/tests/broken_conf_expecting_bool.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bad boolean value in configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_expecting_bool.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Trailing chars '337);' at the end of '.enable(1337);'. diff --git a/src/tests/broken_conf_expecting_int.phpt b/src/tests/broken_conf_expecting_int.phpt new file mode 100644 index 0000000..e806337 --- /dev/null +++ b/src/tests/broken_conf_expecting_int.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bad integer value in configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_expecting_int.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] .mask_ipv4() is expecting a valid integer. diff --git a/src/tests/broken_conf_invalid_cidr.phpt b/src/tests/broken_conf_invalid_cidr.phpt new file mode 100644 index 0000000..515091b --- /dev/null +++ b/src/tests/broken_conf_invalid_cidr.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_cidr.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] '42' isn't a valid ipv4 mask. diff --git a/src/tests/broken_conf_invalid_cidr6.phpt b/src/tests/broken_conf_invalid_cidr6.phpt new file mode 100644 index 0000000..d20cfcd --- /dev/null +++ b/src/tests/broken_conf_invalid_cidr6.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_cidr6.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] 'ZZZ' isn't a valid network mask. diff --git a/src/tests/broken_conf_invalid_cidr6_no_slash.phpt b/src/tests/broken_conf_invalid_cidr6_no_slash.phpt new file mode 100644 index 0000000..de70a05 --- /dev/null +++ b/src/tests/broken_conf_invalid_cidr6_no_slash.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration, invalid cidr for ipv6 because there is no `/` in it +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_cidr6_no_slash.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] '2001:0db8:0000:0000:0000:ff00:0042:8329' isn't a valid network mask, it seems that you forgot a '/'. diff --git a/src/tests/broken_conf_invalid_cidr6_too_big.phpt b/src/tests/broken_conf_invalid_cidr6_too_big.phpt new file mode 100644 index 0000000..47d4a5d --- /dev/null +++ b/src/tests/broken_conf_invalid_cidr6_too_big.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration, cidr for ipv6 is too big, that will `mod` to 25. +(13337%128 = 25) +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_cidr6_too_big.ini +--FILE-- +--EXPECT-- diff --git a/src/tests/broken_conf_invalid_cidr_value.phpt b/src/tests/broken_conf_invalid_cidr_value.phpt new file mode 100644 index 0000000..712f123 --- /dev/null +++ b/src/tests/broken_conf_invalid_cidr_value.phpt @@ -0,0 +1,11 @@ +--TEST-- +Broken configuration, invalid cidr value +(13337%128 = 25) +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_cidr_value.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '"': it doesn't look like a valid string. +[snuffleupagus][0.0.0.0][config][error] " doesn't contain a valid cidr. diff --git a/src/tests/broken_conf_invalid_type.phpt b/src/tests/broken_conf_invalid_type.phpt new file mode 100644 index 0000000..29d2ff5 --- /dev/null +++ b/src/tests/broken_conf_invalid_type.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken conf with wrong type +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_invalid_type.ini +--FILE-- +--EXPECTF-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '"totally_wrong"_type")': it doesn't look like a valid string. diff --git a/src/tests/broken_conf_line_empty_string.phpt b/src/tests/broken_conf_line_empty_string.phpt new file mode 100644 index 0000000..c4334b9 --- /dev/null +++ b/src/tests/broken_conf_line_empty_string.phpt @@ -0,0 +1,9 @@ +--TEST-- +Configuration line with an empty string +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_line_empty_string.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '': it doesn't look like a valid string. diff --git a/src/tests/broken_conf_line_no_closing.phpt b/src/tests/broken_conf_line_no_closing.phpt new file mode 100644 index 0000000..07c94e4 --- /dev/null +++ b/src/tests/broken_conf_line_no_closing.phpt @@ -0,0 +1,9 @@ +--TEST-- +Configuration line without closing parenthese +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_line_no_closing.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '"123"': it doesn't look like a valid string. diff --git a/src/tests/broken_conf_line_too_long.phpt b/src/tests/broken_conf_line_too_long.phpt new file mode 100644 index 0000000..8e82708 --- /dev/null +++ b/src/tests/broken_conf_line_too_long.phpt @@ -0,0 +1,10 @@ +--TEST-- +Line too long in configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_line_too_long.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] The following line is too long: 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111);. +[snuffleupagus][0.0.0.0][error][error] .mask_ipv4() is expecting a valid integer. diff --git a/src/tests/broken_conf_lots_of_quotes.phpt b/src/tests/broken_conf_lots_of_quotes.phpt new file mode 100644 index 0000000..e877cfa --- /dev/null +++ b/src/tests/broken_conf_lots_of_quotes.phpt @@ -0,0 +1,9 @@ +--TEST-- +Configuration line with too many quotes +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_lots_of_quotes.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '"this\"is a weird\"\"\"cookie\"name"");': it doesn't look like a valid string. diff --git a/src/tests/broken_conf_mutually_exclusive.phpt b/src/tests/broken_conf_mutually_exclusive.phpt new file mode 100644 index 0000000..9de7e5a --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").value_r("^id$").drop();':'.value' and '.regexp' are mutually exclusives. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive2.phpt b/src/tests/broken_conf_mutually_exclusive2.phpt new file mode 100644 index 0000000..9d3ea36 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive2.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive2.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").function_r("system").param("id").value("42").drop();': '.r_function' and '.function' are mutually exclusive. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive3.phpt b/src/tests/broken_conf_mutually_exclusive3.phpt new file mode 100644 index 0000000..58686a3 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive3.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive3.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").filename_r("^id$").filename("pouet.txt").drop();':'.r_filename' and '.filename' are mutually exclusive. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive4.phpt b/src/tests/broken_conf_mutually_exclusive4.phpt new file mode 100644 index 0000000..d854380 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive4.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive4.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").param_r("^id$").drop();':'.r_param' and '.param' are mutually exclusive. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive5.phpt b/src/tests/broken_conf_mutually_exclusive5.phpt new file mode 100644 index 0000000..a265c30 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive5.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive5.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").ret("0").drop().ret_r("^0$");':'.r_ret' and '.ret' are mutually exclusive. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive6.phpt b/src/tests/broken_conf_mutually_exclusive6.phpt new file mode 100644 index 0000000..d0cdb85 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive6.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive6.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").ret_r("^0$").drop();':`ret` and `param` are mutually exclusives. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive7.phpt b/src/tests/broken_conf_mutually_exclusive7.phpt new file mode 100644 index 0000000..c9a3513 --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive7.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive7.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.function("system").ret("0").drop().allow();': The rule must either be a `drop` or and `allow` one. \ No newline at end of file diff --git a/src/tests/broken_conf_mutually_exclusive8.phpt b/src/tests/broken_conf_mutually_exclusive8.phpt new file mode 100644 index 0000000..7c5baee --- /dev/null +++ b/src/tests/broken_conf_mutually_exclusive8.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive8.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Invalid configuration line: 'sp.disabled_functions.ret("0").drop();': must take a function name. \ No newline at end of file diff --git a/src/tests/broken_conf_no_closing_misc.phpt b/src/tests/broken_conf_no_closing_misc.phpt new file mode 100644 index 0000000..1d1e112 --- /dev/null +++ b/src/tests/broken_conf_no_closing_misc.phpt @@ -0,0 +1,10 @@ +--TEST-- +Configuration line without closing parenthese, misc +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_no_closing_misc.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Missing closing ) in line 123. +[snuffleupagus][0.0.0.0][error][error] .mask_ipv4() is expecting a valid integer. diff --git a/src/tests/broken_conf_weird_keyword.phpt b/src/tests/broken_conf_weird_keyword.phpt new file mode 100644 index 0000000..5293791 --- /dev/null +++ b/src/tests/broken_conf_weird_keyword.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bad config, unknown keyword +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_weird_keyword.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][config][error] Trailing chars '.not_a_valid_keyword("test");' at the end of '.enable().not_a_valid_keyword("test");'. \ No newline at end of file diff --git a/src/tests/broken_conf_wrong_quotes.phpt b/src/tests/broken_conf_wrong_quotes.phpt new file mode 100644 index 0000000..b6324fe --- /dev/null +++ b/src/tests/broken_conf_wrong_quotes.phpt @@ -0,0 +1,9 @@ +--TEST-- +Configuration line with too many quotes +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_wrong_quotes.ini +--FILE-- +--EXPECT-- +[snuffleupagus][0.0.0.0][error][error] There is an issue with the parsing of '"\)': it doesn't look like a valid string. diff --git a/src/tests/broken_conf_wrong_type.phpt b/src/tests/broken_conf_wrong_type.phpt new file mode 100644 index 0000000..338ca3a --- /dev/null +++ b/src/tests/broken_conf_wrong_type.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken conf with wrong type +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_conf_wrong_type.ini +--FILE-- +--EXPECTF-- +[snuffleupagus][0.0.0.0][error][error] .ret_type() is expecting a valid php type ('false', 'true', 'array'. 'object', 'long', 'double', 'null', 'resource', 'reference', 'undef'). diff --git a/src/tests/broken_regexp.phpt b/src/tests/broken_regexp.phpt new file mode 100644 index 0000000..cbfef7d --- /dev/null +++ b/src/tests/broken_regexp.phpt @@ -0,0 +1,9 @@ +--TEST-- +Broken regexp +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/broken_regexp.ini +--FILE-- +--EXPECTF-- +[snuffleupagus][0.0.0.0][config][error] '.value_r()' is expecting a valid regexp, and not '"^$["'. diff --git a/src/tests/config/borken_conf_enable_disable.ini b/src/tests/config/borken_conf_enable_disable.ini new file mode 100644 index 0000000..4e95294 --- /dev/null +++ b/src/tests/config/borken_conf_enable_disable.ini @@ -0,0 +1 @@ +sp.global_strict.disable().enable(); diff --git a/src/tests/config/broken_conf.ini b/src/tests/config/broken_conf.ini new file mode 100644 index 0000000..0595320 --- /dev/null +++ b/src/tests/config/broken_conf.ini @@ -0,0 +1 @@ +this is a broken line diff --git a/src/tests/config/broken_conf2.ini b/src/tests/config/broken_conf2.ini new file mode 100644 index 0000000..fdb6b8f --- /dev/null +++ b/src/tests/config/broken_conf2.ini @@ -0,0 +1 @@ +sp.wrong diff --git a/src/tests/config/broken_conf_expecting_bool.ini b/src/tests/config/broken_conf_expecting_bool.ini new file mode 100644 index 0000000..51c28b2 --- /dev/null +++ b/src/tests/config/broken_conf_expecting_bool.ini @@ -0,0 +1,5 @@ + # this is an example of broken conf + + + ; this is another comment +sp.harden_random.enable(1337); diff --git a/src/tests/config/broken_conf_expecting_int.ini b/src/tests/config/broken_conf_expecting_int.ini new file mode 100644 index 0000000..8e2efea --- /dev/null +++ b/src/tests/config/broken_conf_expecting_int.ini @@ -0,0 +1,2 @@ +sp.global.secret_key("abcdef"); +sp.cookie_encryption.cookie("super_cookie").mask_ipv4(abc); diff --git a/src/tests/config/broken_conf_invalid_cidr.ini b/src/tests/config/broken_conf_invalid_cidr.ini new file mode 100644 index 0000000..0cdc695 --- /dev/null +++ b/src/tests/config/broken_conf_invalid_cidr.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr("127.0.0.1/42"); diff --git a/src/tests/config/broken_conf_invalid_cidr6.ini b/src/tests/config/broken_conf_invalid_cidr6.ini new file mode 100644 index 0000000..e5a120c --- /dev/null +++ b/src/tests/config/broken_conf_invalid_cidr6.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr("2001:0db8:0000:0000:0000:ff00:0042:8329/ZZZ"); diff --git a/src/tests/config/broken_conf_invalid_cidr6_no_slash.ini b/src/tests/config/broken_conf_invalid_cidr6_no_slash.ini new file mode 100644 index 0000000..e4cf835 --- /dev/null +++ b/src/tests/config/broken_conf_invalid_cidr6_no_slash.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr("2001:0db8:0000:0000:0000:ff00:0042:8329"); diff --git a/src/tests/config/broken_conf_invalid_cidr6_too_big.ini b/src/tests/config/broken_conf_invalid_cidr6_too_big.ini new file mode 100644 index 0000000..417dee7 --- /dev/null +++ b/src/tests/config/broken_conf_invalid_cidr6_too_big.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr("2001:0db8:0000:0000:0000:ff00:0042:8329/13337"); diff --git a/src/tests/config/broken_conf_invalid_cidr_value.ini b/src/tests/config/broken_conf_invalid_cidr_value.ini new file mode 100644 index 0000000..733e889 --- /dev/null +++ b/src/tests/config/broken_conf_invalid_cidr_value.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr(" diff --git a/src/tests/config/broken_conf_invalid_type.ini b/src/tests/config/broken_conf_invalid_type.ini new file mode 100644 index 0000000..b2cd8cd --- /dev/null +++ b/src/tests/config/broken_conf_invalid_type.ini @@ -0,0 +1 @@ +sp.disable_functions.function("strpos").ret_type("totally_wrong"_type") diff --git a/src/tests/config/broken_conf_line_empty_string.ini b/src/tests/config/broken_conf_line_empty_string.ini new file mode 100644 index 0000000..74d0e5a --- /dev/null +++ b/src/tests/config/broken_conf_line_empty_string.ini @@ -0,0 +1 @@ +sp.cookie_encryption.mask_ipv4(123).cookie( diff --git a/src/tests/config/broken_conf_line_no_closing.ini b/src/tests/config/broken_conf_line_no_closing.ini new file mode 100644 index 0000000..bcac291 --- /dev/null +++ b/src/tests/config/broken_conf_line_no_closing.ini @@ -0,0 +1 @@ +sp.cookie_encryption.mask_ipv4(123).cookie("123" diff --git a/src/tests/config/broken_conf_line_too_long.ini b/src/tests/config/broken_conf_line_too_long.ini new file mode 100644 index 0000000..ed057a5 --- /dev/null +++ b/src/tests/config/broken_conf_line_too_long.ini @@ -0,0 +1 @@ +sp.cookie_encryption.cookie("super_cookie").mask_ipv4(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111); diff --git a/src/tests/config/broken_conf_lots_of_quotes.ini b/src/tests/config/broken_conf_lots_of_quotes.ini new file mode 100644 index 0000000..dfd48e7 --- /dev/null +++ b/src/tests/config/broken_conf_lots_of_quotes.ini @@ -0,0 +1 @@ +sp.cookie_encryption.mask_ipv4(123).cookie("this\"is a weird\"\"\"cookie\"name""); diff --git a/src/tests/config/broken_conf_mutually_exclusive.ini b/src/tests/config/broken_conf_mutually_exclusive.ini new file mode 100644 index 0000000..af1d505 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param("id").value("42").value_r("^id$").drop(); diff --git a/src/tests/config/broken_conf_mutually_exclusive2.ini b/src/tests/config/broken_conf_mutually_exclusive2.ini new file mode 100644 index 0000000..29b21d4 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive2.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").function_r("system").param("id").value("42").drop(); diff --git a/src/tests/config/broken_conf_mutually_exclusive3.ini b/src/tests/config/broken_conf_mutually_exclusive3.ini new file mode 100644 index 0000000..556de08 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive3.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param("id").value("42").filename_r("^id$").filename("pouet.txt").drop(); diff --git a/src/tests/config/broken_conf_mutually_exclusive4.ini b/src/tests/config/broken_conf_mutually_exclusive4.ini new file mode 100644 index 0000000..d212ad4 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive4.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param("id").value("42").param_r("^id$").drop(); diff --git a/src/tests/config/broken_conf_mutually_exclusive5.ini b/src/tests/config/broken_conf_mutually_exclusive5.ini new file mode 100644 index 0000000..5b64079 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive5.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").ret("0").drop().ret_r("^0$"); diff --git a/src/tests/config/broken_conf_mutually_exclusive6.ini b/src/tests/config/broken_conf_mutually_exclusive6.ini new file mode 100644 index 0000000..d08ee58 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive6.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param("id").value("42").ret_r("^0$").drop(); diff --git a/src/tests/config/broken_conf_mutually_exclusive7.ini b/src/tests/config/broken_conf_mutually_exclusive7.ini new file mode 100644 index 0000000..645c26c --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive7.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").ret("0").drop().allow(); diff --git a/src/tests/config/broken_conf_mutually_exclusive8.ini b/src/tests/config/broken_conf_mutually_exclusive8.ini new file mode 100644 index 0000000..b08ef57 --- /dev/null +++ b/src/tests/config/broken_conf_mutually_exclusive8.ini @@ -0,0 +1 @@ +sp.disable_functions.ret("0").drop(); diff --git a/src/tests/config/broken_conf_no_closing_misc.ini b/src/tests/config/broken_conf_no_closing_misc.ini new file mode 100644 index 0000000..2cb79a8 --- /dev/null +++ b/src/tests/config/broken_conf_no_closing_misc.ini @@ -0,0 +1 @@ +sp.cookie_encryption.cookie("123").mask_ipv4(123 diff --git a/src/tests/config/broken_conf_to_few_args.ini b/src/tests/config/broken_conf_to_few_args.ini new file mode 100644 index 0000000..89e19be --- /dev/null +++ b/src/tests/config/broken_conf_to_few_args.ini @@ -0,0 +1 @@ +sp.harden_random.enable(); diff --git a/src/tests/config/broken_conf_weird_keyword.ini b/src/tests/config/broken_conf_weird_keyword.ini new file mode 100644 index 0000000..bf5e7f5 --- /dev/null +++ b/src/tests/config/broken_conf_weird_keyword.ini @@ -0,0 +1 @@ +sp.harden_random.enable().not_a_valid_keyword("test"); diff --git a/src/tests/config/broken_conf_wrong_quotes.ini b/src/tests/config/broken_conf_wrong_quotes.ini new file mode 100644 index 0000000..c8cc949 --- /dev/null +++ b/src/tests/config/broken_conf_wrong_quotes.ini @@ -0,0 +1 @@ +sp.cookie_encryption.mask_ipv4(123).cookie("\) diff --git a/src/tests/config/broken_conf_wrong_type.ini b/src/tests/config/broken_conf_wrong_type.ini new file mode 100644 index 0000000..6ecca6a --- /dev/null +++ b/src/tests/config/broken_conf_wrong_type.ini @@ -0,0 +1,5 @@ +sp.disable_functions.function("strpos").ret_type("undef").drop().alias("Return value is undef"); +sp.disable_functions.function("strpos").ret_type("null").drop().alias("Return value is null"); +sp.disable_functions.function("strpos").ret_type("object").drop().alias("Return value is object"); +sp.disable_functions.function("strpos").ret_type("reference").drop().alias("Return value is reference"); +sp.disable_functions.function("strpos").ret_type("totally_wrong_type").drop().alias("Return value is FALSE"); diff --git a/src/tests/config/broken_config_regexp.ini b/src/tests/config/broken_config_regexp.ini new file mode 100644 index 0000000..efad83e --- /dev/null +++ b/src/tests/config/broken_config_regexp.ini @@ -0,0 +1 @@ +sp.disable_functions.function_r("^system$").filename_r("*.").drop(); diff --git a/src/tests/config/broken_regexp.ini b/src/tests/config/broken_regexp.ini new file mode 100644 index 0000000..8e1f69a --- /dev/null +++ b/src/tests/config/broken_regexp.ini @@ -0,0 +1 @@ +sp.disable_functions.function("AwesomeClass::method3").param("a").drop().value_r("^$["); diff --git a/src/tests/config/config_disable_writable.ini b/src/tests/config/config_disable_writable.ini new file mode 100644 index 0000000..9f90601 --- /dev/null +++ b/src/tests/config/config_disable_writable.ini @@ -0,0 +1 @@ + sp.readonly_exec.enable(); diff --git a/src/tests/config/config_disable_writable_disabled.ini b/src/tests/config/config_disable_writable_disabled.ini new file mode 100644 index 0000000..6a33437 --- /dev/null +++ b/src/tests/config/config_disable_writable_disabled.ini @@ -0,0 +1 @@ + sp.readonly_exec.disable(); diff --git a/src/tests/config/config_disable_writable_simulation.ini b/src/tests/config/config_disable_writable_simulation.ini new file mode 100644 index 0000000..52a43ba --- /dev/null +++ b/src/tests/config/config_disable_writable_simulation.ini @@ -0,0 +1 @@ + sp.readonly_exec.enable().simulation(); diff --git a/src/tests/config/config_disabled_functions_filename_r.ini b/src/tests/config/config_disabled_functions_filename_r.ini new file mode 100644 index 0000000..b92f136 --- /dev/null +++ b/src/tests/config/config_disabled_functions_filename_r.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function_r("^system$").filename_r("\\.txt$").drop(); +sp.disable_functions.function_r("^shell_exec$").filename_r("\\.php$").drop(); diff --git a/src/tests/config/config_disabled_functions_method.ini b/src/tests/config/config_disabled_functions_method.ini new file mode 100644 index 0000000..4d088d2 --- /dev/null +++ b/src/tests/config/config_disabled_functions_method.ini @@ -0,0 +1,3 @@ +sp.disable_functions.function("AwesomeClass::method1").drop(); +sp.disable_functions.function("method2").drop(); +sp.disable_functions.function("AwesomeClass::method3").param("a").value("pouet").drop(); diff --git a/src/tests/config/config_disabled_functions_name_r.ini b/src/tests/config/config_disabled_functions_name_r.ini new file mode 100644 index 0000000..3f7178e --- /dev/null +++ b/src/tests/config/config_disabled_functions_name_r.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function_r("^not_system$").ret("42").drop(); +sp.disable_functions.function_r("^system$").ret("1337").drop(); diff --git a/src/tests/config/config_disabled_functions_name_type.ini b/src/tests/config/config_disabled_functions_name_type.ini new file mode 100644 index 0000000..2b433df --- /dev/null +++ b/src/tests/config/config_disabled_functions_name_type.ini @@ -0,0 +1 @@ +sp.disable_functions.function_r("^strcmp$").param("str1").param_type("array").drop(); diff --git a/src/tests/config/config_disabled_functions_namespace.ini b/src/tests/config/config_disabled_functions_namespace.ini new file mode 100644 index 0000000..d09b81b --- /dev/null +++ b/src/tests/config/config_disabled_functions_namespace.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("strcmp").drop(); +sp.disable_functions.function("my_super_namespace::my_function").drop(); diff --git a/src/tests/config/config_disabled_functions_nul_byte.ini b/src/tests/config/config_disabled_functions_nul_byte.ini new file mode 100644 index 0000000..7994583 --- /dev/null +++ b/src/tests/config/config_disabled_functions_nul_byte.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param("command").value_r("id").drop(); \ No newline at end of file diff --git a/src/tests/config/config_disabled_functions_param.ini b/src/tests/config/config_disabled_functions_param.ini new file mode 100644 index 0000000..7363781 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param.ini @@ -0,0 +1,6 @@ +sp.disable_functions.function("system").param("command").value_r("^id$").alias("1").drop(); +sp.disable_functions.function("array_sum").param("array").value_r("^8$").alias("2").drop(); +sp.disable_functions.function("shell_exec").param("cmd").value("id").alias("3").drop(); +sp.disable_functions.function("shell_exec").param("cmd").value("bla").alias("4").drop(); +sp.disable_functions.function("strcmp").param("str1").value("bla").alias("5").drop().simulation(); +sp.disable_functions.function("strncmp").param("str1").value("bla").drop().simulation(); diff --git a/src/tests/config/config_disabled_functions_param_alias.ini b/src/tests/config/config_disabled_functions_param_alias.ini new file mode 100644 index 0000000..f8d9f43 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_alias.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("system").alias("1").drop(); +sp.disable_functions.function("shell_exec").alias("2").drop().simulation(); diff --git a/src/tests/config/config_disabled_functions_param_allow.ini b/src/tests/config/config_disabled_functions_param_allow.ini new file mode 100644 index 0000000..e349b38 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_allow.ini @@ -0,0 +1,3 @@ +sp.disable_functions.function("system").param("command").value("echo win").filename("test.php").drop(); +sp.disable_functions.function("system").param("command").value("echo win").allow(); +sp.disable_functions.function("system").drop(); diff --git a/src/tests/config/config_disabled_functions_param_array.ini b/src/tests/config/config_disabled_functions_param_array.ini new file mode 100644 index 0000000..7b71692 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_array.ini @@ -0,0 +1,4 @@ +sp.disable_functions.function("foo").param("arr").value("abcd").alias("1").drop(); +sp.disable_functions.function("foo").param("arr[bla]").value("abcdef").alias("2").drop(); +sp.disable_functions.function("foo").param("arr[test]").alias("3").drop(); +sp.disable_functions.function("foo").param("arr[test2][foo][lol]").value("aaa").alias("4").drop(); diff --git a/src/tests/config/config_disabled_functions_param_int.ini b/src/tests/config/config_disabled_functions_param_int.ini new file mode 100644 index 0000000..2552f0a --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_int.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("foobar").param("id").value("42").drop(); +sp.disable_functions.function("foobar").param("id").value_r("^1337").drop(); diff --git a/src/tests/config/config_disabled_functions_param_r.ini b/src/tests/config/config_disabled_functions_param_r.ini new file mode 100644 index 0000000..d9f6692 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_r.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").param_r("^command$").value("id").drop(); diff --git a/src/tests/config/config_disabled_functions_param_runtime.ini b/src/tests/config/config_disabled_functions_param_runtime.ini new file mode 100644 index 0000000..641bd0a --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_runtime.ini @@ -0,0 +1 @@ +sp.disable_functions.function("test").param("param").value_r("1337").drop(); diff --git a/src/tests/config/config_disabled_functions_param_str_representation.ini b/src/tests/config/config_disabled_functions_param_str_representation.ini new file mode 100644 index 0000000..7171a30 --- /dev/null +++ b/src/tests/config/config_disabled_functions_param_str_representation.ini @@ -0,0 +1 @@ +sp.disable_functions.function("var_export").param("var").value("bla").drop(); diff --git a/src/tests/config/config_disabled_functions_require.ini b/src/tests/config/config_disabled_functions_require.ini new file mode 100644 index 0000000..474fada --- /dev/null +++ b/src/tests/config/config_disabled_functions_require.ini @@ -0,0 +1 @@ +sp.disable_functions.function("require").param("").value_r("meh$").drop(); diff --git a/src/tests/config/config_disabled_functions_ret_allow.ini b/src/tests/config/config_disabled_functions_ret_allow.ini new file mode 100644 index 0000000..1884227 --- /dev/null +++ b/src/tests/config/config_disabled_functions_ret_allow.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("strpos").hash("70b33f3eaf585b245640bb2c92445d0040b2bcb31395aa25dede9f2df4dbcbe8").allow(); +sp.disable_functions.function("strpos").drop(); diff --git a/src/tests/config/config_disabled_functions_ret_allow_value.ini b/src/tests/config/config_disabled_functions_ret_allow_value.ini new file mode 100644 index 0000000..e179819 --- /dev/null +++ b/src/tests/config/config_disabled_functions_ret_allow_value.ini @@ -0,0 +1 @@ +sp.disable_functions.function("strpos").ret("0").allow(); diff --git a/src/tests/config/config_disabled_functions_ret_right_hash.ini b/src/tests/config/config_disabled_functions_ret_right_hash.ini new file mode 100644 index 0000000..6f49177 --- /dev/null +++ b/src/tests/config/config_disabled_functions_ret_right_hash.ini @@ -0,0 +1,4 @@ +sp.disable_functions.function("system").ret("1").drop(); +sp.disable_functions.function("system").ret("1337").hash("123456789597a81a2b862cdb49920e2cba2e5979a3fc374c58c803e8f5c99a10").drop(); +sp.disable_functions.function("system").ret("1338").hash("522a976fa597a81a2b862cdb49920e2cba2e5979a3fc374c58c803e8f5c99a10").drop(); +sp.disable_functions.function("system").ret("1337").hash("522a976fa597a81a2b862cdb49920e2cba2e5979a3fc374c58c803e8f5c99a10").drop(); diff --git a/src/tests/config/config_disabled_functions_ret_simulation.ini b/src/tests/config/config_disabled_functions_ret_simulation.ini new file mode 100644 index 0000000..ee46c4b --- /dev/null +++ b/src/tests/config/config_disabled_functions_ret_simulation.ini @@ -0,0 +1,3 @@ +sp.disable_functions.function("strpos").ret("0").simulation().drop(); +sp.disable_functions.function("stripos").ret("0").simulation().drop().alias("1"); +sp.disable_functions.function("strcmp").ret("0").drop(); diff --git a/src/tests/config/config_disabled_functions_right_hash.ini b/src/tests/config/config_disabled_functions_right_hash.ini new file mode 100644 index 0000000..fab68fa --- /dev/null +++ b/src/tests/config/config_disabled_functions_right_hash.ini @@ -0,0 +1,3 @@ +sp.disable_functions.function("system").hash("1337c3ad8cf096272cd0e78768af3b11325f498de5c2c36f40adc43643af378a").allow(); +sp.disable_functions.function("system").hash("d259c3ad8cf096272cd0e78768af3b11325f498de5c2c36f40adc43643af378a").allow(); +sp.disable_functions.function("system").drop(); \ No newline at end of file diff --git a/src/tests/config/config_disabled_user_functions.ini b/src/tests/config/config_disabled_user_functions.ini new file mode 100644 index 0000000..15cbccc --- /dev/null +++ b/src/tests/config/config_disabled_user_functions.ini @@ -0,0 +1 @@ +sp.disable_functions.function("my_super_function").drop(); diff --git a/src/tests/config/config_encrypted_cookies.ini b/src/tests/config/config_encrypted_cookies.ini new file mode 100644 index 0000000..710e863 --- /dev/null +++ b/src/tests/config/config_encrypted_cookies.ini @@ -0,0 +1,3 @@ +sp.global.secret_key("abcdef"); +sp.cookie_encryption.cookie("super_cookie").mask_ipv4(8).mask_ipv6(2); +sp.auto_cookie_secure.enable(); diff --git a/src/tests/config/config_noncore_function_hooking.ini b/src/tests/config/config_noncore_function_hooking.ini new file mode 100644 index 0000000..88f2acf --- /dev/null +++ b/src/tests/config/config_noncore_function_hooking.ini @@ -0,0 +1 @@ +sp.disable_functions.function("custom_fun").drop(); diff --git a/src/tests/config/config_rand_harden_disabled.ini b/src/tests/config/config_rand_harden_disabled.ini new file mode 100644 index 0000000..b9cd227 --- /dev/null +++ b/src/tests/config/config_rand_harden_disabled.ini @@ -0,0 +1 @@ +sp.harden_random.disable(); diff --git a/src/tests/config/config_serialize.ini b/src/tests/config/config_serialize.ini new file mode 100644 index 0000000..f2c1699 --- /dev/null +++ b/src/tests/config/config_serialize.ini @@ -0,0 +1,2 @@ +sp.global.secret_key("abcdef"); +sp.unserialize_hmac.enable(); \ No newline at end of file diff --git a/src/tests/config/config_serialize_sim.ini b/src/tests/config/config_serialize_sim.ini new file mode 100644 index 0000000..7f015e0 --- /dev/null +++ b/src/tests/config/config_serialize_sim.ini @@ -0,0 +1,2 @@ +sp.global.secret_key("abcdef"); +sp.unserialize_hmac.enable().simulation(); diff --git a/src/tests/config/disable_xxe.ini b/src/tests/config/disable_xxe.ini new file mode 100644 index 0000000..bc9d1f2 --- /dev/null +++ b/src/tests/config/disable_xxe.ini @@ -0,0 +1 @@ +sp.disable_xxe.enable(); diff --git a/src/tests/config/disable_xxe_disable.ini b/src/tests/config/disable_xxe_disable.ini new file mode 100644 index 0000000..bb1e432 --- /dev/null +++ b/src/tests/config/disable_xxe_disable.ini @@ -0,0 +1 @@ +sp.disable_xxe.disable(); diff --git a/src/tests/config/disabled_function_local_var.ini b/src/tests/config/disabled_function_local_var.ini new file mode 100644 index 0000000..64d98dc --- /dev/null +++ b/src/tests/config/disabled_function_local_var.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("phpinfo").var("b").value("1337").drop(); +sp.disable_functions.function("strlen").var("a").value("1337").drop(); diff --git a/src/tests/config/disabled_function_super_global_var.ini b/src/tests/config/disabled_function_super_global_var.ini new file mode 100644 index 0000000..e0c87e1 --- /dev/null +++ b/src/tests/config/disabled_function_super_global_var.ini @@ -0,0 +1 @@ +sp.disable_functions.function("strlen").var("_GET[bla]").value("test2").drop(); diff --git a/src/tests/config/disabled_functions.ini b/src/tests/config/disabled_functions.ini new file mode 100644 index 0000000..cf54164 --- /dev/null +++ b/src/tests/config/disabled_functions.ini @@ -0,0 +1,7 @@ +sp.disable_functions.function("system").drop(); +sp.disable_functions.function("vprintf").hash("123456789").drop(); +sp.disable_functions.function("printf").disable().drop(); +sp.disable_functions.function("printf").simulation().drop(); +sp.disable_functions.function("print").disable().drop(); # this is a comment +sp.disable_functions.function_r("^var_dump$").drop(); +sp.disable_functions.function("sprintf").filename("wrong file name").drop(); diff --git a/src/tests/config/disabled_functions_cidr.ini b/src/tests/config/disabled_functions_cidr.ini new file mode 100644 index 0000000..9e527ba --- /dev/null +++ b/src/tests/config/disabled_functions_cidr.ini @@ -0,0 +1,4 @@ +sp.disable_functions.function("system").drop().cidr("127.0.0.1/8"); +sp.disable_functions.function("printf").drop().cidr("10.0.0.1/8"); +sp.disable_functions.function("strpos").drop().cidr("2001:0db8:0000:0000:0000:ff00:0042:8329/24"); +sp.disable_functions.function("printf").drop().cidr("2002:0db8:0000:0000:0000:ff00:0042:8329/24"); diff --git a/src/tests/config/disabled_functions_mb.ini b/src/tests/config/disabled_functions_mb.ini new file mode 100644 index 0000000..b6afd97 --- /dev/null +++ b/src/tests/config/disabled_functions_mb.ini @@ -0,0 +1,2 @@ +sp.disable_functions.function("strlen").drop(); +sp.disable_functions.function("mb_strlen").drop(); diff --git a/src/tests/config/disabled_functions_ret.ini b/src/tests/config/disabled_functions_ret.ini new file mode 100644 index 0000000..2b769a9 --- /dev/null +++ b/src/tests/config/disabled_functions_ret.ini @@ -0,0 +1,5 @@ +sp.disable_functions.function("testFunction").ret("0").drop().disable(); +sp.disable_functions.function("strpos").ret("0").drop().filename_r(".*\\.php"); +sp.disable_functions.function_r("str[ia]pos").ret_r("^[^a-z]+$").drop(); +sp.disable_functions.function_r("stripos").ret_r("^[^a-z]+").drop(); +sp.disable_functions.function("Bob::a").ret("0").drop(); diff --git a/src/tests/config/disabled_functions_ret_type.ini b/src/tests/config/disabled_functions_ret_type.ini new file mode 100644 index 0000000..56c8e57 --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type.ini @@ -0,0 +1 @@ +sp.disable_functions.function("strpos").ret_type("false").drop().alias("Return value is FALSE"); diff --git a/src/tests/config/disabled_functions_ret_type_double.ini b/src/tests/config/disabled_functions_ret_type_double.ini new file mode 100644 index 0000000..a1239d8 --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type_double.ini @@ -0,0 +1 @@ +sp.disable_functions.function("cos").ret_type("double").drop().alias("Return value is a double"); diff --git a/src/tests/config/disabled_functions_ret_type_long.ini b/src/tests/config/disabled_functions_ret_type_long.ini new file mode 100644 index 0000000..6cccd4d --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type_long.ini @@ -0,0 +1 @@ +sp.disable_functions.function("strlen").ret_type("long").drop().alias("Return value is a long"); diff --git a/src/tests/config/disabled_functions_ret_type_resource.ini b/src/tests/config/disabled_functions_ret_type_resource.ini new file mode 100644 index 0000000..e81cf2c --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type_resource.ini @@ -0,0 +1 @@ +sp.disable_functions.function("fopen").ret_type("resource").drop().alias("Return value is a resource"); diff --git a/src/tests/config/disabled_functions_ret_type_str.ini b/src/tests/config/disabled_functions_ret_type_str.ini new file mode 100644 index 0000000..b3ff050 --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type_str.ini @@ -0,0 +1 @@ +sp.disable_functions.function("substr").ret_type("string").drop().alias("Return value is a string"); diff --git a/src/tests/config/disabled_functions_ret_type_true.ini b/src/tests/config/disabled_functions_ret_type_true.ini new file mode 100644 index 0000000..02a37dd --- /dev/null +++ b/src/tests/config/disabled_functions_ret_type_true.ini @@ -0,0 +1 @@ +sp.disable_functions.function("is_numeric").ret_type("true").drop().alias("Return value is a true"); diff --git a/src/tests/config/disabled_functions_retval.ini b/src/tests/config/disabled_functions_retval.ini new file mode 100644 index 0000000..20422e4 --- /dev/null +++ b/src/tests/config/disabled_functions_retval.ini @@ -0,0 +1 @@ +sp.disable_functions.function("str_repeat").ret("fufufu").drop(); diff --git a/src/tests/config/disabled_functions_retval_rx.ini b/src/tests/config/disabled_functions_retval_rx.ini new file mode 100644 index 0000000..ca2bce3 --- /dev/null +++ b/src/tests/config/disabled_functions_retval_rx.ini @@ -0,0 +1 @@ +sp.disable_functions.function("str_repeat").ret_r("(fu){3}").drop(); diff --git a/src/tests/config/disabled_functions_zero_cidr.ini b/src/tests/config/disabled_functions_zero_cidr.ini new file mode 100644 index 0000000..bba1af9 --- /dev/null +++ b/src/tests/config/disabled_functions_zero_cidr.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().cidr("0.0.0.0/0"); diff --git a/src/tests/config/dump_request.ini b/src/tests/config/dump_request.ini new file mode 100644 index 0000000..8c595f9 --- /dev/null +++ b/src/tests/config/dump_request.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().dump("./dump_results/"); diff --git a/src/tests/config/dump_request_invalid_folder.ini b/src/tests/config/dump_request_invalid_folder.ini new file mode 100644 index 0000000..b5ae154 --- /dev/null +++ b/src/tests/config/dump_request_invalid_folder.ini @@ -0,0 +1 @@ +sp.disable_functions.function("system").drop().dump("/root/NON_EXISTENT/FOLDER/PLEASE/"); diff --git a/src/tests/config/empty.ini b/src/tests/config/empty.ini new file mode 100644 index 0000000..e69de29 diff --git a/src/tests/config/empty_conf.ini b/src/tests/config/empty_conf.ini new file mode 100644 index 0000000..e69de29 diff --git a/src/tests/config/encryption_key_only.ini b/src/tests/config/encryption_key_only.ini new file mode 100644 index 0000000..7de4438 --- /dev/null +++ b/src/tests/config/encryption_key_only.ini @@ -0,0 +1 @@ +sp.global.secret_key("abcdef"); diff --git a/src/tests/config/global_strict.ini b/src/tests/config/global_strict.ini new file mode 100644 index 0000000..2bc2bdc --- /dev/null +++ b/src/tests/config/global_strict.ini @@ -0,0 +1 @@ + sp.global_strict.enable(); diff --git a/src/tests/config/global_strict_disabled.ini b/src/tests/config/global_strict_disabled.ini new file mode 100644 index 0000000..2e68471 --- /dev/null +++ b/src/tests/config/global_strict_disabled.ini @@ -0,0 +1 @@ +sp.global_strict.disable(); diff --git a/src/tests/config/harden_rand.ini b/src/tests/config/harden_rand.ini new file mode 100644 index 0000000..89e19be --- /dev/null +++ b/src/tests/config/harden_rand.ini @@ -0,0 +1 @@ +sp.harden_random.enable(); diff --git a/src/tests/config/upload_validation.ini b/src/tests/config/upload_validation.ini new file mode 100644 index 0000000..0646134 --- /dev/null +++ b/src/tests/config/upload_validation.ini @@ -0,0 +1,2 @@ +sp.upload_validation.script("tests/upload_ko.sh"); +sp.upload_validation.enable(); diff --git a/src/tests/config/upload_validation_invalid.ini b/src/tests/config/upload_validation_invalid.ini new file mode 100644 index 0000000..7a638a1 --- /dev/null +++ b/src/tests/config/upload_validation_invalid.ini @@ -0,0 +1 @@ +sp.upload_validation.script("./tests/data/upload_invalid.sh").enable(); diff --git a/src/tests/config/upload_validation_ko.ini b/src/tests/config/upload_validation_ko.ini new file mode 100644 index 0000000..b15977f --- /dev/null +++ b/src/tests/config/upload_validation_ko.ini @@ -0,0 +1 @@ +sp.upload_validation.script("./tests/data/upload_ko.sh").enable(); diff --git a/src/tests/config/upload_validation_ko_simulation.ini b/src/tests/config/upload_validation_ko_simulation.ini new file mode 100644 index 0000000..da56439 --- /dev/null +++ b/src/tests/config/upload_validation_ko_simulation.ini @@ -0,0 +1 @@ +sp.upload_validation.script("./tests/data/upload_ko.sh").enable().simulation(); diff --git a/src/tests/config/upload_validation_no_exist.ini b/src/tests/config/upload_validation_no_exist.ini new file mode 100644 index 0000000..24f81a5 --- /dev/null +++ b/src/tests/config/upload_validation_no_exist.ini @@ -0,0 +1 @@ +sp.upload_validation.script("fufufufufu").enable(); diff --git a/src/tests/config/upload_validation_non_exec.ini b/src/tests/config/upload_validation_non_exec.ini new file mode 100644 index 0000000..bdf0a57 --- /dev/null +++ b/src/tests/config/upload_validation_non_exec.ini @@ -0,0 +1 @@ +sp.upload_validation.script("tests/data/upload_no_exec.sh").enable(); diff --git a/src/tests/config/upload_validation_ok.ini b/src/tests/config/upload_validation_ok.ini new file mode 100644 index 0000000..5df8db8 --- /dev/null +++ b/src/tests/config/upload_validation_ok.ini @@ -0,0 +1 @@ +sp.upload_validation.script("./tests/data/upload_ok.sh").enable(); diff --git a/src/tests/data/upload_invalid.sh b/src/tests/data/upload_invalid.sh new file mode 100755 index 0000000..e5eb0c6 --- /dev/null +++ b/src/tests/data/upload_invalid.sh @@ -0,0 +1 @@ +lulz diff --git a/src/tests/data/upload_ko.sh b/src/tests/data/upload_ko.sh new file mode 100755 index 0000000..c4cacdc --- /dev/null +++ b/src/tests/data/upload_ko.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exit 1; diff --git a/src/tests/data/upload_no_exec.sh b/src/tests/data/upload_no_exec.sh new file mode 100644 index 0000000..6b9cafa --- /dev/null +++ b/src/tests/data/upload_no_exec.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0; diff --git a/src/tests/data/upload_ok.sh b/src/tests/data/upload_ok.sh new file mode 100755 index 0000000..6b9cafa --- /dev/null +++ b/src/tests/data/upload_ok.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0; diff --git a/src/tests/deny_writable_execution.phpt b/src/tests/deny_writable_execution.phpt new file mode 100644 index 0000000..2870561 --- /dev/null +++ b/src/tests/deny_writable_execution.phpt @@ -0,0 +1,44 @@ +--TEST-- +Readonly execution attempt +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disable_writable.ini +--FILE-- + +--EXPECTF-- +Code execution within a non-writable file. +[snuffleupagus][0.0.0.0][readonly_exec][drop] Attempted execution of a writable file (%a/writable_file.txt). +--CLEAN-- + \ No newline at end of file diff --git a/src/tests/deny_writable_execution_disabled.phpt b/src/tests/deny_writable_execution_disabled.phpt new file mode 100644 index 0000000..6d1233b --- /dev/null +++ b/src/tests/deny_writable_execution_disabled.phpt @@ -0,0 +1,32 @@ +--TEST-- +Readonly execution attempt +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disable_writable_disabled.ini +--FILE-- + +--EXPECT-- +Code execution within a writable file. +Code execution within a non-writable file. +--CLEAN-- + \ No newline at end of file diff --git a/src/tests/deny_writable_execution_simulation.phpt b/src/tests/deny_writable_execution_simulation.phpt new file mode 100644 index 0000000..3278be8 --- /dev/null +++ b/src/tests/deny_writable_execution_simulation.phpt @@ -0,0 +1,45 @@ +--TEST-- +Readonly execution attempt (simulation mode) +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disable_writable_simulation.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][readonly_exec][notice] Attempted execution of a writable file (%a/writable_file.txt). +Code execution within a writable file. +Code execution within a non-writable file. +--CLEAN-- + \ No newline at end of file diff --git a/src/tests/disable_xxe_dom.phpt b/src/tests/disable_xxe_dom.phpt new file mode 100644 index 0000000..47f3db3 --- /dev/null +++ b/src/tests/disable_xxe_dom.phpt @@ -0,0 +1,71 @@ +--TEST-- +Disable XXE +--SKIPIF-- + +--INI-- +extension=`php-config --extension-dir`/dom.so +sp.configuration_file={PWD}/config/disable_xxe.ini +--FILE-- + + +]> +&foo; +EOD; + +file_put_contents('content.xml', $xml); + +libxml_disable_entity_loader(true); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("libxml_disable_entity to true: %s\n", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +libxml_disable_entity_loader(false); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("libxml_disable_entity to false: %s\n", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +$xml = "foo"; +file_put_contents('content.xml', $xml); + +libxml_disable_entity_loader(false); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("without xxe: %s", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +?> +--EXPECTF-- +Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file://%a/content.txt" in %a/disable_xxe_dom.php on line %d + +Warning: DOMDocument::loadXML(): Failure to process entity foo in Entity, line: %d in %a/disable_xxe_dom.php on line %d + +Warning: DOMDocument::loadXML(): Entity 'foo' not defined in Entity, line: %d in %a/disable_xxe_dom.php on line %d + +Notice: Trying to get property of non-object in %a/disable_xxe_dom.php on line %d +libxml_disable_entity to true: + +Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file://%a/content.txt" in %a/disable_xxe_dom.php on line %d + +Warning: DOMDocument::loadXML(): Failure to process entity foo in Entity, line: %d in %a/disable_xxe_dom.php on line %d + +Warning: DOMDocument::loadXML(): Entity 'foo' not defined in Entity, line: %d in %a/disable_xxe_dom.php on line %d + +Notice: Trying to get property of non-object in %a/disable_xxe_dom.php on line %d +libxml_disable_entity to false: +without xxe: foo +--CLEAN-- + diff --git a/src/tests/disable_xxe_dom_disabled.phpt b/src/tests/disable_xxe_dom_disabled.phpt new file mode 100644 index 0000000..b89b595 --- /dev/null +++ b/src/tests/disable_xxe_dom_disabled.phpt @@ -0,0 +1,56 @@ +--TEST-- +Disable XXE +--SKIPIF-- + +--INI-- +extension=`php-config --extension-dir`/dom.so +sp.configuration_file={PWD}/config/disable_xxe_disable.ini +--FILE-- +WARNING, external entity loaded!'; +file_put_contents($dir . '/content.txt', $content); + +$xml = << + +]> +&foo; +EOD; + +file_put_contents($dir . '/content.xml', $xml); + +libxml_disable_entity_loader(true); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("libxml_disable_entity to true: %s\n", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +libxml_disable_entity_loader(false); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("libxml_disable_entity to false: %s\n", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +$xml = "foo"; +file_put_contents('content.xml', $xml); + +libxml_disable_entity_loader(false); +$dom = new DOMDocument('1.0'); +$dom->loadXML($xml, LIBXML_DTDATTR|LIBXML_DTDLOAD|LIBXML_NOENT); +printf("without xxe: %s", $dom->getElementsByTagName('testing')->item(0)->nodeValue); + +?> +--EXPECTF-- +libxml_disable_entity to true: WARNING, external entity loaded! +libxml_disable_entity to false: WARNING, external entity loaded! +without xxe: foo +--CLEAN-- + diff --git a/src/tests/disable_xxe_simplexml.phpt b/src/tests/disable_xxe_simplexml.phpt new file mode 100644 index 0000000..54404a3 --- /dev/null +++ b/src/tests/disable_xxe_simplexml.phpt @@ -0,0 +1,52 @@ +--TEST-- +Disable XXE +--SKIPIF-- + +--INI-- +extension=`php-config --extension-dir`/simplexml.so +sp.configuration_file={PWD}/config/disable_xxe.ini +--FILE-- + + +]> +&foo; +EOD; + +file_put_contents('content.xml', $xml); + +libxml_disable_entity_loader(true); +$doc = new SimpleXMLElement($xml); +printf("libxml_disable_entity to true: %s\n", $doc->testing); + +libxml_disable_entity_loader(false); +$doc = new SimpleXMLElement($xml); +printf("libxml_disable_entity to false: %s\n", $doc->testing); + +$xml = "foo"; +file_put_contents('content.xml', $xml); + +$doc = new SimpleXMLElement($xml); +printf("without xxe: %s", $doc->testing); + +?> +--EXPECT-- +libxml_disable_entity to true: +libxml_disable_entity to false: +without xxe: foo +--CLEAN-- + diff --git a/src/tests/disable_xxe_simplexml_oop.phpt b/src/tests/disable_xxe_simplexml_oop.phpt new file mode 100644 index 0000000..62762eb --- /dev/null +++ b/src/tests/disable_xxe_simplexml_oop.phpt @@ -0,0 +1,52 @@ +--TEST-- +Disable XXE +--SKIPIF-- + +--INI-- +extension=`php-config --extension-dir`/simplexml.so +sp.configuration_file={PWD}/config/disable_xxe.ini +--FILE-- + + +]> +&foo; +EOD; + +file_put_contents('content.xml', $xml); + +libxml_disable_entity_loader(true); +$doc = simplexml_load_string($xml); +printf("libxml_disable_entity to true: %s\n", $doc->testing); + +libxml_disable_entity_loader(false); +$doc = simplexml_load_string($xml); +printf("libxml_disable_entity to false: %s\n", $doc->testing); + +$xml = "foo"; +file_put_contents('content.xml', $xml); + +$doc = simplexml_load_string($xml); +printf("without xxe: %s", $doc->testing); + +?> +--EXPECT-- +libxml_disable_entity to true: +libxml_disable_entity to false: +without xxe: foo +--CLEAN-- + diff --git a/src/tests/disable_xxe_xml_parse.phpt b/src/tests/disable_xxe_xml_parse.phpt new file mode 100644 index 0000000..944bc38 --- /dev/null +++ b/src/tests/disable_xxe_xml_parse.phpt @@ -0,0 +1,104 @@ +--TEST-- +Disable XXE +--SKIPIF-- + +--INI-- +extension=`php-config --extension-dir`/xml.so +sp.configuration_file={PWD}/config/disable_xxe.ini +--FILE-- + + +]> +&foo; +EOD; + +file_put_contents('content.xml', $xml); + +function create_parser() { + $parser = xml_parser_create(); + xml_set_element_handler( + $parser, + function($parser, $name, array $attributes) { + var_dump($name); + echo "\n"; + var_dump($attributes); + }, + function($parser, $name) { + var_dump($name); + } + ); + + xml_set_character_data_handler( + $parser, + function ($parser, $text){ + echo 'text' . $text; + } + ); + + return $parser; +} + +libxml_disable_entity_loader(true); +$parser = create_parser(); +$doc = xml_parse($parser, $xml, true); +xml_parser_free($parser); + +libxml_disable_entity_loader(false); +$parser = create_parser(); +$doc = xml_parse($parser, $xml, true); +xml_parser_free($parser); + +$xml = "foo"; +file_put_contents('content.xml', $xml); +$parser = create_parser(); +$doc = xml_parse($parser, $xml, true); +xml_parser_free($parser); + +--EXPECT-- +string(4) "TEST" + +array(0) { +} +string(7) "TESTING" + +array(0) { +} +string(7) "TESTING" +string(4) "TEST" +string(4) "TEST" + +array(0) { +} +string(7) "TESTING" + +array(0) { +} +string(7) "TESTING" +string(4) "TEST" +string(4) "TEST" + +array(0) { +} +string(7) "TESTING" + +array(0) { +} +textfoostring(7) "TESTING" +string(4) "TEST" +--CLEAN-- + diff --git a/src/tests/disabled_function_local_var.phpt b/src/tests/disabled_function_local_var.phpt new file mode 100644 index 0000000..3142039 --- /dev/null +++ b/src/tests/disabled_function_local_var.phpt @@ -0,0 +1,24 @@ +--TEST-- +Disable functions - match on a local variable +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_function_local_var.ini +--FILE-- + +--EXPECTF-- +Value of a: 1338 +2 +Value of a: 1337 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_function_local_var.php:%d has been disabled. \ No newline at end of file diff --git a/src/tests/disabled_function_super_global_var.phpt b/src/tests/disabled_function_super_global_var.phpt new file mode 100644 index 0000000..d41897a --- /dev/null +++ b/src/tests/disabled_function_super_global_var.phpt @@ -0,0 +1,20 @@ +--TEST-- +Disable functions - match on a super global +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_function_super_global_var.ini +--GET-- +bla=test +--FILE-- + +--EXPECTF-- +4 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %s/tests/disabled_function_super_global_var.php:%d has been disabled. diff --git a/src/tests/disabled_functions.phpt b/src/tests/disabled_functions.phpt new file mode 100644 index 0000000..37da911 --- /dev/null +++ b/src/tests/disabled_functions.phpt @@ -0,0 +1,21 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions.php:%d has been disabled. +[snuffleupagus][0.0.0.0][disabled_function][notice] The call to the function 'printf' in %a/tests/disabled_functions.php:%d has been disabled. +printf in simulation mode +print in disabled mode +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'var_dump' in %a/tests/disabled_functions.php:%d has been disabled. +1 diff --git a/src/tests/disabled_functions_cidr.phpt b/src/tests/disabled_functions_cidr.phpt new file mode 100644 index 0000000..5b13107 --- /dev/null +++ b/src/tests/disabled_functions_cidr.phpt @@ -0,0 +1,18 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--ENV-- +return << +--EXPECTF-- +[snuffleupagus][127.0.0.1][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_cidr.php:2 has been disabled. +1337 diff --git a/src/tests/disabled_functions_cidr_6.phpt b/src/tests/disabled_functions_cidr_6.phpt new file mode 100644 index 0000000..f2c5f5a --- /dev/null +++ b/src/tests/disabled_functions_cidr_6.phpt @@ -0,0 +1,18 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--ENV-- +return << +--EXPECTF-- +[snuffleupagus][2001:0db8:0000:0000:0000:ff00:0042:8328][disabled_function][drop] The call to the function 'strpos' in %a/tests/disabled_functions_cidr_6.php:2 has been disabled. +1337 diff --git a/src/tests/disabled_functions_filename_r.phpt b/src/tests/disabled_functions_filename_r.phpt new file mode 100644 index 0000000..ed46802 --- /dev/null +++ b/src/tests/disabled_functions_filename_r.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions - filename regexp +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_filename_r.ini +--FILE-- + +--EXPECTF-- +42 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'shell_exec' in %a/tests/disabled_functions_filename_r.php:%d has been disabled. \ No newline at end of file diff --git a/src/tests/disabled_functions_mb.phpt b/src/tests/disabled_functions_mb.phpt new file mode 100644 index 0000000..7089063 --- /dev/null +++ b/src/tests/disabled_functions_mb.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_mb.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strlen' in %a/tests/disabled_functions_mb.php:2 has been disabled. diff --git a/src/tests/disabled_functions_method.phpt b/src/tests/disabled_functions_method.phpt new file mode 100644 index 0000000..33651b7 --- /dev/null +++ b/src/tests/disabled_functions_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_method.ini +--FILE-- +method1("pif"); +$c->method2("paf"); +$c->method3("pouet"); +?> +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'AwesomeClass::method1' in %a/tests/disabled_functions_method.php:4 has been disabled. +method2:paf +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'AwesomeClass::method3' in %a/tests/disabled_functions_method.php:10 has been disabled, because its argument 'a' content (pouet) matched a rule. diff --git a/src/tests/disabled_functions_name_r.phpt b/src/tests/disabled_functions_name_r.phpt new file mode 100644 index 0000000..0e29abb --- /dev/null +++ b/src/tests/disabled_functions_name_r.phpt @@ -0,0 +1,15 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_name_r.ini +--FILE-- + +--EXPECTF-- +42 +1337 +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_name_r.php:3, because the return value (1337) of the function 'system' matched a rule. diff --git a/src/tests/disabled_functions_name_type.phpt b/src/tests/disabled_functions_name_type.phpt new file mode 100644 index 0000000..c5b24d6 --- /dev/null +++ b/src/tests/disabled_functions_name_type.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_name_type.ini +--FILE-- + +--EXPECTF-- +0 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'strcmp' in %a/disabled_functions_name_type.php:%d has been disabled, because its argument 'str1' content (?) matched a rule. diff --git a/src/tests/disabled_functions_namespace.phpt b/src/tests/disabled_functions_namespace.phpt new file mode 100644 index 0000000..72c7d0b --- /dev/null +++ b/src/tests/disabled_functions_namespace.phpt @@ -0,0 +1,31 @@ +--TEST-- +Disable functions: namespaces support isn't implemented now +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_namespace.ini +--FILE-- + +--XFAIL-- +--EXPECTF-- +[snuffleupagus] The call to the function 'strcmp' in %a/tests/disabled_functions_namespace.php:%d has been disabled. diff --git a/src/tests/disabled_functions_noconf.phpt b/src/tests/disabled_functions_noconf.phpt new file mode 100644 index 0000000..cb13413 --- /dev/null +++ b/src/tests/disabled_functions_noconf.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/empty.ini +--FILE-- + +--EXPECT-- +1 diff --git a/src/tests/disabled_functions_nul_byte.phpt b/src/tests/disabled_functions_nul_byte.phpt new file mode 100644 index 0000000..95e87de --- /dev/null +++ b/src/tests/disabled_functions_nul_byte.phpt @@ -0,0 +1,15 @@ +--TEST-- +Disable functions with nul byte +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_nul_byte.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_nul_byte.php:2 has been disabled, because its argument 'command' content (0id) matched a rule. +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_nul_byte.php:3 has been disabled, because its argument 'command' content (id) matched a rule. \ No newline at end of file diff --git a/src/tests/disabled_functions_param.phpt b/src/tests/disabled_functions_param.phpt new file mode 100644 index 0000000..2309217 --- /dev/null +++ b/src/tests/disabled_functions_param.phpt @@ -0,0 +1,24 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/disabled_functions_param.php:2 has been disabled, because its argument 'command' content (id) matched the rule '1'. +win +int(15) +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'shell_exec' in %a/disabled_functions_param.php:5 has been disabled, because its argument 'cmd' content (id) matched the rule '3'. +42 +[snuffleupagus][0.0.0.0][disabled_function][notice] The call to the function 'strcmp' in %a/tests/disabled_functions_param.php:7 has been disabled, because its argument 'str1' content (bla) matched the rule '5'. +[snuffleupagus][0.0.0.0][disabled_function][notice] The call to the function 'strncmp' in %a/tests/disabled_functions_param.php:8 has been disabled, because its argument 'str1' content (bla) matched a rule. diff --git a/src/tests/disabled_functions_param_alias.phpt b/src/tests/disabled_functions_param_alias.phpt new file mode 100644 index 0000000..fe3d1c1 --- /dev/null +++ b/src/tests/disabled_functions_param_alias.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions - alias +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_alias.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_param_alias.php:2 has been disabled, because of the the rule '1'. +[snuffleupagus][0.0.0.0][disabled_function][notice] The call to the function 'shell_exec' in %a/tests/disabled_functions_param_alias.php:3 has been disabled, because of the the rule '2'. diff --git a/src/tests/disabled_functions_param_allow.phpt b/src/tests/disabled_functions_param_allow.phpt new file mode 100644 index 0000000..b6ff01a --- /dev/null +++ b/src/tests/disabled_functions_param_allow.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions - allow +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_allow.ini +--FILE-- + +--EXPECTF-- +win +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_param_allow.php:3 has been disabled. \ No newline at end of file diff --git a/src/tests/disabled_functions_param_array.phpt b/src/tests/disabled_functions_param_array.phpt new file mode 100644 index 0000000..6596d1a --- /dev/null +++ b/src/tests/disabled_functions_param_array.phpt @@ -0,0 +1,37 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_array.ini +--FILE-- +"test1"); +foo($a); +$a=Array("a"=>"abcd"); +foo($a); +$a=Array("a"=>"abcde"); +foo($a); +$a=Array("bla"=>"abcdef"); +foo($a); +$a=Array("bla"=>"aaa", "a"=>"eee" ); +foo($a); +$a=Array("test"=>"aaa", "a"=>"fff" ); +foo($a); +$a=Array("test2"=>Array("foo"=>Array("lol"=>"bbb")), "a"=>"cccc"); +foo($a); +$a=Array("test2"=>Array("foo"=>Array("lol"=>"aaa")), "a"=>"dddd"); +foo($a); +?> +--EXPECTF-- +test1 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '1'. +abcde +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '2'. +eee +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '3'. +cccc +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foo' in %a/disabled_functions_param_array.php:3 has been disabled, because its argument 'arr' content (Array) matched the rule '4'. diff --git a/src/tests/disabled_functions_param_int.phpt b/src/tests/disabled_functions_param_int.phpt new file mode 100644 index 0000000..3b2cc08 --- /dev/null +++ b/src/tests/disabled_functions_param_int.phpt @@ -0,0 +1,25 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_int.ini +--FILE-- + +--EXPECTF-- +1 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument 'id' content (42) matched a rule. +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument 'id' content (1337) matched a rule. +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument 'id' content (13374242) matched a rule. +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'foobar' in %a/tests/disabled_functions_param_int.php:3 has been disabled, because its argument 'id' content (42) matched a rule. +10 diff --git a/src/tests/disabled_functions_param_r.phpt b/src/tests/disabled_functions_param_r.phpt new file mode 100644 index 0000000..3708881 --- /dev/null +++ b/src/tests/disabled_functions_param_r.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_r.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_param_r.php:2 has been disabled, because its argument 'command' content (id) matched a rule. +win diff --git a/src/tests/disabled_functions_param_str_representation.phpt b/src/tests/disabled_functions_param_str_representation.phpt new file mode 100644 index 0000000..7cbdc0f --- /dev/null +++ b/src/tests/disabled_functions_param_str_representation.phpt @@ -0,0 +1,25 @@ +--TEST-- +Disable functions - casting various types to string internally +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_str_representation.ini +--FILE-- + +--EXPECTF-- +true +false +NULL +1 +1.0 +123 diff --git a/src/tests/disabled_functions_parse_class.phpt b/src/tests/disabled_functions_parse_class.phpt new file mode 100644 index 0000000..af9ed88 --- /dev/null +++ b/src/tests/disabled_functions_parse_class.phpt @@ -0,0 +1,22 @@ +--TEST-- +Disable functions - Parsing of an Object as a return value of a function +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret.ini +--FILE-- +a() instanceof StdClass)?'Y':'N'; +?> +--EXPECT-- +Y diff --git a/src/tests/disabled_functions_require.phpt b/src/tests/disabled_functions_require.phpt new file mode 100644 index 0000000..1eedde4 --- /dev/null +++ b/src/tests/disabled_functions_require.phpt @@ -0,0 +1,25 @@ +--TEST-- +Disable functions - Require +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_require.ini +--FILE-- + +--XFAIL-- +PHP doesn't replace the format string, so the test is failing. +--EXPECTF-- +[snuffleupagus][0.0.0.0][include][drop] Inclusion of a forbidden file (%a/test.bla) +--CLEAN-- + diff --git a/src/tests/disabled_functions_ret.phpt b/src/tests/disabled_functions_ret.phpt new file mode 100644 index 0000000..b64bf70 --- /dev/null +++ b/src/tests/disabled_functions_ret.phpt @@ -0,0 +1,13 @@ +--TEST-- +Disable functions check on `ret`. +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret.php:2, because the return value (0) of the function 'strpos' matched a rule. diff --git a/src/tests/disabled_functions_ret2.phpt b/src/tests/disabled_functions_ret2.phpt new file mode 100644 index 0000000..b713201 --- /dev/null +++ b/src/tests/disabled_functions_ret2.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret`. +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret2.php:2, because the return value (0) of the function 'stripos' matched a rule. diff --git a/src/tests/disabled_functions_ret3.phpt b/src/tests/disabled_functions_ret3.phpt new file mode 100644 index 0000000..d5f96d0 --- /dev/null +++ b/src/tests/disabled_functions_ret3.phpt @@ -0,0 +1,22 @@ +--TEST-- +Disable functions check on `ret`. +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret.ini +--FILE-- +a() . ".\n"; +echo("We're at the end of the execution.\n"); +?> +--EXPECTF-- +We're in function `a`. +`a` returned: 1. +We're at the end of the execution. \ No newline at end of file diff --git a/src/tests/disabled_functions_ret_allow.phpt b/src/tests/disabled_functions_ret_allow.phpt new file mode 100644 index 0000000..1690995 --- /dev/null +++ b/src/tests/disabled_functions_ret_allow.phpt @@ -0,0 +1,13 @@ +--TEST-- +Disable functions check on `ret`. +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_ret_allow.ini +--FILE-- + +--EXPECT-- +00 \ No newline at end of file diff --git a/src/tests/disabled_functions_ret_allow_value.phpt b/src/tests/disabled_functions_ret_allow_value.phpt new file mode 100644 index 0000000..881a006 --- /dev/null +++ b/src/tests/disabled_functions_ret_allow_value.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret` allowed +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_ret_allow_value.ini +--FILE-- + +--EXPECT-- +0 diff --git a/src/tests/disabled_functions_ret_right_hash.phpt b/src/tests/disabled_functions_ret_right_hash.phpt new file mode 100644 index 0000000..e0d8b5b --- /dev/null +++ b/src/tests/disabled_functions_ret_right_hash.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_ret_right_hash.ini +--FILE-- + +--EXPECTF-- +1337 diff --git a/src/tests/disabled_functions_ret_simulation.phpt b/src/tests/disabled_functions_ret_simulation.phpt new file mode 100644 index 0000000..58af3a9 --- /dev/null +++ b/src/tests/disabled_functions_ret_simulation.phpt @@ -0,0 +1,18 @@ +--TEST-- +Disable functions check on `ret` simulation +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_ret_simulation.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][notice] The execution has been aborted in %a/disabled_functions_ret_simulation.php:2, because the return value (0) of the function 'strpos' matched a rule. +0 +[snuffleupagus][0.0.0.0][disabled_function][notice] The execution has been aborted in %a/disabled_functions_ret_simulation.php:3, because the function 'stripos' returned '0', which matched the rule '1'. +0 +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_simulation.php:4, because the return value (0) of the function 'strcmp' matched a rule. diff --git a/src/tests/disabled_functions_ret_type.phpt b/src/tests/disabled_functions_ret_type.phpt new file mode 100644 index 0000000..f1c6e4c --- /dev/null +++ b/src/tests/disabled_functions_ret_type.phpt @@ -0,0 +1,16 @@ +--TEST-- +Disable functions check on `ret` by type matching on boolean +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type.ini +--FILE-- + +--EXPECTF-- +0 +1337 +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/tests/disabled_functions_ret_type.php:%d, because the function 'strpos' returned 'FALSE', which matched the rule 'Return value is FALSE'. diff --git a/src/tests/disabled_functions_ret_type_double.phpt b/src/tests/disabled_functions_ret_type_double.phpt new file mode 100644 index 0000000..b7942e1 --- /dev/null +++ b/src/tests/disabled_functions_ret_type_double.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret` by type matching (double). +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type_double.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_type_double.php:%d, because the function 'cos' returned '0.877583', which matched the rule 'Return value is a double'. diff --git a/src/tests/disabled_functions_ret_type_long.phpt b/src/tests/disabled_functions_ret_type_long.phpt new file mode 100644 index 0000000..b841c64 --- /dev/null +++ b/src/tests/disabled_functions_ret_type_long.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret` by type matching (long). +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type_long.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_type_long.php:%d, because the function 'strlen' returned '5', which matched the rule 'Return value is a long'. diff --git a/src/tests/disabled_functions_ret_type_resource.phpt b/src/tests/disabled_functions_ret_type_resource.phpt new file mode 100644 index 0000000..4ceb610 --- /dev/null +++ b/src/tests/disabled_functions_ret_type_resource.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret` by type matching (resource). +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type_resource.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_type_resource.php:2, because the function 'fopen' returned 'RESOURCE', which matched the rule 'Return value is a resource'. diff --git a/src/tests/disabled_functions_ret_type_str.phpt b/src/tests/disabled_functions_ret_type_str.phpt new file mode 100644 index 0000000..8c48b1d --- /dev/null +++ b/src/tests/disabled_functions_ret_type_str.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions check on `ret` by type matching (string). +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type_str.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_type_str.php:%d, because the function 'substr' returned 'et', which matched the rule 'Return value is a string'. diff --git a/src/tests/disabled_functions_ret_type_true.phpt b/src/tests/disabled_functions_ret_type_true.phpt new file mode 100644 index 0000000..a5eae38 --- /dev/null +++ b/src/tests/disabled_functions_ret_type_true.phpt @@ -0,0 +1,16 @@ +--TEST-- +Disable functions check on `ret` by type matching (true). +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_ret_type_true.ini +--FILE-- + +--EXPECTF-- +bool(false) +1337 +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_type_true.php:%d, because the function 'is_numeric' returned 'TRUE', which matched the rule 'Return value is a true'. diff --git a/src/tests/disabled_functions_ret_val.phpt b/src/tests/disabled_functions_ret_val.phpt new file mode 100644 index 0000000..8a02b29 --- /dev/null +++ b/src/tests/disabled_functions_ret_val.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions ret val +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_retval.ini +--FILE-- + +--EXPECTF-- +fufu +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_val.php:3, because the return value (fufufu) of the function 'str_repeat' matched a rule. diff --git a/src/tests/disabled_functions_ret_val_rx.phpt b/src/tests/disabled_functions_ret_val_rx.phpt new file mode 100644 index 0000000..1054b70 --- /dev/null +++ b/src/tests/disabled_functions_ret_val_rx.phpt @@ -0,0 +1,14 @@ +--TEST-- +Disable functions ret val rx +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/disabled_functions_retval_rx.ini +--FILE-- + +--EXPECTF-- +fufu +[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in %a/disabled_functions_ret_val_rx.php:3, because the return value (fufufu) of the function 'str_repeat' matched a rule. diff --git a/src/tests/disabled_functions_right_hash.phpt b/src/tests/disabled_functions_right_hash.phpt new file mode 100644 index 0000000..f3c5fb3 --- /dev/null +++ b/src/tests/disabled_functions_right_hash.phpt @@ -0,0 +1,12 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_right_hash.ini +--FILE-- + +--EXPECTF-- +1337 diff --git a/src/tests/disabled_functions_runtime.phpt b/src/tests/disabled_functions_runtime.phpt new file mode 100644 index 0000000..1c6a141 --- /dev/null +++ b/src/tests/disabled_functions_runtime.phpt @@ -0,0 +1,31 @@ +--TEST-- +Disable functions - runtime inclusion +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_functions_param_runtime.ini +--FILE-- + +--EXPECTF-- +1338 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'test' in %a has been disabled, because its argument 'param' content (1337) matched a rule. +--CLEAN-- + diff --git a/src/tests/disabled_functions_zero_cidr.phpt b/src/tests/disabled_functions_zero_cidr.phpt new file mode 100644 index 0000000..35d187a --- /dev/null +++ b/src/tests/disabled_functions_zero_cidr.phpt @@ -0,0 +1,18 @@ +--TEST-- +Disable functions +--SKIPIF-- + +--ENV-- +return << +--EXPECTF-- +[snuffleupagus][127.0.0.1][disabled_function][drop] The call to the function 'system' in %a/tests/disabled_functions_zero_cidr.php:2 has been disabled. +1337 diff --git a/src/tests/disabled_option.phpt b/src/tests/disabled_option.phpt new file mode 100644 index 0000000..8bc7e39 --- /dev/null +++ b/src/tests/disabled_option.phpt @@ -0,0 +1,16 @@ +--TEST-- +Harden rand +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_rand_harden_disabled.ini +--FILE-- + +--EXPECT-- +84 +84 diff --git a/src/tests/disabled_user_functions.phpt b/src/tests/disabled_user_functions.phpt new file mode 100644 index 0000000..8952d43 --- /dev/null +++ b/src/tests/disabled_user_functions.phpt @@ -0,0 +1,15 @@ +--TEST-- +Disabled user-created functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_disabled_user_functions.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'my_super_function' in %a/tests/disabled_user_functions.php:3 has been disabled. diff --git a/src/tests/dump_request.phpt b/src/tests/dump_request.phpt new file mode 100644 index 0000000..a752def --- /dev/null +++ b/src/tests/dump_request.phpt @@ -0,0 +1,39 @@ +--TEST-- +Dump request +--SKIPIF-- + +--POST-- +post_a=data_post_a&post_b=data_post_b +--GET-- +get_a=data_get_a&get_b=data_get_b +--COOKIE-- +cookie_a=data_cookie_a&cookie_b=data_cookie_b +--INI-- +sp.configuration_file={PWD}/config/dump_request.ini +--FILE-- + +--EXPECTF-- +1 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %a/dump_request.php:%d has been disabled. diff --git a/src/tests/dump_request_invalid_folder.phpt b/src/tests/dump_request_invalid_folder.phpt new file mode 100644 index 0000000..b866f70 --- /dev/null +++ b/src/tests/dump_request_invalid_folder.phpt @@ -0,0 +1,25 @@ +--TEST-- +Dump request - invalid folder. +--SKIPIF-- + +--POST-- +post_a=data_post_a&post_b=data_post_b +--GET-- +get_a=data_get_a&get_b=data_get_b +--COOKIE-- +cookie_a=data_cookie_a&cookie_b=data_cookie_b +--INI-- +sp.configuration_file={PWD}/config/dump_request_invalid_folder.ini +--FILE-- + +--EXPECTF-- +1 +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'system' in %atests/dump_request_invalid_folder.php:3 has been disabled. +[snuffleupagus][0.0.0.0][request_logging][error] Unable to open /root/NON_EXISTENT/FOLDER/PLEASE/sp_dump_%a_0.0.0.0.dump +2 \ No newline at end of file diff --git a/src/tests/dump_request_too_big.phpt b/src/tests/dump_request_too_big.phpt new file mode 100644 index 0000000..81eb71c --- /dev/null +++ b/src/tests/dump_request_too_big.phpt @@ -0,0 +1,42 @@ +--TEST-- +Dump request -- to big, so it's truncated. +--SKIPIF-- + +--POST-- +post_a=data_post_a&post_b=data_post_b&post_c=c +--GET-- +get_a=data_get_a&get_b=data_get_b&get_c=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB +--COOKIE-- +cookie_a=data_cookie_a&cookie_b=data_cookie_b&data_cookie_c=cookie_c +--ENV-- +return << +--EXPECTF-- +1 +[snuffleupagus][127.0.0.1][disabled_function][drop] The call to the function 'system' in %a/dump_request_too_big.php:%d has been disabled. diff --git a/src/tests/empty_conf.phpt b/src/tests/empty_conf.phpt new file mode 100644 index 0000000..411c817 --- /dev/null +++ b/src/tests/empty_conf.phpt @@ -0,0 +1,8 @@ +--TEST-- +Empty configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/empty_conf.ini +--FILE-- +--EXPECT-- diff --git a/src/tests/encrypt_cookies.phpt b/src/tests/encrypt_cookies.phpt new file mode 100644 index 0000000..f8bf64f --- /dev/null +++ b/src/tests/encrypt_cookies.phpt @@ -0,0 +1,22 @@ +--TEST-- +Cookie decryption in ipv4 +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +super_cookie=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEmXkk3H0xheoOMxoWPEDw1Zd8NAmD9KbB2DSjQ=%3d;awful_cookie=awful_cookie_value; +--ENV-- +return << +--EXPECT-- +array(2) { + ["super_cookie"]=> + string(11) "super_value" + ["awful_cookie"]=> + string(18) "awful_cookie_value" +} diff --git a/src/tests/encrypt_cookies2.phpt b/src/tests/encrypt_cookies2.phpt new file mode 100644 index 0000000..be4c990 --- /dev/null +++ b/src/tests/encrypt_cookies2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Cookie encryption in ipv4 +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +--ENV-- +return << +--EXPECT-- +array(0) { +} diff --git a/src/tests/encrypt_cookies3.phpt b/src/tests/encrypt_cookies3.phpt new file mode 100644 index 0000000..c85c5dc --- /dev/null +++ b/src/tests/encrypt_cookies3.phpt @@ -0,0 +1,23 @@ +--TEST-- +Cookie decryption with ipv6 +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +super_cookie=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJNTUge7MpiVNi4q3DqstbcumllXBir0CbIQiDI%3D;awful_cookie=awful_cookie_value; +--ENV-- +return << +--EXPECT-- +array(2) { + ["super_cookie"]=> + string(11) "super_value" + ["awful_cookie"]=> + string(18) "awful_cookie_value" +} diff --git a/src/tests/encrypt_cookies4.phpt b/src/tests/encrypt_cookies4.phpt new file mode 100644 index 0000000..14d737a --- /dev/null +++ b/src/tests/encrypt_cookies4.phpt @@ -0,0 +1,23 @@ +--TEST-- +Cookie encryption in ipv6 +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +--ENV-- +return << +--EXPECT-- +array(0) { +} diff --git a/src/tests/encrypt_cookies_invalid_decryption.phpt b/src/tests/encrypt_cookies_invalid_decryption.phpt new file mode 100644 index 0000000..a5187c1 --- /dev/null +++ b/src/tests/encrypt_cookies_invalid_decryption.phpt @@ -0,0 +1,23 @@ +--TEST-- +Cookie encryption +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +display_errors=1 +display_startup_errors=1 +error_reporting=E_ALL +--COOKIE-- +super_cookie=jWjORGsgZyqzk3WA63XZBmUoSknXWnXDfAAAAAAAAAAAAAAAAAAAAAA7LiMDfkpP94jDnMVH%2Fm41GeL0Y00q3mbOFYz%2FS9mQGySu;awful_cookie=awful_cookie_value; +--ENV-- +return << +--EXPECT-- + +array(1) { + ["awful_cookie"]=> + string(18) "awful_cookie_value" +} diff --git a/src/tests/encrypt_cookies_invalid_decryption2.phpt b/src/tests/encrypt_cookies_invalid_decryption2.phpt new file mode 100644 index 0000000..f18cf6d --- /dev/null +++ b/src/tests/encrypt_cookies_invalid_decryption2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Cookie encryption +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +display_errors=1 +display_startup_errors=1 +error_reporting=E_ALL +--COOKIE-- +super_cookie=1337;awful_cookie=awful_cookie_value; +--ENV-- +return << +--EXPECT-- + +array(1) { + ["awful_cookie"]=> + string(18) "awful_cookie_value" +} diff --git a/src/tests/encrypt_cookies_invalid_decryption3.phpt b/src/tests/encrypt_cookies_invalid_decryption3.phpt new file mode 100644 index 0000000..f4afc32 --- /dev/null +++ b/src/tests/encrypt_cookies_invalid_decryption3.phpt @@ -0,0 +1,21 @@ +--TEST-- +Cookie encryption +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +super_cookie=;awful_cookie=awful_cookie_value; +--ENV-- +return << +--EXPECT-- +array(2) { + ["super_cookie"]=> + string(0) "" + ["awful_cookie"]=> + string(18) "awful_cookie_value" +} diff --git a/src/tests/encryption_key_only.phpt b/src/tests/encryption_key_only.phpt new file mode 100644 index 0000000..bf5edb5 --- /dev/null +++ b/src/tests/encryption_key_only.phpt @@ -0,0 +1,13 @@ +--TEST-- +Encryption key only +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/encryption_key_only.ini +--FILE-- + +--EXPECT-- +1337 + diff --git a/src/tests/example_configuration.phpt b/src/tests/example_configuration.phpt new file mode 100644 index 0000000..0bbf59c --- /dev/null +++ b/src/tests/example_configuration.phpt @@ -0,0 +1,12 @@ +--TEST-- +Shipped configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/../../config/examples.ini +--FILE-- + +--EXPECTF-- +0 diff --git a/src/tests/global_strict.phpt b/src/tests/global_strict.phpt new file mode 100644 index 0000000..e06721c --- /dev/null +++ b/src/tests/global_strict.phpt @@ -0,0 +1,16 @@ +--TEST-- +Global strict mode +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/global_strict.ini +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: strcmp() expects parameter 2 to be string, array given in %a/global_strict.php:2 +Stack trace: +#0 %a/global_strict.php(2): strcmp('pouet', Array) +#1 {main} + thrown in %a/global_strict.php on line 2 diff --git a/src/tests/global_strict_disabled.phpt b/src/tests/global_strict_disabled.phpt new file mode 100644 index 0000000..ca3ddfa --- /dev/null +++ b/src/tests/global_strict_disabled.phpt @@ -0,0 +1,14 @@ +--TEST-- +Global strict mode +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/global_strict_disabled.ini +--FILE-- + +--EXPECTF-- +Warning: strcmp() expects parameter 2 to be string, array given in %a/global_strict_disabled.php on line 2 +1337 diff --git a/src/tests/harden_mt_rand.phpt b/src/tests/harden_mt_rand.phpt new file mode 100644 index 0000000..8887613 --- /dev/null +++ b/src/tests/harden_mt_rand.phpt @@ -0,0 +1,22 @@ +--TEST-- +Harden mt_rand +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/harden_rand.ini +--FILE-- + +--EXPECT-- +win diff --git a/src/tests/harden_rand.phpt b/src/tests/harden_rand.phpt new file mode 100644 index 0000000..391bccc --- /dev/null +++ b/src/tests/harden_rand.phpt @@ -0,0 +1,24 @@ +--TEST-- +Harden rand +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/harden_rand.ini +--FILE-- + +--EXPECT-- +win diff --git a/src/tests/harden_rand_noargs.phpt b/src/tests/harden_rand_noargs.phpt new file mode 100644 index 0000000..643a453 --- /dev/null +++ b/src/tests/harden_rand_noargs.phpt @@ -0,0 +1,62 @@ +--TEST-- +Harden rand without any arguments +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/harden_rand.ini +We should fix this +--FILE-- + +--EXPECTF-- +Warning: rand() expects exactly 2 parameters, 1 given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand() expects exactly 2 parameters, 1 given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand(): max(1) is smaller than min(2) in %s/tests/harden_rand_noargs.php on line %d + +Warning: rand() expects exactly 2 parameters, 3 given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand() expects exactly 2 parameters, 3 given in %s/tests/harden_rand_noargs.php on line %d + +Warning: rand() expects parameter 1 to be integer, string given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand() expects parameter 1 to be integer, string given in %s/tests/harden_rand_noargs.php on line %d + +Warning: rand() expects parameter 2 to be integer, string given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand() expects parameter 2 to be integer, string given in %s/tests/harden_rand_noargs.php on line %d + +Warning: rand() expects exactly 2 parameters, 3 given in %s/tests/harden_rand_noargs.php on line %d + +Warning: mt_rand() expects exactly 2 parameters, 3 given in %s/tests/harden_rand_noargs.php on line %d +Everything is fine +Absolutely everything +Even with single quotes diff --git a/src/tests/inexistent_conf_file.phpt b/src/tests/inexistent_conf_file.phpt new file mode 100644 index 0000000..c7c3fcd --- /dev/null +++ b/src/tests/inexistent_conf_file.phpt @@ -0,0 +1,10 @@ +--TEST-- +Check for snuffleupagus presence +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/unexistent_configuration_file.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][config][error] Could not open configuration file %a/tests/config/unexistent_configuration_file.ini : No such file or directory diff --git a/src/tests/loading.phpt b/src/tests/loading.phpt new file mode 100644 index 0000000..25e2e17 --- /dev/null +++ b/src/tests/loading.phpt @@ -0,0 +1,10 @@ +--TEST-- +Check for snuffleupagus presence +--SKIPIF-- + +--FILE-- + +--EXPECT-- +snuffleupagus extension is available diff --git a/src/tests/noncore_function_hooking.phpt b/src/tests/noncore_function_hooking.phpt new file mode 100644 index 0000000..106123c --- /dev/null +++ b/src/tests/noncore_function_hooking.phpt @@ -0,0 +1,15 @@ +--TEST-- +Hooking of user-defined functions +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_noncore_function_hooking.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'custom_fun' in %a/tests/noncore_function_hooking.php:3 has been disabled. diff --git a/src/tests/phpinfo_presence.phpt b/src/tests/phpinfo_presence.phpt new file mode 100644 index 0000000..35ed0ed --- /dev/null +++ b/src/tests/phpinfo_presence.phpt @@ -0,0 +1,19 @@ +--TEST-- +Unserialize fail +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_serialize.ini +--FILE-- + +--EXPECT-- +1 diff --git a/src/tests/serialize.phpt b/src/tests/serialize.phpt new file mode 100644 index 0000000..e93dbaf --- /dev/null +++ b/src/tests/serialize.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test serialize hmac +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_serialize.ini +--FILE-- + +--EXPECT-- +s:1:"a";650609b417904d0d9bbf1fc44a975d13ecdf6b02b715c1a06271fb3b673f25b1 + diff --git a/src/tests/setcookie.phpt b/src/tests/setcookie.phpt new file mode 100644 index 0000000..ba1d1c1 --- /dev/null +++ b/src/tests/setcookie.phpt @@ -0,0 +1,35 @@ +--TEST-- +Set cookies. +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_encrypted_cookies.ini +--COOKIE-- +--ENV-- +return << +--EXPECTF-- +Warning: setcookie() expects at most 7 parameters, 8 given in %a/setcookie.php on line %d + +Warning: setcookie() expects at least 1 parameter, 0 given in %a/setcookie.php on line %d +1337 diff --git a/src/tests/shipped_configuration.phpt b/src/tests/shipped_configuration.phpt new file mode 100644 index 0000000..c060a85 --- /dev/null +++ b/src/tests/shipped_configuration.phpt @@ -0,0 +1,12 @@ +--TEST-- +Shipped configuration +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/../../config/default.ini +--FILE-- + +--EXPECTF-- +0 diff --git a/src/tests/unserialize.phpt b/src/tests/unserialize.phpt new file mode 100644 index 0000000..b1db915 --- /dev/null +++ b/src/tests/unserialize.phpt @@ -0,0 +1,13 @@ +--TEST-- +Unserialize ok +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_serialize.ini +--FILE-- + +--EXPECT-- +string(1) "a" diff --git a/src/tests/unserialize_fail.phpt b/src/tests/unserialize_fail.phpt new file mode 100644 index 0000000..5c0bb80 --- /dev/null +++ b/src/tests/unserialize_fail.phpt @@ -0,0 +1,23 @@ +--TEST-- +Unserialize fail +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_serialize.ini +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][unserialize][drop] The serialized object is too small. +bool(false) +[snuffleupagus][0.0.0.0][unserialize][drop] Invalid HMAC for s:1:"a";alyualskdufyhalkdjsfh +NULL +[snuffleupagus][0.0.0.0][unserialize][drop] The serialized object is too small. +bool(false) + +Warning: unserialize() expects at most 2 parameters, 4 given in %a/tests/unserialize_fail.php on line %d +bool(false) \ No newline at end of file diff --git a/src/tests/unserialize_sim.phpt b/src/tests/unserialize_sim.phpt new file mode 100644 index 0000000..8ebf64d --- /dev/null +++ b/src/tests/unserialize_sim.phpt @@ -0,0 +1,17 @@ +--TEST-- +Unserialize ok +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_serialize_sim.ini +--FILE-- + +--EXPECT-- +s:1:"a";650609b417904d0d9bbf1fc44a975d13ecdf6b02b715c1a06271fb3b673f25b1string(1) "a" +[snuffleupagus][0.0.0.0][unserialize][notice] Invalid HMAC for s:1:"a";alyualskdufyhalkdjsfh +string(1) "a" diff --git a/src/tests/upload_validation.phpt b/src/tests/upload_validation.phpt new file mode 100644 index 0000000..c802c16 --- /dev/null +++ b/src/tests/upload_validation.phpt @@ -0,0 +1,16 @@ +--TEST-- +Upload a file, validation ok, no simulation +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation.ini +--POST_RAW-- +Content-Type: multipart/form-data; boundary=blabla +--blabla +Content-Disposition: form-data; name="test"; filename="test.php" +--blabla-- +--FILE-- + +--EXPECTF-- +1 diff --git a/src/tests/upload_validation_invalid.phpt b/src/tests/upload_validation_invalid.phpt new file mode 100644 index 0000000..f8c993b --- /dev/null +++ b/src/tests/upload_validation_invalid.phpt @@ -0,0 +1,17 @@ +--TEST-- +Upload a file, invalid validation script +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation_invalid.ini +--POST_RAW-- +Content-Type: multipart/form-data; boundary=blabla +--blabla +Content-Disposition: form-data; name="test"; filename="test.php" +--blabla-- +--FILE-- + +--EXPECTF-- +[snuffleupagus][0.0.0.0][upload_validation][error] Could not call './tests/data/upload_invalid.sh' : Exec format error +[snuffleupagus][0.0.0.0][upload_valiation][drop] The upload of test.php on ? was rejected. diff --git a/src/tests/upload_validation_ko.phpt b/src/tests/upload_validation_ko.phpt new file mode 100644 index 0000000..cf4057a --- /dev/null +++ b/src/tests/upload_validation_ko.phpt @@ -0,0 +1,14 @@ +--TEST-- +Upload a file, validation ko, no simulation +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation_ko.ini +output_buffering=off +--POST_RAW-- +Content-Type: multipart/form-data; boundary=blabla +--blabla +Content-Disposition: form-data; name="test"; filename="test.php" +--blabla-- +--FILE-- +--EXPECTF-- +[snuffleupagus][0.0.0.0][upload_valiation][drop] The upload of test.php on ? was rejected. diff --git a/src/tests/upload_validation_no_exec.phpt b/src/tests/upload_validation_no_exec.phpt new file mode 100644 index 0000000..90a58da --- /dev/null +++ b/src/tests/upload_validation_no_exec.phpt @@ -0,0 +1,32 @@ +--TEST-- +Upload a file, validation script not executable +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation_non_exec.ini +output_buffering=off +--POST_RAW-- +Content-Type: multipart/form-data; boundary=blabla +--blabla +Content-Disposition: form-data; name="test"; filename="test.php" +--blabla-- +--FILE-- + +--EXPECTF-- +array(1) { + ["test"]=> + array(5) { + ["name"]=> + string(8) "test.php" + ["type"]=> + string(0) "" + ["tmp_name"]=> + string(0) "" + ["error"]=> + int(3) + ["size"]=> + int(0) + } +} diff --git a/src/tests/upload_validation_nocrash.phpt b/src/tests/upload_validation_nocrash.phpt new file mode 100644 index 0000000..6fa50d0 --- /dev/null +++ b/src/tests/upload_validation_nocrash.phpt @@ -0,0 +1,12 @@ +--TEST-- +Upload validation isn't crashing +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation_ok.ini +output_buffering=off +--FILE-- + +--EXPECTF-- +1 diff --git a/src/tests/upload_validation_ok.phpt b/src/tests/upload_validation_ok.phpt new file mode 100644 index 0000000..f9b5015 --- /dev/null +++ b/src/tests/upload_validation_ok.phpt @@ -0,0 +1,17 @@ +--TEST-- +Upload a file, validation ok, no simulation +--INI-- +file_uploads=1 +sp.configuration_file={PWD}/config/upload_validation_ok.ini +output_buffering=off +--POST_RAW-- +Content-Type: multipart/form-data; boundary=blabla +--blabla +Content-Disposition: form-data; name="test"; filename="test.php" +--blabla-- +--FILE-- + +--EXPECTF-- +1 diff --git a/src/tweetnacl.c b/src/tweetnacl.c new file mode 100644 index 0000000..937e879 --- /dev/null +++ b/src/tweetnacl.c @@ -0,0 +1,842 @@ +#include "tweetnacl.h" +#define FOR(i,n) for (i = 0;i < n;++i) +#define sv static void + +typedef unsigned char u8; +typedef unsigned long u32; +typedef unsigned long long u64; +typedef long long i64; +typedef i64 gf[16]; + + +/* it's really stupid that there isn't a syscall for this */ + +static int fd = -1; + +void randombytes(unsigned char *x,unsigned long long xlen) +{ + int i; + + if (fd == -1) { + for (;;) { + fd = open("/dev/urandom",O_RDONLY); + if (fd != -1) break; + sleep(1); + } + } + + while (xlen > 0) { + if (xlen < 1048576) i = xlen; else i = 1048576; + + i = read(fd,x,i); + if (i < 1) { + sleep(1); + continue; + } + + x += i; + xlen -= i; + } +} + + +static const u8 + _0[16], + _9[32] = {9}; +static const gf + gf0, + gf1 = {1}, + _121665 = {0xDB41,1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); } + +static u32 ld32(const u8 *x) +{ + u32 u = x[3]; + u = (u<<8)|x[2]; + u = (u<<8)|x[1]; + return (u<<8)|x[0]; +} + +static u64 dl64(const u8 *x) +{ + u64 i,u=0; + FOR(i,8) u=(u<<8)|x[i]; + return u; +} + +sv st32(u8 *x,u32 u) +{ + int i; + FOR(i,4) { x[i] = u; u >>= 8; } +} + +sv ts64(u8 *x,u64 u) +{ + int i; + for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; } +} + +static int vn(const u8 *x,const u8 *y,int n) +{ + int i = 0; + u32 d = 0; + FOR(i,n) d |= x[i]^y[i]; + return (1 & ((d - 1) >> 8)) - 1; +} + +int crypto_verify_16(const u8 *x,const u8 *y) +{ + return vn(x,y,16); +} + +int crypto_verify_32(const u8 *x,const u8 *y) +{ + return vn(x,y,32); +} + +sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h) +{ + u32 w[16],x[16],y[16],t[4]; + int i,j,m; + + FOR(i,4) { + x[5*i] = ld32(c+4*i); + x[1+i] = ld32(k+4*i); + x[6+i] = ld32(in+4*i); + x[11+i] = ld32(k+16+4*i); + } + + FOR(i,16) y[i] = x[i]; + + FOR(i,20) { + FOR(j,4) { + FOR(m,4) t[m] = x[(5*j+4*m)%16]; + t[1] ^= L32(t[0]+t[3], 7); + t[2] ^= L32(t[1]+t[0], 9); + t[3] ^= L32(t[2]+t[1],13); + t[0] ^= L32(t[3]+t[2],18); + FOR(m,4) w[4*j+(j+m)%4] = t[m]; + } + FOR(m,16) x[m] = w[m]; + } + + if (h) { + FOR(i,16) x[i] += y[i]; + FOR(i,4) { + x[5*i] -= ld32(c+4*i); + x[6+i] -= ld32(in+4*i); + } + FOR(i,4) { + st32(out+4*i,x[5*i]); + st32(out+16+4*i,x[6+i]); + } + } else + FOR(i,16) st32(out + 4 * i,x[i] + y[i]); +} + +int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) +{ + core(out,in,k,c,0); + return 0; +} + +int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) +{ + core(out,in,k,c,1); + return 0; +} + +static const u8 sigma[16] = "expand 32-byte k"; + +int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k) +{ + u8 z[16],x[64]; + u32 u,i; + if (!b) return 0; + FOR(i,16) z[i] = 0; + FOR(i,8) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + FOR(i,64) c[i] = (m?m[i]:0) ^ x[i]; + u = 1; + for (i = 8;i < 16;++i) { + u += (u32) z[i]; + z[i] = u; + u >>= 8; + } + b -= 64; + c += 64; + if (m) m += 64; + } + if (b) { + crypto_core_salsa20(x,z,k,sigma); + FOR(i,b) c[i] = (m?m[i]:0) ^ x[i]; + } + return 0; +} + +int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k) +{ + return crypto_stream_salsa20_xor(c,0,d,n,k); +} + +int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k) +{ + u8 s[32]; + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20(c,d,n+16,s); +} + +int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + u8 s[32]; + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20_xor(c,m,d,n+16,s); +} + +sv add1305(u32 *h,const u32 *c) +{ + u32 j,u = 0; + FOR(j,17) { + u += h[j] + c[j]; + h[j] = u & 255; + u >>= 8; + } +} + +static const u32 minusp[17] = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +} ; + +int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k) +{ + u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17]; + + FOR(j,17) r[j]=h[j]=0; + FOR(j,16) r[j]=k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + FOR(j,17) c[j] = 0; + for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j]; + c[j] = 1; + m += j; n -= j; + add1305(h,c); + FOR(i,17) { + x[i] = 0; + FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]); + } + FOR(i,17) h[i] = x[i]; + u = 0; + FOR(j,16) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u & 3; + u = 5 * (u >> 2); + FOR(j,16) { + u += h[j]; + h[j] = u & 255; + u >>= 8; + } + u += h[16]; h[16] = u; + } + + FOR(j,17) g[j] = h[j]; + add1305(h,minusp); + s = -(h[16] >> 7); + FOR(j,17) h[j] ^= s & (g[j] ^ h[j]); + + FOR(j,16) c[j] = k[j + 16]; + c[16] = 0; + add1305(h,c); + FOR(j,16) out[j] = h[j]; + return 0; +} + +int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k) +{ + u8 x[16]; + crypto_onetimeauth(x,m,n,k); + return crypto_verify_16(h,x); +} + +int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + int i; + if (d < 32) return -1; + crypto_stream_xor(c,m,d,n,k); + crypto_onetimeauth(c + 16,c + 32,d - 32,c); + FOR(i,16) c[i] = 0; + return 0; +} + +int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) +{ + int i; + u8 x[32]; + if (d < 32) return -1; + crypto_stream(x,32,n,k); + if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1; + crypto_stream_xor(m,c,d,n,k); + FOR(i,32) m[i] = 0; + return 0; +} + +sv set25519(gf r, const gf a) +{ + int i; + FOR(i,16) r[i]=a[i]; +} + +sv car25519(gf o) +{ + int i; + i64 c; + FOR(i,16) { + o[i]+=(1LL<<16); + c=o[i]>>16; + o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); + o[i]-=c<<16; + } +} + +sv sel25519(gf p,gf q,int b) +{ + i64 t,i,c=~(b-1); + FOR(i,16) { + t= c&(p[i]^q[i]); + p[i]^=t; + q[i]^=t; + } +} + +sv pack25519(u8 *o,const gf n) +{ + int i,j,b; + gf m,t; + FOR(i,16) t[i]=n[i]; + car25519(t); + car25519(t); + car25519(t); + FOR(j,2) { + m[0]=t[0]-0xffed; + for(i=1;i<15;i++) { + m[i]=t[i]-0xffff-((m[i-1]>>16)&1); + m[i-1]&=0xffff; + } + m[15]=t[15]-0x7fff-((m[14]>>16)&1); + b=(m[15]>>16)&1; + m[14]&=0xffff; + sel25519(t,m,1-b); + } + FOR(i,16) { + o[2*i]=t[i]&0xff; + o[2*i+1]=t[i]>>8; + } +} + +static int neq25519(const gf a, const gf b) +{ + u8 c[32],d[32]; + pack25519(c,a); + pack25519(d,b); + return crypto_verify_32(c,d); +} + +static u8 par25519(const gf a) +{ + u8 d[32]; + pack25519(d,a); + return d[0]&1; +} + +sv unpack25519(gf o, const u8 *n) +{ + int i; + FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); + o[15]&=0x7fff; +} + +sv A(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]+b[i]; +} + +sv Z(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]-b[i]; +} + +sv M(gf o,const gf a,const gf b) +{ + i64 i,j,t[31]; + FOR(i,31) t[i]=0; + FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; + FOR(i,15) t[i]+=38*t[i+16]; + FOR(i,16) o[i]=t[i]; + car25519(o); + car25519(o); +} + +sv S(gf o,const gf a) +{ + M(o,a,a); +} + +sv inv25519(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=253;a>=0;a--) { + S(c,c); + if(a!=2&&a!=4) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +sv pow2523(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=250;a>=0;a--) { + S(c,c); + if(a!=1) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) +{ + u8 z[32]; + i64 x[80],r,i; + gf a,b,c,d,e,f; + FOR(i,31) z[i]=n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + FOR(i,16) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for(i=254;i>=0;--i) { + r=(z[i>>3]>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + FOR(i,16) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + inv25519(x+32,x+32); + M(x+16,x+16,x+32); + pack25519(q,x+16); + return 0; +} + +int crypto_scalarmult_base(u8 *q,const u8 *n) +{ + return crypto_scalarmult(q,n,_9); +} + +int crypto_box_keypair(u8 *y,u8 *x) +{ + randombytes(x,32); + return crypto_scalarmult_base(y,x); +} + +int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x) +{ + u8 s[32]; + crypto_scalarmult(s,x,y); + return crypto_core_hsalsa20(k,_0,s,sigma); +} + +int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k) +{ + return crypto_secretbox(c,m,d,n,k); +} + +int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k) +{ + return crypto_secretbox_open(m,c,d,n,k); +} + +int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x) +{ + u8 k[32]; + crypto_box_beforenm(k,y,x); + return crypto_box_afternm(c,m,d,n,k); +} + +int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x) +{ + u8 k[32]; + crypto_box_beforenm(k,y,x); + return crypto_box_open_afternm(m,c,d,n,k); +} + +static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); } +static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); } +static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); } +static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); } +static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); } +static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); } +static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); } + +static const u64 K[80] = +{ + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +int crypto_hashblocks(u8 *x,const u8 *m,u64 n) +{ + u64 z[8],b[8],a[8],w[16],t; + int i,j; + + FOR(i,8) z[i] = a[i] = dl64(x + 8 * i); + + while (n >= 128) { + FOR(i,16) w[i] = dl64(m + 8 * i); + + FOR(i,80) { + FOR(j,8) b[j] = a[j]; + t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16]; + b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]); + b[3] += t; + FOR(j,8) a[(j+1)%8] = b[j]; + if (i%16 == 15) + FOR(j,16) + w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]); + } + + FOR(i,8) { a[i] += z[i]; z[i] = a[i]; } + + m += 128; + n -= 128; + } + + FOR(i,8) ts64(x+8*i,z[i]); + + return n; +} + +static const u8 iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +} ; + +int crypto_hash(u8 *out,const u8 *m,u64 n) +{ + u8 h[64],x[256]; + u64 i,b = n; + + FOR(i,64) h[i] = iv[i]; + + crypto_hashblocks(h,m,n); + m += n; + n &= 127; + m -= n; + + FOR(i,256) x[i] = 0; + FOR(i,n) x[i] = m[i]; + x[n] = 128; + + n = 256-128*(n<112); + x[n-9] = b >> 61; + ts64(x+n-8,b<<3); + crypto_hashblocks(h,x,n); + + FOR(i,64) out[i] = h[i]; + + return 0; +} + +sv add(gf p[4],gf q[4]) +{ + gf a,b,c,d,t,e,f,g,h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +sv cswap(gf p[4],gf q[4],u8 b) +{ + int i; + FOR(i,4) + sel25519(p[i],q[i],b); +} + +sv pack(u8 *r,gf p[4]) +{ + gf tx, ty, zi; + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +sv scalarmult(gf p[4],gf q[4],const u8 *s) +{ + int i; + set25519(p[0],gf0); + set25519(p[1],gf1); + set25519(p[2],gf1); + set25519(p[3],gf0); + for (i = 255;i >= 0;--i) { + u8 b = (s[i/8]>>(i&7))&1; + cswap(p,q,b); + add(q,p); + add(p,p); + cswap(p,q,b); + } +} + +sv scalarbase(gf p[4],const u8 *s) +{ + gf q[4]; + set25519(q[0],X); + set25519(q[1],Y); + set25519(q[2],gf1); + M(q[3],X,Y); + scalarmult(p,q,s); +} + +int crypto_sign_keypair(u8 *pk, u8 *sk) +{ + u8 d[64]; + gf p[4]; + int i; + + randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + FOR(i,32) sk[32 + i] = pk[i]; + return 0; +} + +static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +sv modL(u8 *r,i64 x[64]) +{ + i64 carry,i,j; + for (i = 63;i >= 32;--i) { + carry = 0; + for (j = i - 32;j < i - 12;++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + FOR(j,32) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + FOR(j,32) x[j] -= carry * L[j]; + FOR(i,32) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +sv reduce(u8 *r) +{ + i64 x[64],i; + FOR(i,64) x[i] = (u64) r[i]; + FOR(i,64) r[i] = 0; + modL(r,x); +} + +int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk) +{ + u8 d[64],h[64],r[64]; + u64 i; + i64 j,x[64]; + gf p[4]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = n+64; + FOR(i,n) sm[64 + i] = m[i]; + FOR(i,32) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm+32, n+32); + reduce(r); + scalarbase(p,r); + pack(sm,p); + + FOR(i,32) sm[i+32] = sk[i+32]; + crypto_hash(h,sm,n + 64); + reduce(h); + + FOR(i,64) x[i] = 0; + FOR(i,32) x[i] = (u64) r[i]; + FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; + modL(sm + 32,x); + + return 0; +} + +static int unpackneg(gf r[4],const u8 p[32]) +{ + gf t, chk, num, den, den2, den4, den6; + set25519(r[2],gf1); + unpack25519(r[1],p); + S(num,r[1]); + M(den,num,D); + Z(num,num,r[2]); + A(den,r[2],den); + + S(den2,den); + S(den4,den2); + M(den6,den4,den2); + M(t,den6,num); + M(t,t,den); + + pow2523(t,t); + M(t,t,num); + M(t,t,den); + M(t,t,den); + M(r[0],t,den); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) M(r[0],r[0],I); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk) +{ + u64 i; + u8 t[32],h[64]; + gf p[4],q[4]; + + *mlen = -1; + if (n < 64) return -1; + + if (unpackneg(q,pk)) return -1; + + FOR(i,n) m[i] = sm[i]; + FOR(i,32) m[i+32] = pk[i]; + crypto_hash(h,m,n); + reduce(h); + scalarmult(p,q,h); + + scalarbase(q,sm + 32); + add(p,q); + pack(t,p); + + n -= 64; + if (crypto_verify_32(sm, t)) { + FOR(i,n) m[i] = 0; + return -1; + } + + FOR(i,n) m[i] = sm[i + 64]; + *mlen = n; + return 0; +} diff --git a/src/tweetnacl.h b/src/tweetnacl.h new file mode 100644 index 0000000..508876d --- /dev/null +++ b/src/tweetnacl.h @@ -0,0 +1,277 @@ +#include +#include +#include +#include + +#ifndef TWEETNACL_H +#define TWEETNACL_H +#define crypto_auth_PRIMITIVE "hmacsha512256" +#define crypto_auth crypto_auth_hmacsha512256 +#define crypto_auth_verify crypto_auth_hmacsha512256_verify +#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES +#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES +#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION +#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION +#define crypto_auth_hmacsha512256_tweet_BYTES 32 +#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32 +extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_auth_hmacsha512256_tweet_VERSION "-" +#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet +#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify +#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES +#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES +#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION +#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet" +#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305" +#define crypto_box crypto_box_curve25519xsalsa20poly1305 +#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open +#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair +#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm +#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm +#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm +#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES +#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES +#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES +#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES +#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION +#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION +#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-" +#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet +#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open +#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair +#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm +#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm +#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm +#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES +#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES +#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION +#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet" +#define crypto_core_PRIMITIVE "salsa20" +#define crypto_core crypto_core_salsa20 +#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES +#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES +#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES +#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES +#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION +#define crypto_core_VERSION crypto_core_salsa20_VERSION +#define crypto_core_salsa20_tweet_OUTPUTBYTES 64 +#define crypto_core_salsa20_tweet_INPUTBYTES 16 +#define crypto_core_salsa20_tweet_KEYBYTES 32 +#define crypto_core_salsa20_tweet_CONSTBYTES 16 +extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_salsa20_tweet_VERSION "-" +#define crypto_core_salsa20 crypto_core_salsa20_tweet +#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES +#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES +#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES +#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES +#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION +#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet" +#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32 +#define crypto_core_hsalsa20_tweet_INPUTBYTES 16 +#define crypto_core_hsalsa20_tweet_KEYBYTES 32 +#define crypto_core_hsalsa20_tweet_CONSTBYTES 16 +extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +#define crypto_core_hsalsa20_tweet_VERSION "-" +#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet +#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES +#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES +#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES +#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES +#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION +#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet" +#define crypto_hashblocks_PRIMITIVE "sha512" +#define crypto_hashblocks crypto_hashblocks_sha512 +#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES +#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES +#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION +#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION +#define crypto_hashblocks_sha512_tweet_STATEBYTES 64 +#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128 +extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha512_tweet_VERSION "-" +#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet +#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES +#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES +#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION +#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet" +#define crypto_hashblocks_sha256_tweet_STATEBYTES 32 +#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64 +extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hashblocks_sha256_tweet_VERSION "-" +#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet +#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES +#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES +#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION +#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet" +#define crypto_hash_PRIMITIVE "sha512" +#define crypto_hash crypto_hash_sha512 +#define crypto_hash_BYTES crypto_hash_sha512_BYTES +#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION +#define crypto_hash_VERSION crypto_hash_sha512_VERSION +#define crypto_hash_sha512_tweet_BYTES 64 +extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha512_tweet_VERSION "-" +#define crypto_hash_sha512 crypto_hash_sha512_tweet +#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES +#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION +#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet" +#define crypto_hash_sha256_tweet_BYTES 32 +extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long); +#define crypto_hash_sha256_tweet_VERSION "-" +#define crypto_hash_sha256 crypto_hash_sha256_tweet +#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES +#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION +#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet" +#define crypto_onetimeauth_PRIMITIVE "poly1305" +#define crypto_onetimeauth crypto_onetimeauth_poly1305 +#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify +#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES +#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES +#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION +#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION +#define crypto_onetimeauth_poly1305_tweet_BYTES 16 +#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32 +extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); +#define crypto_onetimeauth_poly1305_tweet_VERSION "-" +#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet +#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify +#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES +#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES +#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION +#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet" +#define crypto_scalarmult_PRIMITIVE "curve25519" +#define crypto_scalarmult crypto_scalarmult_curve25519 +#define crypto_scalarmult_base crypto_scalarmult_curve25519_base +#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES +#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES +#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION +#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION +#define crypto_scalarmult_curve25519_tweet_BYTES 32 +#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32 +extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *); +extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *); +#define crypto_scalarmult_curve25519_tweet_VERSION "-" +#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet +#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base +#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES +#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES +#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION +#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet" +#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305" +#define crypto_secretbox crypto_secretbox_xsalsa20poly1305 +#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open +#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES +#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES +#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES +#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES +#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION +#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION +#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24 +#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32 +#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16 +extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-" +#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet +#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open +#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES +#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES +#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES +#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION +#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet" +#define crypto_sign_PRIMITIVE "ed25519" +#define crypto_sign crypto_sign_ed25519 +#define crypto_sign_open crypto_sign_ed25519_open +#define crypto_sign_keypair crypto_sign_ed25519_keypair +#define crypto_sign_BYTES crypto_sign_ed25519_BYTES +#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES +#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES +#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION +#define crypto_sign_VERSION crypto_sign_ed25519_VERSION +#define crypto_sign_ed25519_tweet_BYTES 64 +#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32 +#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64 +extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *); +#define crypto_sign_ed25519_tweet_VERSION "-" +#define crypto_sign_ed25519 crypto_sign_ed25519_tweet +#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open +#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair +#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES +#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES +#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES +#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION +#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet" +#define crypto_stream_PRIMITIVE "xsalsa20" +#define crypto_stream crypto_stream_xsalsa20 +#define crypto_stream_xor crypto_stream_xsalsa20_xor +#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES +#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES +#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION +#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION +#define crypto_stream_xsalsa20_tweet_KEYBYTES 32 +#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24 +extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_xsalsa20_tweet_VERSION "-" +#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet +#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor +#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES +#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES +#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION +#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet" +#define crypto_stream_salsa20_tweet_KEYBYTES 32 +#define crypto_stream_salsa20_tweet_NONCEBYTES 8 +extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); +#define crypto_stream_salsa20_tweet_VERSION "-" +#define crypto_stream_salsa20 crypto_stream_salsa20_tweet +#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor +#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES +#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES +#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION +#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet" +#define crypto_verify_PRIMITIVE "16" +#define crypto_verify crypto_verify_16 +#define crypto_verify_BYTES crypto_verify_16_BYTES +#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION +#define crypto_verify_VERSION crypto_verify_16_VERSION +#define crypto_verify_16_tweet_BYTES 16 +extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_16_tweet_VERSION "-" +#define crypto_verify_16 crypto_verify_16_tweet +#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES +#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION +#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet" +#define crypto_verify_32_tweet_BYTES 32 +extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *); +#define crypto_verify_32_tweet_VERSION "-" +#define crypto_verify_32 crypto_verify_32_tweet +#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES +#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION +#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet" +#endif -- cgit v1.3