コード例 #1
0
ファイル: mk_memory.c プロジェクト: f13mash/monkey
void mk_mem_pointers_init()
{
    /* Short server response headers */
    mk_pointer_set(&mk_header_short_date, MK_HEADER_SHORT_DATE);
    mk_pointer_set(&mk_header_short_location, MK_HEADER_SHORT_LOCATION);
    mk_pointer_set(&mk_header_short_ct, MK_HEADER_SHORT_CT);

    /* Request vars */
    mk_pointer_set(&mk_crlf, MK_CRLF);
    mk_pointer_set(&mk_endblock, MK_ENDBLOCK);

    /* Client headers */
    mk_pointer_set(&mk_rh_accept, RH_ACCEPT);
    mk_pointer_set(&mk_rh_accept_charset, RH_ACCEPT_CHARSET);
    mk_pointer_set(&mk_rh_accept_encoding, RH_ACCEPT_ENCODING);
    mk_pointer_set(&mk_rh_accept_language, RH_ACCEPT_LANGUAGE);
    mk_pointer_set(&mk_rh_connection, RH_CONNECTION);
    mk_pointer_set(&mk_rh_cookie, RH_COOKIE);
    mk_pointer_set(&mk_rh_content_length, RH_CONTENT_LENGTH);
    mk_pointer_set(&mk_rh_content_range, RH_CONTENT_RANGE);
    mk_pointer_set(&mk_rh_content_type, RH_CONTENT_TYPE);
    mk_pointer_set(&mk_rh_if_modified_since, RH_IF_MODIFIED_SINCE);
    mk_pointer_set(&mk_rh_host, RH_HOST);
    mk_pointer_set(&mk_rh_last_modified, RH_LAST_MODIFIED);
    mk_pointer_set(&mk_rh_last_modified_since, RH_LAST_MODIFIED_SINCE);
    mk_pointer_set(&mk_rh_referer, RH_REFERER);
    mk_pointer_set(&mk_rh_range, RH_RANGE);
    mk_pointer_set(&mk_rh_user_agent, RH_USER_AGENT);

    /* Server response normal headers */
    mk_pointer_set(&mk_header_conn_ka, MK_HEADER_CONN_KA);
    mk_pointer_set(&mk_header_conn_close, MK_HEADER_CONN_CLOSE);
    mk_pointer_set(&mk_header_content_length, MK_HEADER_CONTENT_LENGTH);
    mk_pointer_set(&mk_header_content_encoding, MK_HEADER_CONTENT_ENCODING);
    mk_pointer_set(&mk_header_accept_ranges, MK_HEADER_ACCEPT_RANGES);
    mk_pointer_set(&mk_header_te_chunked, MK_HEADER_TE_CHUNKED);
    mk_pointer_set(&mk_header_last_modified, MK_HEADER_LAST_MODIFIED);

    mk_http_status_list_init();
    mk_iov_separators_init();

    /* Server */
    mk_pointer_set(&mk_monkey_protocol, HTTP_PROTOCOL_11_STR);

    /* HTTP */
    mk_pointer_set(&mk_http_method_get_p, HTTP_METHOD_GET_STR);
    mk_pointer_set(&mk_http_method_post_p, HTTP_METHOD_POST_STR);
    mk_pointer_set(&mk_http_method_head_p, HTTP_METHOD_HEAD_STR);
    mk_pointer_set(&mk_http_method_put_p, HTTP_METHOD_PUT_STR);
    mk_pointer_set(&mk_http_method_delete_p, HTTP_METHOD_DELETE_STR);
    mk_pointer_reset(&mk_http_method_null_p);

    mk_pointer_set(&mk_http_protocol_09_p, HTTP_PROTOCOL_09_STR);
    mk_pointer_set(&mk_http_protocol_10_p, HTTP_PROTOCOL_10_STR);
    mk_pointer_set(&mk_http_protocol_11_p, HTTP_PROTOCOL_11_STR);
    mk_pointer_reset(&mk_http_protocol_null_p);

}
コード例 #2
0
ファイル: mk_header.c プロジェクト: dhanunjaya/monkey
void mk_header_response_reset(struct response_headers *header)
{
    header->status = 0;
    header->sent = MK_FALSE;
    header->ranges[0] = -1;
    header->ranges[1] = -1;
    header->content_length = -1;
    header->connection = 0;
    header->transfer_encoding = -1;
    header->last_modified = -1;
    header->cgi = SH_NOCGI;
    mk_pointer_reset(&header->content_type);
    mk_pointer_reset(&header->content_encoding);
    header->location = NULL;
    header->_extra_rows = NULL;
}
コード例 #3
0
ファイル: mk_request.c プロジェクト: f13mash/monkey
/* Create a memory allocation in order to handle the request data */
static void mk_request_init(struct session_request *request)
{
    request->status = MK_FALSE;  /* Request not processed yet */
    request->close_now = MK_FALSE;

    mk_pointer_reset(&request->body);
    request->status = MK_TRUE;
    request->method = HTTP_METHOD_UNKNOWN;

    mk_pointer_reset(&request->uri);
    request->uri_processed.data = NULL;

    request->content_length = 0;
    request->content_type.data = NULL;
    request->connection.data = NULL;
    request->host.data = NULL;
    request->if_modified_since.data = NULL;
    request->last_modified_since.data = NULL;
    request->range.data = NULL;

    request->data.data = NULL;
    mk_pointer_reset(&request->query_string);

    request->file_info.size = -1;
    request->virtual_user = NULL;
    request->keep_alive = MK_FALSE;

    mk_pointer_reset(&request->real_path);
    request->host_conf = config->hosts;

    request->loop = 0;
    request->bytes_to_send = -1;
    request->bytes_offset = 0;
    request->fd_file = -1;

    /* Response Headers */
    mk_header_response_reset(&request->headers);

    /* Plugin handler */
    request->handled_by = NULL;

    /* Headers TOC */
    request->headers_toc.length = 0;
}
コード例 #4
0
ファイル: mk_memory.c プロジェクト: alepharchives/monkey
mk_pointer mk_pointer_create(char *buf, long init, long end)
{
    mk_pointer p;

    mk_pointer_reset(&p);
    p.data = buf + init;

    if (init != end) {
        p.len = (end - init);
    }
    else {
        p.len = 1;
    }

    return p;
}
コード例 #5
0
ファイル: mk_http.c プロジェクト: sourabh0612/monkey
int mk_http_directory_redirect_check(struct client_session *cs,
                                     struct session_request *sr)
{
    int port_redirect = 0;
    char *host;
    char *location = 0;
    char *real_location = 0;
    unsigned long len;

    /*
     * We have to check if exist an slash to the end of
     * this string, if doesn't exist we send a redirection header
     */
    if (sr->uri_processed.data[sr->uri_processed.len - 1] == '/') {
        return 0;
    }

    host = mk_pointer_to_buf(sr->host);

    /*
     * Add ending slash to the location string
     */
    location = mk_mem_malloc(sr->uri_processed.len + 2);
    memcpy(location, sr->uri_processed.data, sr->uri_processed.len);
    location[sr->uri_processed.len]     = '/';
    location[sr->uri_processed.len + 1] = '\0';

    /* FIXME: should we done something similar for SSL = 443 */
    if (sr->host.data && sr->port > 0) {
        if (sr->port != config->standard_port) {
            port_redirect = sr->port;
        }
    }

    if (port_redirect > 0) {
        mk_string_build(&real_location, &len, "%s://%s:%i%s",
                        config->transport, host, port_redirect, location);
    }
    else {
        mk_string_build(&real_location, &len, "%s://%s%s",
                        config->transport, host, location);
    }

#ifdef TRACE
    MK_TRACE("Redirecting to '%s'", real_location);
#endif

    mk_mem_free(host);

    mk_header_set_http_status(sr, MK_REDIR_MOVED);
    sr->headers.content_length = 0;

    mk_pointer_reset(&sr->headers.content_type);
    sr->headers.location = real_location;
    sr->headers.cgi = SH_NOCGI;
    sr->headers.pconnections_left =
        (config->max_keep_alive_request - cs->counter_connections);

    mk_header_send(cs->socket, cs, sr);
    mk_socket_set_cork_flag(cs->socket, TCP_CORK_OFF);

    /*
     *  we do not free() real_location
     *  as it's freed by iov
     */
    mk_mem_free(location);
    sr->headers.location = NULL;
    return -1;
}
コード例 #6
0
ファイル: mk_http.c プロジェクト: sourabh0612/monkey
int mk_http_init(struct client_session *cs, struct session_request *sr)
{
    int ret;
    int bytes = 0;
    struct mimetype *mime;

    MK_TRACE("HTTP Protocol Init");

    /* Request to root path of the virtualhost in question */
    if (sr->uri_processed.len == 1 && sr->uri_processed.data[0] == '/') {
        sr->real_path.data = sr->host_conf->documentroot.data;
        sr->real_path.len = sr->host_conf->documentroot.len;
    }

    /* Compose real path */
    if (sr->user_home == MK_FALSE) {
        int len;

        len = sr->host_conf->documentroot.len + sr->uri_processed.len;
        if (len < MK_PATH_BASE) {
            memcpy(sr->real_path_static,
                   sr->host_conf->documentroot.data,
                   sr->host_conf->documentroot.len);
            memcpy(sr->real_path_static + sr->host_conf->documentroot.len,
                   sr->uri_processed.data,
                   sr->uri_processed.len);
            sr->real_path_static[len] = '\0';
            sr->real_path.data = sr->real_path_static;
            sr->real_path.len = len;
        }
        else {
            ret = mk_buffer_cat(&sr->real_path,
                                sr->host_conf->documentroot.data,
                                sr->host_conf->documentroot.len,
                                sr->uri_processed.data,
                                sr->uri_processed.len);

            if (ret < 0) {
                MK_TRACE("Error composing real path");
                return EXIT_ERROR;
            }
        }
    }

    /* Check backward directory request */
    if (memmem(sr->uri_processed.data, sr->uri_processed.len,
               HTTP_DIRECTORY_BACKWARD, sizeof(HTTP_DIRECTORY_BACKWARD) - 1)) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }


    if (mk_file_get_info(sr->real_path.data, &sr->file_info) != 0) {
        /* if the resource requested doesn't exists, let's
         * check if some plugin would like to handle it
         */
        MK_TRACE("No file, look for handler plugin");
        ret = mk_plugin_stage_run(MK_PLUGIN_STAGE_30, cs->socket, NULL, cs, sr);
        if (ret == MK_PLUGIN_RET_CLOSE_CONX) {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
        else if (ret == MK_PLUGIN_RET_CONTINUE) {
            return MK_PLUGIN_RET_CONTINUE;
        }
        else if (ret == MK_PLUGIN_RET_END) {
            return EXIT_NORMAL;
        }

        if (sr->file_info.exists == MK_FALSE) {
            return mk_request_error(MK_CLIENT_NOT_FOUND, cs, sr);
        }
        else {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
    }

    /* is it a valid directory ? */
    if (sr->file_info.is_directory == MK_TRUE) {
        /* Send redirect header if end slash is not found */
        if (mk_http_directory_redirect_check(cs, sr) == -1) {
            MK_TRACE("Directory Redirect");

            /* Redirect has been sent */
            return -1;
        }

        /* looking for a index file */
        mk_pointer index_file;
        char tmppath[MAX_PATH];
        index_file = mk_request_index(sr->real_path.data, tmppath, MAX_PATH);

        if (index_file.data) {
            if (sr->real_path.data != sr->real_path_static) {
                mk_pointer_free(&sr->real_path);
                sr->real_path = index_file;
                sr->real_path.data = strdup(index_file.data);
            }
            /* If it's static, and still fits */
            else if (index_file.len < MK_PATH_BASE) {
                memcpy(sr->real_path_static, index_file.data, index_file.len);
                sr->real_path_static[index_file.len] = '\0';
                sr->real_path.len = index_file.len;
            }
            /* It was static, but didn't fit */
            else {
                sr->real_path = index_file;
                sr->real_path.data = strdup(index_file.data);
            }

            mk_file_get_info(sr->real_path.data, &sr->file_info);
        }
    }

    /* Check symbolic link file */
    if (sr->file_info.is_link == MK_TRUE) {
        if (config->symlink == MK_FALSE) {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
        else {
            int n;
            char linked_file[MAX_PATH];
            n = readlink(sr->real_path.data, linked_file, MAX_PATH);
            if (n < 0) {
                return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
            }
        }
    }

    /* Plugin Stage 30: look for handlers for this request */
    ret  = mk_plugin_stage_run(MK_PLUGIN_STAGE_30, cs->socket, NULL, cs, sr);
    MK_TRACE("[FD %i] STAGE_30 returned %i", cs->socket, ret);
    switch (ret) {
    case MK_PLUGIN_RET_CONTINUE:
        return MK_PLUGIN_RET_CONTINUE;
    case MK_PLUGIN_RET_CLOSE_CONX:
        if (sr->headers.status > 0) {
            return mk_request_error(sr->headers.status, cs, sr);
        }
        else {
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
    case MK_PLUGIN_RET_END:
        return EXIT_NORMAL;
    }

    /*
     * Monkey listen for PUT and DELETE methods in addition to GET, POST and
     * HEAD, but it does not care about them, so if any plugin did not worked
     * on it, Monkey will return error 501 (501 Not Implemented).
     */
    if (sr->method == HTTP_METHOD_PUT || sr->method == HTTP_METHOD_DELETE ||
        sr->method == HTTP_METHOD_UNKNOWN) {
        return mk_request_error(MK_SERVER_NOT_IMPLEMENTED, cs, sr);
    }

    /* read permissions and check file */
    if (sr->file_info.read_access == MK_FALSE) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }

    /* Matching MimeType  */
    mime = mk_mimetype_find(&sr->real_path);
    if (!mime) {
        mime = mimetype_default;
    }

    if (sr->file_info.is_directory == MK_TRUE) {
        return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
    }

    /* get file size */
    if (sr->file_info.size < 0) {
        return mk_request_error(MK_CLIENT_NOT_FOUND, cs, sr);
    }

    /* counter connections */
    sr->headers.pconnections_left = (int)
        (config->max_keep_alive_request - cs->counter_connections);


    sr->headers.last_modified = sr->file_info.last_modification;

    if (sr->if_modified_since.data && sr->method == HTTP_METHOD_GET) {
        time_t date_client;       /* Date sent by client */
        time_t date_file_server;  /* Date server file */

        date_client = mk_utils_gmt2utime(sr->if_modified_since.data);
        date_file_server = sr->file_info.last_modification;

        if (date_file_server <= date_client && date_client > 0 &&
            date_client <= log_current_utime) {

            mk_header_set_http_status(sr, MK_NOT_MODIFIED);
            mk_header_send(cs->socket, cs, sr);
            return EXIT_NORMAL;
        }
    }
    mk_header_set_http_status(sr, MK_HTTP_OK);
    sr->headers.location = NULL;

    /* Object size for log and response headers */
    sr->headers.content_length = sr->file_info.size;
    sr->headers.real_length = sr->file_info.size;

    /* Process methods */
    if (sr->method == HTTP_METHOD_GET || sr->method == HTTP_METHOD_HEAD) {
        sr->headers.content_type = mime->type;
        /* Range */
        if (sr->range.data != NULL && config->resume == MK_TRUE) {
            if (mk_http_range_parse(sr) < 0) {
                return mk_request_error(MK_CLIENT_BAD_REQUEST, cs, sr);
            }
            if (sr->headers.ranges[0] >= 0 || sr->headers.ranges[1] >= 0) {
                mk_header_set_http_status(sr, MK_HTTP_PARTIAL);
            }
        }
    }
    else {
        /* without content-type */
        mk_pointer_reset(&sr->headers.content_type);
    }



    /* Open file */
    if (sr->file_info.size > 0) {
        sr->fd_file = open(sr->real_path.data, sr->file_info.flags_read_only);
        if (sr->fd_file == -1) {
            MK_TRACE("open() failed");
            return mk_request_error(MK_CLIENT_FORBIDDEN, cs, sr);
        }
    }

    /* Send headers */
    mk_header_send(cs->socket, cs, sr);

    if (sr->headers.content_length == 0) {
        return 0;
    }

    /* Send file content*/
    if (sr->method == HTTP_METHOD_GET || sr->method == HTTP_METHOD_POST) {
        /* Calc bytes to send & offset */
        if (mk_http_range_set(sr, sr->file_info.size) != 0) {
            return mk_request_error(MK_CLIENT_BAD_REQUEST, cs, sr);
        }

        bytes = mk_http_send_file(cs, sr);
    }

    return bytes;
}