コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #5
0
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;
}
コード例 #6
0
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;
}
コード例 #7
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.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;
}