summaryrefslogtreecommitdiff
path: root/ext/session/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/session/session.c')
-rw-r--r--ext/session/session.c84
1 files changed, 54 insertions, 30 deletions
diff --git a/ext/session/session.c b/ext/session/session.c
index 456471efbe..44fe30c147 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -153,6 +153,8 @@ PHP_INI_BEGIN()
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) */
PHP_INI_END()
@@ -536,25 +538,67 @@ static void php_session_decode(const char *val, int vallen TSRMLS_DC)
}
}
-static char hexconvtab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+/*
+ * 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 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;
- unsigned int w;
zval **array;
zval **token;
char *remote_addr = NULL;
@@ -628,33 +672,13 @@ char *php_session_create_id(PS_CREATE_SID_ARGS)
break;
}
- if (digest_len == 16) {
- for (i = 0; i < digest_len; i++) {
- c = digest[i];
-
- buf[j++] = hexconvtab[c >> 4];
- buf[j++] = hexconvtab[c & 15];
- }
- } else {
- int bit_offset, off2, off3;
-
- /* take 5 bits from the bit stream per iteration */
-
- /* ensure that there is a NUL byte at the end */
- digest[digest_len] = 0;
- for (i = 0; i < digest_len * 8 / 5; i++) {
- bit_offset = i * 5;
- off2 = bit_offset >> 3;
- off3 = bit_offset & 7;
-
- w = digest[off2] + (digest[off2+1] << 8);
-
- w = (w >> off3) & 31;
+ if (PS(hash_bits_per_character) < 4
+ || PS(hash_bits_per_character) > 6) {
+ PS(hash_bits_per_character) = 4;
- buf[j++] = hexconvtab[w];
- }
+ php_error(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 = bin_to_readable(digest, digest_len, buf, PS(hash_bits_per_character)) - buf;
if (newlen)
*newlen = j;