static ngx_int_t ngx_http_timestamp_handler(ngx_http_request_t* r) { ngx_uint_t i; ngx_http_timestamp_loc_conf_t* alcf; alcf = ngx_http_get_module_loc_conf(r, ngx_http_timestamp_module); if (!alcf->enable) { return NGX_OK; } ngx_str_t args = r->args; ngx_uint_t j = 0, k = 0, l = 0; for (i = 0; i <= args.len; i++) { if ( ( i == args.len) || (args.data[i] == '&') ) { if (j > 1) { k = j; l = i; } j = 0; } else if ((j == 0) && (i < args.len - ngx_http_timestamp_key.len) ) { if ((ngx_strncmp(args.data + i, ngx_http_timestamp_key.data, ngx_http_timestamp_key.len) == 0) && (args.data[i + ngx_http_timestamp_key.len] == '=') ) { j = i + ngx_http_timestamp_key.len + 1; i = j - 1; } else { j = 1; } } } ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "timestamp: attempting to parse value of %d length from string that is %d", l - k, l); time_t timestamp_value; timestamp_value = ngx_atotm(args.data + k, l - k); if (timestamp_value == NGX_ERROR) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "timestamp: Could not parse timestamp from query string parameters"); return NGX_HTTP_FORBIDDEN; } time_t now = time(0); ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "timestamp: the time is %d and given timestamp is %d", now, timestamp_value); int range = alcf->range; if (timestamp_value > now + range) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "timestamp: timestamp_value (%d) is above max range (%d; %d)", timestamp_value, now + range, range); return NGX_HTTP_FORBIDDEN; } if (timestamp_value < now - range) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "timestamp: timestamp_value (%d) is below min range (%d; %d)", timestamp_value, now - range, range); return NGX_HTTP_FORBIDDEN; } return NGX_OK; }
static ngx_int_t ngx_http_session_sticky_get_cookie(ngx_http_request_t *r) { time_t now; u_char *p, *v, *vv, *st, *last, *end; ngx_int_t diff, delimiter, legal, rc; ngx_str_t *cookie; ngx_uint_t i; ngx_table_elt_t **cookies; ngx_http_ss_ctx_t *ctx; ngx_http_upstream_ss_srv_conf_t *sscf; enum { pre_key = 0, key, pre_equal, pre_value, value } state; legal = 1; ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module); sscf = ctx->sscf; ctx->tries = 1; p = NULL; cookie = NULL; now = ngx_time(); cookies = (ngx_table_elt_t **) r->headers_in.cookies.elts; for (i = 0; i < r->headers_in.cookies.nelts; i++) { cookie = &cookies[i]->value; p = ngx_strnstr(cookie->data, (char *) sscf->cookie.data, cookie->len); if (p == NULL) { continue; } if (*(p + sscf->cookie.len) == ' ' || *(p + sscf->cookie.len) == '=') { break; } } if (i >= r->headers_in.cookies.nelts) { goto not_found; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session sticky cookie: \"%V\"", &cookies[i]->value); st = p; v = p + sscf->cookie.len + 1; last = cookie->data + cookie->len; state = 0; while (p < last) { switch (state) { case pre_key: if (*p == ';') { goto not_found; } else if (!is_space(*p)) { state = key; } break; case key: if (is_space(*p)) { state = pre_equal; } else if (*p == '=') { state = pre_value; } break; case pre_equal: if (*p == '=') { state = pre_value; } else if (!is_space(*p)) { goto not_found; } break; case pre_value: if (!is_space(*p)) { state = value; v = p--; } break; case value: if (*p == ';') { end = p + 1; goto success; } if (p + 1 == last) { end = last; p++; goto success; } break; default: break; } p++; } not_found: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session sticky [firstseen]"); ctx->frist = 1; ctx->sid.len = 0; ctx->sid.data = NULL; ctx->firstseen = now; ctx->lastseen = now; ngx_http_session_sticky_tmtoa(r, &ctx->s_lastseen, ctx->lastseen); ngx_http_session_sticky_tmtoa(r, &ctx->s_firstseen, ctx->firstseen); if (ctx->s_lastseen.data == NULL || ctx->s_firstseen.data == NULL) { return NGX_ERROR; } return NGX_OK; success: if (sscf->flag & NGX_HTTP_SESSION_STICKY_PREFIX) { for (vv = v; vv < p; vv++) { if (*vv == '~') { end = vv + 1; break; } } if (vv >= p) { goto not_found; } st = v; } else { vv = p; } if ((sscf->flag & NGX_HTTP_SESSION_STICKY_INSERT) && sscf->maxidle != NGX_CONF_UNSET) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session_sticky mode [insert]"); delimiter = 0; for (p = v; p < vv; p++) { if (*p == NGX_HTTP_SESSION_STICKY_DELIMITER) { delimiter++; if (delimiter == 1) { ctx->sid.len = p - v; ctx->sid.data = ngx_pnalloc(r->pool, ctx->sid.len); if (ctx->sid.data == NULL) { return NGX_ERROR; } ngx_memcpy(ctx->sid.data, v, ctx->sid.len); v = p + 1; } else if(delimiter == 2) { ctx->s_lastseen.len = p - v; ctx->s_lastseen.data = ngx_pnalloc(r->pool, ctx->s_lastseen.len); if (ctx->s_lastseen.data == NULL) { return NGX_ERROR; } ngx_memcpy(ctx->s_lastseen.data, v, ctx->s_lastseen.len); v = p + 1; break; } else { legal = 0; goto finish; } } } if (p >= vv || v >= vv) { legal = 0; goto finish; } ctx->s_firstseen.len = vv - v; ctx->s_firstseen.data = ngx_pnalloc(r->pool, ctx->s_firstseen.len); if (ctx->s_firstseen.data == NULL) { return NGX_ERROR; } ngx_memcpy(ctx->s_firstseen.data, v, ctx->s_firstseen.len); ctx->firstseen = ngx_atotm(ctx->s_firstseen.data, ctx->s_firstseen.len); ctx->lastseen = ngx_atotm(ctx->s_lastseen.data, ctx->s_lastseen.len); if (ctx->firstseen == NGX_ERROR || ctx->lastseen == NGX_ERROR) { legal = 0; goto finish; } if (ctx->sid.len != 0) { diff = (ngx_int_t) (now - ctx->lastseen); if (diff > ctx->sscf->maxidle || diff < -86400) { legal = 0; goto finish; } diff = (ngx_int_t) (now - ctx->firstseen); if (diff > ctx->sscf->maxlife || diff < -86400) { legal = 0; goto finish; } } ngx_http_session_sticky_tmtoa(r, &ctx->s_lastseen, now); } else { ctx->sid.len = vv - v; ctx->sid.data = ngx_pnalloc(r->pool, ctx->sid.len); if (ctx->sid.data == NULL) { return NGX_ERROR; } ngx_memcpy(ctx->sid.data, v, ctx->sid.len); } finish: if (sscf->flag & (NGX_HTTP_SESSION_STICKY_PREFIX | NGX_HTTP_SESSION_STICKY_INDIRECT)) { cookie->len -= (end - st); if (cookie->len == 0) { rc = ngx_list_delete(&r->headers_in.headers, cookies[i]); if (rc != NGX_OK) { return NGX_ERROR; } } while (end < last) { *st++ = *end++; } } if (legal == 0) { goto not_found; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session sticky sid [%V]", &ctx->sid); return NGX_OK; }
static char * ngx_http_upstream_session_sticky(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_int_t rc; ngx_uint_t i; ngx_str_t *value; ngx_http_upstream_srv_conf_t *uscf; ngx_http_upstream_ss_srv_conf_t *sscf = conf; uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); uscf->peer.init_upstream = ngx_http_upstream_session_sticky_init_upstream; uscf->flags = NGX_HTTP_UPSTREAM_CREATE | NGX_HTTP_UPSTREAM_WEIGHT | NGX_HTTP_UPSTREAM_MAX_FAILS | NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | NGX_HTTP_UPSTREAM_DOWN; value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "cookie=", 7) == 0){ sscf->cookie.data = value[i].data + 7; sscf->cookie.len = value[i].len - 7; if (sscf->cookie.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid cookie"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "domain=", 7) == 0) { sscf->domain.data = value[i].data + 7; sscf->domain.len = value[i].len - 7; if (sscf->domain.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid domain"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "path=", 5) == 0) { sscf->path.data = value[i].data + 5; sscf->path.len = value[i].len - 5; if (sscf->path.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid path"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "maxage=", 7) == 0) { sscf->maxage.data = value[i].data + 7; sscf->maxage.len = value[i].len - 7; rc = ngx_atoi(sscf->maxage.data, sscf->maxage.len); if (rc == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid maxage"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "maxidle=", 8) == 0) { sscf->maxidle = ngx_atotm(value[i].data + 8, value[i].len - 8); if (sscf->maxidle <= NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid maxidle"); return NGX_CONF_ERROR; } if (sscf->maxlife == NGX_CONF_UNSET) { sscf->maxlife = NGX_MAX_INT32_VALUE; } continue; } if (ngx_strncmp(value[i].data, "maxlife=", 8) == 0) { sscf->maxlife = ngx_atotm(value[i].data + 8, value[i].len - 8); if (sscf->maxlife <= NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid maxlife"); return NGX_CONF_ERROR; } if (sscf->maxidle == NGX_CONF_UNSET) { sscf->maxidle = NGX_MAX_INT32_VALUE; } continue; } if (ngx_strncmp(value[i].data, "mode=", 5) == 0) { value[i].data = value[i].data + 5; value[i].len = value[i].len - 5; if (ngx_strncmp(value[i].data, "insert", 6) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_INSERT; } else if (ngx_strncmp(value[i].data, "prefix", 6) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_PREFIX; sscf->flag &= (~NGX_HTTP_SESSION_STICKY_INSERT); } else if (ngx_strncmp(value[i].data, "rewrite", 7) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_REWRITE; sscf->flag &= (~NGX_HTTP_SESSION_STICKY_INDIRECT); sscf->flag &= (~NGX_HTTP_SESSION_STICKY_INSERT); } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid mode"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "option=", 7) == 0) { value[i].data = value[i].data + 7; value[i].len = value[i].len - 7; if (ngx_strncmp(value[i].data, "indirect", 8) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_INDIRECT; } else if (ngx_strncmp(value[i].data, "direct", 6) == 0) { sscf->flag &= ~NGX_HTTP_SESSION_STICKY_INDIRECT; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid option"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "fallback=", 9) == 0) { value[i].data = value[i].data + 9; value[i].len = value[i].len - 9; if (ngx_strncmp(value[i].data, "on", 2) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_FALLBACK_ON; } else if (ngx_strncmp(value[i].data, "off", 3) == 0) { sscf->flag |= NGX_HTTP_SESSION_STICKY_FALLBACK_OFF; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid fallback"); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "hash=", 5) == 0) { value[i].data = value[i].data + 5; value[i].len = value[i].len - 5; if (ngx_strncmp(value[i].data, "plain", 5) == 0) { sscf->flag = (sscf->flag & (~NGX_HTTP_SESSION_STICKY_MD5)) | NGX_HTTP_SESSION_STICKY_PLAIN; } else if (ngx_strncmp(value[i].data, "md5", 4) == 0) { sscf->flag = (sscf->flag & (~NGX_HTTP_SESSION_STICKY_PLAIN)) | NGX_HTTP_SESSION_STICKY_MD5; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hash mode"); return NGX_CONF_ERROR; } continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid argument"); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
//获取secure_link配置的值,同时与secure_link_md5运算的值进行比较,相同则置$secure_link变量为1,不同则置0 static ngx_int_t ngx_http_secure_link_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *p, *last; ngx_str_t val, hash; time_t expires; ngx_md5_t md5; ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; u_char hash_buf[16], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); if (conf->secret.data) { return ngx_http_secure_link_old_variable(r, conf, v, data); } if (conf->variable == NULL || conf->md5 == NULL) { goto not_found; } if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link: \"%V\"", &val); last = val.data + val.len; p = ngx_strlchr(val.data, last, ','); ////secure_link md5_str, 120配置, expires = 0; if (p) { val.len = p++ - val.data; //这时候,val.len=md5_str的字符串长度了,不包括后面的,120字符串 expires = ngx_atotm(p, last - p); //获取//secure_link md5_str, 120配置中的120 if (expires <= 0) { goto not_found; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module); ctx->expires.len = last - p; ctx->expires.data = p; } //这时候,val.len=md5_str的字符串长度了,不包括后面的,120字符串 if (val.len > 24) {//secure_link配置解析出的字符串不能超过24个字符 ?????? 为什么呢 goto not_found; } hash.len = 16; hash.data = hash_buf; //把secure_link md5_str, 120配置中的md5_str字符串进行base64解密decode运算后的值存到这里面 if (ngx_decode_base64url(&hash, &val) != NGX_OK) { goto not_found; } if (hash.len != 16) { goto not_found; } //解析secure_link_md5 $the_uri_you_want_to_hashed_by_md5配置的字符串 if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link md5: \"%V\"", &val); //echo -n 'ttlsa.com/download/nginx-1.9.2.rar1452130593' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = ngx_md5_init(&md5); ngx_md5_update(&md5, val.data, val.len); ngx_md5_final(md5_buf, &md5); if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) { //比较判断是否一致 goto not_found; } //设置v变量对应的值为0或者1 v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1"); v->len = 1; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }
static ngx_inline ngx_int_t ngx_http_modsecurity_save_headers_in(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); /* clean up headers_in */ ngx_memzero(&r->headers_in, sizeof(ngx_http_headers_in_t)); if (ngx_list_init(&r->headers_in.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { return NGX_ERROR; } if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) { return NGX_ERROR; } r->headers_in.content_length_n = -1; r->headers_in.keep_alive_n = -1; r->headers_in.headers.part.nelts = 0; r->headers_in.headers.part.next = NULL; r->headers_in.headers.last = &r->headers_in.headers.part; /* shadow copy */ if (apr_table_do(ngx_http_modsecurity_save_headers_in_visitor, r, ctx->req->headers_in, NULL) == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: save headers in error"); return NGX_ERROR; } if (r->headers_in.content_length) { r->headers_in.content_length_n = ngx_atoof(r->headers_in.content_length->value.data, r->headers_in.content_length->value.len); if (r->headers_in.content_length_n == NGX_ERROR) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "ModSecurity: invalid \"Content-Length\" header"); return NGX_ERROR; } } if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) { if (r->headers_in.keep_alive) { r->headers_in.keep_alive_n = ngx_atotm(r->headers_in.keep_alive->value.data, r->headers_in.keep_alive->value.len); } } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: save headers in done"); return NGX_OK; }
static ngx_int_t ngx_http_secure_token_parse_input(ngx_http_request_t *r) { ngx_http_secure_token_loc_conf_t *stlcf; ngx_http_secure_token_ctx_t *stctx; u_char *p, *last, *end; size_t len; stlcf = ngx_http_get_module_loc_conf(r, ngx_http_secure_token_module); stctx = ngx_http_get_module_ctx(r, ngx_http_secure_token_module); if (ngx_http_complex_value(r, stlcf->input, &stctx->input) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (stctx->input.len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: missing input"); return NGX_HTTP_FORBIDDEN; } if (stlcf->input_sep != '\0') { p = stctx->input.data; last = stctx->input.data + stctx->input.len; end = NULL; while (end < last) { end = ngx_strlchr(p, last, stlcf->input_sep); if (end == NULL) { end = last; } len = end - p; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: parse: \"%*s\"", len, p); if ((len == 18 && ngx_strncmp(p, "expires", 7) == 0) || (len == 17 && ngx_strncmp(p, "expire", 6) == 0)) { stctx->expire_time = ngx_atotm(end - 10, 10); if (stctx->expire_time == NGX_ERROR) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: invalid input"); return NGX_HTTP_FORBIDDEN; } stctx->expire_str.data = end - 10; stctx->expire_str.len = 10; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: expire: %d", stctx->expire_time); } else if ((len == 38 && ngx_strncmp(p, "token", 5) == 0) || (len == 36 && ngx_strncmp(p, "md5", 3) == 0)) { stctx->token.data = end - 32; stctx->token.len = 32; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: token: %V", &stctx->token); } else if (len > 7 && ngx_strncmp(p, "access", 6) == 0) { stctx->access.data = p + 7; stctx->access.len = len - 7; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: access: %V", &stctx->access); } p = end + 1; } } else { if (stctx->input.len != 43) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: invalid input"); return NGX_HTTP_FORBIDDEN; } stctx->expire_time = ngx_atotm(stctx->input.data, 10); if (stctx->expire_time == NGX_ERROR) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: invalid input"); return NGX_HTTP_FORBIDDEN; } stctx->expire_str.data = stctx->input.data; stctx->expire_str.len = 10; stctx->token.data = stctx->input.data + 11; stctx->token.len = 32; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: expire: %d token: %V", stctx->expire_time, &stctx->token); } if (stctx->token.len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: missing token"); return NGX_HTTP_FORBIDDEN; } if (stctx->expire_time == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure token: input: missing expire"); return NGX_HTTP_FORBIDDEN; } return NGX_OK; }
static ngx_int_t ngx_http_secure_link_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *p, *last; ngx_str_t val, hash; time_t expires; ngx_md5_t md5; ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; u_char hash_buf[16], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); if (conf->secret.len) { return ngx_http_secure_link_old_variable(r, conf, v, data); } if (conf->variable == NULL || conf->md5 == NULL) { goto not_found; } if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link: \"%V\"", &val); last = val.data + val.len; p = ngx_strlchr(val.data, last, ','); expires = 0; if (p) { val.len = p++ - val.data; expires = ngx_atotm(p, last - p); if (expires <= 0) { goto not_found; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module); ctx->expires.len = last - p; ctx->expires.data = p; } if (val.len > 24) { goto not_found; } hash.len = 16; hash.data = hash_buf; if (ngx_decode_base64url(&hash, &val) != NGX_OK) { goto not_found; } if (hash.len != 16) { goto not_found; } if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure link md5: \"%V\"", &val); ngx_md5_init(&md5); ngx_md5_update(&md5, val.data, val.len); ngx_md5_final(md5_buf, &md5); if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) { goto not_found; } v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1"); v->len = 1; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }