xref: /PHP-7.4/ext/session/mod_user.c (revision a6d21963)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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(NULL, 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 		*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