xref: /PHP-7.3/ext/session/mod_user.c (revision a6d21963)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Sascha Schumann <sascha@schumann.cx>                         |
16    +----------------------------------------------------------------------+
17  */
18 
19 #include "php.h"
20 #include "php_session.h"
21 #include "mod_user.h"
22 
23 const ps_module ps_mod_user = {
24 	PS_MOD_UPDATE_TIMESTAMP(user)
25 };
26 
27 
ps_call_handler(zval * func,int argc,zval * argv,zval * retval)28 static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval)
29 {
30 	int i;
31 	if (PS(in_save_handler)) {
32 		PS(in_save_handler) = 0;
33 		ZVAL_UNDEF(retval);
34 		php_error_docref(NULL, E_WARNING, "Cannot call session save handler in a recursive manner");
35 		return;
36 	}
37 	PS(in_save_handler) = 1;
38 	if (call_user_function(EG(function_table), NULL, func, retval, argc, argv) == FAILURE) {
39 		zval_ptr_dtor(retval);
40 		ZVAL_UNDEF(retval);
41 	} else if (Z_ISUNDEF_P(retval)) {
42 		ZVAL_NULL(retval);
43 	}
44 	PS(in_save_handler) = 0;
45 	for (i = 0; i < argc; i++) {
46 		zval_ptr_dtor(&argv[i]);
47 	}
48 }
49 
50 #define STDVARS								\
51 	zval retval;							\
52 	int ret = FAILURE
53 
54 #define PSF(a) PS(mod_user_names).name.ps_##a
55 
56 #define FINISH \
57 	if (Z_TYPE(retval) != IS_UNDEF) { \
58 		if (Z_TYPE(retval) == IS_TRUE) { \
59 			ret = SUCCESS; \
60 		} else if (Z_TYPE(retval) == IS_FALSE) { \
61 			ret = FAILURE; \
62         }  else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == -1)) { \
63 			/* BC for clever users - Deprecate me */ \
64 			ret = FAILURE; \
65 		} else if ((Z_TYPE(retval) == IS_LONG) && (Z_LVAL(retval) == 0)) { \
66 			/* BC for clever users - Deprecate me */ \
67 			ret = SUCCESS; \
68 		} else { \
69 			if (!EG(exception)) { \
70 				php_error_docref(NULL, E_WARNING, \
71 				                 "Session callback expects true/false return value"); \
72 			} \
73 			ret = FAILURE; \
74 			zval_ptr_dtor(&retval); \
75 		} \
76 	} \
77 	return ret
78 
PS_OPEN_FUNC(user)79 PS_OPEN_FUNC(user)
80 {
81 	zval args[2];
82 	STDVARS;
83 
84 	if (Z_ISUNDEF(PSF(open))) {
85 		php_error_docref(NULL, E_WARNING,
86 			"user session functions 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 	zend_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 		convert_to_long(&retval);
193 		*nrdels = Z_LVAL(retval);
194 	} else if (Z_TYPE(retval) == IS_TRUE) {
195 		/* This is for older API compatibility */
196 		*nrdels = 1;
197 	} else {
198 		/* Anything else is some kind of error */
199 		*nrdels = -1; // Error
200 	}
201 	return *nrdels;
202 }
203 
PS_CREATE_SID_FUNC(user)204 PS_CREATE_SID_FUNC(user)
205 {
206 	/* maintain backwards compatibility */
207 	if (!Z_ISUNDEF(PSF(create_sid))) {
208 		zend_string *id = NULL;
209 		zval retval;
210 
211 		ps_call_handler(&PSF(create_sid), 0, NULL, &retval);
212 
213 		if (!Z_ISUNDEF(retval)) {
214 			if (Z_TYPE(retval) == IS_STRING) {
215 				id = zend_string_copy(Z_STR(retval));
216 			}
217 			zval_ptr_dtor(&retval);
218 		} else {
219 			zend_throw_error(NULL, "No session id returned by function");
220 			return NULL;
221 		}
222 
223 		if (!id) {
224 			zend_throw_error(NULL, "Session id must be a string");
225 			return NULL;
226 		}
227 
228 		return id;
229 	}
230 
231 	/* function as defined by PS_MOD */
232 	return php_session_create_id(mod_data);
233 }
234 
PS_VALIDATE_SID_FUNC(user)235 PS_VALIDATE_SID_FUNC(user)
236 {
237 	/* maintain backwards compatibility */
238 	if (!Z_ISUNDEF(PSF(validate_sid))) {
239 		zval args[1];
240 		STDVARS;
241 
242 		ZVAL_STR_COPY(&args[0], key);
243 
244 		ps_call_handler(&PSF(validate_sid), 1, args, &retval);
245 
246 		FINISH;
247 	}
248 
249 	/* dummy function defined by PS_MOD */
250 	return php_session_validate_sid(mod_data, key);
251 }
252 
PS_UPDATE_TIMESTAMP_FUNC(user)253 PS_UPDATE_TIMESTAMP_FUNC(user)
254 {
255 	zval args[2];
256 	STDVARS;
257 
258 	ZVAL_STR_COPY(&args[0], key);
259 	ZVAL_STR_COPY(&args[1], val);
260 
261 	/* maintain backwards compatibility */
262 	if (!Z_ISUNDEF(PSF(update_timestamp))) {
263 		ps_call_handler(&PSF(update_timestamp), 2, args, &retval);
264 	} else {
265 		ps_call_handler(&PSF(write), 2, args, &retval);
266 	}
267 
268 	FINISH;
269 }
270 
271 /*
272  * Local variables:
273  * tab-width: 4
274  * c-basic-offset: 4
275  * End:
276  * vim600: sw=4 ts=4 fdm=marker
277  * vim<600: sw=4 ts=4
278  */
279