Welcome! Log In Create A New Profile

Advanced

Re: Redirect based on php-set cookies

February 10, 2011 07:11AM
[b]For someone who is interested in using this module[/b]

To compile with nginx, do the following steps:

1. Download Nginx source code from http://wiki.nginx.org/NginxInstall, and put them in, let's say, folder 'nginx'

2. Install OpenSSL for your Linux.

3. You need also to download OpenSSL source code, and copy folder openssl/crypto/sha to nginx/src. This step is important, as the secret_cookie module depends on OpenSSL at compile time.

4. Copy sha/sha.h in openssl/crypto/sha into nginx/src/core. You will get compilation error if not doing this.

5. Now create a folder name nginx/src/secret_cookie to store the secret_cookie module. Put the config and ngx_http_secret_cookie_module.c (described below) in this folder.

7. Go to folder nginx and now you can configure the make:

./configure --prefix=/usr/local/nginx-proxy/ --with-http_ssl_module --add-module=src/secret_cookie --with-sha1=src/sha

Please change the directory as per your server configuration.

8. Run make, if everything is ok, you should now be able to compile nginx with the secret_cookie module.

Content of the config file:

[code]ngx_addon_name=ngx_http_secret_cookie_module
HTTP_MODULES="$HTTP_MODULES ngx_http_secret_cookie_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_secret_cookie_module.c"
[/code]

Content of the ngx_http_secret_cookie_module.c file:
[code]
/*
* Copyright (C) Huan Cong Nguyen
* Version 1.0.6
*/

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <ngx_sha1.h>

/*
* This module set the $secret_cookie_value variable
* to the names of valid secret cookies set at client.
* Based on the variable, user can be classified
* into verified and non-verified one.
*/
#define NGX_HTTP_SECRET_COOKIE_OFF 0 // Default state
#define NGX_HTTP_SECRET_COOKIE_ON 1

#define NGX_HTTP_SECRET_COOKIE_NOT_SET 0

#define NGX_HTTP_SECRET_COOKIE_MINIMUM_DURATION 600 // 10 minutes
#define NGX_HTTP_SECRET_COOKIE_MINIMUM_UA_LIMIT 10 // 10 characters
#define NGX_HTTP_SECRET_COOKIE_MAX_SHORT_STR_SIZE 12 // Allow only 12 characters in name, salt and rule

// Rule elements
#define NGX_HTTP_SECRET_COOKIE_RULE_SALT 's'
#define NGX_HTTP_SECRET_COOKIE_RULE_ADDRESS 'a'
#define NGX_HTTP_SECRET_COOKIE_RULE_TIME 't'
#define NGX_HTTP_SECRET_COOKIE_RULE_USER_AGENT 'u'
#define NGX_HTTP_SECRET_COOKIE_DIVIDER ' '

// Record for each secret cookie
typedef struct {
ngx_flag_t status;
ngx_flag_t log;
ngx_uint_t duration;
ngx_str_t name;
ngx_str_t rule;
ngx_str_t salt;
ngx_uint_t ua_limit;
} ngx_http_secret_cookie_t;

// Record for Location configuration
typedef struct {
ngx_flag_t status;
ngx_array_t *secret_cookies;
ngx_http_variable_value_t *secret_cookie_value_disabled;
} ngx_http_secret_cookie_conf_t;

// Context variable: This alive for request's duration
typedef struct {
ngx_http_variable_value_t *secret_cookie_value;
} ngx_http_secret_cookie_ctx_t;

// Return variable structure
typedef struct {
ngx_str_t name;
ngx_http_get_variable_pt handler;
uintptr_t data;
} ngx_http_secret_cookie_variable_t;

static void *ngx_http_secret_cookie_create_conf(ngx_conf_t *cf);
static char *ngx_http_secret_cookie_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
static ngx_int_t ngx_http_secret_cookie_add_variable(ngx_conf_t *cf);
static ngx_int_t ngx_http_secret_cookie_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_http_secret_cookie_ctx_t * ngx_http_secret_cookie_handler(ngx_http_request_t *r,
ngx_http_secret_cookie_conf_t *cf);
static char *ngx_http_secret_cookie_def(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static u_char * ngx_num2str(u_char *buf, u_char *last, uint64_t ui64);
static ngx_int_t ngx_raw_vs_hex(u_char *rawbuf, size_t rlen, u_char *hexbuf, size_t hlen);

static ngx_command_t ngx_http_secret_cookie_commands[] = {
/* Define secret_cookie directive (on or off).
* Location: Main, HTTP
* Take: 1 parameter, a Flag
*/
{ ngx_string("secret_cookie"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot, // Convert on/off to value
NGX_HTTP_LOC_CONF_OFFSET, // Instruct value to be written to Location Config,
offsetof(ngx_http_secret_cookie_conf_t, status), // with this offset
NULL }, // No post-handler is necessary.

/* Define secret_cookie_def directive ([off] name=xyz salt=abc rule=mnk duration=8323)
* Location: Main, HTTP
* Taking: 4 or 5 parameters
*/
{ ngx_string("secret_cookie_def"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE4|NGX_CONF_TAKE5|NGX_CONF_TAKE6|NGX_CONF_TAKE7,
ngx_http_secret_cookie_def,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },

ngx_null_command
};


static ngx_http_module_t ngx_http_secret_cookie_module_ctx = {
ngx_http_secret_cookie_add_variable, /* preconfiguration */
NULL, /* postconfiguration */

NULL, /* create main configuration */
NULL, /* init main configuration */

NULL, /* create server configuration */
NULL, /* merge server configuration */

ngx_http_secret_cookie_create_conf, /* create location configuration */
ngx_http_secret_cookie_merge_conf /* merge location configuration */
};


ngx_module_t ngx_http_secret_cookie_module = {
NGX_MODULE_V1,
&ngx_http_secret_cookie_module_ctx, /* module context */
ngx_http_secret_cookie_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};

static ngx_http_secret_cookie_variable_t ngx_http_secret_cookie_vars[] = {
{ ngx_string("secret_cookie_value"), ngx_http_secret_cookie_variable,
NGX_HTTP_SECRET_COOKIE_NOT_SET },
{ ngx_null_string, NULL, 0 }
};

/*
* This function set the $secret_cookie_value to found secret_cookie names,
* if they are set and valid.
*/
static ngx_int_t
ngx_http_secret_cookie_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v,
uintptr_t data)
{
ngx_http_secret_cookie_ctx_t *rctx;
ngx_http_secret_cookie_conf_t *cf;

cf = ngx_http_get_module_loc_conf(r, ngx_http_secret_cookie_module);
// Check if the module is enable?
if (cf->status == NGX_HTTP_SECRET_COOKIE_ON){
// Only perform cookie search if the module is enable
rctx = ngx_http_secret_cookie_handler(r, cf);

if (rctx != NULL){
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: Rctx is returned with value");
#endif
*v = *rctx->secret_cookie_value;
return NGX_OK;
} else {
// There is something wrong with the search for secret cookies,
// just return null value to fail all user-defined checks
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Rctx is null, which is often due to lack of memory");
*v = ngx_http_variable_null_value;
return NGX_OK;
}
}
// In case the secret_cookie is disabled,
// all defined secret cookies are assumed to be found,
// so that user-defined checks are successful
*v = *cf->secret_cookie_value_disabled;
return NGX_OK;
}

/*
* This is the main function: It looks for a secret cookie
* in the HTTP request header, and compared with constructed value
* Return: Secret Cookie SET or NOT SET!
*/
static ngx_http_secret_cookie_ctx_t *
ngx_http_secret_cookie_handler(ngx_http_request_t *r, ngx_http_secret_cookie_conf_t *cf)
{
ngx_http_secret_cookie_ctx_t *ctx;
ngx_http_secret_cookie_t *sc;

ngx_uint_t n, i, ua_len;
ngx_int_t m;
ngx_str_t name, rule, salt, last_change,
remote_address, user_agent,
computed_sc, submitted_sc, sc_string,
secret_cookie_value;
time_t timestamp; // Current UNIX timestamp
u_char *p;
ngx_sha1_t sha_ctx;

// Try to get the context variable
ctx = ngx_http_get_module_ctx(r, ngx_http_secret_cookie_module);

// If context existed, secret_cookie was checked before, so stop!
if (ctx){
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: Checking was done before, aborting!");
#endif
return ctx;
}
// Otherwise, start the checking process
if (ctx == NULL) {
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: Checking was not done before, start checking");
#endif
// This r->pool temporary memory will be destroyed later,
// after this request is served!
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secret_cookie_ctx_t));
if (ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for context variable (ctx)");
return NULL;
}
ngx_http_set_ctx(r, ctx, ngx_http_secret_cookie_module);
}
ctx->secret_cookie_value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
if (ctx->secret_cookie_value == NULL){
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for ctx->secret_cookie_value variable");
return NULL;
}
*ctx->secret_cookie_value = ngx_http_variable_null_value;

remote_address.len = r->connection->addr_text.len;
remote_address.data = r->connection->addr_text.data;
if (r->headers_in.user_agent == NULL) {
// The user-agent value is null
user_agent.len = 0;
user_agent.data = NULL;
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: User agent is empty");
#endif
} else {
// The user-agent value is not null
user_agent.len = r->headers_in.user_agent->value.len;
user_agent.data = r->headers_in.user_agent->value.data;
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: User agent is not empty");
#endif
}
secret_cookie_value.len = 0;
// Allocate maximum size for this variable
secret_cookie_value.data = ngx_pcalloc(r->pool, cf->secret_cookie_value_disabled->len);
if (secret_cookie_value.data == NULL){
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for secret_cookie_value string");
return NULL;
}

sc = cf->secret_cookies->elts;
for (i=0; i < cf->secret_cookies->nelts; i++){
// Cookie name must be initialized first, in case of jumping to secret_cookie_found!
name.len = sc[i].name.len;
name.data = sc[i].name.data;

if (sc[i].status == NGX_HTTP_SECRET_COOKIE_OFF){
#if (NGX_DEBUG)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: checking of cookie \"%V\" is off", &name);
#endif
goto secret_cookie_found;
}

// First, search for the secret_cookie's name in http header:
m = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &name,
&submitted_sc);
if (m == NGX_DECLINED) {
#if (NGX_DEBUG)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: cookie \"%V\" is not found in header", &name);
#endif
goto secret_cookie_not_found;
}

#if (NGX_DEBUG)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: cookie \"%V\" found in header, value=%V and length=%i",
&name, &submitted_sc, submitted_sc.len);
#endif

if (submitted_sc.len != 2*SHA_DIGEST_LENGTH) {
#if (NGX_DEBUG)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: size of cookie \"%V\" is incorrect", &name);
#endif
goto secret_cookie_not_found;
}

// User Agent can be very large. Limit to a certain size
// to keep small memory footprint
if ((sc[i].ua_limit > 0) && (user_agent.len > sc[i].ua_limit)) {
ua_len = sc[i].ua_limit;
} else {
ua_len = user_agent.len;
}

salt.len = sc[i].salt.len;
salt.data = sc[i].salt.data;
rule.len = sc[i].rule.len;
rule.data = sc[i].rule.data;
// Obtain current time in second
timestamp = ngx_time();
// Calculate the last_change and convert it to string
last_change.data = ngx_pcalloc(r->pool, NGX_INT64_LEN);
if (last_change.data == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for last_change string");
return NULL;
}
p = ngx_num2str(last_change.data,
last_change.data + NGX_INT64_LEN,
(uint64_t) timestamp / sc[i].duration);
last_change.len = p - last_change.data;

#if (NGX_DEBUG)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: name has length=%i and value=%V", name.len, &name);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: salt has length=%i and value=%V", salt.len, &salt);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: rule has length=%i and value=%V", rule.len, &rule);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: duration = %i", sc[i].duration);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: last_change = %V", &last_change);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: remote_address has length=%i and value=%V",
remote_address.len, &remote_address);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: user-agent has length=%i from value=%V",
ua_len, &user_agent);
#endif

// Second, compute the secret_cookie according to the rule:
sc_string.len = 0;
for (n=0; n < rule.len; n++){
switch (ngx_tolower(rule.data[n])){
case NGX_HTTP_SECRET_COOKIE_RULE_ADDRESS:
sc_string.len += remote_address.len;
break;
case NGX_HTTP_SECRET_COOKIE_RULE_SALT:
sc_string.len += salt.len;
break;
case NGX_HTTP_SECRET_COOKIE_RULE_USER_AGENT:
sc_string.len += ua_len;
break;
case NGX_HTTP_SECRET_COOKIE_RULE_TIME:
sc_string.len += last_change.len;
break;
default:
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: Unknown rule");
#endif
break;
} // End of switch
}

sc_string.data = ngx_pcalloc(r->pool, sc_string.len);
if (sc_string.data == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for sc_string variable");
return NULL;
}
p = sc_string.data;
for (n=0; n < rule.len; n++){
switch (ngx_tolower(rule.data[n])){
case NGX_HTTP_SECRET_COOKIE_RULE_ADDRESS:
// This ngx_copy faster than ngx_cpymem with buffer < 16 bytes
p = ngx_copy(p, remote_address.data, remote_address.len);
break;
case NGX_HTTP_SECRET_COOKIE_RULE_SALT:
p = ngx_copy(p, salt.data, salt.len);
break;
case NGX_HTTP_SECRET_COOKIE_RULE_USER_AGENT:
if (ua_len > 0){
p = ngx_cpymem(p, user_agent.data, ua_len);
}
break;
case NGX_HTTP_SECRET_COOKIE_RULE_TIME:
p = ngx_copy(p, last_change.data, last_change.len);
break;
default:
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: Unknown rule");
#endif
break;
} // End of switch
}
#if (NGX_DEBUG)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: String to compute secret_cookie has length=%i and value=%V",
sc_string.len, &sc_string);
#endif

// Third, perform sha1 on the content
computed_sc.len = SHA_DIGEST_LENGTH;
computed_sc.data = ngx_pcalloc(r->pool, SHA_DIGEST_LENGTH);
if (computed_sc.data == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: Out of memory for computed_sc variable");
return NULL;
}
n = ngx_sha1_init(&sha_ctx);
if (n == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: SHA1 init fails");
return NULL;
}
n = ngx_sha1_update(&sha_ctx, sc_string.data, sc_string.len);
if (n == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: SHA1 update fails");
return NULL;
}
n = ngx_sha1_final(computed_sc.data, &sha_ctx);
if (n == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: SHA1 final fails");
return NULL;
}
// Release the sc_string memory:

#if (NGX_DEBUG)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: computed_secret_cookie has length=%i and value=%V", SHA_DIGEST_LENGTH, &computed_sc);
#endif
if (ngx_raw_vs_hex(computed_sc.data, SHA_DIGEST_LENGTH, submitted_sc.data, 2*SHA_DIGEST_LENGTH) == 0){
if (sc[i].log == NGX_HTTP_SECRET_COOKIE_ON){
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: cookie \"%V\" is valid", &name);
}
goto secret_cookie_found;
}
#if (NGX_DEBUG)
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: cookie \"%V\" does not match", &name);
#endif

secret_cookie_not_found:
if (sc[i].log == NGX_HTTP_SECRET_COOKIE_ON){
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"secret_cookie: no valid cookie \"%V\" in header", &name);
}
continue;

secret_cookie_found:
// Append the found secret_cookie's name into secret_cookie_value:
p = ngx_copy(secret_cookie_value.data + secret_cookie_value.len, name.data, name.len);
*p = (u_char) NGX_HTTP_SECRET_COOKIE_DIVIDER; // Name is separate by a space
secret_cookie_value.len += name.len + 1;
}
// Setup the secret_cookie_value variable:
ctx->secret_cookie_value->len = secret_cookie_value.len;
ctx->secret_cookie_value->data = secret_cookie_value.data;
ctx->secret_cookie_value->valid = 1;
ctx->secret_cookie_value->no_cacheable = 1;
ctx->secret_cookie_value->not_found = 0;

#if (NGX_DEBUG)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"secret_cookie: The final secret_cookie_value has length=%i and value=%V", secret_cookie_value.len, &secret_cookie_value);
#endif
// Return the result
return ctx;
}

/* Add $secret_cookie_set variable to the http process.
* Called by "preconfiguration" hook!
*/
static ngx_int_t
ngx_http_secret_cookie_add_variable(ngx_conf_t *cf)
{
ngx_http_secret_cookie_variable_t *var;
ngx_http_variable_t *v;

for (var = ngx_http_secret_cookie_vars; var->name.len; var++) {

v = ngx_http_add_variable(cf, &var->name, NGX_HTTP_VAR_CHANGEABLE);
if (v == NULL) {
return NGX_ERROR;
}

v->get_handler = var->handler;
v->data = var->data;
}

return NGX_OK;
}

/*
* This function is called when location configuration is created.
* It will create a default configuration for secret_cookie module.
*/
static void *
ngx_http_secret_cookie_create_conf(ngx_conf_t *cf)
{
ngx_http_secret_cookie_conf_t *conf;

conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_secret_cookie_conf_t));
if (conf == NULL) {
return NULL;
}

/*
* Set by ngx_pcalloc():
*
* conf->secret_cookies = NULL;
* conf->secret_cookies_value_disabled = NULL;
*/
conf->status = NGX_CONF_UNSET;
return conf;
}

/*
* This function is called when location configuration is merged to main config.
* It will create a default configuration for secret_cookie module.
*/
static char *
ngx_http_secret_cookie_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_secret_cookie_conf_t *prev = parent;
ngx_http_secret_cookie_conf_t *conf = child;
u_char *p;
ngx_str_t secret_cookie_value_disabled;
ngx_uint_t i;
ngx_http_secret_cookie_t *sc;

// Merge previous to current configration, with a default value:
ngx_conf_merge_value(conf->status, prev->status,
NGX_HTTP_SECRET_COOKIE_OFF);
if (conf->secret_cookies == NULL){
conf->secret_cookies = prev->secret_cookies;
conf->secret_cookie_value_disabled = prev->secret_cookie_value_disabled;
} else {
// Generate the disabled_value for this configuration:
// First, count the required string length
secret_cookie_value_disabled.len = 0;
sc = conf->secret_cookies->elts;
for (i=0; i<conf->secret_cookies->nelts; i++){
secret_cookie_value_disabled.len += sc[i].name.len + 1;
}
// Secondly, create the buffer containing disabled_value
secret_cookie_value_disabled.data = ngx_pcalloc(cf->pool, secret_cookie_value_disabled.len);
if (secret_cookie_value_disabled.data == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Not enough memory for secret_cookie_value_disabled string");
return NGX_CONF_ERROR;
}
// Thirdly, copy all secret cookie's name to disabled_value
p = secret_cookie_value_disabled.data;
for (i=0; i<conf->secret_cookies->nelts; i++){
p = ngx_copy(p, sc[i].name.data, sc[i].name.len);
*p = (u_char) NGX_HTTP_SECRET_COOKIE_DIVIDER; // Name is separate by a space
p++;
}
#if (NGX_DEBUG)
ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
"String secret_cookie_value_disabled has length = %i and value = %V", secret_cookie_value_disabled.len, &secret_cookie_value_disabled);
#endif
conf->secret_cookie_value_disabled = ngx_pcalloc(cf->pool, sizeof(ngx_http_variable_value_t));
if (conf->secret_cookie_value_disabled == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Not enough memory for conf->secret_cookie_value_disabled variable");
return NGX_CONF_ERROR;
}
conf->secret_cookie_value_disabled->len = secret_cookie_value_disabled.len;
conf->secret_cookie_value_disabled->valid = 1;
conf->secret_cookie_value_disabled->no_cacheable = 1;
conf->secret_cookie_value_disabled->not_found = 0;
conf->secret_cookie_value_disabled->data = secret_cookie_value_disabled.data;
}

return NGX_CONF_OK;
}

/*
* This function is called after secret_cookie_def is passed
* from config to module. Here you can validate the param, or change the
* param to meaningful value.
*/
static char *
ngx_http_secret_cookie_def(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_secret_cookie_conf_t *sccf = conf;

ngx_uint_t n, i, anumber;
u_char c;
ngx_str_t *value;
ngx_http_secret_cookie_t *sc;

// Create secret_cookies array to hold definitions
if (sccf->secret_cookies == NULL){
sccf->secret_cookies = ngx_array_create(cf->pool, 3,
sizeof(ngx_http_secret_cookie_t));
if (sccf->secret_cookies == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

"Not enough memory for sccf->secret_cookies array");
return NGX_CONF_ERROR;
}
}
// Create new element in the array to hold one definition
sc = ngx_array_push(sccf->secret_cookies);
if (sc == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Not enough memory for new element in sccf->secret_cookies array");
return NGX_CONF_ERROR;
}
// Process the parameters
sc->status = NGX_HTTP_SECRET_COOKIE_ON;
sc->log = NGX_HTTP_SECRET_COOKIE_OFF;
sc->ua_limit = 0;
value = cf->args->elts;
for (n=1; n < cf->args->nelts; n++){
// off
if (ngx_strncmp(value[n].data,"off",3)==0){
sc->status = NGX_HTTP_SECRET_COOKIE_OFF;
continue;
}
// log
if (ngx_strncmp(value[n].data,"log=on",6)==0){
sc->log = NGX_HTTP_SECRET_COOKIE_ON;
continue;
}
//ua_limit=
if (ngx_strncmp(value[n].data, "ua_limit=", 9) == 0){
// Convert ua_limit to number:
anumber = 0;
for (i=9; i < value[n].len; i++){
c = value[n].data[i];
if (c >= '0' && c <= '9'){
anumber = anumber*10 + (c - '0');
continue;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Invalid \"ua_limit\" (must be an integer)");
return NGX_CONF_ERROR;
}
// Validate the ua_limit:
if ((anumber > 0) && (anumber < NGX_HTTP_SECRET_COOKIE_MINIMUM_UA_LIMIT)){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Invalid \"ua_limit\" (must be greater than %i)", NGX_HTTP_SECRET_COOKIE_MINIMUM_UA_LIMIT);
return NGX_CONF_ERROR;
}
sc->ua_limit = anumber;
continue;
}
// name=
if (ngx_strncmp(value[n].data, "name=", 5) == 0){
sc->name.len = value[n].len - 5;
if ((sc->name.len < 1) || (sc->name.len > NGX_HTTP_SECRET_COOKIE_MAX_SHORT_STR_SIZE)){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Parameter \"name\" is empty or too long");
return NGX_CONF_ERROR;
}
sc->name.data = value[n].data + 5;
continue;
}
// salt=
if (ngx_strncmp(value[n].data, "salt=", 5) == 0){
sc->salt.len = value[n].len - 5;
if ((sc->salt.len < 1) || (sc->salt.len > NGX_HTTP_SECRET_COOKIE_MAX_SHORT_STR_SIZE)){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Parameter \"salt\" is empty or too long");
return NGX_CONF_ERROR;
}
sc->salt.data = value[n].data + 5;
continue;
}
// rule=
if (ngx_strncmp(value[n].data, "rule=", 5) == 0){
// Validate the rule:
for (i=5; i < value[n].len; i++){
c = ngx_tolower(value[n].data[i]);
switch (c){
case NGX_HTTP_SECRET_COOKIE_RULE_ADDRESS:
case NGX_HTTP_SECRET_COOKIE_RULE_TIME:
case NGX_HTTP_SECRET_COOKIE_RULE_SALT:
case NGX_HTTP_SECRET_COOKIE_RULE_USER_AGENT:
break;
default:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Rule does not accept characters other than \"a\", \"t\", \"s\" and \"u\"");
return NGX_CONF_ERROR;
}
}

sc->rule.len = value[n].len - 5;
if ((sc->rule.len < 1) || (sc->rule.len > NGX_HTTP_SECRET_COOKIE_MAX_SHORT_STR_SIZE)){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Parameter \"rule\" is empty or too long");
return NGX_CONF_ERROR;
}
sc->rule.data = value[n].data + 5;
continue;
}
// duration
if (ngx_strncmp(value[n].data, "duration=", 9) == 0){
// Convert duration to number:
anumber = 0;
for (i=9; i < value[n].len; i++){
c = value[n].data[i];
if (c >= '0' && c <= '9'){
anumber = anumber*10 + (c - '0');
continue;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Invalid \"duration\" (must be an integer)");
return NGX_CONF_ERROR;
}
// Validate the duration:
if (anumber < NGX_HTTP_SECRET_COOKIE_MINIMUM_DURATION){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Invalid \"duration\" (must be greater than %i)", NGX_HTTP_SECRET_COOKIE_MINIMUM_DURATION);
return NGX_CONF_ERROR;
}
sc->duration = anumber;
continue;
}
}

if (sc->rule.data == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"The required parameter \"rule\" is missing!");
return NGX_CONF_ERROR;
}
if (sc->salt.data == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"The required parameter \"salt\" is missing!");
return NGX_CONF_ERROR;
}
if (sc->name.data == NULL){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"The required parameter \"name\" is missing!");
return NGX_CONF_ERROR;
}
if (sc->duration == 0){
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"The required parameter \"duration\" is missing");
return NGX_CONF_ERROR;
}
#if (NGX_DEBUG)
ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0,
"Secret_cookie_def: on/off=%i name=%V salt=%V rule=%V duration=%i",
sc->status, &sc->name, &sc->salt, &sc->rule, sc->duration);
#endif
return NGX_CONF_OK;
}

/*
* Convert an int64 to string presentation
*/
static u_char * ngx_num2str(u_char *buf, u_char *last, uint64_t ui64)
{
u_char *p, temp[NGX_INT64_LEN + 1];
/*
* we need temp[NGX_INT64_LEN] only,
* but icc issues the warning
*/
size_t len;
uint32_t ui32;

p = temp + NGX_INT64_LEN;

if (ui64 <= NGX_MAX_UINT32_VALUE) {
ui32 = (uint32_t) ui64;

do {
*--p = (u_char) (ui32 % 10 + '0');
} while (ui32 /= 10);

} else {
do {
*--p = (u_char) (ui64 % 10 + '0');
} while (ui64 /= 10);
}

/* number safe copy */

len = (temp + NGX_INT64_LEN) - p;

if (buf + len > last) {
len = last - buf;
}

return ngx_cpymem(buf, p, len);
}

/*
* Comparison of a raw string and a hex-style string
*/
static ngx_int_t ngx_raw_vs_hex(u_char *rawbuf, size_t rlen, u_char *hexbuf, size_t hlen)
{
static u_char hex[] = "0123456789abcdef";
u_char hexchar[] = "aa";
ngx_int_t len, i;
// Compare by the shortest length
len = ((rlen < hlen / 2) ? rlen : hlen / 2);
i = 0;
while (i < len){
// Calculate a hexchar from rawbuff
hexchar[1] = hex[rawbuf[i] & 0xf];
hexchar[0] = hex[(rawbuf[i]>>4) & 0xf];
if ((hexchar[0] != hexbuf[2*i]) || (hexchar[1] != hexbuf[2*i+1])){
return 1;
}
i++;
}
return 0;
}
[/code]
Subject Author Posted

Redirect based on php-set cookies

tqvn2004 February 18, 2010 05:04PM

Re: Redirect based on php-set cookies

tqvn2004 February 22, 2010 04:11PM

Re: Redirect based on php-set cookies

tqvn2004 September 21, 2010 04:05PM

Re: Redirect based on php-set cookies

tqvn2004 February 10, 2011 07:11AM

Re: Redirect based on php-set cookies

tqvn2004 February 10, 2011 07:42AM

Re: Redirect based on php-set cookies

Kev December 10, 2011 11:21AM

Re: Redirect based on php-set cookies

tqvn2004 February 24, 2010 09:06AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 266
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready