summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemi Collet2018-08-27 14:59:52 +0200
committerjvoisin2018-08-27 12:59:52 +0000
commit1270bc0621989c5c542e610886cd589a6b8ea27f (patch)
treedb2841ac5aa69d48814bc914172c9c821da3d4b4
parent096e7faa6a5e21e5416a7c8c484e27acd4636a66 (diff)
Use php_setcookie function (PHP public API)
This commit vastly simplifies the code of cookies-fiddling mechanisms.
-rw-r--r--src/sp_cookie_encryption.c84
-rw-r--r--src/tests/samesite_cookies.phpt1
2 files changed, 39 insertions, 46 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
5ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) 6ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
6 7
@@ -42,13 +43,16 @@ static zend_string *encrypt_data(zend_string *data) {
42} 43}
43 44
44PHP_FUNCTION(sp_setcookie) { 45PHP_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(&params[1], encrypted_data);
93 zend_string_release(encrypted_data);
94 } else if (value) {
95 ZVAL_STR_COPY(&params[1], value);
96 } 96 }
97 97
98 ZVAL_STRING(&func_name, "setcookie");
99 ZVAL_STR_COPY(&params[0], name);
100 ZVAL_LONG(&params[2], expires);
101 if (domain) {
102 ZVAL_STR_COPY(&params[4], domain);
103 }
104 if (secure) {
105 ZVAL_LONG(&params[5], secure);
106 }
107 if (httponly) {
108 ZVAL_LONG(&params[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(&params[3], samesite); 114#else
128 } else if (path) { 115 cookie_samesite = (cookie_node->samesite == lax)
129 ZVAL_STR_COPY(&params[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
151int hook_cookies() { 145int hook_cookies() {
diff --git a/src/tests/samesite_cookies.phpt b/src/tests/samesite_cookies.phpt
index 3247432..5ba92a3 100644
--- a/src/tests/samesite_cookies.phpt
+++ b/src/tests/samesite_cookies.phpt
@@ -3,7 +3,6 @@ Cookie samesite
3--SKIPIF-- 3--SKIPIF--
4<?php 4<?php
5if (!extension_loaded("snuffleupagus")) die("skip"); 5if (!extension_loaded("snuffleupagus")) die("skip");
6if (PHP_VERSION_ID >= 70300) die("skip BROKEN with 7.3");
7?> 6?>
8--INI-- 7--INI--
9sp.configuration_file={PWD}/config/config_samesite_cookies.ini 8sp.configuration_file={PWD}/config/config_samesite_cookies.ini