Example #1
0
/**
 * Parses a single v0 request cookie and places the results into tx->request_cookies.
 *
 * @param[in] connp
 * @param[in] data
 * @param[in] len
 * @return HTP_OK on success, HTP_ERROR on error.
 */
int htp_parse_single_cookie_v0(htp_connp_t *connp, unsigned char *data, size_t len) {
    if (len == 0) return HTP_OK;
    
    size_t pos = 0;

    // Look for '='
    while ((pos < len) && (data[pos] != '=')) pos++;
    if (pos == 0) return HTP_OK; // Ignore nameless cookies

    bstr *name = bstr_dup_mem(data, pos);
    if (name == NULL) return HTP_ERROR;

    bstr *value = NULL;
    if (pos == len) {
        // Cookie is empty
        value = bstr_dup_c("");
    } else {
        // Cookie is not empty
        value = bstr_dup_mem(data + pos + 1, len - pos - 1);
    }

    if (value == NULL) {
        bstr_free(name);
        return HTP_ERROR;
    }

    // Add cookie directly
    htp_table_addn(connp->in_tx->request_cookies, name, value);

    return HTP_OK;
}
Example #2
0
/**
 * Transcode all parameters supplied in the table.
 *
 * @param[in] connp
 * @param[in] params
 * @param[in] destroy_old
 */
int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_old) {
    htp_table_t *input_params = *params;

    // No transcoding unless necessary
    if ((connp->cfg->internal_encoding == NULL)||(connp->cfg->request_encoding == NULL)) return HTP_OK;

    // Create a new table that will hold transcoded parameters
    htp_table_t *output_params = htp_table_create(htp_table_size(input_params));
    if (output_params == NULL) return HTP_ERROR;
    
    // Initialize iconv
    iconv_t cd = iconv_open(connp->cfg->internal_encoding, connp->cfg->request_encoding);
    if (cd == (iconv_t) -1) {        
        htp_table_destroy(output_params);
        return HTP_ERROR;
    }

    #if (_LIBICONV_VERSION >= 0x0108)
    int iconv_param = 0;
    iconvctl(cd, ICONV_SET_TRANSLITERATE, &iconv_param);
    iconv_param = 1;
    iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &iconv_param);
    #endif
    
    // Convert the parameters, one by one
    bstr *name = NULL;
    bstr *value = NULL;    
    for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
        value = htp_table_get_index(input_params, i, &name);
        
        bstr *new_name = NULL, *new_value = NULL;        
        
        // Convert name
        htp_transcode_bstr(cd, name, &new_name);
        if (new_name == NULL) {
            iconv_close(cd);

            bstr *b = NULL;
            for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
                b = htp_table_get_index(output_params, j, NULL);
                bstr_free(b);
            }
            
            htp_table_destroy(output_params);
            return HTP_ERROR;
        }
        
        // Convert value        
        htp_transcode_bstr(cd, value, &new_value);
        if (new_value == NULL) {
            bstr_free(new_name);
            iconv_close(cd);

            bstr *b = NULL;
            for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
                b = htp_table_get_index(output_params, j, NULL);
                bstr_free(b);
            }
            
            htp_table_destroy(output_params);
            return HTP_ERROR;
        }
        
        // Add to new table
        htp_table_addn(output_params, new_name, new_value);
    }
    
    // Replace the old parameter table
    *params = output_params;

    // Destroy the old parameter table if necessary
    if (destroy_old) {
        bstr *b = NULL;
        for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
            b = htp_table_get_index(input_params, i, NULL);
            bstr_free(b);
        }      
    
        htp_table_destroy(input_params);
    }
    
    iconv_close(cd);

    return HTP_OK;
}
Example #3
0
/**
 * This method is invoked whenever a piece of data, belonging to a single field (name or value)
 * becomes available. It will either create a new parameter or store the transient information
 * until a parameter can be created.
 *
 * @param[in] urlenp
 * @param[in] data
 * @param[in] startpos
 * @param[in] endpos
 * @param[in] c Should contain -1 if the reason this function is called is because the end of
 *          the current data chunk is reached.
 */
static void htp_urlenp_add_field_piece(htp_urlenp_t *urlenp, const unsigned char *data, size_t startpos, size_t endpos, int last_char) {    
    // Add field if we know it ended (last_char is something other than -1)
    // or if we know that there won't be any more input data (urlenp->_complete is true).
    if ((last_char != -1) || (urlenp->_complete)) {       
        // Prepare the field value, assembling from multiple pieces as necessary.
    
        bstr *field = NULL;

        // Did we use the string builder for this field?
        if (bstr_builder_size(urlenp->_bb) > 0) {            
            // The current field consists of more than once piece, we have to use the string builder.

            // Add current piece to string builder.
            if ((data != NULL) && (endpos - startpos > 0)) {
                bstr_builder_append_mem(urlenp->_bb, data + startpos, endpos - startpos);
            }

            // Generate the field and clear the string builder.
            field = bstr_builder_to_str(urlenp->_bb);
            if (field == NULL) return;

            bstr_builder_clear(urlenp->_bb);
        } else {            
            // We only have the current piece to work with, so no need to involve the string builder.
            if ((data != NULL) && (endpos - startpos > 0)) {
                field = bstr_dup_mem(data + startpos, endpos - startpos);
                if (field == NULL) return;
            }
        }

        // Process field as key or value, as appropriate.
        
        if (urlenp->_state == HTP_URLENP_STATE_KEY) {
            // Key.

            // If there is no more work left to do, then we have a single key. Add it.
            if ((urlenp->_complete)||(last_char == urlenp->argument_separator)) {                
                
                // Handling empty pairs is tricky. We don't want to create a pair for
                // an entirely empty input, but in some cases it may be appropriate
                // (e.g., /index.php?&q=2).
                if ((field != NULL)||(last_char == urlenp->argument_separator)) {
                    // Add one pair, with an empty value and possibly empty key too.

                    bstr *name = field;
                    if (name == NULL) {
                        name = bstr_dup_c("");
                        if (name == NULL) return;
                    }

                    bstr *value = bstr_dup_c("");
                    if (value == NULL) {
                        bstr_free(name);
                        return;
                    }

                    if (urlenp->decode_url_encoding) {
                        htp_tx_urldecode_params_inplace(urlenp->tx, name);
                    }

                    htp_table_addn(urlenp->params, name, value);

                    urlenp->_name = NULL;

                    #ifdef HTP_DEBUG
                    fprint_raw_data(stderr, "NAME", bstr_ptr(name), bstr_len(name));
                    fprint_raw_data(stderr, "VALUE", bstr_ptr(value), bstr_len(value));
                    #endif
                }
            } else {                
                // This key will possibly be followed by a value, so keep it for later.
                urlenp->_name = field;
            }
        } else {            
            // Value (with a key remembered from before).

            bstr *name = urlenp->_name;
            urlenp->_name = NULL;

            if (name == NULL) {
                name = bstr_dup_c("");
                if (name == NULL) {
                    bstr_free(field);
                    return;
                }
            }

            bstr *value = field;
            if (value == NULL) {
                value = bstr_dup_c("");
                if (value == NULL) {
                    bstr_free(name);
                    return;
                }
            }

            if (urlenp->decode_url_encoding) {
                htp_tx_urldecode_params_inplace(urlenp->tx, name);
                htp_tx_urldecode_params_inplace(urlenp->tx, value);
            }

            htp_table_addn(urlenp->params, name, value);           

            #ifdef HTP_DEBUG
            fprint_raw_data(stderr, "NAME", bstr_ptr(name), bstr_len(name));
            fprint_raw_data(stderr, "VALUE", bstr_ptr(value), bstr_len(value));
            #endif
        }        
    } else {
        // The field has not ended. We'll make a copy of of the available data for later.
        if ((data != NULL) && (endpos - startpos > 0)) {
            bstr_builder_append_mem(urlenp->_bb, data + startpos, endpos - startpos);
        }
    }
}