Esempio n. 1
0
static int mk_http_request_prepare(struct mk_http_session *cs,
                                   struct mk_http_request *sr)
{
    int status = 0;
    char *temp;
    struct mk_list *hosts = &mk_config->hosts;
    struct mk_list *alias;
    struct mk_http_header *header;

    /*
     * Process URI, if it contains ASCII encoded strings like '%20',
     * it will return a new memory buffer with the decoded string, otherwise
     * it returns NULL
     */
    temp = mk_utils_url_decode(sr->uri);

    if (temp) {
        sr->uri_processed.data = temp;
        sr->uri_processed.len  = strlen(temp);
    }
    else {
        sr->uri_processed.data = sr->uri.data;
        sr->uri_processed.len  = sr->uri.len;
    }

    /* Always assign the default vhost' */
    sr->host_conf = mk_list_entry_first(hosts, struct host, _head);

    sr->user_home = MK_FALSE;

    /* Valid request URI? */
    if (sr->uri_processed.data[0] != '/') {
        mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr);
        return MK_EXIT_OK;
    }

    /* Check if we have a Host header: Hostname ; port */
    mk_http_point_header(&sr->host, &cs->parser, MK_HEADER_HOST);

    /* Header: Connection */
    mk_http_point_header(&sr->connection, &cs->parser, MK_HEADER_CONNECTION);

    /* Header: Range */
    mk_http_point_header(&sr->range, &cs->parser, MK_HEADER_RANGE);

    /* Header: If-Modified-Since */
    mk_http_point_header(&sr->if_modified_since,
                         &cs->parser,
                         MK_HEADER_IF_MODIFIED_SINCE);

    /* HTTP/1.1 needs Host header */
    if (!sr->host.data && sr->protocol == MK_HTTP_PROTOCOL_11) {
        mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr);
        return MK_EXIT_OK;
    }

    /* Should we close the session after this request ? */
    mk_http_keepalive_check(cs, sr);

    /* Content Length */
    header = &cs->parser.headers[MK_HEADER_CONTENT_LENGTH];
    if (header->type == MK_HEADER_CONTENT_LENGTH) {
        sr->_content_length.data = header->val.data;
        sr->_content_length.len  = header->val.len;
    }
    else {
        sr->_content_length.data = NULL;
    }

    /* Assign the first node alias */
    alias = &sr->host_conf->server_names;
    sr->host_alias = mk_list_entry_first(alias,
                                         struct host_alias, _head);

    if (sr->host.data) {
        /* Set the given port */
        if (cs->parser.header_host_port > 0) {
            sr->port = cs->parser.header_host_port;
        }

        /* Match the virtual host */
        mk_vhost_get(sr->host, &sr->host_conf, &sr->host_alias);

        /* Check if this virtual host have some redirection */
        if (sr->host_conf->header_redirect.data) {
            mk_header_set_http_status(sr, MK_REDIR_MOVED);
            sr->headers.location = mk_string_dup(sr->host_conf->header_redirect.data);
            sr->headers.content_length = 0;
            sr->headers.location = NULL;
            mk_header_prepare(cs, sr);
            return 0;
        }
    }

    /* Is requesting an user home directory ? */
    if (mk_config->user_dir &&
            sr->uri_processed.len > 2 &&
            sr->uri_processed.data[1] == MK_USER_HOME) {

        if (mk_user_init(cs, sr) != 0) {
            mk_http_error(MK_CLIENT_NOT_FOUND, cs, sr);
            return MK_EXIT_ABORT;
        }
    }

    /* Plugins Stage 20 */
    int ret;
    ret = mk_plugin_stage_run_20(cs, sr);
    if (ret == MK_PLUGIN_RET_CLOSE_CONX) {
        MK_TRACE("STAGE 20 requested close conexion");
        return MK_EXIT_ABORT;
    }

    /* Normal HTTP process */
    status = mk_http_init(cs, sr);

    MK_TRACE("[FD %i] HTTP Init returning %i", cs->socket, status);

    return status;
}
Esempio n. 2
0
/* Return a struct with method, URI , protocol version
and all static headers defined here sent in request */
static int mk_request_header_process(struct session_request *sr)
{
    int uri_init = 0, uri_end = 0;
    int query_init = 0;
    int prot_init = 0, prot_end = 0, pos_sep = 0;
    int fh_limit;
    char *headers;
    char *temp = 0;
    mk_ptr_t host;

    /* Method */
    sr->method_p = mk_http_method_check_str(sr->method);

    /* Request URI */
    temp = index(sr->body.data, ' ');
    if (mk_unlikely(!temp)) {
        MK_TRACE("Error, invalid first header");
        return -1;
    }
    uri_init = (temp - sr->body.data) + 1;

    temp = index(sr->body.data, '\n');
    if (mk_unlikely(!temp)) {
        MK_TRACE("Error, invalid header CRLF");
        return -1;
    }
    fh_limit = (temp - sr->body.data);

    uri_end = mk_string_char_search_r(sr->body.data, ' ', fh_limit) - 1;
    if (mk_unlikely(uri_end <= 0)) {
        MK_TRACE("Error, first header bad formed");
        return -1;
    }

    prot_init = uri_end + 2;

    if (mk_unlikely(uri_end < uri_init)) {
        return -1;
    }

    /* Query String */
    query_init = mk_string_char_search(sr->body.data + uri_init, '?', prot_init);
    if (query_init > 0) {
        int init, end;

        init = query_init + uri_init;
        if (init <= uri_end) {
            end = uri_end;
            uri_end = init - 1;

            sr->query_string = mk_ptr_create(sr->body.data,
                                                 init + 1, end + 1);
        }
    }

    /* Request URI Part 2 */
    sr->uri = mk_ptr_create(sr->body.data, uri_init, uri_end + 1);
    if (mk_unlikely(sr->uri.len < 1)) {
        return -1;
    }

    /* HTTP Version */
    prot_end = fh_limit - 1;
    if (mk_unlikely(prot_init == prot_end)) {
        return  -1;
    }

    if (prot_end != prot_init && prot_end > 0) {
        sr->protocol = mk_http_protocol_check(sr->body.data + prot_init,
                                              prot_end - prot_init);
        sr->protocol_p = mk_http_protocol_check_str(sr->protocol);
    }

    headers = sr->body.data + prot_end + mk_crlf.len;

    /*
     * Process URI, if it contains ASCII encoded strings like '%20',
     * it will return a new memory buffer with the decoded string, otherwise
     * it returns NULL
     */
    temp = mk_utils_url_decode(sr->uri);
    if (temp) {
        sr->uri_processed.data = temp;
        sr->uri_processed.len  = strlen(temp);
    }
    else {
        sr->uri_processed.data = sr->uri.data;
        sr->uri_processed.len  = sr->uri.len;
    }

    /* Creating Table of Content (index) for HTTP headers */
    sr->headers_len = sr->body.len - (prot_end + mk_crlf.len);
    if (mk_request_header_toc_parse(&sr->headers_toc, headers, sr->headers_len) < 0) {
        MK_TRACE("Invalid headers");
        return -1;
    }

    /* Host */
    host = mk_request_header_get(&sr->headers_toc,
                                 mk_rh_host.data,
                                 mk_rh_host.len);
    if (host.data) {
        if ((pos_sep = mk_string_char_search_r(host.data, ':', host.len)) >= 0) {
            /* TCP port should not be higher than 65535 */
            char *p;
            short int port_len, port_size = 6;
            char port[port_size];

            /* just the host */
            sr->host.data = host.data;
            sr->host.len = pos_sep;

            /* including the port */
            sr->host_port = host;

            /* Port string length */
            port_len = (host.len - pos_sep - 1);
            if (port_len >= port_size) {
                return -1;
            }

            /* Copy to buffer */
            memcpy(port, host.data + pos_sep + 1, port_len);
            port[port_len] = '\0';

            /* Validate that the input port is numeric */
            p = port;
            while (*p) {
                if (!isdigit(*p)) return -1;
                p++;
            }

            /* Convert to base 10 */
            errno = 0;
            sr->port = strtol(port, (char **) NULL, 10);
            if ((errno == ERANGE && (sr->port == LONG_MAX || sr->port == LONG_MIN))
                || sr->port == 0) {
                return -1;
            }
        }
        else {
            sr->host = host;    /* maybe null */
            sr->port = config->standard_port;
        }
    }
    else {
        sr->host.data = NULL;
    }

    /* Looking for headers that ONLY Monkey uses */
    sr->connection = mk_request_header_get(&sr->headers_toc,
                                           mk_rh_connection.data,
                                           mk_rh_connection.len);

    sr->range = mk_request_header_get(&sr->headers_toc,
                                      mk_rh_range.data,
                                      mk_rh_range.len);

    sr->if_modified_since = mk_request_header_get(&sr->headers_toc,
                                                  mk_rh_if_modified_since.data,
                                                  mk_rh_if_modified_since.len);

    /* Default Keepalive is off */
    if (sr->protocol == MK_HTTP_PROTOCOL_10) {
        sr->keep_alive = MK_FALSE;
        sr->close_now = MK_TRUE;
    }
    else if(sr->protocol == MK_HTTP_PROTOCOL_11) {
        sr->keep_alive = MK_TRUE;
        sr->close_now = MK_FALSE;
    }

    if (sr->connection.data) {
        if (mk_string_search_n(sr->connection.data, "Keep-Alive",
                               MK_STR_INSENSITIVE, sr->connection.len) >= 0) {
            sr->keep_alive = MK_TRUE;
            sr->close_now = MK_FALSE;
        }
        else if (mk_string_search_n(sr->connection.data, "Close",
                                    MK_STR_INSENSITIVE, sr->connection.len) >= 0) {
            sr->keep_alive = MK_FALSE;
            sr->close_now = MK_TRUE;
        }
        else {
            /* Set as a non-valid connection header value */
            sr->connection.len = 0;
        }
    }

    return 0;
}