Skip to content

Commit

Permalink
Add callbacks validate_sid() & update_timestamp() to session handler
Browse files Browse the repository at this point in the history
Newer session handler API(PS_MOD_UPDATE_TIMESTAMP) supports 2 more callbacks:

* validate_sid() is used by session.use_strict_mode, which provides better security.
* update_timestamp() is used by session.lazy_write, which can improve performance in some situations.
  • Loading branch information
hongboliu authored and yatsukhnenko committed Jun 4, 2018
1 parent 28ec432 commit aaaf0f2
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
106 changes: 106 additions & 0 deletions redis_session.c
Expand Up @@ -61,9 +61,16 @@
/* Check if a response is the Redis +OK status response */
#define IS_REDIS_OK(r, len) (r != NULL && len == 3 && !memcmp(r, "+OK", 3))

#if (PHP_MAJOR_VERSION < 7)
ps_module ps_mod_redis = {
PS_MOD_SID(redis)
};
#else
ps_module ps_mod_redis = {
PS_MOD_UPDATE_TIMESTAMP(redis)
};
#endif

ps_module ps_mod_redis_cluster = {
PS_MOD(rediscluster)
};
Expand Down Expand Up @@ -636,6 +643,105 @@ PS_CREATE_SID_FUNC(redis)
}
/* }}} */

#if (PHP_MAJOR_VERSION >= 7)
/* {{{ PS_VALIDATE_SID_FUNC
*/
PS_VALIDATE_SID_FUNC(redis)
{
char *cmd, *response;
int cmd_len, response_len;
#if (PHP_MAJOR_VERSION < 7)
const char *skey = key;
size_t skeylen = strlen(key);
#else
const char *skey = ZSTR_VAL(key);
size_t skeylen = ZSTR_LEN(key);
#endif

if (!skeylen) return FAILURE;

redis_pool *pool = PS_GET_MOD_DATA();
redis_pool_member *rpm = redis_pool_get_sock(pool, skey TSRMLS_CC);
RedisSock *redis_sock = rpm ? rpm->redis_sock : NULL;
if (!redis_sock) {
return FAILURE;
}

/* send EXISTS command */
zend_string *session = redis_session_key(rpm, skey, skeylen);
cmd_len = REDIS_SPPRINTF(&cmd, "EXISTS", "S", session);
zend_string_release(session);
if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
efree(cmd);
return FAILURE;
}
efree(cmd);

/* read response */
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
return FAILURE;
}

if (response_len == 2 && response[0] == ':' && response[1] == '1') {
efree(response);
return SUCCESS;
} else {
efree(response);
return FAILURE;
}
}
/* }}} */

/* {{{ PS_UPDATE_TIMESTAMP_FUNC
*/
PS_UPDATE_TIMESTAMP_FUNC(redis)
{
char *cmd, *response;
int cmd_len, response_len;
#if (PHP_MAJOR_VERSION < 7)
const char *skey = key, *sval = val;
size_t skeylen = strlen(key), svallen = vallen;
#else
const char *skey = ZSTR_VAL(key), *sval = ZSTR_VAL(val);
size_t skeylen = ZSTR_LEN(key), svallen = ZSTR_LEN(val);
#endif

if (!skeylen) return FAILURE;

redis_pool *pool = PS_GET_MOD_DATA();
redis_pool_member *rpm = redis_pool_get_sock(pool, skey TSRMLS_CC);
RedisSock *redis_sock = rpm ? rpm->redis_sock : NULL;
if (!redis_sock) {
return FAILURE;
}

/* send EXPIRE command */
zend_string *session = redis_session_key(rpm, skey, skeylen);
cmd_len = REDIS_SPPRINTF(&cmd, "EXPIRE", "Sd", session, INI_INT("session.gc_maxlifetime"));
zend_string_release(session);

if (!write_allowed(redis_sock, &pool->lock_status TSRMLS_CC) || redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
efree(cmd);
return FAILURE;
}
efree(cmd);

/* read response */
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC)) == NULL) {
return FAILURE;
}

if (response_len == 2 && response[0] == ':' && response[1] == '1') {
efree(response);
return SUCCESS;
} else {
efree(response);
return FAILURE;
}
}
/* }}} */
#endif

/* {{{ PS_READ_FUNC
*/
PS_READ_FUNC(redis)
Expand Down
5 changes: 5 additions & 0 deletions redis_session.h
Expand Up @@ -11,6 +11,11 @@ PS_DESTROY_FUNC(redis);
PS_GC_FUNC(redis);
PS_CREATE_SID_FUNC(redis);

#if (PHP_MAJOR_VERSION >= 7)
PS_VALIDATE_SID_FUNC(redis);
PS_UPDATE_TIMESTAMP_FUNC(redis);
#endif

PS_OPEN_FUNC(rediscluster);
PS_CLOSE_FUNC(rediscluster);
PS_READ_FUNC(rediscluster);
Expand Down

0 comments on commit aaaf0f2

Please sign in to comment.