[PHP-users 28314] Re: Strict Sessionパッチ

Seiji Masugata s.masugata @ digicom.dnp.co.jp
2006年 2月 3日 (金) 12:47:48 JST


こんにちわ、桝形です。

> 昨年の11月にHardedned PHPのStefanさんがStrict Sessionパッチを公開さ
> れました。PHP 5.1.2にもそのまま適用できるのですが、SQLite用のvalidation
> 関数が定義されていない為、SQLiteと一緒にビルドできませんでした。
> 
> 個人的なニーズがあったのでSQLiteも一緒にビルドできるパッチを作りました。
> 
> http://blog.ohgaki.net/index.php/yohgaki/2006/02/02/strict_sessioncric_a_a_a
> 
> PHP4は運用していないのでパッチは作っていません。PHP 5.1.2用のみです。

オリジナルのStrict SessionパッチがPHP4.4.2では当たらないようなので
手直ししてみました。

(mm辺りとか)検証していないので人柱になってくれる方がいたら嬉しいです。
fileとユーザー定義のハンドラ辺りでの検証はやってますけど。

既に似たようなモノがあったらスミマセン。
少し長くて恐縮ですが。。。

------------------------------------------------------------------------------
--- php-4.4.2,orig/ext/session/mod_files.c	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/mod_files.c	2006-02-02 18:09:37.000000000 +0900
@@ -389,6 +389,34 @@
 	return SUCCESS;
 }
 
+PS_VALIDATE_SID_FUNC(files)
+{
+	char buf[MAXPATHLEN];
+	int fd;
+	PS_FILES_DATA;
+	
+	if (!ps_files_valid_key(key)) {
+		return FAILURE;
+	}
+	
+	if (!PS(use_strict_mode)) {
+		return SUCCESS;
+	}
+	
+	if (!ps_files_path_create(buf, sizeof(buf), data, key)) {
+		return FAILURE;
+	}
+	
+	fd = VCWD_OPEN_MODE(buf, O_RDWR | O_BINARY, 0600);
+	
+	if (fd != -1) {
+		close(fd);
+		return SUCCESS;
+	}
+	
+	return FAILURE;
+}
+
 /*
  * Local variables:
  * tab-width: 4
--- php-4.4.2,orig/ext/session/mod_mm.c	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/mod_mm.c	2006-02-02 18:09:37.000000000 +0900
@@ -425,6 +425,42 @@
 	return SUCCESS;
 }
 
+PS_VALIDATE_SID_FUNC(mm)
+{
+	PS_MM_DATA;
+	ps_sd *sd;
+	const char *p;
+	char c;
+	int ret = SUCCESS;
+	
+	for (p = key; (c = *p); p++) {
+		/* valid characters are a..z,A..Z,0..9 */
+		if (!((c >= 'a' && c <= 'z')
+				|| (c >= 'A' && c <= 'Z')
+				|| (c >= '0' && c <= '9')
+				|| c == ','
+				|| c == '-')) {
+			return FAILURE;
+		}
+	}
+	
+	if (!PS(use_strict_mode)) {
+		return SUCCESS;
+	}
+	
+	mm_lock(data->mm, MM_LOCK_RD);
+	
+	sd = ps_sd_lookup(data, key, 0);
+	if (sd) {
+		mm_unlock(data->mm);
+		return SUCCESS;
+	}
+	
+	mm_unlock(data->mm);
+	
+	return FAILURE;
+}
+
 #endif
 
 /*
--- php-4.4.2,orig/ext/session/mod_user.c	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/mod_user.c	2006-02-02 18:09:37.000000000 +0900
@@ -23,7 +23,7 @@
 #include "mod_user.h"
 
 ps_module ps_mod_user = {
-	PS_MOD(user)
+	PS_MOD_SID(user)
 };
 
 #define SESS_ZVAL_LONG(val, a) 					\
@@ -174,6 +174,83 @@
 	FINISH;
 }
 
+PS_CREATE_SID_FUNC(user)
+{
+	int i;
+	char *val = NULL;
+	zval *retval;
+	ps_user *mdata = PS_GET_MOD_DATA();
+	
+	if (!mdata)
+		return estrndup("", 0);
+	
+	if (PSF(create) == NULL || ZVAL_IS_NULL(PSF(create))) {
+		return php_session_create_id(mod_data, newlen TSRMLS_CC);
+	}
+	retval = ps_call_handler(PSF(create), 0, NULL TSRMLS_CC);
+
+	if (retval) {
+		if (Z_TYPE_P(retval) == IS_STRING) {
+			val = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+		} else {
+			val = estrndup("", 0);
+		}
+		zval_ptr_dtor(&retval);
+	} else {
+		val = estrndup("", 0);
+	}
+	
+	return val;
+}
+
+static int ps_user_valid_key(const char *key TSRMLS_DC)
+{
+	size_t len;
+	const char *p;
+	char c;
+	int ret = SUCCESS;
+
+	for (p = key; (c = *p); p++) {
+		/* valid characters are a..z,A..Z,0..9 */
+		if (!((c >= 'a' && c <= 'z')
+				|| (c >= 'A' && c <= 'Z')
+				|| (c >= '0' && c <= '9')
+				|| c == ','
+				|| c == '-')) {
+			ret = FAILURE;
+			break;
+		}
+	}
+
+	len = p - key;
+	
+	if (len == 0)
+		ret = FAILURE;
+	
+	return ret;
+}
+
+PS_VALIDATE_SID_FUNC(user)
+{
+	zval *args[1];
+	STDVARS;
+	
+	if (PSF(validate) == NULL || ZVAL_IS_NULL(PSF(validate))) {
+		return ps_user_valid_key(key TSRMLS_CC);
+	}
+	SESS_ZVAL_STRING(key, args[0]);
+	
+	retval = ps_call_handler(PSF(validate), 1, args TSRMLS_CC);
+	
+	if (retval) {
+		convert_to_long(retval);
+		ret = Z_LVAL_P(retval) ? SUCCESS : FAILURE;
+		zval_ptr_dtor(&retval);
+	}
+	
+	return ret;
+}
+
 /*
  * Local variables:
  * tab-width: 4
--- php-4.4.2,orig/ext/session/mod_user.h	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/mod_user.h	2006-02-02 18:09:37.000000000 +0900
@@ -22,7 +22,7 @@
 #define MOD_USER_H
 
 typedef union {
-	zval *names[6];
+	zval *names[8];
 	struct {
 		zval *ps_open;
 		zval *ps_close;
@@ -30,6 +30,8 @@
 		zval *ps_write;
 		zval *ps_destroy;
 		zval *ps_gc;
+		zval *ps_create;
+		zval *ps_validate;
 	} name;
 } ps_user;
 
--- php-4.4.2,orig/ext/session/php_session.h	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/php_session.h	2006-02-02 18:09:37.000000000 +0900
@@ -23,7 +23,7 @@
 
 #include "ext/standard/php_var.h"
 
-#define PHP_SESSION_API 20020330
+#define PHP_SESSION_API 20051121
 
 #define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name TSRMLS_DC
 #define PS_CLOSE_ARGS void **mod_data TSRMLS_DC
@@ -32,6 +32,7 @@
 #define PS_DESTROY_ARGS void **mod_data, const char *key TSRMLS_DC
 #define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels TSRMLS_DC
 #define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC
+#define PS_VALIDATE_SID_ARGS void **mod_data, const char *key TSRMLS_DC
 
 /* default create id function */
 char *php_session_create_id(PS_CREATE_SID_ARGS);
@@ -45,6 +46,7 @@
 	int (*s_destroy)(PS_DESTROY_ARGS);
 	int (*s_gc)(PS_GC_ARGS);
 	char *(*s_create_sid)(PS_CREATE_SID_ARGS);
+	int (*s_validate_sid)(PS_VALIDATE_SID_ARGS);
 } ps_module;
 
 #define PS_GET_MOD_DATA() *mod_data
@@ -57,6 +59,7 @@
 #define PS_DESTROY_FUNC(x) 	int ps_delete_##x(PS_DESTROY_ARGS)
 #define PS_GC_FUNC(x) 		int ps_gc_##x(PS_GC_ARGS)
 #define PS_CREATE_SID_FUNC(x)	char *ps_create_sid_##x(PS_CREATE_SID_ARGS)
+#define PS_VALIDATE_SID_FUNC(x)	int ps_validate_sid_##x(PS_VALIDATE_SID_ARGS)
 
 #define PS_FUNCS(x) \
 	PS_OPEN_FUNC(x); \
@@ -65,11 +68,12 @@
 	PS_WRITE_FUNC(x); \
 	PS_DESTROY_FUNC(x); \
 	PS_GC_FUNC(x);	\
-	PS_CREATE_SID_FUNC(x)
+	PS_CREATE_SID_FUNC(x); \
+	PS_VALIDATE_SID_FUNC(x)
 
 #define PS_MOD(x) \
 	#x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \
-	 ps_delete_##x, ps_gc_##x, php_session_create_id
+	 ps_delete_##x, ps_gc_##x, php_session_create_id, ps_validate_sid_##x
 
 /* SID enabled module handler definitions */
 #define PS_FUNCS_SID(x) \
@@ -79,11 +83,12 @@
 	PS_WRITE_FUNC(x); \
 	PS_DESTROY_FUNC(x); \
 	PS_GC_FUNC(x); \
-	PS_CREATE_SID_FUNC(x)
+	PS_CREATE_SID_FUNC(x); \
+	PS_VALIDATE_SID(x)
 
 #define PS_MOD_SID(x) \
 	#x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \
-	 ps_delete_##x, ps_gc_##x, ps_create_sid_##x
+	 ps_delete_##x, ps_gc_##x, ps_create_sid_##x, ps_validate_sid_##x
 
 typedef enum {
 	php_session_disabled,
@@ -120,6 +125,7 @@
 	zend_bool use_only_cookies;
 	zend_bool use_trans_sid;	/* contains the INI value of whether to use trans-sid */
 	zend_bool apply_trans_sid;	/* whether or not to enable trans-sid for the current request */
+	zend_bool use_strict_mode;      /* whether or not PHP accepts unknown session ids */
 	int send_cookie;
 	int define_sid;
 } php_ps_globals;
--- php-4.4.2,orig/ext/session/session.c	2006-01-01 22:46:56.000000000 +0900
+++ php-4.4.2/ext/session/session.c	2006-02-02 18:09:37.000000000 +0900
@@ -155,6 +155,7 @@
 	STD_PHP_INI_BOOLEAN("session.cookie_secure",    "",          PHP_INI_ALL, OnUpdateBool,   cookie_secure,      php_ps_globals,    ps_globals)
 	STD_PHP_INI_BOOLEAN("session.use_cookies",      "1",         PHP_INI_ALL, OnUpdateBool,   use_cookies,        php_ps_globals,    ps_globals)
 	STD_PHP_INI_BOOLEAN("session.use_only_cookies", "0",         PHP_INI_ALL, OnUpdateBool,   use_only_cookies,   php_ps_globals,    ps_globals)
+	STD_PHP_INI_BOOLEAN("session.use_strict_mode",  "1",         PHP_INI_ALL, OnUpdateBool,   use_strict_mode,    php_ps_globals,    ps_globals)
 	STD_PHP_INI_ENTRY("session.referer_check",      "",          PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals,    ps_globals)
 	STD_PHP_INI_ENTRY("session.entropy_file",       "",          PHP_INI_ALL, OnUpdateString, entropy_file,       php_ps_globals,    ps_globals)
 	STD_PHP_INI_ENTRY("session.entropy_length",     "0",         PHP_INI_ALL, OnUpdateInt,    entropy_length,     php_ps_globals,    ps_globals)
@@ -637,6 +638,15 @@
 		return;
 	}
 	
+	/* If there is an ID, use session module to verify it */
+	if (PS(id)) {
+		if (PS(mod)->s_validate_sid(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) {
+			efree(PS(id));
+			PS(id) = NULL;
+			PS(send_cookie) = 1;
+		}
+	}
+	
 	/* If there is no ID, use session module to create one */
 	if (!PS(id))
 		PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC);
@@ -1256,22 +1266,29 @@
 }
 /* }}} */
 
-/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc)
-   Sets user-level functions */
+/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc[, string create, string validate])
+    Sets user-level functions */
 PHP_FUNCTION(session_set_save_handler)
 {
-	zval **args[6];
-	int i;
+	zval **args[8];
+	int i, numargs;
 	ps_user *mdata;
 	char *name;
 
-	if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE)
+	numargs = ZEND_NUM_ARGS();
+	args[6] = NULL;
+	args[7] = NULL;
+	
+	if (numargs < 6 || numargs > 8 || zend_get_parameters_array_ex(numargs, args) == FAILURE)
 		WRONG_PARAM_COUNT;
 	
 	if (PS(session_status) != php_session_none) 
 		RETURN_FALSE;
 
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 8; i++) {
+		if (i >= 6 && (args[i] == NULL || ZVAL_IS_NULL(*args[i]))) {
+			continue;
+		}
 		if (!zend_is_callable(*args[i], 0, &name)) {
 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1);
 			efree(name);
@@ -1284,7 +1301,11 @@
 
 	mdata = emalloc(sizeof(*mdata));
 	
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 8; i++) {
+		if (i >= 6 && (args[i] == NULL || ZVAL_IS_NULL(*args[i]))) {
+			mdata->names[i] = NULL;
+			continue;
+		}
 		ZVAL_ADDREF(*args[i]);
 		mdata->names[i] = *args[i];
 	}
------------------------------------------------------------------------------

-- 
Seiji Masugata <s.masugata @ digicom.dnp.co.jp>



PHP-users メーリングリストの案内