From 7832438b7abedf567ce6376f99949f419abcdff1 Mon Sep 17 00:00:00 2001 From: kkadosh Date: Tue, 29 May 2018 19:34:16 +0000 Subject: Support session encryption Implement session encryption.--- src/config.m4 | 2 +- src/php_snuffleupagus.h | 2 + src/snuffleupagus.c | 6 + src/sp_config.c | 1 + src/sp_config.h | 7 ++ src/sp_config_keywords.c | 43 +++++++ src/sp_config_keywords.h | 1 + src/sp_cookie_encryption.c | 6 - src/sp_crypt.c | 52 +++++--- src/sp_crypt.h | 2 +- src/sp_session.c | 159 ++++++++++++++++++++++++ src/sp_session.h | 11 ++ src/tests/config/config_crypt_session.ini | 2 + src/tests/config/config_crypt_session_simul.ini | 3 + src/tests/crypt_session_invalid.phpt | 24 ++++ src/tests/crypt_session_invalid_simul.phpt | 27 ++++ src/tests/crypt_session_read_uncrypt.phpt | 33 +++++ src/tests/crypt_session_valid.phpt | 27 ++++ src/tests/crypt_session_valid_simul.phpt | 27 ++++ src/tests/samesite_cookies.phpt | 51 ++++---- 20 files changed, 438 insertions(+), 48 deletions(-) create mode 100644 src/sp_session.c create mode 100644 src/sp_session.h create mode 100644 src/tests/config/config_crypt_session.ini create mode 100644 src/tests/config/config_crypt_session_simul.ini create mode 100644 src/tests/crypt_session_invalid.phpt create mode 100644 src/tests/crypt_session_invalid_simul.phpt create mode 100644 src/tests/crypt_session_read_uncrypt.phpt create mode 100644 src/tests/crypt_session_valid.phpt create mode 100644 src/tests/crypt_session_valid_simul.phpt (limited to 'src') diff --git a/src/config.m4 b/src/config.m4 index 9909da2..a4fea4d 100644 --- a/src/config.m4 +++ b/src/config.m4 @@ -6,7 +6,7 @@ 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_var_parser.c sp_var_value.c sp_tree.c" -sources="$sources sp_pcre_compat.c sp_crypt.c" +sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c" PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, [ --enable-snuffleupagus Enable snuffleupagus support]) diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index c658dac..f80ae66 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h @@ -18,6 +18,7 @@ #include "ext/standard/info.h" #include "ext/standard/php_var.h" #include "ext/pcre/php_pcre.h" +#include "ext/session/php_session.h" #include "php.h" #include "php_ini.h" #include "zend_hash.h" @@ -41,6 +42,7 @@ #include "sp_upload_validation.h" #include "sp_utils.h" #include "sp_crypt.h" +#include "sp_session.h" extern zend_module_entry snuffleupagus_module_entry; diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 3cdcfb9..c3fc686 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -81,6 +81,7 @@ PHP_GINIT_FUNCTION(snuffleupagus) { SP_INIT(snuffleupagus_globals->config.config_disabled_functions); SP_INIT(snuffleupagus_globals->config.config_disabled_functions_ret); SP_INIT(snuffleupagus_globals->config.config_cookie); + SP_INIT(snuffleupagus_globals->config.config_session); SP_INIT(snuffleupagus_globals->config.config_disabled_constructs); SP_INIT(snuffleupagus_globals->config.config_eval); @@ -124,6 +125,7 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { 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_session), 1); #define FREE_LST_DISABLE(L) \ do { \ @@ -229,6 +231,10 @@ static PHP_INI_MH(OnUpdateConfiguration) { } hook_cookies(); + if (SNUFFLEUPAGUS_G(config).config_session->encrypt) { + hook_session(); + } + if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { zend_extension_entry.startup = NULL; diff --git a/src/sp_config.c b/src/sp_config.c index 67140a0..a89174a 100644 --- a/src/sp_config.c +++ b/src/sp_config.c @@ -21,6 +21,7 @@ sp_config_tokens const sp_func[] = { {.func = parse_disable_xxe, .token = SP_TOKEN_DISABLE_XXE}, {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, + {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, {NULL, NULL}}; /* Top level keyword parsing */ diff --git a/src/sp_config.h b/src/sp_config.h index e537ec2..b44960f 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -65,6 +65,11 @@ typedef struct { bool simulation; } sp_cookie; +typedef struct { + bool encrypt; + bool simulation; +} sp_config_session; + typedef struct { bool enable; bool simulation; @@ -158,6 +163,7 @@ typedef struct { sp_config_disable_xxe *config_disable_xxe; sp_config_disabled_constructs *config_disabled_constructs; sp_config_eval *config_eval; + sp_config_session *config_session; } sp_config; typedef struct { @@ -175,6 +181,7 @@ typedef struct { #define SP_TOKEN_AUTO_COOKIE_SECURE ".auto_cookie_secure" #define SP_TOKEN_COOKIE_ENCRYPTION ".cookie" +#define SP_TOKEN_SESSION_ENCRYPTION ".session" #define SP_TOKEN_DISABLE_FUNC ".disable_function" #define SP_TOKEN_GLOBAL ".global" #define SP_TOKEN_GLOBAL_STRICT ".global_strict" diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index 9faaafb..f702f4d 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -60,6 +60,49 @@ static int parse_enable(char *line, bool *restrict retval, return ret; } +int parse_session(char *line) { + sp_config_session *session = + pecalloc(sizeof(sp_config_session), 1, 0); + + sp_config_functions sp_config_funcs_session_encryption[] = { + {parse_empty, SP_TOKEN_ENCRYPT, &(session->encrypt)}, + {parse_empty, SP_TOKEN_SIMULATION, &(session->simulation)}, + {0}}; + int ret = parse_keywords(sp_config_funcs_session_encryption, line); + if (0 != ret) { + return ret; + } + if (session->encrypt) { + if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)) { + sp_log_err( + "config", + "You're trying to use the session cookie encryption feature" + "on line %zu without having set the `.cookie_env_var` option in" + "`sp.global`: please set it first.", + sp_line_no); + pefree(session, 0); + return -1; + } else if (0 == + (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { + sp_log_err( + "config", + "You're trying to use the session cookie encryption feature" + "on line %zu without having set the `.encryption_key` option in" + "`sp.global`: please set it first.", + sp_line_no); + pefree(session, 0); + return -1; + } + } + + SNUFFLEUPAGUS_G(config).config_session->encrypt = + session->encrypt; + SNUFFLEUPAGUS_G(config).config_session->simulation = + session->simulation; + pefree(session, 0); + return ret; +} + int parse_random(char *line) { return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_random->enable), NULL); diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h index 4205dac..f1f414a 100644 --- a/src/sp_config_keywords.h +++ b/src/sp_config_keywords.h @@ -14,5 +14,6 @@ int parse_disabled_functions(char *line); int parse_upload_validation(char *line); int parse_eval_blacklist(char *line); int parse_eval_whitelist(char *line); +int parse_session(char *line); #endif // __SP_CONFIG_KEYWORDS_H diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c index 9030112..72223ad 100644 --- a/src/sp_cookie_encryption.c +++ b/src/sp_cookie_encryption.c @@ -21,7 +21,6 @@ static inline const sp_cookie *sp_lookup_cookie_config(const char *key) { int decrypt_cookie(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key) { const sp_cookie *cookie = sp_lookup_cookie_config(ZSTR_VAL(hash_key->key)); - int ret = 0; /* If the cookie isn't in the conf, it shouldn't be encrypted. */ if (!cookie || !cookie->encrypt) { @@ -36,11 +35,6 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, return decrypt_zval(pDest, cookie->simulation, hash_key); } -/* -** This function will return the `data` of length `data_len` encrypted in the -** form `base64(nonce | encrypted_data)` (with `|` being the concatenation -** operation). -*/ static zend_string *encrypt_data(char *data, unsigned long long data_len) { zend_string *z = encrypt_zval(data, data_len); sp_log_debug("cookie_encryption", "Cookie value:%s:", z->val); diff --git a/src/sp_crypt.c b/src/sp_crypt.c index 0c40f1f..55ae37b 100644 --- a/src/sp_crypt.c +++ b/src/sp_crypt.c @@ -4,9 +4,7 @@ ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) -static zend_long nonce_d = 0; - -static void generate_key(unsigned char *key) { +void generate_key(unsigned char *key) { PHP_SHA256_CTX ctx; const char *user_agent = getenv("HTTP_USER_AGENT"); const char *env_var = @@ -50,14 +48,13 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), Z_STRLEN_P(pDest)); - if (ZSTR_LEN(debase64) < - crypto_secretbox_NONCEBYTES + crypto_secretbox_ZEROBYTES) { + if (ZSTR_LEN(debase64) < crypto_secretbox_NONCEBYTES) { if (true == simulation) { sp_log_msg( "cookie_encryption", SP_LOG_SIMULATION, "Buffer underflow tentative detected in cookie encryption handling " "for %s. Using the cookie 'as it' instead of decrypting it.", - ZSTR_VAL(hash_key->key)); + hash_key ? ZSTR_VAL(hash_key->key) : "the session"); return ZEND_HASH_APPLY_KEEP; } else { sp_log_msg( @@ -67,9 +64,26 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { } } + + if (ZSTR_LEN(debase64) + (size_t)crypto_secretbox_ZEROBYTES < ZSTR_LEN(debase64)) { + if (true == simulation) { + sp_log_msg( + "cookie_encryption", SP_LOG_SIMULATION, + "Integer overflow tentative detected in cookie encryption handling " + "for %s. Using the cookie 'as it' instead of decrypting it.", + hash_key ? ZSTR_VAL(hash_key->key) : "the session"); + return ZEND_HASH_APPLY_KEEP; + } else { + sp_log_msg( + "cookie_encryption", SP_LOG_DROP, + "Integer overflow tentative detected in cookie encryption handling."); + return ZEND_HASH_APPLY_REMOVE; + } + } + generate_key(key); - decrypted = ecalloc(ZSTR_LEN(debase64), 1); + decrypted = ecalloc(ZSTR_LEN(debase64) + crypto_secretbox_ZEROBYTES, 1); ret = crypto_secretbox_open( decrypted, @@ -83,12 +97,12 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { "cookie_encryption", SP_LOG_SIMULATION, "Something went wrong with the decryption of %s. Using the cookie " "'as it' instead of decrypting it", - ZSTR_VAL(hash_key->key)); + hash_key ? ZSTR_VAL(hash_key->key) : "the session"); return ZEND_HASH_APPLY_KEEP; } else { sp_log_msg("cookie_encryption", SP_LOG_DROP, "Something went wrong with the decryption of %s.", - ZSTR_VAL(hash_key->key)); + hash_key ? ZSTR_VAL(hash_key->key) : "the session"); return ZEND_HASH_APPLY_REMOVE; } } @@ -100,8 +114,14 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { 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). +*/ zend_string *encrypt_zval(char *data, unsigned long long data_len) { const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; + // FIXME : We know that this len is too long const size_t emsg_and_nonce_len = encrypted_msg_len + crypto_secretbox_NONCEBYTES; @@ -112,25 +132,21 @@ zend_string *encrypt_zval(char *data, unsigned long long data_len) { generate_key(key); + // Put random bytes in the nonce + php_random_bytes(nonce, sizeof(nonce), 0); + /* 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(zend_long) <= crypto_secretbox_NONCEBYTES); - if (0 == nonce_d) { - /* A zend_long should be enough to avoid collisions */ - if (php_random_int_throw(0, ZEND_LONG_MAX, &nonce_d) == FAILURE) { - return NULL; // LCOV_EXCL_LINE - } - } - nonce_d++; - sscanf((char *)nonce, "%ld", &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); + return z; } \ No newline at end of file diff --git a/src/sp_crypt.h b/src/sp_crypt.h index 1852a0a..3ede104 100644 --- a/src/sp_crypt.h +++ b/src/sp_crypt.h @@ -10,7 +10,7 @@ #include "ext/hash/php_hash_sha.h" #include "ext/standard/base64.h" -static void generate_key(unsigned char *key); +void generate_key(unsigned char *key); int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hask_key); zend_string *encrypt_zval(char *data, unsigned long long data_len); diff --git a/src/sp_session.c b/src/sp_session.c new file mode 100644 index 0000000..4085007 --- /dev/null +++ b/src/sp_session.c @@ -0,0 +1,159 @@ +#include "php_snuffleupagus.h" +#include "ext/session/php_session.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +#ifdef ZTS +static ts_rsrc_id session_globals_id = 0; +#define SESSION_G(v) ZEND_TSRMG(session_globals_id, php_ps_globals *, v) +#ifdef COMPILE_DL_SESSION +ZEND_TSRMLS_CACHE_EXTERN(); +#endif +#else +#define SESSION_G(v) (ps_globals.v) +#endif + +static php_ps_globals *session_globals = NULL; +static ps_module *s_module; +static ps_module *s_original_mod; +static int (*old_s_read)(PS_READ_ARGS); +static int (*old_s_write)(PS_WRITE_ARGS); +static int (*previous_sessionRINIT)(INIT_FUNC_ARGS) = NULL; +static ZEND_INI_MH((*old_OnUpdateSaveHandler)) = NULL; + + +static int sp_hook_s_read(PS_READ_ARGS) { + int r = old_s_read(mod_data, key, val, maxlifetime); + if (r == SUCCESS && SNUFFLEUPAGUS_G(config).config_session->encrypt && + val != NULL && *val != NULL && ZSTR_LEN(*val)) { + zend_string *orig_val = *val; + zval val_zval; + ZVAL_PSTRINGL(&val_zval, ZSTR_VAL(*val), ZSTR_LEN(*val)); + + int ret = decrypt_zval( + &val_zval, SNUFFLEUPAGUS_G(config).config_session->simulation, + NULL); + if (0 != ret) { + if (SNUFFLEUPAGUS_G(config).config_session->simulation) { + return ret; + } else { + sp_terminate(); + } + } + + *val = zend_string_dup(val_zval.value.str, 0); + if (*val == NULL) { + *val = ZSTR_EMPTY_ALLOC(); + } + zend_string_release(orig_val); + } + + return r; +} + + +static int sp_hook_s_write(PS_WRITE_ARGS) { + if (ZSTR_LEN(val) > 0 && + SNUFFLEUPAGUS_G(config).config_session->encrypt) { + zend_string *new_val = encrypt_zval(ZSTR_VAL(val), ZSTR_LEN(val)); + return old_s_write(mod_data, key, new_val, maxlifetime); + } + return old_s_write(mod_data, key, val, maxlifetime); +} + +static void sp_hook_session_module() { + ps_module *old_mod = SESSION_G(mod); + ps_module *mod; + + if (old_mod == NULL || s_module == old_mod) { + return; + } + + if (s_module == NULL) { + s_module = mod = malloc(sizeof(ps_module)); + if (mod == NULL) { + return; + } + } + + s_original_mod = old_mod; + + mod = s_module; + memcpy(mod, old_mod, sizeof(ps_module)); + + old_s_read = mod->s_read; + mod->s_read = sp_hook_s_read; + + old_s_write = mod->s_write; + mod->s_write = sp_hook_s_write; + + SESSION_G(mod) = mod; +} + +static PHP_INI_MH(sp_OnUpdateSaveHandler) { + if (stage == PHP_INI_STAGE_RUNTIME && + SESSION_G(session_status) == php_session_none && + s_original_mod && + zend_string_equals_literal(new_value, "user") == 0 && + strcmp(((ps_module *)s_original_mod)->s_name, "user") == + 0) { + return SUCCESS; + } + + SESSION_G(mod) = s_original_mod; + + int r = old_OnUpdateSaveHandler(entry, new_value, mh_arg1, mh_arg2, mh_arg3, + stage); + + sp_hook_session_module(); + + return r; +} + +static int sp_hook_session_RINIT(INIT_FUNC_ARGS) { + if (SESSION_G(mod) == NULL) { + zend_ini_entry *ini_entry; + if ((ini_entry = zend_hash_str_find_ptr( + EG(ini_directives), ZEND_STRL("session.save_handler")))) { + if (ini_entry->value) { + sp_OnUpdateSaveHandler(NULL, ini_entry->value, NULL, NULL, NULL, 0); + } + } + } + return previous_sessionRINIT(INIT_FUNC_ARGS_PASSTHRU); +} + +void hook_session() { + zend_module_entry *module; + + if ((module = zend_hash_str_find_ptr(&module_registry, + ZEND_STRL("session"))) == NULL) { + return; + } + +#ifdef ZTS + if (session_globals_id == 0) { + session_globals_id = *module->globals_id_ptr; + } +#else + if (session_globals == NULL) { + session_globals = module->globals_ptr; + } +#endif + if (old_OnUpdateSaveHandler != NULL) { + return; + } + + previous_sessionRINIT = module->request_startup_func; + module->request_startup_func = sp_hook_session_RINIT; + + zend_ini_entry *ini_entry; + if ((ini_entry = zend_hash_str_find_ptr( + EG(ini_directives), ZEND_STRL("session.save_handler"))) != NULL) { + old_OnUpdateSaveHandler = ini_entry->on_modify; + ini_entry->on_modify = sp_OnUpdateSaveHandler; + } + s_module = NULL; + + sp_hook_session_module(); +} \ No newline at end of file diff --git a/src/sp_session.h b/src/sp_session.h new file mode 100644 index 0000000..c2a0357 --- /dev/null +++ b/src/sp_session.h @@ -0,0 +1,11 @@ +#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" + + +void hook_session(); diff --git a/src/tests/config/config_crypt_session.ini b/src/tests/config/config_crypt_session.ini new file mode 100644 index 0000000..14b0c2c --- /dev/null +++ b/src/tests/config/config_crypt_session.ini @@ -0,0 +1,2 @@ +sp.global.secret_key("abcdef").cookie_env_var("REMOTE_ADDR"); +sp.session.encrypt(); \ No newline at end of file diff --git a/src/tests/config/config_crypt_session_simul.ini b/src/tests/config/config_crypt_session_simul.ini new file mode 100644 index 0000000..fbd43eb --- /dev/null +++ b/src/tests/config/config_crypt_session_simul.ini @@ -0,0 +1,3 @@ +sp.global.secret_key("abcdef").cookie_env_var("REMOTE_ADDR"); +sp.session.encrypt(); +sp.session.simulation(); \ No newline at end of file diff --git a/src/tests/crypt_session_invalid.phpt b/src/tests/crypt_session_invalid.phpt new file mode 100644 index 0000000..687a407 --- /dev/null +++ b/src/tests/crypt_session_invalid.phpt @@ -0,0 +1,24 @@ +--TEST-- +SESSION crypt and bad decrypt +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_crypt_session.ini +--ENV-- +return << +--EXPECTF-- +[snuffleupagus][127.0.0.2][cookie_encryption][drop] Something went wrong with the decryption of the session. \ No newline at end of file diff --git a/src/tests/crypt_session_invalid_simul.phpt b/src/tests/crypt_session_invalid_simul.phpt new file mode 100644 index 0000000..7bfefcb --- /dev/null +++ b/src/tests/crypt_session_invalid_simul.phpt @@ -0,0 +1,27 @@ +--TEST-- +SESSION crypt and bad decrypt +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_crypt_session_simul.ini +--ENV-- +return << +--EXPECTF-- +array(1) { + ["toto"]=> + string(4) "tata" +} diff --git a/src/tests/crypt_session_read_uncrypt.phpt b/src/tests/crypt_session_read_uncrypt.phpt new file mode 100644 index 0000000..f15d8b6 --- /dev/null +++ b/src/tests/crypt_session_read_uncrypt.phpt @@ -0,0 +1,33 @@ +--TEST-- +SESSION crypt/decrypt valid +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_crypt_session_simul.ini +--ENV-- +return << +--EXPECTF-- +array(1) { + ["toto"]=> + string(4) "tata" +} +OK diff --git a/src/tests/crypt_session_valid.phpt b/src/tests/crypt_session_valid.phpt new file mode 100644 index 0000000..bf9fea0 --- /dev/null +++ b/src/tests/crypt_session_valid.phpt @@ -0,0 +1,27 @@ +--TEST-- +SESSION crypt/decrypt valid +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_crypt_session.ini +--ENV-- +return << +--EXPECTF-- +array(1) { + ["toto"]=> + string(4) "tata" +} diff --git a/src/tests/crypt_session_valid_simul.phpt b/src/tests/crypt_session_valid_simul.phpt new file mode 100644 index 0000000..28083cf --- /dev/null +++ b/src/tests/crypt_session_valid_simul.phpt @@ -0,0 +1,27 @@ +--TEST-- +SESSION crypt/decrypt valid +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/config_crypt_session_simul.ini +--ENV-- +return << +--EXPECTF-- +array(1) { + ["toto"]=> + string(4) "tata" +} diff --git a/src/tests/samesite_cookies.phpt b/src/tests/samesite_cookies.phpt index fe74172..d010963 100644 --- a/src/tests/samesite_cookies.phpt +++ b/src/tests/samesite_cookies.phpt @@ -27,12 +27,13 @@ if (!setcookie("nice_cookie", "nice_value", 1, "1", "1", true, true)) { echo "setcookie failed.\n"; } +// If the cookie value start with "!", it means that we don't want the value in the headers, but the encrypted cookie $expected = array( - 'Set-Cookie: super_cookie=super_value; path=; samesite=Lax', - 'Set-Cookie: awful_cookie=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFyZcYjfEskB0AU0V3%2BvwazcRuU%2Ft6KpcUahvxw%3D; path=; samesite=Strict; HttpOnly', - 'Set-Cookie: not_encrypted=test_value; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=1; domain=1; HttpOnly', - 'Set-Cookie: nice_cookie=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ8ko%2ByA4y%2Bmw5MGBx8fgc3TWOAvhIu%2BfF%2Bx2g%3D%3D; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=1; samesite=Strict; domain=1; secure; HttpOnly', - ); + "awful_cookie" => "!awful_value", + "not_encrypted" => "test_value", + "nice_cookie" => "!nice_value", + "super_cookie" => "super_value", +); $headers = headers_list(); if (($i = count($expected)) > count($headers)) @@ -41,31 +42,37 @@ if (($i = count($expected)) > count($headers)) return; } -do -{ +$i = 0; + +do { if (strncmp(current($headers), 'Set-Cookie:', 11) !== 0) { continue; } - - if (current($headers) === current($expected)) - { - $i--; + foreach ($expected as $key => $value) { + if (strpos(current($headers), $key) !== false) { // If the header contains the cookie + if (substr($value, 0, 1) === "!") { // ! is because we don't want to see the cookie value in plaintext, it must be encrypted + if (strpos(current($headers), substr($value,1,-1)) === false) { // If the header doesn't contain de cookie value, it's good + $i++; + break; + } + echo "Received : " . current($headers) . " and the cookie isn't encrypted . \n"; + } else { + if (strpos(current($headers), $value) !== false) { + $i++; + break; + } + echo "Received : " . current($headers) . " and the cookie value of " . $key . " doesn't match it's value. \n"; + } + break; + } } - else - { - echo "Header mismatch:\n\tExpected: " - .current($expected) - ."\n\tReceived: ".current($headers)."\n"; - } - - next($expected); } -while (next($headers) !== FALSE); +while (next($headers)); -echo ($i === 0) +echo ($i === 4) ? 'OK' - : 'A total of '.$i.' errors found.'; + : 'A total of '. (count($expected) - $i) .' errors found.'; ?> --EXPECT-- OK -- cgit v1.3