ます’s Blog - どうでもいい記事100選

どうでもいい記事100選

SessionモジュールSHA1パッチ(4.4.2用)

コレに関連する事ですが(主にコレ)。
PHP5からはセッションIDの生成にSHA1を利用できるのですが、PHP4ではMD5だけです。
(なんとなく)PHP4でもSHA1を利用したいので(またしても適当な)タコさんパッチ。
作ったというよりは移植だなぁ。。。かなりコピー&ペースト作業だし。(w
(これまた長いけど)全文貼り付けぢゃっ!事前にこのパッチを当ててから、以下のパッチを当てて下さい。

--- php-4.4.2/ext/session/php_session.h,orig	2006-02-02 18:09:37.000000000 +0900
+++ php-4.4.2/ext/session/php_session.h	2006-03-06 08:48:07.000000000 +0900
@@ -126,6 +126,8 @@
 	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 */
+	long hash_func;
+	long hash_bits_per_character;
 	int send_cookie;
 	int define_sid;
 } php_ps_globals;
--- php-4.4.2/ext/session/session.c,orig	2006-02-02 18:09:37.000000000 +0900
+++ php-4.4.2/ext/session/session.c	2006-03-06 08:48:07.000000000 +0900
@@ -38,6 +38,7 @@
 #include "SAPI.h"
 #include "php_session.h"
 #include "ext/standard/md5.h"
+#include "ext/standard/sha1.h"
 #include "ext/standard/php_var.h"
 #include "ext/standard/datetime.h"
 #include "ext/standard/php_lcg.h"
@@ -162,6 +163,8 @@
 	STD_PHP_INI_ENTRY("session.cache_limiter",      "nocache",   PHP_INI_ALL, OnUpdateString, cache_limiter,      php_ps_globals,    ps_globals)
 	STD_PHP_INI_ENTRY("session.cache_expire",       "180",       PHP_INI_ALL, OnUpdateInt,    cache_expire,       php_ps_globals,    ps_globals)
 	STD_PHP_INI_BOOLEAN("session.use_trans_sid",    "0",         PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool,   use_trans_sid,      php_ps_globals,    ps_globals)
+	STD_PHP_INI_ENTRY("session.hash_function",      "0",         PHP_INI_ALL, OnUpdateInt,    hash_func,          php_ps_globals,    ps_globals)
+	STD_PHP_INI_ENTRY("session.hash_bits_per_character",      "4",         PHP_INI_ALL, OnUpdateInt,    hash_bits_per_character,          php_ps_globals,    ps_globals)
 
 	/* Commented out until future discussion */
 	/* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */
@@ -571,55 +574,150 @@
 	}
 }
 
-static char hexconvtab[] = "0123456789abcdef";
+/*
+ * Note that we cannot use the BASE64 alphabet here, because
+ * it contains "/" and "+": both are unacceptable for simple inclusion
+ * into URLs.
+ */
+
+static char hexconvtab[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-";
+
+enum {
+	PS_HASH_FUNC_MD5,
+	PS_HASH_FUNC_SHA1
+};
+
+/* returns a pointer to the byte after the last valid character in out */
+static char *bin_to_readable(char *in, size_t inlen, char *out, char nbits)
+{
+	unsigned char *p, *q;
+	unsigned short w;
+	int mask;
+	int have;
+	
+	p = in;
+	q = in + inlen;
+
+	w = 0;
+	have = 0;
+	mask = (1 << nbits) - 1;
+	
+	while (1) {
+		if (have < nbits) {
+			if (p < q) {
+				w |= *p++ << have;
+				have += 8;
+			} else {
+				/* consumed everything? */
+				if (have == 0) break;
+				/* No? We need a final round */
+				have = nbits;
+			}
+		}
+
+		/* consume nbits */
+		*out++ = hexconvtab[w & mask];
+		w >>= nbits;
+		have -= nbits;
+	}
+	
+	*out = '\0';
+	return out;
+}
 
 char *php_session_create_id(PS_CREATE_SID_ARGS)
 {
-	PHP_MD5_CTX context;
-	unsigned char digest[16];
-	char buf[256];
+	PHP_MD5_CTX md5_context;
+	PHP_SHA1_CTX sha1_context;
+	unsigned char digest[21];
+	int digest_len;
+	int j;
+	char *buf;
 	struct timeval tv;
-	int i;
-	int j = 0;
-	unsigned char c;
+	zval **array;
+	zval **token;
+	char *remote_addr = NULL;
 
 	gettimeofday(&tv, NULL);
-	PHP_MD5Init(&context);
 	
-	sprintf(buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10);
-	PHP_MD5Update(&context, buf, strlen(buf));
+	if (zend_hash_find(&EG(symbol_table), "_SERVER",
+				sizeof("_SERVER"), (void **) &array) == SUCCESS &&
+			Z_TYPE_PP(array) == IS_ARRAY &&
+			zend_hash_find(Z_ARRVAL_PP(array), "REMOTE_ADDR",
+				sizeof("REMOTE_ADDR"), (void **) &token) == SUCCESS) {
+		remote_addr = Z_STRVAL_PP(token);
+	}
+
+	buf = emalloc(100);
+
+	/* maximum 15+19+19+10 bytes */	
+	sprintf(buf, "%.15s%ld%ld%0.8f", remote_addr ? remote_addr : "", 
+			tv.tv_sec, tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10);
+
+	switch (PS(hash_func)) {
+	case PS_HASH_FUNC_MD5:
+		PHP_MD5Init(&md5_context);
+		PHP_MD5Update(&md5_context, buf, strlen(buf));
+		digest_len = 16;
+		break;
+	case PS_HASH_FUNC_SHA1:
+		PHP_SHA1Init(&sha1_context);
+		PHP_SHA1Update(&sha1_context, buf, strlen(buf));
+		digest_len = 20;
+		break;
+	default:
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid session hash function");
+		efree(buf);
+		return NULL;
+	}
 
 	if (PS(entropy_length) > 0) {
 		int fd;
 
 		fd = VCWD_OPEN(PS(entropy_file), O_RDONLY);
 		if (fd >= 0) {
-			unsigned char buf[2048];
+			unsigned char rbuf[2048];
 			int n;
 			int to_read = PS(entropy_length);
 			
 			while (to_read > 0) {
-				n = read(fd, buf, MIN(to_read, sizeof(buf)));
+				n = read(fd, rbuf, MIN(to_read, sizeof(rbuf)));
 				if (n <= 0) break;
-				PHP_MD5Update(&context, buf, n);
+				
+				switch (PS(hash_func)) {
+				case PS_HASH_FUNC_MD5:
+					PHP_MD5Update(&md5_context, rbuf, n);
+					break;
+				case PS_HASH_FUNC_SHA1:
+					PHP_SHA1Update(&sha1_context, rbuf, n);
+					break;
+				}
 				to_read -= n;
 			}
 			close(fd);
 		}
 	}
 
-	PHP_MD5Final(digest, &context);
-	
-	for (i = 0; i < 16; i++) {
-		c = digest[i];
-		buf[j++] = hexconvtab[c >> 4];
-		buf[j++] = hexconvtab[c & 15];
+	switch (PS(hash_func)) {
+	case PS_HASH_FUNC_MD5:
+		PHP_MD5Final(digest, &md5_context);
+		break;
+	case PS_HASH_FUNC_SHA1:
+		PHP_SHA1Final(digest, &sha1_context);
+		break;
+	}
+
+	if (PS(hash_bits_per_character) < 4
+			|| PS(hash_bits_per_character) > 6) {
+		PS(hash_bits_per_character) = 4;
+
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ini setting hash_bits_per_character is out of range (should be 4, 5, or 6) - using 4 for now");
 	}
-	buf[j] = '\0';
+	j = (int) (bin_to_readable(digest, digest_len, buf, PS(hash_bits_per_character)) - buf);
 	
 	if (newlen) 
 		*newlen = j;
-	return estrdup(buf);
+	return buf;
 }
 
 static void php_session_initialize(TSRMLS_D)

「php.ini」ファイルにに「session.hash_function = 1」のエントリを追加する事をお忘れなく。