static ngx_int_t ngx_http_cp_handler(ngx_http_request_t *r) { ngx_http_cp_loc_conf_t *cplcf; ngx_str_t cookie, cookie_name; ngx_str_t neteye_cookie; #if (NGX_DEBUG) ngx_str_t cookie_magic; #endif ngx_int_t ret; ngx_uint_t i, j; ngx_table_elt_t **h; u_char *start, *end, *p; ngx_http_cp_monitored_cookie_t *m_cookie; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie poison handler begin"); if (ngx_http_session_test_create(r) || ngx_http_session_test_bypass(r)) { return NGX_DECLINED; } cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cookie_poisoning_module); if (!cplcf->enabled) { return NGX_DECLINED; } if (ngx_http_ns_test_bypass_all(r)) { return NGX_DECLINED; } memset(&cookie, 0, sizeof(ngx_str_t)); memset(&cookie_name, 0, sizeof(ngx_str_t)); memset(&neteye_cookie, 0, sizeof(ngx_str_t)); h = r->headers_in.cookies.elts; for (i = 0; i < r->headers_in.cookies.nelts; i++) { start = p = h[i]->value.data; end = start + h[i]->value.len; /* skip the spaces at head */ for (; start < end && *start == ' '; start++) { } if (start == end) { /* no more in this value */ continue; } for (j = 0; j < h[i]->value.len; j++, p++) { if (*p == '=') { cookie_name.data = start; cookie_name.len = p - start; if (cookie_name.len == strlen(NGX_HTTP_SESSION_DEFAULT_COOKIE)) { if (!memcmp(cookie_name.data, NGX_HTTP_SESSION_DEFAULT_COOKIE, strlen(NGX_HTTP_SESSION_DEFAULT_COOKIE))) { goto next; } } /* store this cookie's value to cookie */ ret = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &cookie_name, &cookie); if (ret == NGX_DECLINED || cookie.len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "BIG ERROR!"); goto next; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie_name: %V, cookie_data: %V", &cookie_name, &cookie); m_cookie = ngx_http_cp_check_cookie(r, &cookie_name); if (m_cookie != NULL) { /* this cookie is monitored */ if (ngx_http_cp_gen_cookie_data(r, &cookie, &neteye_cookie, m_cookie->magic) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if (NGX_DEBUG) cookie_magic.data = m_cookie->cookie_magic; cookie_magic.len = NGX_HTTP_CP_MD5_LEN; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "neteye_cookie_data: %V, expected: %V", &neteye_cookie, &cookie_magic); #endif if (memcmp(m_cookie->cookie_magic, neteye_cookie.data, NGX_HTTP_CP_MD5_LEN)) { /* not matched, do action */ ret = ngx_http_cp_do_action(r, &cookie_name, &cookie); if (ret != NGX_OK) { return ret; } } } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie is not monitored"); } next: for (; start < end && *start != ';'; start++) { } if (start == end) { /* no more in this value */ break; } /* *start == ';' */ start++; for (; start < end && *start == ' '; start++) { } if (start == end) { /* no more in this value */ break; } p = start; } } } return NGX_DECLINED; }
ngx_int_t ngx_http_cp_header_handler(ngx_http_request_t *r) { ngx_table_elt_t *h; ngx_list_part_t *part; ngx_http_upstream_t *u; ngx_uint_t i, j, cmp_len; u_char *start, *end, *p; ngx_str_t cookie, cookie_name; ngx_str_t neteye_cookie; ngx_http_cp_loc_conf_t *cplcf; ngx_uint_t magic; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie poison header handler"); if (ngx_http_session_test_create(r) || ngx_http_session_test_bypass(r)) { return NGX_DECLINED; } if (ngx_http_ns_test_bypass_all(r)) { return NGX_DECLINED; } cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cookie_poisoning_module); if (cplcf->enabled != 1) { /* Cookie Poison not enabled */ return NGX_DECLINED; } u = r->upstream; if (u) { part = &u->headers_in.headers.part; } else { /* response from local */ part = &r->headers_out.headers.part; } if (part == NULL) { /* Have no headers */ return NGX_DECLINED; } memset(&cookie, 0, sizeof(ngx_str_t)); memset(&cookie_name, 0, sizeof(ngx_str_t)); memset(&neteye_cookie, 0, sizeof(ngx_str_t)); h = part->elts; for (i = 0; ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].key.len != strlen("Set-Cookie")) { continue; } if (!memcmp(h[i].key.data, "Set-Cookie", h[i].key.len)) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "found set cookie"); start = p = h[i].value.data; end = h[i].value.data + h[i].value.len; for (j = 0; j < h[i].value.len; j++, p++) { if (*p == ' ' || *p == '=') { cookie_name.data = start; cookie_name.len = p - start; /* store this cookie's value to cookie */ if (*p == ' ') { for (; *p != '='; p++) ; } p++; cookie.data = p; for (; *p != ';' && p < end; p++) ; cookie.len = p - cookie.data; if (cookie.len == 0) { break; } cmp_len = cookie.len >= strlen("deleted") ? strlen("deleted") : cookie.len; if (!strncmp((char *)cookie.data, "deleted", cmp_len)) { /* update monitored cookies in session*/ ngx_http_cp_delete_monitored_cookies(r, &cookie_name); break; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie_name: %V, cookie_data: %V", &cookie_name, &cookie); /* md5 the cookie_data, and add it to the header */ magic = ngx_random(); if (ngx_http_cp_gen_cookie_data(r, &cookie, &neteye_cookie, magic) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "neteye_cookie_data: %V", &neteye_cookie); /* update monitored cookies in session*/ ngx_http_cp_update_monitored_cookies(r, &cookie_name, &neteye_cookie, magic); break; } } } } return NGX_DECLINED; }
static ngx_int_t ngx_http_session_header_filter(ngx_http_request_t *r) { ngx_http_session_conf_t *sscf; ngx_str_t sid; ngx_int_t ret; ngx_uint_t status; ngx_http_upstream_t *u; ngx_table_elt_t *set_cookie; u_char *cookie; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session filter begin\n"); sscf = ngx_http_get_module_loc_conf(r, ngx_http_session_module); if (!sscf->enabled) { return NGX_DECLINED; } if (ngx_http_session_test_bypass(r)) { return NGX_DECLINED; } if (!ngx_http_session_test_create(r)) { return NGX_DECLINED; } /* r->session_create is set, create a new session */ u = r->upstream; if (!u && !ngx_http_session_test_local(r)) { return NGX_DECLINED; } if (u) { status = u->state->status; if (status < 200 || status > 400) { return NGX_DECLINED; } } memset(&sid, 0, sizeof(ngx_str_t)); sid.data = ngx_pcalloc(r->pool, 33); if (sid.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ret = ngx_http_session_gen_sid(r, &sid); if (ret != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ret = ngx_http_session_insert(r, &sid); if (ret != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cookie = ngx_pcalloc(r->pool, (strlen((char *)sscf->keyword.data) + 2 + NGX_HTTP_SESSION_DEFAULT_SID_LEN + strlen("; Path=/; HttpOnly"))); if (cookie == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_sprintf(cookie, "%s=%s; Path=/; HttpOnly", sscf->keyword.data, sid.data); set_cookie = ngx_list_push(&r->headers_out.headers); if (set_cookie == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } set_cookie->hash = 1; set_cookie->key.len = sizeof ("Set-Cookie") - 1; set_cookie->key.data = (u_char *) "Set-Cookie"; set_cookie->value.len = ngx_strlen(cookie); set_cookie->value.data = cookie; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "filter end\n"); return NGX_OK; }