Esempio n. 1
0
ERROR_CODE parse_url_static(char *url, size_t url_size, struct url_static_t *url_s) {
    /* allocates space for the temporary error variable to
    be used to detect errors in calls */
    ERROR_CODE error;

    /* allocates the space for the temporary (dynamic) url structure
    to be used as basis for the construction of the static one */
    struct url_t _url_s;

    error = parse_url(url, url_size, &_url_s);
    if(error) {
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Problem parsing the url"
        );
    }

    memset(url_s, 0, sizeof(struct url_static_t));

    if(_url_s.scheme.buffer != NULL) {
        memcpy(url_s->scheme, _url_s.scheme.buffer, _url_s.scheme.length);
        url_s->scheme[_url_s.scheme.length] = '\0';
    }

    if(_url_s.username.buffer != NULL) {
        memcpy(url_s->username, _url_s.username.buffer, _url_s.username.length);
        url_s->username[_url_s.username.length] = '\0';
    }

    if(_url_s.password.buffer != NULL) {
        memcpy(url_s->password, _url_s.password.buffer, _url_s.password.length);
        url_s->password[_url_s.password.length] = '\0';
    }

    if(_url_s.host.buffer != NULL) {
        memcpy(url_s->host, _url_s.host.buffer, _url_s.host.length);
        url_s->password[_url_s.host.length] = '\0';
    }

    if(_url_s.port != 0) { url_s->port = _url_s.port; }

    if(_url_s.path.buffer != NULL) {
        memcpy(url_s->path, _url_s.path.buffer, _url_s.path.length);
        url_s->password[_url_s.path.length] = '\0';
    }

    if(_url_s.query.buffer != NULL) {
        memcpy(url_s->query, _url_s.query.buffer, _url_s.query.length);
        url_s->password[_url_s.query.length] = '\0';
    }

    if(_url_s.fragment.buffer != NULL) {
        memcpy(url_s->fragment, _url_s.fragment.buffer, _url_s.fragment.length);
        url_s->password[_url_s.fragment.length] = '\0';
    }

    RAISE_NO_ERROR;
}
Esempio n. 2
0
ERROR_CODE log_http_request(char *host, char *identity, char *user, char *method, char *uri, enum http_version_e version, int error_code, size_t content_length) {
    /* allocates space for the buffer to hild the date and time
    information to be logged */
    char date_buffer[1024];

    /* allocates space for the internal date structures to be used
    for the retrieval of the time information and retrieves the
    current time to be used converting it then to the local time*/
    struct tm *_local_time;
    time_t _time = time(NULL);
    LOCAL_TIME(_local_time, &_time);

    /* checks if the converted local time is invalid and in case it
    is raises the apropriate runtime error to be caught */
    if(_local_time == NULL) {
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Problem retrieving local time"
        );
    }

    /* formats the local time into the data buffer and then uses it and
    the other (sent) variables to format the output buffer */
    strftime(date_buffer, 1024, "%d/%b/%Y %H:%M:%S", _local_time);
    PRINTF_F(
        "%s %s %s [%s] \"%s %s %s\" %d %lu\n",
        host,
        identity,
        user,
        date_buffer,
        method,
        uri,
        http_version_codes[version - 1],
        error_code,
        (long unsigned int) content_length
    );

    /* raises no error */
    RAISE_NO_ERROR;
}
Esempio n. 3
0
ERROR_CODE parse_url(char *url, size_t url_size, struct url_t *url_s) {
    /* allocates space for the index and length counters to be
    used on the parse of the provided url */
    size_t index;
    size_t length;

    /* sets space for the variables to be set with the current
    (byte) in parsing and for the current state of the parse */
    unsigned char current;
    enum url_parse_state_e state;

    /* allocates space for the internal markers and pointers to
    be used durring the parsin main loop */
    unsigned char *mark;
    unsigned char *pointer;

    /* creates space for a "local" buffer that is going to
    be used as temporary for some of the conversion operations */
    unsigned char buffer[128];

    /* resets the url structure by setting all of its contents
    to the default zero (reset) value */
    memset(url_s, 0, sizeof(struct url_t));

    /* sets the url pointer as the initial mark value and also
    sets the initial state of the parsing as the scheme state */
    mark = (unsigned char *) url;
    state = SCHEME_STATE;

    /* iterate over the complete url buffer to try to gather
    the range of the various parts of the url */
    for(index = 0; index < url_size; index++) {
        /* retrieves the current byte in iteration and the pointer
        address to the current buffer position */
        current = (unsigned char) url[index];
        pointer = (unsigned char *) &url[index];

        switch(state) {
            case SCHEME_STATE:
                switch(current) {
                    case ':':
                        length = pointer - mark;
                        url_s->scheme.buffer = mark;
                        url_s->scheme.length = length;
                        state = SLA_STATE;
                        break;
                }

                break;

            case SLA_STATE:
                switch(current) {
                    case '/':
                        state = SLA_SLA_STATE;
                        break;

                    default:
                        goto error;
                        break;
                }

                break;

            case SLA_SLA_STATE:
                switch(current) {
                    case '/':
                        state = AUTH_STATE;
                        mark = pointer + 1;
                        break;

                    default:
                        goto error;
                        break;
                }

                break;

            case AUTH_STATE:
                switch(current) {
                    case '/':
                        length = pointer - mark;
                        url_s->host_c.buffer = mark;
                        url_s->host_c.length = length;
                        state = PATH_STATE;
                        mark = pointer;
                        break;

                    case '@':
                        length = pointer - mark;
                        url_s->auth.buffer = mark;
                        url_s->auth.length = length;
                        state = HOST_STATE;
                        mark = pointer + 1;
                        break;
                }

                break;

            case HOST_STATE:
                switch(current) {
                    case '/':
                        length = pointer - mark;
                        url_s->host.buffer = mark;
                        url_s->host.length = length;
                        state = PATH_STATE;
                        mark = pointer;
                        break;

                    case ':':
                        length = pointer - mark;
                        url_s->host.buffer = mark;
                        url_s->host.length = length;
                        state = PORT_STATE;
                        mark = pointer + 1;
                        break;
                }

                break;

            case PORT_STATE:
                switch(current) {
                    case '/':
                        length = pointer - mark;
                        url_s->port_s.buffer = mark;
                        url_s->port_s.length = length;
                        state = PATH_STATE;
                        mark = pointer;
                        break;
                }

                break;

            case PATH_STATE:
                switch(current) {
                    case '?':
                        length = pointer - mark;
                        url_s->path.buffer = mark;
                        url_s->path.length = length;
                        state = QUERY_STATE;
                        mark = pointer + 1;
                        break;
                }

                break;

            case QUERY_STATE:
                switch(current) {
                    case '#':
                        length = pointer - mark;
                        url_s->query.buffer = mark;
                        url_s->query.length = length;
                        state = FRAGMENT_STATE;
                        mark = pointer + 1;
                        break;
                }

                break;

            case FRAGMENT_STATE:
                break;
        }
    }
    pointer++;

    /* runs the final swith operation to clone the still
    opened parse step (the final step) */
    switch(state) {
        case PATH_STATE:
            length = pointer - mark;
            url_s->path.buffer = mark;
            url_s->path.length = length;
            break;

        case QUERY_STATE:
            length = pointer - mark;
            url_s->query.buffer = mark;
            url_s->query.length = length;
            break;

        case FRAGMENT_STATE:
            length = pointer - mark;
            url_s->fragment.buffer = mark;
            url_s->fragment.length = length;
            break;

        default:
            goto error;
            break;
    }

    if(url_s->host_c.buffer != NULL) {
        pointer = memchr(url_s->host_c.buffer, ':', url_s->host_c.length);
        if(pointer == NULL) {
            url_s->host.buffer = url_s->host_c.buffer;
            url_s->host.length = url_s->host_c.length;
        } else {
            url_s->host.buffer = url_s->host_c.buffer;
            url_s->host.length = pointer - url_s->host_c.buffer;

            url_s->port_s.buffer = pointer + 1;
            url_s->port_s.length = url_s->host_c.buffer +\
                url_s->host_c.length - (pointer + 1);
        }
    }

    if(url_s->auth.buffer != NULL) {
        pointer = memchr(url_s->auth.buffer, ':', url_s->auth.length);
        if(pointer == NULL) { goto error; }

        url_s->username.buffer = url_s->auth.buffer;
        url_s->username.length = pointer - url_s->auth.buffer;

        url_s->password.buffer = pointer + 1;
        url_s->password.length = url_s->auth.buffer +\
            url_s->auth.length - (pointer + 1);
    }

    if(url_s->port_s.buffer != NULL) {
        memcpy(buffer, url_s->port_s.buffer, url_s->port_s.length);
        buffer[url_s->port_s.length] = '\0';

        url_s->port = atoi((char *) buffer);
    }

    RAISE_NO_ERROR;

error:
    RAISE_ERROR_M(
        RUNTIME_EXCEPTION_ERROR_CODE,
        (unsigned char *) "Problem parsing url string"
    );
}
Esempio n. 4
0
ERROR_CODE parameters_http_c(char *buffer, size_t size, size_t count, ...) {
    /* allocates space for the variable list of arguments
    provided as arguments to this function and tha should
    contain sequences of key, value and length */
    va_list arguments;

    /* allocates space for the various indexes to be
    used in the iteration including the sequence offset
    and the global index counter */
    size_t index;
    size_t index_g;
    size_t offset;

    /* allocates space for the three components of the
    parameter the key, the value and the length of the
    provided value buffer (it's not null terminated) */
    char *key_s;
    char *buffer_s;
    size_t length_s;

    /* allocates space for the pointer to the buffer that
    will hold the created parameters string */
    char *params_buffer;
    size_t params_size;

    /* creates space for the pointer to the map that will
    contain all the arranjed sequence of keys and values
    representing the various parameters */
    struct hash_map_t *parameters_map;

    /* statically allocates space in the stack for the various
    value strings representing the parameter values */
    struct string_t strings[256];

    /* in case the number of tuples provided as arguments is
    more that the space available for the value strings must
    fail with an error otherwise a buffer overflow occurs */
    if(count > 256) {
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Problem creating parameters"
        );
    }

    /* sets the inial key string value as null so that the
    value is started initialized, required for safe execution */
    key_s = NULL;

    /* multiplies the count by three as it must contain
    the real number of arguments and not just the number
    of tuples of three in it */
    count *= 3;

    /* creates the hash map that is going to be used to
    temporarly store the various key value associations */
    create_hash_map(&parameters_map, 0);

    /* iterates over the sequence of dynamic arguments
    provided to the function to retrieve them as sequences
    of key, value and length, then sets them in the map
    representing the various parameters */
    va_start(arguments, count);
    for(index = 0; index < count; index++) {
        offset = index % 3;
        index_g = index / 3;

        switch(offset) {
            case 0:
                key_s = va_arg(arguments, char *);
                break;

            case 1:
                buffer_s = va_arg(arguments, char *);
                strings[index_g].buffer = (unsigned char *) buffer_s;
                break;

            case 2:
                length_s = va_arg(arguments, size_t);
                strings[index_g].length = length_s;

                set_value_string_hash_map(
                    parameters_map,
                    (unsigned char *) key_s,
                    (void *) &strings[index_g]
                );

                break;
        }
    }
    va_end(arguments);

    /* generates the (get) parameters for an http request
    from the provided hash map of key values, the returned
    buffer is owned by the caller and must be released */
    parameters_http(
        parameters_map,
        (unsigned char **) &params_buffer,
        &params_size
    );
    delete_hash_map(parameters_map);

    /* in case the amount of bytes to be copied from the
    dynamically created params buffer to the buffer is
    greater than the size provided raises an error */
    if(params_size > size - 1) {
        FREE(params_buffer);
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Problem creating parameters"
        );
    }

    /* copies the generated params buffer into the final
    buffer defined in the parameters structure, then closes
    the string with the final character and releases the
    temporary buffer (params buffer) */
    memcpy(buffer, params_buffer, params_size);
    buffer[params_size] = '\0';
    FREE(params_buffer);

    /* raises no error as the creation of the parameters
    buffer has completed with success */
    RAISE_NO_ERROR;
}
Esempio n. 5
0
ERROR_CODE auth_file_http(char *auth_file, char *authorization, unsigned char *result) {
    /* allocates space for the error return value to be
    used in error checking for function calls */
    ERROR_CODE return_value;

    /* allocates space for the pointer to the passwd key
    value structure to be created by parsing the auth file */
    struct hash_map_t *passwd;

    /* allocates space to the various pointer values to be
    used for the separation and treatment of the auth value */
    char *pointer;
    char *authorization_b64;
    char *authorization_d;
    char *password_pointer;

    /* allocates space for the buffers to be used for the username
    and password values extracted from the authorization token */
    char username[128];
    char password[128];
    char *password_v;

    /* allocates the various size relates values for the buffer
    variables creation */
    size_t authorization_size;
    size_t username_size;
    size_t password_size;

    /* tries to find the token that separates the authentication
    type from the authorization base 64 value in case the value
    is not found raises an error indicating the problem */
    pointer = strchr(authorization, ' ');
    if(pointer == NULL) {
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Authorization value not valid"
        );
    }
    authorization_b64 = pointer + 1;

    /* tries to decode the authorization base 64 value into a plain
    text value in case the decoding fails, re-raises the error to
    the upper levels for caller information */
    return_value = decode_base64(
        (unsigned char *) authorization_b64,
        strlen(authorization_b64),
        (unsigned char **) &authorization_d,
        &authorization_size
    );
    if(IS_ERROR_CODE(return_value)) {
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "Problem decoding base 64 authorization"
        );
    }

    /* tries to find the token that separates the username part of the
    authorization from the password part in case the value is not found
    raises an error to the upper levels */
    pointer = memchr(authorization_d, ':', authorization_size);
    if(pointer == NULL) {
        FREE(authorization_d);
        RAISE_ERROR_M(
            RUNTIME_EXCEPTION_ERROR_CODE,
            (unsigned char *) "No password separator found in authorization"
        );
    }
    password_pointer = pointer + 1;

    /* calculates the size of both the username and the password
    from the diference between the various pointers */
    username_size = password_pointer - authorization_d - 1;
    password_size = authorization_d + authorization_size - password_pointer;

    /* copies both the username and the password values to
    the apropriate internal buffers (to be used in comparision) */
    memcpy(username, authorization_d, username_size);
    username[username_size] = '\0';
    memcpy(password, password_pointer, password_size);
    password[password_size] = '\0';

    /* processes the passwd file using the provided file path
    for it, this is an expensive io driven operation, and must
    be used wth care */
    process_passwd_file(auth_file, &passwd);

    /* retrieves the password verification value for the
    retrieved username and in case it's valid compares it
    and sets the result value accordingly */
    get_value_string_hash_map(
        passwd,
        (unsigned char *) username,
        (void **) &password_v
    );
    if(password_v != NULL && strcmp(password, password_v) == 0) {
        *result = TRUE;
    } else { *result = FALSE; }

    /* releases the memory associated with the complete set
    of values in the passwd structure and then releases the
    memory from the hash map structure itself, then releases
    the memory associated with the authorization decoded string */
    delete_values_hash_map(passwd);
    delete_hash_map(passwd);
    FREE(authorization_d);

    /* raises no error, as everything has been done as possible
    with no problems created in the processing */
    RAISE_NO_ERROR;
}
Esempio n. 6
0
ERROR_CODE _send_response_handler_lua(struct http_parser_t *http_parser) {
    /* retrieves the connection from the HTTP parser parameters */
    struct connection_t *connection = (struct connection_t *) http_parser->parameters;

    /* retrieves the HTTP connection from the io connection and uses it to retrieve
    the correct (mod Lua) handler to operate around it */
    struct http_connection_t *http_connection = (struct http_connection_t *) ((struct io_connection_t *) connection->lower)->lower;
    struct mod_lua_http_handler_t *mod_lua_http_handler = (struct mod_lua_http_handler_t *) http_connection->http_handler->lower;

    /* allocates space for the result code */
    ERROR_CODE result_code;

    /* acquires the lock on the HTTP connection, this will avoids further
    messages to be processed, no parallel request handling problems */
    http_connection->acquire(http_connection);

    /* in case the Lua state is not started an error must
    have occured so need to return immediately in error */
    if(mod_lua_http_handler->lua_state == NULL) {
        /* writes the error to the connection and then returns
        in error to the caller function */
        _write_error_connection_lua(http_parser, "no Lua state available");
        RAISE_ERROR_M(RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem accessing Lua state");
    }

    /* registers the current connection in Lua */
    lua_pushlightuserdata(mod_lua_http_handler->lua_state, (void *) http_parser);
    lua_setglobal(mod_lua_http_handler->lua_state, "connection");

    /* registers the write connection function in Lua */
    lua_register(mod_lua_http_handler->lua_state, "write_connection", _lua_write_connection);

    /* runs the script in case the current file is considered to be
    dirty, this is the case for the loading of the module and reloading*/
    if(mod_lua_http_handler->file_dirty) { result_code = luaL_dofile(mod_lua_http_handler->lua_state, mod_lua_http_handler->file_path); mod_lua_http_handler->file_dirty = 0; }
    else { result_code = 0; }

    /* in case there was an error in Lua */
    if(LUA_ERROR(result_code)) {
        /* retrieves the error message and then writes it to the connection
        so that the end user may be able to respond to it */
        char *error_message = (char *) lua_tostring(mod_lua_http_handler->lua_state, -1);
        _write_error_connection_lua(http_parser, error_message);

        /* sets the file as dirty (forces reload) and then reloads the curernt
        internal Lua state, virtual machine reset (to avoid corruption) */
        mod_lua_http_handler->file_dirty = 1;
        _reload_lua_state(&mod_lua_http_handler->lua_state);

        /* prints a warning message, closes the Lua interpreter and then
        raises the error to the upper levels */
        V_WARNING_F("There was a problem executing: %s\n", mod_lua_http_handler->file_path);
        RAISE_ERROR_M(RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem executing script file");
    }

    /* retrieves the field reference to the handle method that symbol
    to call the function (in protected mode) and retrieves the result */
    lua_getfield(mod_lua_http_handler->lua_state, LUA_GLOBALSINDEX, "handle");
    result_code = lua_pcall(mod_lua_http_handler->lua_state, 0, 0, 0);

    /* in case there was an error in Lua */
    if(LUA_ERROR(result_code)) {
        /* retrieves the error message and then writes it to the connection
        so that the end user may be able to respond to it */
        char *error_message = (char *) lua_tostring(mod_lua_http_handler->lua_state, -1);
        _write_error_connection_lua(http_parser, error_message);

        /* sets the file reference as dirty, this will force the script file
        to be reload on next request */
        mod_lua_http_handler->file_dirty = 1;

        /* prints a warning message, closes the Lua interpreter and then
        raises the error to the upper levels */
        V_WARNING_F("There was a problem running call on file: %s\n", mod_lua_http_handler->file_path);
        RAISE_ERROR_M(RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem calling the handle method");
    }

    /* raise no error */
    RAISE_NO_ERROR;
}