xref: /PHP-8.2/ext/session/mod_user.c (revision 4a5699ae)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: Sascha Schumann <sascha@schumann.cx>                         |
14    +----------------------------------------------------------------------+
15  */
16 
17 #include "php.h"
18 #include "php_session.h"
19 #include "mod_user.h"
20 
21 const ps_module ps_mod_user = {
22 	PS_MOD_UPDATE_TIMESTAMP(user)
23 };
24 
25 
ps_call_handler(zval * func,int argc,zval * argv,zval * retval)26 static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval)
27 {
28 	int i;
29 	if (PS(in_save_handler)) {
30 		PS(in_save_handler) = 0;
31 		ZVAL_UNDEF(retval);
32 		php_error_docref(NULL, E_WARNING, "Cannot call session save handler in a recursive manner");
33 		return;
34 	}
35 	PS(in_save_handler) = 1;
36 	if (call_user_function(NULL, NULL, func, retval, argc, argv) == FAILURE) {
37 		zval_ptr_dtor(retval);
38 		ZVAL_UNDEF(retval);
39 	} else if (Z_ISUNDEF_P(retval)) {
40 		ZVAL_NULL(retval);
41 	}
42 	PS(in_save_handler) = 0;
43 	for (i = 0; i < argc; i++) {
44 		zval_ptr_dtor(&argv[i]);
45 	}
46 }
47 
48 #define STDVARS								\
49 	zval retval;							\
50 	zend_result ret = FAILURE
51 
52 #define PSF(a) PS(mod_user_names).name.ps_##a
53 
54 #define FINISH \
55 	if (Z_TYPE(retval) != IS_UNDEF) { \
56 		if (Z_TYPE(retval) == IS_TRUE) { \
57 			ret = SUCCESS; \
58 		} else if (Z_TYPE(retval) == IS_FALSE) { \
59 			ret = FAILURE; \
60 		}  else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == -1)) { \
61 			if (!EG(exception)) { \
62 				php_error_docref(NULL, E_DEPRECATED, "Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
63 			} \
64 			ret = FAILURE; \
65 		} else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == 0)) { \
66 			if (!EG(exception)) { \
67 				php_error_docref(NULL, E_DEPRECATED, "Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
68 			} \
69 			ret = SUCCESS; \
70 		} else { \
71 			if (!EG(exception)) { \
72 				zend_type_error("Session callback must have a return value of type bool, %s returned", zend_zval_type_name(&retval)); \
73 			} \
74 			ret = FAILURE; \
75 			zval_ptr_dtor(&retval); \
76 		} \
77 	} \
78 	return ret
79 
PS_OPEN_FUNC(user)80 PS_OPEN_FUNC(user)
81 {
82 	zval args[2];
83 	STDVARS;
84 
85 	if (Z_ISUNDEF(PSF(open))) {
86 		php_error_docref(NULL, E_WARNING, "User session functions are not defined");
87 
88 		return FAILURE;
89 	}
90 
91 	ZVAL_STRING(&args[0], (char*)save_path);
92 	ZVAL_STRING(&args[1], (char*)session_name);
93 
94 	zend_try {
95 		ps_call_handler(&PSF(open), 2, args, &retval);
96 	} zend_catch {
97 		PS(session_status) = php_session_none;
98 		if (!Z_ISUNDEF(retval)) {
99 			zval_ptr_dtor(&retval);
100 		}
101 		zend_bailout();
102 	} zend_end_try();
103 
104 	PS(mod_user_implemented) = 1;
105 
106 	FINISH;
107 }
108 
PS_CLOSE_FUNC(user)109 PS_CLOSE_FUNC(user)
110 {
111 	bool bailout = 0;
112 	STDVARS;
113 
114 	if (!PS(mod_user_implemented)) {
115 		/* already closed */
116 		return SUCCESS;
117 	}
118 
119 	zend_try {
120 		ps_call_handler(&PSF(close), 0, NULL, &retval);
121 	} zend_catch {
122 		bailout = 1;
123 	} zend_end_try();
124 
125 	PS(mod_user_implemented) = 0;
126 
127 	if (bailout) {
128 		if (!Z_ISUNDEF(retval)) {
129 			zval_ptr_dtor(&retval);
130 		}
131 		zend_bailout();
132 	}
133 
134 	FINISH;
135 }
136 
PS_READ_FUNC(user)137 PS_READ_FUNC(user)
138 {
139 	zval args[1];
140 	STDVARS;
141 
142 	ZVAL_STR_COPY(&args[0], key);
143 
144 	ps_call_handler(&PSF(read), 1, args, &retval);
145 
146 	if (!Z_ISUNDEF(retval)) {
147 		if (Z_TYPE(retval) == IS_STRING) {
148 			*val = zend_string_copy(Z_STR(retval));
149 			ret = SUCCESS;
150 		}
151 		zval_ptr_dtor(&retval);
152 	}
153 
154 	return ret;
155 }
156 
PS_WRITE_FUNC(user)157 PS_WRITE_FUNC(user)
158 {
159 	zval args[2];
160 	STDVARS;
161 
162 	ZVAL_STR_COPY(&args[0], key);
163 	ZVAL_STR_COPY(&args[1], val);
164 
165 	ps_call_handler(&PSF(write), 2, args, &retval);
166 
167 	FINISH;
168 }
169 
PS_DESTROY_FUNC(user)170 PS_DESTROY_FUNC(user)
171 {
172 	zval args[1];
173 	STDVARS;
174 
175 	ZVAL_STR_COPY(&args[0], key);
176 
177 	ps_call_handler(&PSF(destroy), 1, args, &retval);
178 
179 	FINISH;
180 }
181 
PS_GC_FUNC(user)182 PS_GC_FUNC(user)
183 {
184 	zval args[1];
185 	zval retval;
186 
187 	ZVAL_LONG(&args[0], maxlifetime);
188 
189 	ps_call_handler(&PSF(gc), 1, args, &retval);
190 
191 	if (Z_TYPE(retval) == IS_LONG) {
192 		*nrdels = Z_LVAL(retval);
193 	} else if (Z_TYPE(retval) == IS_TRUE) {
194 		/* This is for older API compatibility */
195 		*nrdels = 1;
196 	} else {
197 		/* Anything else is some kind of error */
198 		*nrdels = -1; // Error
199 	}
200 	return *nrdels;
201 }
202 
PS_CREATE_SID_FUNC(user)203 PS_CREATE_SID_FUNC(user)
204 {
205 	/* maintain backwards compatibility */
206 	if (!Z_ISUNDEF(PSF(create_sid))) {
207 		zend_string *id = NULL;
208 		zval retval;
209 
210 		ps_call_handler(&PSF(create_sid), 0, NULL, &retval);
211 
212 		if (!Z_ISUNDEF(retval)) {
213 			if (Z_TYPE(retval) == IS_STRING) {
214 				id = zend_string_copy(Z_STR(retval));
215 			}
216 			zval_ptr_dtor(&retval);
217 		} else {
218 			zend_throw_error(NULL, "No session id returned by function");
219 			return NULL;
220 		}
221 
222 		if (!id) {
223 			zend_throw_error(NULL, "Session id must be a string");
224 			return NULL;
225 		}
226 
227 		return id;
228 	}
229 
230 	/* function as defined by PS_MOD */
231 	return php_session_create_id(mod_data);
232 }
233 
PS_VALIDATE_SID_FUNC(user)234 PS_VALIDATE_SID_FUNC(user)
235 {
236 	/* maintain backwards compatibility */
237 	if (!Z_ISUNDEF(PSF(validate_sid))) {
238 		zval args[1];
239 		STDVARS;
240 
241 		ZVAL_STR_COPY(&args[0], key);
242 
243 		ps_call_handler(&PSF(validate_sid), 1, args, &retval);
244 
245 		FINISH;
246 	}
247 
248 	/* dummy function defined by PS_MOD */
249 	return php_session_validate_sid(mod_data, key);
250 }
251 
PS_UPDATE_TIMESTAMP_FUNC(user)252 PS_UPDATE_TIMESTAMP_FUNC(user)
253 {
254 	zval args[2];
255 	STDVARS;
256 
257 	ZVAL_STR_COPY(&args[0], key);
258 	ZVAL_STR_COPY(&args[1], val);
259 
260 	/* maintain backwards compatibility */
261 	if (!Z_ISUNDEF(PSF(update_timestamp))) {
262 		ps_call_handler(&PSF(update_timestamp), 2, args, &retval);
263 	} else {
264 		ps_call_handler(&PSF(write), 2, args, &retval);
265 	}
266 
267 	FINISH;
268 }
269