static ret_t parse_x_real_ip (cherokee_logger_t *logger, cherokee_connection_t *conn) { ret_t ret; cuint_t len = 0; char *val = NULL; /* Look for the X-Real-IP header */ ret = cherokee_header_get_known (&conn->header, header_x_real_ip, &val, &len); if (ret != ret_ok) { char *p; /* Look for the X-Forwarded-For header */ ret = cherokee_header_get_known (&conn->header, header_x_forwarded_for, &val, &len); if (ret != ret_ok) { return ret_not_found; } p = val; while (*p && (p - val < len)) { if ((*p == ' ') || (*p == ',')) { len = p - val; break; } p++; } } /* Is the client allowed to use X-Real-IP? */ ret = cherokee_x_real_ip_is_allowed (&logger->priv->x_real_ip, &conn->socket); if (ret != ret_ok) { return ret_deny; } /* Store the X-Real-IP value */ ret = cherokee_buffer_add (&conn->logger_real_ip, val, len); if (unlikely (ret != ret_ok)) { return ret_error; } return ret_ok; }
ret_t cherokee_post_read_header (cherokee_post_t *post, void *cnt) { ret_t ret; char *info = NULL; cuint_t info_len = 0; cherokee_connection_t *conn = CONN(cnt); switch (post->read_header_phase) { case cherokee_post_read_header_init: /* Read the header */ ret = parse_header (post, conn); if (unlikely (ret != ret_ok)) { return ret; } post->has_info = true; ret = remove_surplus (post, conn); if (unlikely (ret != ret_ok)) { return ret; } /* Expect: 100-continue * http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html */ ret = cherokee_header_get_known (&conn->header, header_expect, &info, &info_len); if (likely (ret != ret_ok)) { return ret_ok; } cherokee_buffer_add_str (&post->read_header_100cont, HTTP_100_RESPONSE); post->read_header_phase = cherokee_post_read_header_100cont; case cherokee_post_read_header_100cont: return reply_100_continue (post, conn); } SHOULDNT_HAPPEN; return ret_error; }
static ret_t match_regex (cherokee_rule_header_t *rule, cherokee_connection_t *conn, cherokee_config_entry_t *ret_conf) { int re; ret_t ret; char *info = NULL; cuint_t info_len = 0; UNUSED(ret_conf); /* Find the header */ ret = cherokee_header_get_known (&conn->header, rule->header, &info, &info_len); if ((ret != ret_ok) || (info == NULL)) { TRACE (ENTRIES, "Request '%s'; couldn't find header(%d)\n", conn->request.buf, rule->header); return ret_not_found; } /* Check whether it matches */ re = pcre_exec (rule->pcre, NULL, info, info_len, 0, 0, NULL, 0); if (re < 0) { TRACE (ENTRIES, "Request '%s' didn't match header(%d) with '%s'\n", conn->request.buf, rule->header, rule->match.buf); return ret_not_found; } TRACE (ENTRIES, "Request '%s' matched header(%d) with '%s'\n", conn->request.buf, rule->header, rule->match.buf); return ret_ok; }
static ret_t parse_header (cherokee_post_t *post, cherokee_connection_t *conn) { ret_t ret; char *info = NULL; cuint_t info_len = 0; CHEROKEE_TEMP(buf, 64); /* RFC 2616: * * If a message is received with both a Transfer-Encoding * header field and a Content-Length header field, the latter * MUST be ignored. */ /* Check "Transfer-Encoding" */ ret = cherokee_header_get_known (&conn->header, header_transfer_encoding, &info, &info_len); if (ret == ret_ok) { if (strncasecmp (info, "chunked", MIN(info_len, 7)) == 0) { TRACE (ENTRIES, "Post type: %s\n", "chunked"); post->encoding = post_enc_chunked; return ret_ok; } } TRACE (ENTRIES, "Post type: %s\n", "plain"); /* Check "Content-Length" */ ret = cherokee_header_get_known (&conn->header, header_content_length, &info, &info_len); if (unlikely (ret != ret_ok)) { conn->error_code = http_length_required; return ret_error; } /* Parse the POST length */ if (unlikely ((info == NULL) || (info_len == 0) || (info_len >= buf_size))) { conn->error_code = http_bad_request; return ret_error; } memcpy (buf, info, info_len); buf[info_len] = '\0'; /* Check: Post length >= 0 */ post->len = (off_t) atoll(buf); if (unlikely (post->len < 0)) { conn->error_code = http_bad_request; return ret_error; } TRACE (ENTRIES, "Post claims to be %llu bytes long\n", post->len); return ret_ok; }