summaryrefslogtreecommitdiff
path: root/src/sp_cookie_encryption.c
diff options
context:
space:
mode:
authorjvoisin2019-05-14 21:57:13 +0200
committerjvoisin2019-05-14 22:48:55 +0200
commit1cdb880fac5044194f0bc62dd82fcd4480192ebe (patch)
treeace8fdb1a2e00be2ac2c99bd7054a8d7a19fd3b3 /src/sp_cookie_encryption.c
parent6ae912e2dc8c7f47d240e6910e42bb31263eb339 (diff)
Fix the cookie's handling for PHP7.3+
PHP 7.3+ added a new prototype for the cookie setting mechanism, breaking our ghetto samesite-injection, this commit takes care of it.
Diffstat (limited to 'src/sp_cookie_encryption.c')
-rw-r--r--src/sp_cookie_encryption.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c
index 9c034da..249de2d 100644
--- a/src/sp_cookie_encryption.c
+++ b/src/sp_cookie_encryption.c
@@ -1,6 +1,5 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3
4ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) 3ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
5 4
6static inline const sp_cookie *sp_lookup_cookie_config(const zend_string *key) { 5static inline const sp_cookie *sp_lookup_cookie_config(const zend_string *key) {
@@ -40,6 +39,54 @@ static zend_string *encrypt_data(zend_string *data) {
40 return z; 39 return z;
41} 40}
42 41
42#if PHP_VERSION_ID >= 70300
43static void php_head_parse_cookie_options_array(
44 zval *options, zend_long *expires, zend_string **path, zend_string **domain,
45 zend_bool *secure, zend_bool *httponly, zend_string **samesite) {
46 int found = 0;
47 zend_string *key;
48 zval *value;
49
50 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(options), key, value) {
51 if (key) {
52 if (zend_string_equals_literal_ci(key, "expires")) {
53 *expires = zval_get_long(value);
54 found++;
55 } else if (zend_string_equals_literal_ci(key, "path")) {
56 *path = zval_get_string(value);
57 found++;
58 } else if (zend_string_equals_literal_ci(key, "domain")) {
59 *domain = zval_get_string(value);
60 found++;
61 } else if (zend_string_equals_literal_ci(key, "secure")) {
62 *secure = zval_is_true(value);
63 found++;
64 } else if (zend_string_equals_literal_ci(key, "httponly")) {
65 *httponly = zval_is_true(value);
66 found++;
67 } else if (zend_string_equals_literal_ci(key, "samesite")) {
68 *samesite = zval_get_string(value);
69 found++;
70 } else {
71 php_error_docref(NULL, E_WARNING,
72 "Unrecognized key '%s' found in the options array",
73 ZSTR_VAL(key));
74 }
75 } else {
76 php_error_docref(NULL, E_WARNING,
77 "Numeric key found in the options array");
78 }
79 }
80 ZEND_HASH_FOREACH_END();
81
82 /* Array is not empty but no valid keys were found */
83 if (found == 0 && zend_hash_num_elements(Z_ARRVAL_P(options)) > 0) {
84 php_error_docref(NULL, E_WARNING,
85 "No valid options were found in the given array");
86 }
87}
88#endif
89
43PHP_FUNCTION(sp_setcookie) { 90PHP_FUNCTION(sp_setcookie) {
44 zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, 91 zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL,
45 *value_enc = NULL, 92 *value_enc = NULL,
@@ -50,6 +97,7 @@ PHP_FUNCTION(sp_setcookie) {
50#endif 97#endif
51 98
52 zend_long expires = 0; 99 zend_long expires = 0;
100 zval *expires_or_options = NULL;
53 zend_bool secure = 0, httponly = 0; 101 zend_bool secure = 0, httponly = 0;
54 const sp_cookie *cookie_node = NULL; 102 const sp_cookie *cookie_node = NULL;
55 char *cookie_samesite; 103 char *cookie_samesite;
@@ -59,7 +107,7 @@ PHP_FUNCTION(sp_setcookie) {
59 Z_PARAM_STR(name) 107 Z_PARAM_STR(name)
60 Z_PARAM_OPTIONAL 108 Z_PARAM_OPTIONAL
61 Z_PARAM_STR(value) 109 Z_PARAM_STR(value)
62 Z_PARAM_LONG(expires) 110 Z_PARAM_ZVAL(expires_or_options)
63 Z_PARAM_STR(path) 111 Z_PARAM_STR(path)
64 Z_PARAM_STR(domain) 112 Z_PARAM_STR(domain)
65 Z_PARAM_BOOL(secure) 113 Z_PARAM_BOOL(secure)
@@ -67,6 +115,25 @@ PHP_FUNCTION(sp_setcookie) {
67 ZEND_PARSE_PARAMETERS_END(); 115 ZEND_PARSE_PARAMETERS_END();
68 // LCOV_EXCL_BR_END 116 // LCOV_EXCL_BR_END
69 117
118 if (expires_or_options) {
119#if PHP_VERSION_ID < 70300
120 expires = zval_get_long(expires_or_options);
121#else
122 if (Z_TYPE_P(expires_or_options) == IS_ARRAY) {
123 if (UNEXPECTED(ZEND_NUM_ARGS() > 3)) {
124 php_error_docref(NULL, E_WARNING,
125 "Cannot pass arguments after the options array");
126 RETURN_FALSE;
127 }
128 php_head_parse_cookie_options_array(expires_or_options, &expires, &path,
129 &domain, &secure, &httponly,
130 &samesite);
131 } else {
132 expires = zval_get_long(expires_or_options);
133 }
134#endif
135 }
136
70 /* If the request was issued over HTTPS, the cookie should be "secure" */ 137 /* If the request was issued over HTTPS, the cookie should be "secure" */
71 if (SNUFFLEUPAGUS_G(config).config_auto_cookie_secure) { 138 if (SNUFFLEUPAGUS_G(config).config_auto_cookie_secure) {
72 const zval server_vars = PG(http_globals)[TRACK_VARS_SERVER]; 139 const zval server_vars = PG(http_globals)[TRACK_VARS_SERVER];