diff options
| author | Remi Collet | 2018-08-27 14:59:52 +0200 |
|---|---|---|
| committer | jvoisin | 2018-08-27 12:59:52 +0000 |
| commit | 1270bc0621989c5c542e610886cd589a6b8ea27f (patch) | |
| tree | db2841ac5aa69d48814bc914172c9c821da3d4b4 /src/sp_cookie_encryption.c | |
| parent | 096e7faa6a5e21e5416a7c8c484e27acd4636a66 (diff) | |
Use php_setcookie function (PHP public API)
This commit vastly simplifies the code of cookies-fiddling mechanisms.
Diffstat (limited to 'src/sp_cookie_encryption.c')
| -rw-r--r-- | src/sp_cookie_encryption.c | 84 |
1 files changed, 39 insertions, 45 deletions
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c index 3f58fb0..1b59e44 100644 --- a/src/sp_cookie_encryption.c +++ b/src/sp_cookie_encryption.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | #include "ext/standard/url.h" | 3 | #include "ext/standard/url.h" |
| 4 | #include "ext/standard/head.h" | ||
| 4 | 5 | ||
| 5 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | 6 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) |
| 6 | 7 | ||
| @@ -42,13 +43,16 @@ static zend_string *encrypt_data(zend_string *data) { | |||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | PHP_FUNCTION(sp_setcookie) { | 45 | PHP_FUNCTION(sp_setcookie) { |
| 45 | zval params[7] = {{{0}}}; | 46 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, *value_enc = NULL, |
| 46 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, | 47 | #if PHP_VERSION_ID < 70300 |
| 48 | *path_samesite = NULL; | ||
| 49 | #else | ||
| 47 | *samesite = NULL; | 50 | *samesite = NULL; |
| 51 | #endif | ||
| 52 | |||
| 48 | zend_long expires = 0; | 53 | zend_long expires = 0; |
| 49 | zend_bool secure = 0, httponly = 0; | 54 | zend_bool secure = 0, httponly = 0; |
| 50 | const sp_cookie *cookie_node = NULL; | 55 | const sp_cookie *cookie_node = NULL; |
| 51 | zval func_name; | ||
| 52 | char *cookie_samesite; | 56 | char *cookie_samesite; |
| 53 | 57 | ||
| 54 | // LCOV_EXCL_BR_START | 58 | // LCOV_EXCL_BR_START |
| @@ -88,64 +92,54 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 88 | 92 | ||
| 89 | /* Shall we encrypt the cookie's value? */ | 93 | /* Shall we encrypt the cookie's value? */ |
| 90 | if (cookie_node && cookie_node->encrypt && value) { | 94 | if (cookie_node && cookie_node->encrypt && value) { |
| 91 | zend_string *encrypted_data = encrypt_data(value); | 95 | value_enc = encrypt_data(value); |
| 92 | ZVAL_STR_COPY(¶ms[1], encrypted_data); | ||
| 93 | zend_string_release(encrypted_data); | ||
| 94 | } else if (value) { | ||
| 95 | ZVAL_STR_COPY(¶ms[1], value); | ||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | ZVAL_STRING(&func_name, "setcookie"); | ||
| 99 | ZVAL_STR_COPY(¶ms[0], name); | ||
| 100 | ZVAL_LONG(¶ms[2], expires); | ||
| 101 | if (domain) { | ||
| 102 | ZVAL_STR_COPY(¶ms[4], domain); | ||
| 103 | } | ||
| 104 | if (secure) { | ||
| 105 | ZVAL_LONG(¶ms[5], secure); | ||
| 106 | } | ||
| 107 | if (httponly) { | ||
| 108 | ZVAL_LONG(¶ms[6], httponly); | ||
| 109 | } | ||
| 110 | 98 | ||
| 111 | /* param[3](path) is concatenated to path= and is not filtered in PHP < 7.3 | ||
| 112 | we can inject the samesite parameter here | ||
| 113 | TODO find another solution with 7.3 */ | ||
| 114 | if (cookie_node && cookie_node->samesite) { | 99 | if (cookie_node && cookie_node->samesite) { |
| 115 | if (!path) { | 100 | if (!path) { |
| 116 | path = zend_string_init("", 0, 0); | 101 | path = zend_string_init("", 0, 0); |
| 117 | } | 102 | } |
| 103 | #if PHP_VERSION_ID < 70300 | ||
| 118 | cookie_samesite = (cookie_node->samesite == lax) | 104 | cookie_samesite = (cookie_node->samesite == lax) |
| 119 | ? SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_LAX | 105 | ? SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_LAX |
| 120 | : SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_STRICT; | 106 | : SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_STRICT; |
| 107 | |||
| 121 | /* Concatenating everything, as is in PHP internals */ | 108 | /* Concatenating everything, as is in PHP internals */ |
| 122 | samesite = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0); | 109 | path_samesite = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0); |
| 123 | samesite = zend_string_extend( | 110 | path_samesite = zend_string_extend( |
| 124 | samesite, ZSTR_LEN(path) + strlen(cookie_samesite) + 1, 0); | 111 | path_samesite, ZSTR_LEN(path) + strlen(cookie_samesite) + 1, 0); |
| 125 | memcpy(ZSTR_VAL(samesite) + ZSTR_LEN(path), cookie_samesite, | 112 | memcpy(ZSTR_VAL(path_samesite) + ZSTR_LEN(path), cookie_samesite, |
| 126 | strlen(cookie_samesite) + 1); | 113 | strlen(cookie_samesite) + 1); |
| 127 | ZVAL_STR_COPY(¶ms[3], samesite); | 114 | #else |
| 128 | } else if (path) { | 115 | cookie_samesite = (cookie_node->samesite == lax) |
| 129 | ZVAL_STR_COPY(¶ms[3], path); | 116 | ? SP_TOKEN_SAMESITE_LAX |
| 117 | : SP_TOKEN_SAMESITE_STRICT; | ||
| 118 | |||
| 119 | samesite = zend_string_init(cookie_samesite, strlen(cookie_samesite), 0); | ||
| 120 | #endif | ||
| 130 | } | 121 | } |
| 131 | 122 | ||
| 132 | /* This is the _fun_ part: because PHP is utterly idiotic and nonsensical, | ||
| 133 | the `call_user_function` macro will __discard__ (yes) its first argument | ||
| 134 | (the hashtable), effectively calling functions from `CG(function_table)`. | ||
| 135 | This is why were replacing our hook with the original function, calling | ||
| 136 | the function, and then re-hooking it. */ | ||
| 137 | void (*handler)(INTERNAL_FUNCTION_PARAMETERS); | ||
| 138 | handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), | ||
| 139 | "setcookie", strlen("setcookie")); | ||
| 140 | zend_internal_function *func = zend_hash_str_find_ptr( | ||
| 141 | CG(function_table), "setcookie", strlen("setcookie")); | ||
| 142 | func->handler = handler; | ||
| 143 | 123 | ||
| 144 | call_user_function(CG(function_table), NULL, &func_name, return_value, 7, | 124 | #if PHP_VERSION_ID < 70300 |
| 145 | params); | 125 | if (php_setcookie(name, (value_enc ? value_enc : value), expires, (path_samesite ? path_samesite : path), domain, secure, 1, httponly)) { |
| 126 | #else | ||
| 127 | if (php_setcookie(name, (value_enc ? value_enc : value), expires, path, domain, secure, httponly, samesite, 1)) { | ||
| 128 | #endif | ||
| 129 | RETVAL_TRUE; | ||
| 130 | } else { | ||
| 131 | RETVAL_FALSE; | ||
| 132 | } | ||
| 146 | 133 | ||
| 147 | func->handler = PHP_FN(sp_setcookie); | 134 | if (value_enc) { |
| 148 | RETURN_TRUE; | 135 | zend_string_release(value_enc); |
| 136 | } | ||
| 137 | #if PHP_VERSION_ID < 70300 | ||
| 138 | if (path_samesite) { | ||
| 139 | zend_string_release(path_samesite); | ||
| 140 | } | ||
| 141 | #endif | ||
| 142 | RETURN_TRUE; // TODO why always true ? | ||
| 149 | } | 143 | } |
| 150 | 144 | ||
| 151 | int hook_cookies() { | 145 | int hook_cookies() { |
