示例#1
0
static void
ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q,
    u_char *name)
{
    u_char                      *p;
    size_t                       len;
    ngx_path_t                  *path;
    ngx_http_file_cache_node_t  *fcn;

    fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);

    if (fcn->exists) {
        cache->sh->size -= fcn->fs_size;

        path = cache->path;
        p = name + path->name.len + 1 + path->len;
        p = ngx_hex_dump(p, (u_char *) &fcn->node.key,
                         sizeof(ngx_rbtree_key_t));
        len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
        p = ngx_hex_dump(p, fcn->key, len);
        *p = '\0';

        fcn->count++;
        fcn->deleting = 1;
        ngx_shmtx_unlock(&cache->shpool->mutex);

        len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
        ngx_create_hashed_filename(path, name, len);

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                       "http file cache expire: \"%s\"", name);

        if (ngx_delete_file(name) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
                          ngx_delete_file_n " \"%s\" failed", name);
        }

        ngx_shmtx_lock(&cache->shpool->mutex);
        fcn->count--;
        fcn->deleting = 0;
    }

    if (fcn->count == 0) {
        ngx_queue_remove(q);
        ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
        ngx_slab_free_locked(cache->shpool, fcn);
    }
}
static ngx_int_t
ngx_extra_var_cache_key(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
    u_char            *p;
    ngx_http_cache_t  *c;

    c = r->cache;
    if (c == NULL) {
        v->not_found = 1;
        return NGX_OK;
    }

    p = ngx_pnalloc(r->pool, 2 * NGX_HTTP_CACHE_KEY_LEN);
    if (p == NULL) {
        return NGX_ERROR;
    }

    ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);

    v->len = 2 * NGX_HTTP_CACHE_KEY_LEN;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = p;

    return NGX_OK;
}
static u_char *
ngx_http_lua_digest_hex(u_char *dest, const u_char *buf, int buf_len)
{
    u_char digest[MD5_DIGEST_LENGTH];
    MD5(buf, buf_len, digest);
    return ngx_hex_dump(dest, digest, sizeof(digest));
}
static int
ngx_http_lua_ngx_md5(lua_State *L)
{
    u_char                  *src;
    size_t                   slen;

    ngx_md5_t                md5;
    u_char                   md5_buf[MD5_DIGEST_LENGTH];
    u_char                   hex_buf[2 * sizeof(md5_buf)];

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting one argument");
    }

    if (strcmp(luaL_typename(L, 1), (char *) "nil") == 0) {
        src     = (u_char *) "";
        slen    = 0;

    } else {
        src = (u_char *) luaL_checklstring(L, 1, &slen);
    }

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, src, slen);
    ngx_md5_final(md5_buf, &md5);

    ngx_hex_dump(hex_buf, md5_buf, sizeof(md5_buf));

    lua_pushlstring(L, (char *) hex_buf, sizeof(hex_buf));

    return 1;
}
示例#5
0
static ngx_int_t
ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
{
    u_char            *p;
    ngx_http_cache_t  *c;

    c = r->cache;

    if (c->file.name.len) {
        return NGX_OK;
    }

    c->file.name.len = path->name.len + 1 + path->len
                       + 2 * NGX_HTTP_CACHE_KEY_LEN;

    c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
    if (c->file.name.data == NULL) {
        return NGX_ERROR;
    }

    ngx_memcpy(c->file.name.data, path->name.data, path->name.len);

    p = c->file.name.data + path->name.len + 1 + path->len;
    p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
    *p = '\0';

    ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "cache file: \"%s\"", c->file.name.data);

    return NGX_OK;
}
ngx_int_t
ngx_http_set_misc_set_encode_hex(ngx_http_request_t *r,
                                 ngx_str_t *res, ngx_http_variable_value_t *v)
{
    res->len = (v->len)*2;
    ndk_palloc_re(res->data, r->pool, res->len);
    ngx_hex_dump(res->data, v->data, v->len);
    return NGX_OK;
}
u_char *
ngx_http_lua_digest_hex(u_char *dest, const u_char *buf, int buf_len)
{
    ngx_md5_t                     md5;
    u_char                        md5_buf[MD5_DIGEST_LENGTH];

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, buf, buf_len);
    ngx_md5_final(md5_buf, &md5);

    return ngx_hex_dump(dest, md5_buf, sizeof(md5_buf));
}
void
ngx_http_lua_ffi_md5(const u_char *src, size_t len, u_char *dst)
{
    ngx_md5_t           md5;
    u_char              md5_buf[MD5_DIGEST_LENGTH];

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, src, len);
    ngx_md5_final(md5_buf, &md5);

    ngx_hex_dump(dst, md5_buf, sizeof(md5_buf));
}
static ngx_uint_t
ngx_http_auth_mysql_check_md5(ngx_http_request_t *r, ngx_str_t sent_password, ngx_str_t actual_password) {
	u_char md5_str[2*MD5_DIGEST_LENGTH + 1];
	u_char md5_digest[MD5_DIGEST_LENGTH];	
	ngx_md5_t md5;
	
	ngx_md5_init(&md5);
	ngx_md5_update(&md5, sent_password.data, sent_password.len);
	ngx_md5_final(md5_digest, &md5);
	ngx_hex_dump(md5_str, md5_digest, MD5_DIGEST_LENGTH);
	md5_str[2*MD5_DIGEST_LENGTH] = '\0';
	return (ngx_strcmp(actual_password.data, md5_str) == 0)? NGX_OK : NGX_DECLINED;
}
ngx_int_t
ngx_http_set_misc_set_encode_hex(ngx_http_request_t *r, ngx_str_t *res,
    ngx_http_variable_value_t *v)
{
    res->len = v->len << 1;
    res->data = ngx_palloc(r->pool, res->len);
    if (res->data == NULL) {
        return NGX_ERROR;
    }

    ngx_hex_dump(res->data, v->data, v->len);
    return NGX_OK;
}
/*
 * Calculate the HMAC-SHA1 digest for a specified message with a defined key.
 *
 *	@parameters:	*pool		pool for memory allocation;
 *					*key		the hmac key;
 *					*message	the message to digest;
 *	
 *	@return	NGX_ERROR 	on error
 *			NGX_OK		on success
 */
static ngx_int_t
ngx_apikey_hamac_sha1_digest( ngx_pool_t *pool, ngx_str_t *key, ngx_str_t *message, ngx_str_t *digest ) {

	ngx_str_t	hmac_digest		= ngx_null_string;

	u_char		*last			= NULL;
	

	hmac_digest.len 	= EVP_MAX_MD_SIZE;
	hmac_digest.data = ngx_pcalloc( pool, EVP_MAX_MD_SIZE );
	if ( hmac_digest.data == NULL ) {
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed allocating memory", __func__ );
        return NGX_ERROR;
	}

	/*
	HMAC_CTX ctx;
	HMAC_Init( &ctx, key->data, sizeof(key->data), EVP_sha1() );
	HMAC_Update(&ctx,  message->data, sizeof(message->data));
 	HMAC_Final(&ctx, hmac_digest.data, &hmac_digest.len );		
	HMAC_cleanup(&ctx);
	*/
	
	last = HMAC (EVP_sha1 (), 
		(const void *)key->data, (int)key->len, 
		message->data, (int)message->len, 
		hmac_digest.data, (unsigned int *)&hmac_digest.len );

	if ( last == NULL ) {
		ngx_pfree( pool, hmac_digest.data );
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed calculating HMAC digest", __func__ );
        return NGX_ERROR;
	}
	
	digest->len  = EVP_MAX_MD_SIZE*2;
	digest->data = ngx_pcalloc( pool, digest->len + 1 );
    if ( digest->data == NULL ) {
		ngx_pfree( pool, hmac_digest.data );
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed allocating memory", __func__ );
        return NGX_ERROR;
	}
	
	ngx_hex_dump(digest->data, hmac_digest.data, hmac_digest.len);
	

	ngx_pfree( pool, hmac_digest.data );

	
	return NGX_OK;
}
static u_char*
ngx_http_memcached_hash_sha256_hash(u_char *result, const u_char *key, size_t key_length)
{
    SHA256_CTX sha256;
    u_char hash[SHA256_DIGEST_LENGTH];

    SHA256_Init(&sha256);
    SHA256_Update(&sha256, key, key_length);
    SHA256_Final(hash, &sha256);

    result = ngx_hex_dump(result, hash, SHA256_DIGEST_LENGTH);

    return result;
}
static void
ngx_rtmp_notify_set_name(u_char *dst, size_t dst_len, u_char *src,
    size_t src_len)
{
    u_char     result[16], *p;
    ngx_md5_t  md5;

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, src, src_len);
    ngx_md5_final(result, &md5);

    p = ngx_hex_dump(dst, result, ngx_min((dst_len - 1) / 2, 16));
    *p = '\0';
}
void
calc_req_digest( ngx_http_request_t* r, radius_str_t* secret, u_char* digest ) {

    ngx_md5_t md5; 
    ngx_md5_init( &md5 ); 
    ngx_md5_update( &md5, secret->s, secret->len ); 
    ngx_md5_update( &md5, r->headers_in.user.data, r->headers_in.user.len ); 
    ngx_md5_update( &md5, r->headers_in.passwd.data, r->headers_in.passwd.len ); 

    u_char d[ 16 ];
    ngx_md5_final( d, &md5 ); 

    ngx_hex_dump( digest, d, sizeof( d ) );

}
ngx_int_t ngx_http_sticky_misc_hmac_sha1(ngx_pool_t *pool, void *in, size_t len, ngx_str_t *key, ngx_str_t *digest)
{
	u_char hash[SHA_DIGEST_LENGTH];
	u_char k[SHA_CBLOCK];
	ngx_sha1_t sha1;
	u_int i;

	digest->data = ngx_pcalloc(pool, SHA_DIGEST_LENGTH * 2);
	if (digest->data == NULL) {
		return NGX_ERROR;
	}
	digest->len = SHA_DIGEST_LENGTH * 2;

	ngx_memzero(k, sizeof(k));

	if (key->len > SHA_CBLOCK) {
		ngx_sha1_init(&sha1);
		ngx_sha1_update(&sha1, key->data, key->len);
		ngx_sha1_final(k, &sha1);
	} else {
		ngx_memcpy(k, key->data, key->len);
	}

	/* XOR ipad */
	for (i=0; i < SHA_CBLOCK; i++) {
		k[i] ^= 0x36;
	}

	ngx_sha1_init(&sha1);
	ngx_sha1_update(&sha1, k, SHA_CBLOCK);
	ngx_sha1_update(&sha1, in, len);
	ngx_sha1_final(hash, &sha1);

	/* Convert k to opad -- 0x6A = 0x36 ^ 0x5C */
	for (i=0; i < SHA_CBLOCK; i++) {
		k[i] ^= 0x6a;
	}

	ngx_sha1_init(&sha1);
	ngx_sha1_update(&sha1, k, SHA_CBLOCK);
	ngx_sha1_update(&sha1, hash, SHA_DIGEST_LENGTH);
	ngx_sha1_final(hash, &sha1);

	ngx_hex_dump(digest->data, hash, SHA_DIGEST_LENGTH);

	return NGX_OK;
}
/* serialize the session id from lua context into buf.
 * the memory allocation of buf should be handled externally. */
int
ngx_http_lua_ffi_ssl_get_session_id(ngx_http_request_t *r,
    u_char *buf, char **err)
{
    int                              id_len;
    u_char                          *id;
    ngx_ssl_conn_t                  *ssl_conn;
    ngx_connection_t                *c;
    ngx_http_lua_ssl_ctx_t          *cctx;

    c = r->connection;

    if (c == NULL || c->ssl == NULL) {
        *err = "bad request";
        return NGX_ERROR;
    }

    ssl_conn = c->ssl->connection;
    if (ssl_conn == NULL) {
        *err = "bad ssl conn";
        return NGX_ERROR;
    }

    dd("get cctx session");
    cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection);
    if (cctx == NULL) {
        *err = "bad lua context";
        return NGX_ERROR;
    }

    id = cctx->session_id.data;
    if (id == NULL) {
        *err = "uninitialized session id in lua context";
        return NGX_ERROR;
    }

    id_len = cctx->session_id.len;
    if (id_len == 0) {
        *err = "uninitialized session id len in lua context";
        return NGX_ERROR;
    }

    ngx_hex_dump(buf, id, id_len);

    return NGX_OK;
}
ngx_int_t ngx_http_sticky_misc_md5(ngx_pool_t *pool, void *in, size_t len, ngx_str_t *digest)
{
	ngx_md5_t md5;
	u_char hash[MD5_DIGEST_LENGTH];

	digest->data = ngx_pcalloc(pool, MD5_DIGEST_LENGTH * 2);
	if (digest->data == NULL) {
		return NGX_ERROR;
	}

	digest->len = MD5_DIGEST_LENGTH * 2;
	ngx_md5_init(&md5);
	ngx_md5_update(&md5, in, len);
	ngx_md5_final(hash, &md5);

	ngx_hex_dump(digest->data, hash, MD5_DIGEST_LENGTH);
	return NGX_OK;
}
ngx_int_t ngx_http_sticky_misc_sha1(ngx_pool_t *pool, void *in, size_t len, ngx_str_t *digest)
{
	ngx_sha1_t sha1;
	u_char hash[SHA_DIGEST_LENGTH];

	digest->data = ngx_pcalloc(pool, SHA_DIGEST_LENGTH * 2);
	if (digest->data == NULL) {
		return NGX_ERROR;
	}

	digest->len = SHA_DIGEST_LENGTH * 2;
	ngx_sha1_init(&sha1);
	ngx_sha1_update(&sha1, in, len);
	ngx_sha1_final(hash, &sha1);

	ngx_hex_dump(digest->data, hash, SHA_DIGEST_LENGTH);
	return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_session_sticky_set_sid(ngx_conf_t *cf,
    ngx_http_ss_server_t *s)
{
    u_char     buf[16];
    ngx_md5_t  md5;

    s->sid.len = 32;
    s->sid.data = ngx_pnalloc(cf->pool, 32);
    if (s->sid.data == NULL) {
        return NGX_ERROR;
    }

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, s->name->data, s->name->len);
    ngx_md5_final(buf, &md5);

    ngx_hex_dump(s->sid.data, buf, 16);

    return NGX_OK;
}
示例#20
0
static JSBool
method_md5(JSContext *cx, JSObject *self, uintN argc, jsval *argv, jsval *rval)
{
	JSString                      *jsstr;
	ngx_md5_t                      md5;
	u_char                        *str, hash[16], hex[32];
	size_t                         len;
	
	TRACE();
	
	if (argc != 1)
	{
		JS_ReportError(cx, "Nginx.md5 takes 1 argument");
		return JS_FALSE;
	}
	
	jsstr = JS_ValueToString(cx, argv[0]);
	if (jsstr == NULL)
	{
		return JS_FALSE;
	}
	
	str = (u_char *) JS_GetStringBytes(jsstr);
	if (str == NULL)
	{
		return JS_FALSE;
	}
	
	len = ngx_strlen(str);
	
	ngx_md5_init(&md5);
	ngx_md5_update(&md5, str, len);
	ngx_md5_final(hash, &md5);
	
	ngx_hex_dump(hex, hash, 16);
	
	DATA_LEN_to_JS_STRING_to_JSVAL(cx, hex, 32, *rval);
	
	return JS_TRUE;
}
示例#21
0
ngx_int_t
ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
    ssl_session  *session = c->ssl->connection->session;

    /*
     * ngx_event_openssl's implementation of this returns a hexdump of
     * the ASN.1 encoded SSL session object.  Our implementation just
     * returns a hexdump of the session id, because this routine is not
     * named ngx_ssl_get_entire_session_object.
     */

    s->len = session->length * 2;
    s->data = ngx_pnalloc(pool, s->len);
    if (s->data == NULL) {
        return NGX_ERROR;
    }

    ngx_hex_dump(s->data, session->id, session->length);

    return NGX_OK;
}
示例#22
0
int main (int argc, char *argv[])
{
    ngx_int_t i;
    ngx_md5_t md5;
    u_char *p, md5_buf[16], md5_dump_buf[32];
    ngx_str_t s = ngx_string("bokko");

    printf("%s:", s.data);

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, s.data, s.len);
    ngx_md5_final(md5_buf, &md5);

    p = md5_dump_buf;
    p = ngx_hex_dump(p, md5_buf, 16);
    for (i=0;i<32;i++) {
        printf("%c", md5_dump_buf[i]);
    }
    printf("\n");


    return 0;
}
static int
ngx_http_lua_ngx_get_cache_data(lua_State *L) {
    int                          n;
    ngx_http_request_t          *r;
    ngx_http_cache_t            *c;
    ngx_http_file_cache_t       *cache, cache_tmp;
    ngx_http_file_cache_sh_t    *sh, sh_tmp;
    ngx_http_file_cache_node_t  *fcn, fcn_tmp;
    u_char                      *p;


    n = lua_gettop(L);

    if (n != 0) {
        return luaL_error(L, "expecting no arguments");
    }

    r = ngx_http_lua_get_request(L);
    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "lua cache.metadata");

    // TODO setup empty return
    lua_createtable(L, 0, 2 /* nrec */); /* return table */

    c = r->cache;
    if (!c) {
        /* empty response */
        return 1;
    }

    /* make copies of all structs, to avoid locking for too long */
    fcn = c->node;
    cache = c->file_cache;
    sh = cache ? cache->sh : NULL;
    memset(&cache_tmp, 0, sizeof(cache_tmp));
    memset(&fcn_tmp, 0, sizeof(fcn_tmp));
    memset(&sh_tmp, 0, sizeof(sh_tmp));

    ngx_shmtx_lock(&c->file_cache->shpool->mutex);

    if (fcn) {
        fcn_tmp = *c->node;
    }

    if (cache) {
        cache_tmp = *c->file_cache;
        if (sh) {
            sh_tmp = *cache->sh;
            cache_tmp.sh = &sh_tmp;
        }
    }

    ngx_shmtx_unlock(&c->file_cache->shpool->mutex);

    p = ngx_pnalloc(r->pool, 2*NGX_HTTP_CACHE_KEY_LEN);
    if (!p) {
        return luaL_error(L, "Cannot allocate space for cache key string");
    }

    ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
    lua_pushlstring(L, "key", sizeof("key")-1);
    lua_pushlstring(L, (char*)p, 2*NGX_HTTP_CACHE_KEY_LEN);
    lua_rawset(L, -3);

    lua_pushlstring(L, "crc32", sizeof("crc32")-1);
    lua_pushnumber(L, c->crc32);
    lua_rawset(L, -3);

    lua_pushlstring(L, "valid_sec", sizeof("valid_sec")-1);
    lua_pushnumber(L, c->valid_sec);
    lua_rawset(L, -3);

    lua_pushlstring(L, "last_modified", sizeof("last_modified")-1);
    lua_pushnumber(L, c->last_modified);
    lua_rawset(L, -3);

    lua_pushlstring(L, "date", sizeof("date")-1);
    lua_pushnumber(L, c->date);
    lua_rawset(L, -3);

    lua_pushlstring(L, "length", sizeof("length")-1);
    lua_pushnumber(L, c->length);
    lua_rawset(L, -3);

    lua_pushlstring(L, "fs_size", sizeof("fs_size")-1);
    lua_pushnumber(L, c->fs_size);
    lua_rawset(L, -3);

    lua_pushlstring(L, "min_uses", sizeof("min_uses")-1);
    lua_pushnumber(L, c->min_uses);
    lua_rawset(L, -3);

    lua_pushlstring(L, "error", sizeof("error")-1);
    lua_pushnumber(L, c->error);
    lua_rawset(L, -3);

    lua_pushlstring(L, "valid_msec", sizeof("valid_msec")-1);
    lua_pushnumber(L, c->valid_msec);
    lua_rawset(L, -3);

    /* shared memory block */
    if (sh) {
        lua_createtable(L, 0, 2 /* nrec */); /* subtable */

        lua_pushlstring(L, "size", sizeof("size")-1);
        lua_pushnumber(L, sh_tmp.size);
        lua_rawset(L, -3);

        lua_setfield(L, -2, "sh");
    }

    /* cache entry */
    if (cache) {
        lua_createtable(L, 0, 8 /* nrec */); /* subtable */

        lua_pushlstring(L, "max_size", sizeof("max_size")-1);
        lua_pushnumber(L, cache_tmp.max_size);
        lua_rawset(L, -3);

        lua_pushlstring(L, "bsize", sizeof("bsize")-1);
        lua_pushnumber(L, cache_tmp.bsize);
        lua_rawset(L, -3);

        lua_pushlstring(L, "inactive", sizeof("inactive")-1);
        lua_pushnumber(L, cache_tmp.inactive);
        lua_rawset(L, -3);

        lua_pushlstring(L, "files", sizeof("files")-1);
        lua_pushnumber(L, cache_tmp.files);
        lua_rawset(L, -3);

        lua_pushlstring(L, "loader_files", sizeof("loader_files")-1);
        lua_pushnumber(L, cache_tmp.loader_files);
        lua_rawset(L, -3);

        lua_pushlstring(L, "loader_sleep", sizeof("loader_sleep")-1);
        lua_pushnumber(L, cache_tmp.loader_sleep);
        lua_rawset(L, -3);

        lua_pushlstring(L, "loader_threshold", sizeof("loader_threshold")-1);
        lua_pushnumber(L, cache_tmp.inactive);
        lua_rawset(L, -3);

        lua_setfield(L, -2, "cache");
    }

    /* file_cache_node */
    if (fcn) {
        lua_createtable(L, 0, 11 /* nrec */); /* subtable */

        lua_pushlstring(L, "count", sizeof("count")-1);
        lua_pushnumber(L, fcn_tmp.count);
        lua_rawset(L, -3);

        lua_pushlstring(L, "uses", sizeof("uses")-1);
        lua_pushnumber(L, fcn_tmp.uses);
        lua_rawset(L, -3);

        lua_pushlstring(L, "valid_msec", sizeof("valid_msec")-1);
        lua_pushnumber(L, fcn_tmp.valid_msec);
        lua_rawset(L, -3);

        lua_pushlstring(L, "error", sizeof("error")-1);
        lua_pushnumber(L, fcn_tmp.error);
        lua_rawset(L, -3);

        lua_pushlstring(L, "exists", sizeof("exists")-1);
        lua_pushnumber(L, fcn_tmp.exists);
        lua_rawset(L, -3);

        lua_pushlstring(L, "updating", sizeof("updating")-1);
        lua_pushnumber(L, fcn_tmp.updating);
        lua_rawset(L, -3);

        lua_pushlstring(L, "deleting", sizeof("deleting")-1);
        lua_pushnumber(L, fcn_tmp.deleting);
        lua_rawset(L, -3);

        lua_pushlstring(L, "exists", sizeof("exists")-1);
        lua_pushnumber(L, fcn_tmp.exists);
        lua_rawset(L, -3);

        lua_pushlstring(L, "expire", sizeof("expire")-1);
        lua_pushnumber(L, fcn_tmp.expire);
        lua_rawset(L, -3);

        lua_pushlstring(L, "valid_sec", sizeof("valid_sec")-1);
        lua_pushnumber(L, fcn_tmp.valid_sec);
        lua_rawset(L, -3);

        lua_pushlstring(L, "fs_size", sizeof("fs_size")-1);
        lua_pushnumber(L, fcn_tmp.fs_size);
        lua_rawset(L, -3);

        lua_setfield(L, -2, "fcn");
    }

    return 1;
}
static ngx_int_t 
ngx_http_weixin_auth(ngx_http_request_t *r)
{
    u_char     *p;
    ngx_int_t   rc;
    ngx_str_t   signature, str, array_str[3], tmp;
    ngx_sha1_t  sha;
    u_char      sha_buf[SHA_DIGEST_LENGTH];
    u_char      sha_buf_str[SHA_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
    ngx_http_weixin_auth_loc_conf_t *auth_conf;
    
    auth_conf = ngx_http_get_module_loc_conf(r, ngx_http_weixin_auth_module);
    
    if (ngx_http_arg(r, (u_char *) "signature", 9, &signature) != NGX_OK) {
        return NGX_DECLINED;
    }
    
    if (ngx_http_arg(r, (u_char *) "timestamp", 9, &array_str[0]) != NGX_OK) {
        return NGX_DECLINED;
    }
    
    if (ngx_http_arg(r, (u_char *) "nonce", 5, &array_str[1]) != NGX_OK) {
        return NGX_DECLINED;
    }
    
    if (signature.len != SHA_DIGEST_LENGTH * 2) {
        return NGX_DECLINED;
    }
    
    array_str[2] = auth_conf->token;
    
    //  token¡¢timestamp¡¢nonce
    if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) {
        tmp = array_str[0];
        array_str[0] = array_str[1];
        array_str[1] = tmp;
    }
    
    if (ngx_memn2cmp(array_str[1].data, array_str[2].data, array_str[1].len, array_str[2].len) > 0) {
        tmp = array_str[1];
        array_str[1] = array_str[2];
        array_str[2] = tmp;
    }

    if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) {
        tmp = array_str[0];
        array_str[0] = array_str[1];
        array_str[1] = tmp;
    }
    
    str.len = array_str[0].len + array_str[1].len + array_str[2].len;
    str.data = ngx_pcalloc(r->pool, str.len + 1);
    if (str.data == NULL) {
        return NGX_ERROR;
    }
    
    p = str.data;
    p = ngx_cpymem(p, array_str[0].data, array_str[0].len);
    p = ngx_cpymem(p, array_str[1].data, array_str[1].len);
    p = ngx_cpymem(p, array_str[2].data, array_str[2].len);
    p = '\0';
    
    ngx_sha1_init(&sha);
    ngx_sha1_update(&sha, str.data, str.len);
    ngx_sha1_final(sha_buf, &sha);
    
    p = ngx_hex_dump(sha_buf_str, sha_buf, SHA_DIGEST_LENGTH);
    p = '\0';
    
    rc = ngx_memcmp(sha_buf_str, signature.data, SHA_DIGEST_LENGTH * 2);
    if (rc != 0) {
        return NGX_DECLINED;
    }
    
    return NGX_OK;
}
/*
	ngx_http_file_cache_expire,使用了LRU,也就是队列最尾端保存的是最长时间没有被使用的,并且这个函数返回的就是一个wait值

*/
static time_t
ngx_http_file_cache_expire(ngx_http_file_cache_t *cache)
{
    u_char                      *name, *p;
    size_t                       len;
    time_t                       now, wait;
    ngx_path_t                  *path;
    ngx_queue_t                 *q;
    ngx_http_file_cache_node_t  *fcn;
    u_char                       key[2 * NGX_HTTP_CACHE_KEY_LEN];

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                   "http file cache expire");

    path = cache->path;
    len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;			//	

    name = ngx_alloc(len + 1, ngx_cycle->log);
    if (name == NULL) {
        return 10;
    }

	//	拷贝路径名 -- cache存放的目录,不包括子目录
    ngx_memcpy(name, path->name.data, path->name.len);

    now = ngx_time();

    ngx_shmtx_lock(&cache->shpool->mutex);		//	共享内存区上锁

    for ( ;; ) {

		//	队列空,直接返回
        if (ngx_queue_empty(&cache->sh->queue)) {
            wait = 10;
            break;
        }

		//	在队列的尾部取出一个节点,检查是否已经过期
        q = ngx_queue_last(&cache->sh->queue);

        fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);

        wait = fcn->expire - now;	

        if (wait > 0) {			//	wait大于0说明未过期
            wait = wait > 10 ? 10 : wait;
            break;
        }

		//	此节点已经过期
        ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                       "http file cache expire: #%d %d %02xd%02xd%02xd%02xd",
                       fcn->count, fcn->exists,
                       fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);

        if (fcn->count == 0) {
            ngx_http_file_cache_delete(cache, q, name);
            continue;
        }

        if (fcn->deleting) {
            wait = 1;
            break;
        }

		//	转换文件名到acsii格式
        p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
                         sizeof(ngx_rbtree_key_t));
        len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
        (void) ngx_hex_dump(p, fcn->key, len);

        /*
         * abnormally exited workers may leave locked cache entries,
         * and although it may be safe to remove them completely,
         * we prefer to just move them to the top of the inactive queue
         */

		//	将节点放入队列的头部
        ngx_queue_remove(q);

		//	重新计算过期时间
        fcn->expire = ngx_time() + cache->inactive;

        ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);

        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                      "ignore long locked inactive cache entry %*s, count:%d",
                      2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
    }

    ngx_shmtx_unlock(&cache->shpool->mutex);

    ngx_free(name);

    return wait;
}
static ngx_int_t
ngx_http_auth_digest_verify_hash(ngx_http_request_t *r, ngx_http_auth_digest_cred_t *fields, u_char *hashed_pw)
{
  u_char      *p;
  ngx_str_t    http_method;
  ngx_str_t    HA1, HA2, ha2_key;
  ngx_str_t    digest, digest_key;
  ngx_md5_t    md5;
  u_char       hash[16];

  //  the hashing scheme:
  //    digest: MD5(MD5(username:realm:password):nonce:nc:cnonce:qop:MD5(method:uri))
  //                ^- HA1                                           ^- HA2
  //    verify: fields->response == MD5($hashed_pw:nonce:nc:cnonce:qop:MD5(method:uri))

  // ha1 was precalculated and saved to the passwd file: md5(username:realm:password)
  HA1.len = 33;
  HA1.data = ngx_pcalloc(r->pool, HA1.len);
  p = ngx_cpymem(HA1.data, hashed_pw, 32);
  
  // calculate ha2: md5(method:uri)
  http_method.len = r->method_name.len+1;
  http_method.data = ngx_pcalloc(r->pool, http_method.len);
  if (http_method.data==NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
  p = ngx_cpymem(http_method.data, r->method_name.data, r->method_end - r->method_name.data+1);
  
  ha2_key.len = http_method.len + r->uri.len + 1;
  ha2_key.data = ngx_pcalloc(r->pool, ha2_key.len);
  if (ha2_key.data==NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
  p = ngx_cpymem(ha2_key.data, http_method.data, http_method.len-1); *p++ = ':';
  p = ngx_cpymem(p, r->uri.data, r->uri.len);

  HA2.len = 33;
  HA2.data = ngx_pcalloc(r->pool, HA2.len);
  ngx_md5_init(&md5);
  ngx_md5_update(&md5, ha2_key.data, ha2_key.len-1);
  ngx_md5_final(hash, &md5);  
  ngx_hex_dump(HA2.data, hash, 16);
  
  // calculate digest: md5(ha1:nonce:nc:cnonce:qop:ha2)
  digest_key.len = HA1.len-1 + fields->nonce.len-1 + fields->nc.len-1 + fields->cnonce.len-1 + fields->qop.len-1 + HA2.len-1 + 5 + 1;
  digest_key.data = ngx_pcalloc(r->pool, digest_key.len);
  if (digest_key.data==NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
  
  p = ngx_cpymem(digest_key.data, HA1.data, HA1.len-1); *p++ = ':';  
  p = ngx_cpymem(p, fields->nonce.data, fields->nonce.len-1); *p++ = ':';
  p = ngx_cpymem(p, fields->nc.data, fields->nc.len-1); *p++ = ':';
  p = ngx_cpymem(p, fields->cnonce.data, fields->cnonce.len-1); *p++ = ':';
  p = ngx_cpymem(p, fields->qop.data, fields->qop.len-1); *p++ = ':';
  p = ngx_cpymem(p, HA2.data, HA2.len-1);  

  digest.len = 33;
  digest.data = ngx_pcalloc(r->pool, 33);
  if (digest.data==NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
  ngx_md5_init(&md5);
  ngx_md5_update(&md5, digest_key.data, digest_key.len-1);
  ngx_md5_final(hash, &md5);  
  ngx_hex_dump(digest.data, hash, 16);

  // compare the hash of the full digest string to the response field of the auth header
  // and bail out if they don't match
  if (ngx_strcmp(digest.data, fields->response.data) != 0) return NGX_DECLINED;
  
  ngx_http_auth_digest_nonce_t     nonce;
  ngx_uint_t                       key;
  ngx_http_auth_digest_node_t     *found;
  ngx_slab_pool_t                 *shpool;
  ngx_http_auth_digest_loc_conf_t *alcf;
  ngx_table_elt_t                 *info_header;
  ngx_str_t                        hkey, hval;
  
  shpool = (ngx_slab_pool_t *)ngx_http_auth_digest_shm_zone->shm.addr;
  alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_digest_module);
  nonce.rnd = ngx_hextoi(fields->nonce.data, 8);
  nonce.t = ngx_hextoi(&fields->nonce.data[8], 8);
  key = ngx_crc32_short((u_char *) &nonce.rnd, sizeof nonce.rnd) ^
        ngx_crc32_short((u_char *) &nonce.t, sizeof(nonce.t));

  int nc = ngx_atoi(fields->nc.data, fields->nc.len-1);
  if (nc<0 || nc>=alcf->replays){ 
    fields->stale = 1;    
    return NGX_DECLINED; 
  }

  // make sure nonce and nc are both valid
  ngx_shmtx_lock(&shpool->mutex);    
  found = (ngx_http_auth_digest_node_t *)ngx_http_auth_digest_rbtree_find(key, ngx_http_auth_digest_rbtree->root, ngx_http_auth_digest_rbtree->sentinel);
  if (found!=NULL && ngx_bitvector_test(found->nc, nc)){    
    if (ngx_bitvector_test(found->nc, 0)){
      // if this is the first use of this nonce, switch the expiration time from the timeout
      // param to now+expires. using the 0th element of the nc vector to flag this...
      ngx_bitvector_set(found->nc, 0);
      found->expires = ngx_time() + alcf->expires;
    }
    
    // mark this nc as ‘used’ to prevent replays 
    ngx_bitvector_set(found->nc, nc);

    
    // todo: if the bitvector is now ‘full’, could preemptively expire the node from the rbtree
    // ngx_rbtree_delete(ngx_http_auth_digest_rbtree, found);
    // ngx_slab_free_locked(shpool, found);


    
    ngx_shmtx_unlock(&shpool->mutex);
    
    // recalculate the digest with a modified HA2 value (for rspauth) and emit the
    // Authentication-Info header    
    ngx_memset(ha2_key.data, 0, ha2_key.len);
    p = ngx_sprintf(ha2_key.data, ":%s", r->uri.data);

    ngx_memset(HA2.data, 0, HA2.len);
    ngx_md5_init(&md5);
    ngx_md5_update(&md5, ha2_key.data, r->uri.len);
    ngx_md5_final(hash, &md5);  
    ngx_hex_dump(HA2.data, hash, 16);

    ngx_memset(digest_key.data, 0, digest_key.len);
    p = ngx_cpymem(digest_key.data, HA1.data, HA1.len-1); *p++ = ':';  
    p = ngx_cpymem(p, fields->nonce.data, fields->nonce.len-1); *p++ = ':';
    p = ngx_cpymem(p, fields->nc.data, fields->nc.len-1); *p++ = ':';
    p = ngx_cpymem(p, fields->cnonce.data, fields->cnonce.len-1); *p++ = ':';
    p = ngx_cpymem(p, fields->qop.data, fields->qop.len-1); *p++ = ':';
    p = ngx_cpymem(p, HA2.data, HA2.len-1);  

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, digest_key.data, digest_key.len-1);
    ngx_md5_final(hash, &md5);  
    ngx_hex_dump(digest.data, hash, 16);
    
    ngx_str_set(&hkey, "Authentication-Info");
    hval.len = sizeof("qop=\"auth\", rspauth=\"\", cnonce=\"\", nc=") + fields->cnonce.len + fields->nc.len + digest.len;
    hval.data = ngx_pcalloc(r->pool, hval.len);
    if (hval.data==NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
    p = ngx_sprintf(hval.data, "qop=\"auth\", rspauth=\"%s\", cnonce=\"%s\", nc=%s", digest.data, fields->cnonce.data, fields->nc.data);
    
    info_header = ngx_list_push(&r->headers_out.headers);
    if (info_header == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;    
    info_header->key = hkey;
    info_header->value = hval;
    info_header->hash = 1;
    return NGX_OK;
  }else{
    // nonce is invalid/expired or client reused an nc value. suspicious...
    ngx_shmtx_unlock(&shpool->mutex);
    return NGX_DECLINED;
  }      
}
示例#27
0
ngx_int_t
ngx_http_file_cache_open(ngx_http_request_t *r)
{
    u_char                    *p;
    ngx_int_t                  rc, rv;
    ngx_uint_t                 cold, test;
    ngx_path_t                *path;
    ngx_http_cache_t          *c;
    ngx_pool_cleanup_t        *cln;
    ngx_open_file_info_t       of;
    ngx_http_file_cache_t     *cache;
    ngx_http_core_loc_conf_t  *clcf;

    c = r->cache;

    if (c->buf) {
        return ngx_http_file_cache_read(r, c);
    }

    cache = c->file_cache;

    cln = ngx_pool_cleanup_add(r->pool, 0);
    if (cln == NULL) {
        return NGX_ERROR;
    }

    rc = ngx_http_file_cache_exists(cache, c);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http file cache exists: %i e:%d", rc, c->exists);

    if (rc == NGX_ERROR) {
        return rc;
    }

    cln->handler = ngx_http_file_cache_cleanup;
    cln->data = c;

    if (rc == NGX_AGAIN) {
        return NGX_HTTP_CACHE_SCARCE;
    }

    cold = cache->sh->cold;

    if (rc == NGX_OK) {

        if (c->error) {
            return c->error;
        }

        c->temp_file = 1;
        test = c->exists ? 1 : 0;
        rv = NGX_DECLINED;

    } else { /* rc == NGX_DECLINED */

        if (c->min_uses > 1) {

            if (!cold) {
                return NGX_HTTP_CACHE_SCARCE;
            }

            test = 1;
            rv = NGX_HTTP_CACHE_SCARCE;

        } else {
            c->temp_file = 1;
            test = cold ? 1 : 0;
            rv = NGX_DECLINED;
        }
    }

    path = cache->path;

    c->file.name.len = path->name.len + 1 + path->len
                       + 2 * NGX_HTTP_CACHE_KEY_LEN;

    c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
    if (c->file.name.data == NULL) {
        return NGX_ERROR;
    }

    ngx_memcpy(c->file.name.data, path->name.data, path->name.len);

    p = c->file.name.data + path->name.len + 1 + path->len;
    p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
    *p = '\0';

    ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                   "cache file: \"%s\"", c->file.name.data);

    if (!test) {
        return NGX_DECLINED;
    }

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    ngx_memzero(&of, sizeof(ngx_open_file_info_t));

    of.uniq = c->uniq;
    of.valid = clcf->open_file_cache_valid;
    of.min_uses = clcf->open_file_cache_min_uses;
    of.events = clcf->open_file_cache_events;
    of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
    of.read_ahead = clcf->read_ahead;

    if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &of, r->pool)
        != NGX_OK)
    {
        switch (of.err) {

        case 0:
            return NGX_ERROR;

        case NGX_ENOENT:
        case NGX_ENOTDIR:
            return rv;

        default:
            ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
                          ngx_open_file_n " \"%s\" failed", c->file.name.data);
            return NGX_ERROR;
        }
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http file cache fd: %d", of.fd);

    c->file.fd = of.fd;
    c->file.log = r->connection->log;
    c->uniq = of.uniq;
    c->length = of.size;

    c->buf = ngx_create_temp_buf(r->pool, c->body_start);
    if (c->buf == NULL) {
        return NGX_ERROR;
    }

    return ngx_http_file_cache_read(r, c);
}
示例#28
0
static time_t
ngx_http_file_cache_expire(ngx_http_file_cache_t *cache)
{
    u_char                      *name, *p;
    size_t                       len;
    time_t                       now, wait;
    ngx_path_t                  *path;
    ngx_queue_t                 *q;
    ngx_http_file_cache_node_t  *fcn;
    u_char                       key[2 * NGX_HTTP_CACHE_KEY_LEN];

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                   "http file cache expire");

    path = cache->path;
    len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;

    name = ngx_alloc(len + 1, ngx_cycle->log);
    if (name == NULL) {
        return 10;
    }

    ngx_memcpy(name, path->name.data, path->name.len);

    now = ngx_time();

    ngx_shmtx_lock(&cache->shpool->mutex);

    for ( ;; ) {

        if (ngx_queue_empty(&cache->sh->queue)) {
            wait = 10;
            break;
        }

        q = ngx_queue_last(&cache->sh->queue);

        fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);

        wait = fcn->expire - now;

        if (wait > 0) {
            wait = wait > 10 ? 10 : wait;
            break;
        }

        ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                       "http file cache expire: #%d %d %02xd%02xd%02xd%02xd",
                       fcn->count, fcn->exists,
                       fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);

        if (fcn->count) {

            p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
                             sizeof(ngx_rbtree_key_t));

            len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
            (void) ngx_hex_dump(p, fcn->key, len);

            /*
             * abnormally exited workers may leave locked cache entries,
             * and although it may be safe to remove them completely,
             * we prefer to remove them from inactive queue and rbtree
             * only, and to allow other leaks
             */

            ngx_queue_remove(q);
            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);

            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                       "ignore long locked inactive cache entry %*s, count:%d",
                       2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);

            continue;
        }

        if (!fcn->exists) {

            ngx_queue_remove(q);
            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
            ngx_slab_free_locked(cache->shpool, fcn);

            continue;
        }

        ngx_http_file_cache_delete(cache, q, name);
    }

    ngx_shmtx_unlock(&cache->shpool->mutex);

    ngx_free(name);

    return wait;
}
static ngx_int_t
ngx_http_secure_token_handler(ngx_http_request_t *r)
{
    ngx_http_secure_token_loc_conf_t  *stlcf;
    ngx_http_secure_token_ctx_t       *stctx;
    ngx_http_complex_value_t          *cv;
    ngx_md5_t                          md5;
    ngx_str_t                          val;
    ngx_int_t                          rc;
    ngx_uint_t                         i;
    size_t                             adjust, len;
    u_char                             hex[32];

    stlcf = ngx_http_get_module_loc_conf(r, ngx_http_secure_token_module);

    if (!stlcf->enable) {
        return NGX_DECLINED;
    }

    if (stlcf->key.len == 0 || stlcf->md5 == NULL || stlcf->input == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    stctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_token_ctx_t));
    if (stctx == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_http_set_ctx(r, stctx, ngx_http_secure_token_module);

    rc = ngx_http_secure_token_parse_input(r);
    if (rc != NGX_OK) {
        return rc;
    }

    if (stctx->expire_time < ngx_time()) {
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "secure token: token expired: input: %d now: %d",
                       stctx->expire_time, ngx_time());

        return NGX_HTTP_FORBIDDEN;
    }

    if (stctx->access.len > 0) {
        adjust = stctx->access.data[stctx->access.len - 1] == '*' ? 1 : 0;

        len = r->args.data ? (size_t) (r->args.data - r->unparsed_uri.data) - 1
                           : r->unparsed_uri.len;

        if (len < stctx->access.len - adjust
            || ngx_strncmp(r->unparsed_uri.data,
                           stctx->access.data, stctx->access.len - adjust) != 0)
        {
            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "secure token: access mismatch: input: %V uri: %*s",
                           &stctx->access, len, r->unparsed_uri.data);

            return NGX_HTTP_FORBIDDEN;
        }
    }

    cv = stlcf->md5->elts;

    for (i = 0; i < stlcf->md5->nelts; i++) {

        if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        if (val.len == 0) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_md5_init(&md5);
        ngx_md5_update(&md5, val.data, val.len);
        ngx_md5_final(stctx->md5, &md5);

#if (NGX_DEBUG)
        (void) ngx_hex_dump(hex, stctx->md5, 16);
#endif

        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "secure token: md5/%d: %*s", i, 32, hex);
    }

#if (!NGX_DEBUG)
    (void) ngx_hex_dump(hex, stctx->md5, 16);
#endif

    if (ngx_strncasecmp(hex, stctx->token.data, 32)) {
        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "secure token: token mismatch: input: %V expected: %*s",
                       &stctx->token, 32, hex);

        return NGX_HTTP_FORBIDDEN;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "secure token: OK");

    return NGX_OK;
}