Blame apache2/msc_crypt.c

Packit 284210
/*
Packit 284210
 * ModSecurity for Apache 2.x, http://www.modsecurity.org/
Packit 284210
 * Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Packit 284210
 *
Packit 284210
 * You may not use this file except in compliance with
Packit 284210
 * the License.  You may obtain a copy of the License at
Packit 284210
 *
Packit 284210
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 284210
 *
Packit 284210
 * If any of the files related to licensing are missing or if you have any
Packit 284210
 * other questions related to licensing please contact Trustwave Holdings, Inc.
Packit 284210
 * directly using the email address security@modsecurity.org.
Packit 284210
 */
Packit 284210
Packit 284210
#include "msc_crypt.h"
Packit 284210
#include "msc_util.h"
Packit 284210
#include "apr_sha1.h"
Packit 284210
#include "apr_uri.h"
Packit 284210
#include "apr_base64.h"
Packit 284210
#include "acmp.h"
Packit 284210
#include "libxml/HTMLtree.h"
Packit 284210
#include "libxml/uri.h"
Packit 284210
#include <string.h>
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Normalize path in URI
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 * \param input The URI to be normalized
Packit 284210
 *
Packit 284210
 * \retval input normalized input
Packit 284210
 * \retval NULL on fail
Packit 284210
 */
Packit 284210
char *normalize_path(modsec_rec *msr, char *input) {
Packit 284210
    xmlURI *uri = NULL;
Packit 284210
    char *parsed_content = NULL;
Packit 284210
    char *content = NULL;
Packit 284210
Packit 284210
    if(msr == NULL) return NULL;
Packit 284210
Packit 284210
    if(input == NULL) return NULL;
Packit 284210
Packit 284210
    uri = xmlParseURI(input);
Packit 284210
Packit 284210
    if(uri != NULL && uri->path)    {
Packit 284210
        if(uri->scheme) {
Packit 284210
            content = apr_psprintf(msr->mp, "%s://", uri->scheme);
Packit 284210
            parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
        }
Packit 284210
Packit 284210
        if(uri->server) {
Packit 284210
            content = apr_psprintf(msr->mp, "%s", uri->server);
Packit 284210
            if(parsed_content)
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, parsed_content, content, NULL);
Packit 284210
            else
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
        }
Packit 284210
Packit 284210
        if(uri->port)   {
Packit 284210
            content = apr_psprintf(msr->mp, ":%d", uri->port);
Packit 284210
            if(parsed_content)
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, parsed_content, content, NULL);
Packit 284210
            else
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
        }
Packit 284210
Packit 284210
        if(uri->path)   {
Packit 284210
            char *Uri = NULL;
Packit 284210
            int bytes = 0;
Packit 284210
            /*int i;*/
Packit 284210
            char *abs_link = NULL;
Packit 284210
            char *filename = NULL;
Packit 284210
            char *abs_path = NULL;
Packit 284210
            char *abs_uri = NULL;
Packit 284210
Packit 284210
            if (uri->path[0] != '/') {
Packit 284210
                /* uri->path is relative. make it absolute */
Packit 284210
                filename = file_basename(msr->mp, msr->r->parsed_uri.path);
Packit 284210
Packit 284210
                if(filename == NULL || (strlen(msr->r->parsed_uri.path) - strlen(filename) < 0))
Packit 284210
                    return NULL;
Packit 284210
Packit 284210
                abs_path = apr_pstrndup(msr->mp, msr->r->parsed_uri.path, strlen(msr->r->parsed_uri.path) - strlen(filename));
Packit 284210
                abs_uri = apr_pstrcat(msr->mp, abs_path, uri->path, NULL);
Packit 284210
Packit 284210
                abs_link = apr_pstrdup(msr->mp, abs_uri);
Packit 284210
            }
Packit 284210
            else {
Packit 284210
                abs_link = apr_pstrdup(msr->mp, uri->path);
Packit 284210
            }
Packit 284210
Packit 284210
            xmlNormalizeURIPath(abs_link);
Packit 284210
Packit 284210
            Uri = apr_pstrdup(msr->mp, abs_link);
Packit 284210
Packit 284210
/*
Packit 284210
            for(i = 0; i < (int)strlen(Uri); i++)    {
Packit 284210
                if(Uri[i] != '.' && Uri[i] != '/')  {
Packit 284210
                    if (i - 1 < 0)
Packit 284210
                        i = 0;
Packit 284210
                    else
Packit 284210
                        i--;
Packit 284210
                    if(Uri[i] == '/')
Packit 284210
                        --bytes;
Packit 284210
                    break;
Packit 284210
                }   else    {
Packit 284210
                    bytes++;
Packit 284210
                }
Packit 284210
            }
Packit 284210
Packit 284210
            if(bytes >= (int)strlen(uri->path))
Packit 284210
                return NULL;
Packit 284210
*/
Packit 284210
Packit 284210
            content = apr_psprintf(msr->mp, "%s", Uri);
Packit 284210
Packit 284210
            if(parsed_content)
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, parsed_content, content, NULL);
Packit 284210
            else
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
Packit 284210
        }
Packit 284210
Packit 284210
        if(uri->query_raw)  {
Packit 284210
            content = apr_psprintf(msr->mp, "?%s", uri->query_raw);
Packit 284210
            if(parsed_content)
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, parsed_content, content, NULL);
Packit 284210
            else
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
        }
Packit 284210
Packit 284210
        if(uri->fragment)   {
Packit 284210
            content = apr_psprintf(msr->mp, "#%s", uri->fragment);
Packit 284210
            if(parsed_content)
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, parsed_content, content, NULL);
Packit 284210
            else
Packit 284210
                parsed_content = apr_pstrcat(msr->mp, content, NULL);
Packit 284210
        }
Packit 284210
        xmlFreeURI(uri);
Packit 284210
        return apr_pstrdup(msr->mp, parsed_content);
Packit 284210
    }
Packit 284210
Packit 284210
    if(uri != NULL) xmlFreeURI(uri);
Packit 284210
    return apr_pstrdup(msr->mp, input);
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Create a random password
Packit 284210
 *
Packit 284210
 * \param mp ModSecurity transaction memory pool
Packit 284210
 *
Packit 284210
 * \retval key random key
Packit 284210
 */
Packit 284210
char *getkey(apr_pool_t *mp) {
Packit 284210
    unsigned char digest[APR_SHA1_DIGESTSIZE];
Packit 284210
    char *sig, *key, *value;
Packit 284210
    apr_sha1_ctx_t ctx;
Packit 284210
    char salt[64];
Packit 284210
Packit 284210
    apr_generate_random_bytes(salt, sizeof(salt));
Packit 284210
    key = apr_psprintf(mp,"%.*s",(int)sizeof(salt),salt);
Packit 284210
Packit 284210
    apr_sha1_init (&ctx;;
Packit 284210
    apr_sha1_update (&ctx, (const char*)key, strlen(key));
Packit 284210
    apr_sha1_update (&ctx, "\0", 1);
Packit 284210
Packit 284210
    apr_generate_random_bytes(salt, sizeof(salt));
Packit 284210
    value = apr_psprintf(mp,"%.*s",(int)sizeof(salt),salt);
Packit 284210
Packit 284210
    apr_sha1_update (&ctx, value, strlen (value));
Packit 284210
    apr_sha1_final (digest, &ctx;;
Packit 284210
Packit 284210
    sig = apr_pcalloc (mp, apr_base64_encode_len (sizeof (digest)));
Packit 284210
    apr_base64_encode (sig, (const char*)digest, sizeof (digest));
Packit 284210
Packit 284210
    return sig;
Packit 284210
}
Packit 284210
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Generate the MAC for a given message
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 * \param key The key used within HMAC
Packit 284210
 * \param key_len Key length
Packit 284210
 * \param msg The message to generate the MAC
Packit 284210
 * \param msglen The message length
Packit 284210
 *
Packit 284210
 * \retval hex_digest The MAC
Packit 284210
 */
Packit 284210
char *hmac(modsec_rec *msr, const char *key, int key_len,
Packit 284210
        unsigned char *msg, int msglen) {
Packit 284210
    apr_sha1_ctx_t ctx;
Packit 284210
    unsigned char digest[APR_SHA1_DIGESTSIZE];
Packit 284210
    unsigned char hmac_ipad[HMAC_PAD_SIZE], hmac_opad[HMAC_PAD_SIZE];
Packit 284210
    unsigned char nkey[APR_SHA1_DIGESTSIZE];
Packit 284210
    unsigned char *hmac_key = (unsigned char *) key;
Packit 284210
    char hex_digest[APR_SHA1_DIGESTSIZE * 2 + 1], *hmac_digest;
Packit 284210
    const char hex[] = "0123456789abcdef";
Packit 284210
    int i;
Packit 284210
Packit 284210
    if (key_len > HMAC_PAD_SIZE-1) {
Packit 284210
        hmac_key = nkey;
Packit 284210
        key_len = APR_SHA1_DIGESTSIZE;
Packit 284210
    }
Packit 284210
Packit 284210
    memset ((void *) hmac_ipad, 0, sizeof (hmac_ipad));
Packit 284210
    memset ((void *) hmac_opad, 0, sizeof (hmac_opad));
Packit 284210
    memmove (hmac_ipad, hmac_key, key_len);
Packit 284210
    memmove (hmac_opad, hmac_key, key_len);
Packit 284210
Packit 284210
    for (i = 0; i < HMAC_PAD_SIZE-1; i++)  {
Packit 284210
        hmac_ipad[i] ^= 0x36;
Packit 284210
        hmac_opad[i] ^= 0x5c;
Packit 284210
    }
Packit 284210
Packit 284210
    apr_sha1_init (&ctx;;
Packit 284210
    apr_sha1_update_binary (&ctx, hmac_ipad, HMAC_PAD_SIZE-1);
Packit 284210
    apr_sha1_update_binary (&ctx, (const unsigned char *) msg, msglen);
Packit 284210
    apr_sha1_final (digest, &ctx;;
Packit 284210
Packit 284210
    apr_sha1_init (&ctx;;
Packit 284210
    apr_sha1_update_binary (&ctx, hmac_opad, HMAC_PAD_SIZE-1);
Packit 284210
    apr_sha1_update_binary (&ctx, digest, sizeof (digest));
Packit 284210
    apr_sha1_final (digest, &ctx;;
Packit 284210
Packit 284210
    hmac_digest = hex_digest;
Packit 284210
    for (i = 0; i < sizeof (digest); i++) {
Packit 284210
        *hmac_digest++ = hex[digest[i] >> 4];
Packit 284210
        *hmac_digest++ = hex[digest[i] & 0xF];
Packit 284210
    }
Packit 284210
Packit 284210
    *hmac_digest = '\0';
Packit 284210
Packit 284210
    return apr_pstrdup (msr->mp, hex_digest);
Packit 284210
}
Packit 284210
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Init html response body parser
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 *
Packit 284210
 * \retval 1 on success
Packit 284210
 * \retval -1 on fail
Packit 284210
 */
Packit 284210
int init_response_body_html_parser(modsec_rec *msr)   {
Packit 284210
    char *charset = NULL;
Packit 284210
    char *final_charset = NULL;
Packit 284210
    char sep;
Packit 284210
Packit 284210
    if(msr == NULL) return -1;
Packit 284210
Packit 284210
    if(msr->r == NULL) return -1;
Packit 284210
Packit 284210
    if(msr->r->content_type == NULL) return -1;
Packit 284210
Packit 284210
    if(msr->crypto_html_tree != NULL){
Packit 284210
        xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
        msr->crypto_html_tree = NULL;
Packit 284210
    }
Packit 284210
Packit 284210
    if((strncmp("text/html",msr->r->content_type,  9) != 0)){
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4,
Packit 284210
                    "init_response_body_html_parser: skipping html_tree generation for Content[%s].", msr->r->content_type);
Packit 284210
        if(msr->crypto_html_tree != NULL){
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr->crypto_html_tree = NULL;
Packit 284210
        }
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
Packit 284210
    if (msr->resbody_length == 0) {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "init_response_body_html_parser: skipping html_tree generation for zero length respomse body.");
Packit 284210
        msr->crypto_html_tree = NULL;
Packit 284210
        return 0;
Packit 284210
    }
Packit 284210
Packit 284210
    if((msr->r->content_encoding == NULL)||(apr_strnatcasecmp(msr->r->content_encoding,"(null)")==0)){
Packit 284210
        charset=m_strcasestr(msr->r->content_type,"charset=");
Packit 284210
        if(charset == NULL){
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4, "init_response_body_html_parser: assuming ISO-8859-1.");
Packit 284210
            msr->crypto_html_tree = htmlReadMemory(msr->resbody_data, msr->resbody_length, NULL,
Packit 284210
                    "ISO-8859-1", HTML_PARSE_RECOVER | HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);
Packit 284210
            htmlSetMetaEncoding ((htmlDocPtr) msr->crypto_html_tree, (const xmlChar *) "ISO-8859-1");
Packit 284210
        }
Packit 284210
        else{
Packit 284210
            charset+=8;
Packit 284210
            final_charset=strchr(charset,' ');
Packit 284210
            if(final_charset == NULL) final_charset = strchr(charset,';');
Packit 284210
            if(final_charset != NULL) {
Packit 284210
                sep = *final_charset;
Packit 284210
                *final_charset = '\0';
Packit 284210
            }
Packit 284210
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4,
Packit 284210
                        "init_response_body_html_parser: Charset[%s]",charset);
Packit 284210
            msr->crypto_html_tree = htmlReadMemory(msr->resbody_data, msr->resbody_length, NULL,
Packit 284210
                    charset, HTML_PARSE_RECOVER| HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);
Packit 284210
            htmlSetMetaEncoding ((htmlDocPtr) msr->crypto_html_tree, (const xmlChar *)charset);
Packit 284210
            if(final_charset != NULL) *final_charset=sep;
Packit 284210
        }
Packit 284210
Packit 284210
    }
Packit 284210
    else{
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4,"init_response_body_html_parser: Enconding[%s].",msr->r->content_encoding);
Packit 284210
        msr->crypto_html_tree = htmlReadMemory(msr->resbody_data, msr->resbody_length, NULL,
Packit 284210
                msr->r->content_encoding, HTML_PARSE_RECOVER | HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);
Packit 284210
        htmlSetMetaEncoding ((htmlDocPtr) msr->crypto_html_tree, (const xmlChar *)msr->r->content_encoding);
Packit 284210
    }
Packit 284210
    if(msr->crypto_html_tree == NULL){
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4,
Packit 284210
                    "init_response_body_html_parser: Failed to parse response body.");
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
    else {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4,
Packit 284210
                    "init_response_body_html_parser: Successfully html parser generated.");
Packit 284210
        return 1;
Packit 284210
    }
Packit 284210
Packit 284210
    return 1;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Execute all hash methods
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 * \param link The html attr value to be checked
Packit 284210
 * \param type The hash method type
Packit 284210
 *
Packit 284210
 * \retval 1 Match
Packit 284210
 * \retval 0 No Match
Packit 284210
 * \retval -1 on fail
Packit 284210
 */
Packit 284210
int do_hash_method(modsec_rec *msr, char *link, int type)   {
Packit 284210
    hash_method **em = NULL;
Packit 284210
    int i = 0;
Packit 284210
    char *error_msg = NULL;
Packit 284210
    char *my_error_msg = NULL;
Packit 284210
    int ovector[33];
Packit 284210
    int rc;
Packit 284210
Packit 284210
    if(msr == NULL) return -1;
Packit 284210
Packit 284210
    em = (hash_method **)msr->txcfg->hash_method->elts;
Packit 284210
Packit 284210
    if(msr->txcfg->hash_method->nelts == 0)
Packit 284210
        return 1;
Packit 284210
Packit 284210
    for (i = 0; i < msr->txcfg->hash_method->nelts; i++) {
Packit 284210
Packit 284210
        if(em[i] != NULL && em[i]->param_data != NULL){
Packit 284210
Packit 284210
            switch(type)    {
Packit 284210
                case HASH_URL_HREF_HASH_PM:
Packit 284210
                    if(em[i]->type == HASH_URL_HREF_HASH_PM)   {
Packit 284210
                        const char *match = NULL;
Packit 284210
                        apr_status_t rc = 0;
Packit 284210
                        ACMPT pt;
Packit 284210
Packit 284210
                        pt.parser = (ACMP *)em[i]->param_data;
Packit 284210
                        pt.ptr = NULL;
Packit 284210
Packit 284210
                        rc = acmp_process_quick(&pt, &match, link, strlen(link));
Packit 284210
Packit 284210
                        if (rc) {
Packit 284210
                            return 1;
Packit 284210
                        } else  {
Packit 284210
                            return 0;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_HREF_HASH_RX:
Packit 284210
                    if(em[i]->type == HASH_URL_HREF_HASH_RX)   {
Packit 284210
                        rc = msc_regexec_capture(em[i]->param_data, link, strlen(link), ovector, 30, &my_error_msg);
Packit 284210
                        if ((rc == PCRE_ERROR_MATCHLIMIT) || (rc == PCRE_ERROR_RECURSIONLIMIT)) {
Packit 284210
                            msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
Packit 284210
Packit 284210
                            if (s == NULL) return -1;
Packit 284210
                            s->name = apr_pstrdup(msr->mp, "MSC_PCRE_LIMITS_EXCEEDED");
Packit 284210
                            if (s->name == NULL) return -1;
Packit 284210
                            s->name_len = strlen(s->name);
Packit 284210
                            s->value = apr_pstrdup(msr->mp, "1");
Packit 284210
                            if (s->value == NULL) return -1;
Packit 284210
                            s->value_len = 1;
Packit 284210
                            apr_table_setn(msr->tx_vars, s->name, (void *)s);
Packit 284210
Packit 284210
                            error_msg = apr_psprintf(msr->mp,
Packit 284210
                                    "Execution error - "
Packit 284210
                                    "PCRE limits exceeded for Hash regex [%s] (%d): %s",
Packit 284210
                                    em[i]->param,rc, my_error_msg);
Packit 284210
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
Packit 284210
                            return 0; /* No match. */
Packit 284210
                        }
Packit 284210
                        else if (rc < -1) {
Packit 284210
                            error_msg = apr_psprintf(msr->mp, "Regex execution failed (%d): %s",
Packit 284210
                                    rc, my_error_msg);
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
                            return -1;
Packit 284210
                        }
Packit 284210
                        if (rc != PCRE_ERROR_NOMATCH) { /* Match. */
Packit 284210
                            return 1;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_FACTION_HASH_PM:
Packit 284210
                    if(em[i]->type == HASH_URL_FACTION_HASH_PM)   {
Packit 284210
                       const char *match = NULL;
Packit 284210
                        apr_status_t rc = 0;
Packit 284210
                        ACMPT pt;
Packit 284210
Packit 284210
                        pt.parser = (ACMP *)em[i]->param_data;
Packit 284210
                        pt.ptr = NULL;
Packit 284210
Packit 284210
                        rc = acmp_process_quick(&pt, &match, link, strlen(link));
Packit 284210
Packit 284210
                        if (rc) {
Packit 284210
                            return 1;
Packit 284210
                        } else  {
Packit 284210
                            return 0;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_FACTION_HASH_RX:
Packit 284210
                    if(em[i]->type == HASH_URL_FACTION_HASH_RX)   {
Packit 284210
                        rc = msc_regexec_capture(em[i]->param_data, link, strlen(link), ovector, 30, &my_error_msg);
Packit 284210
                        if ((rc == PCRE_ERROR_MATCHLIMIT) || (rc == PCRE_ERROR_RECURSIONLIMIT)) {
Packit 284210
                            msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
Packit 284210
Packit 284210
                            if (s == NULL) return -1;
Packit 284210
                            s->name = apr_pstrdup(msr->mp, "MSC_PCRE_LIMITS_EXCEEDED");
Packit 284210
                            if (s->name == NULL) return -1;
Packit 284210
                            s->name_len = strlen(s->name);
Packit 284210
                            s->value = apr_pstrdup(msr->mp, "1");
Packit 284210
                            if (s->value == NULL) return -1;
Packit 284210
                            s->value_len = 1;
Packit 284210
                            apr_table_setn(msr->tx_vars, s->name, (void *)s);
Packit 284210
Packit 284210
                            error_msg = apr_psprintf(msr->mp,
Packit 284210
                                    "Execution error - "
Packit 284210
                                    "PCRE limits exceeded for Hash regex [%s] (%d): %s",
Packit 284210
                                    em[i]->param,rc, my_error_msg);
Packit 284210
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
Packit 284210
                            return 0; /* No match. */
Packit 284210
                        }
Packit 284210
                        else if (rc < -1) {
Packit 284210
                            error_msg = apr_psprintf(msr->mp, "Regex execution failed (%d): %s",
Packit 284210
                                    rc, my_error_msg);
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
                            return -1;
Packit 284210
                        }
Packit 284210
                        if (rc != PCRE_ERROR_NOMATCH) { /* Match. */
Packit 284210
                            return 1;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_LOCATION_HASH_PM:
Packit 284210
                    if(em[i]->type == HASH_URL_LOCATION_HASH_PM)   {
Packit 284210
                       const char *match = NULL;
Packit 284210
                        apr_status_t rc = 0;
Packit 284210
                        ACMPT pt;
Packit 284210
Packit 284210
                        pt.parser = (ACMP *)em[i]->param_data;
Packit 284210
                        pt.ptr = NULL;
Packit 284210
Packit 284210
                        rc = acmp_process_quick(&pt, &match, link, strlen(link));
Packit 284210
Packit 284210
                        if (rc) {
Packit 284210
                            return 1;
Packit 284210
                        } else  {
Packit 284210
                            return 0;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_LOCATION_HASH_RX:
Packit 284210
                    if(em[i]->type == HASH_URL_LOCATION_HASH_RX)   {
Packit 284210
                        rc = msc_regexec_capture(em[i]->param_data, link, strlen(link), ovector, 30, &my_error_msg);
Packit 284210
                        if ((rc == PCRE_ERROR_MATCHLIMIT) || (rc == PCRE_ERROR_RECURSIONLIMIT)) {
Packit 284210
                            msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
Packit 284210
Packit 284210
                            if (s == NULL) return -1;
Packit 284210
                            s->name = apr_pstrdup(msr->mp, "MSC_PCRE_LIMITS_EXCEEDED");
Packit 284210
                            if (s->name == NULL) return -1;
Packit 284210
                            s->name_len = strlen(s->name);
Packit 284210
                            s->value = apr_pstrdup(msr->mp, "1");
Packit 284210
                            if (s->value == NULL) return -1;
Packit 284210
                            s->value_len = 1;
Packit 284210
                            apr_table_setn(msr->tx_vars, s->name, (void *)s);
Packit 284210
Packit 284210
                            error_msg = apr_psprintf(msr->mp,
Packit 284210
                                    "Execution error - "
Packit 284210
                                    "PCRE limits exceeded for Hash regex [%s] (%d): %s",
Packit 284210
                                    em[i]->param,rc, my_error_msg);
Packit 284210
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
Packit 284210
                            return 0; /* No match. */
Packit 284210
                        }
Packit 284210
                        else if (rc < -1) {
Packit 284210
                            error_msg = apr_psprintf(msr->mp, "Regex execution failed (%d): %s",
Packit 284210
                                    rc, my_error_msg);
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
                            return -1;
Packit 284210
                        }
Packit 284210
                        if (rc != PCRE_ERROR_NOMATCH) { /* Match. */
Packit 284210
                            return 1;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_IFRAMESRC_HASH_PM:
Packit 284210
                    if(em[i]->type == HASH_URL_IFRAMESRC_HASH_PM)   {
Packit 284210
                       const char *match = NULL;
Packit 284210
                        apr_status_t rc = 0;
Packit 284210
                        ACMPT pt;
Packit 284210
Packit 284210
                        pt.parser = (ACMP *)em[i]->param_data;
Packit 284210
                        pt.ptr = NULL;
Packit 284210
Packit 284210
                        rc = acmp_process_quick(&pt, &match, link, strlen(link));
Packit 284210
Packit 284210
                        if (rc) {
Packit 284210
                            return 1;
Packit 284210
                        } else  {
Packit 284210
                            return 0;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_IFRAMESRC_HASH_RX:
Packit 284210
                    if(em[i]->type == HASH_URL_IFRAMESRC_HASH_RX)   {
Packit 284210
                        rc = msc_regexec_capture(em[i]->param_data, link, strlen(link), ovector, 30, &my_error_msg);
Packit 284210
                        if ((rc == PCRE_ERROR_MATCHLIMIT) || (rc == PCRE_ERROR_RECURSIONLIMIT)) {
Packit 284210
                            msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
Packit 284210
Packit 284210
                            if (s == NULL) return -1;
Packit 284210
                            s->name = apr_pstrdup(msr->mp, "MSC_PCRE_LIMITS_EXCEEDED");
Packit 284210
                            if (s->name == NULL) return -1;
Packit 284210
                            s->name_len = strlen(s->name);
Packit 284210
                            s->value = apr_pstrdup(msr->mp, "1");
Packit 284210
                            if (s->value == NULL) return -1;
Packit 284210
                            s->value_len = 1;
Packit 284210
                            apr_table_setn(msr->tx_vars, s->name, (void *)s);
Packit 284210
Packit 284210
                            error_msg = apr_psprintf(msr->mp,
Packit 284210
                                    "Execution error - "
Packit 284210
                                    "PCRE limits exceeded for Hash regex [%s] (%d): %s",
Packit 284210
                                    em[i]->param,rc, my_error_msg);
Packit 284210
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
Packit 284210
                            return 0; /* No match. */
Packit 284210
                        }
Packit 284210
                        else if (rc < -1) {
Packit 284210
                            error_msg = apr_psprintf(msr->mp, "Regex execution failed (%d): %s",
Packit 284210
                                    rc, my_error_msg);
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
                            return -1;
Packit 284210
                        }
Packit 284210
                        if (rc != PCRE_ERROR_NOMATCH) { /* Match. */
Packit 284210
                            return 1;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_FRAMESRC_HASH_PM:
Packit 284210
                    if(em[i]->type == HASH_URL_FRAMESRC_HASH_PM)   {
Packit 284210
                       const char *match = NULL;
Packit 284210
                        apr_status_t rc = 0;
Packit 284210
                        ACMPT pt;
Packit 284210
Packit 284210
                        pt.parser = (ACMP *)em[i]->param_data;
Packit 284210
                        pt.ptr = NULL;
Packit 284210
Packit 284210
                        rc = acmp_process_quick(&pt, &match, link, strlen(link));
Packit 284210
Packit 284210
                        if (rc) {
Packit 284210
                            return 1;
Packit 284210
                        } else  {
Packit 284210
                            return 0;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
                case HASH_URL_FRAMESRC_HASH_RX:
Packit 284210
                    if(em[i]->type == HASH_URL_FRAMESRC_HASH_RX)   {
Packit 284210
                        rc = msc_regexec_capture(em[i]->param_data, link, strlen(link), ovector, 30, &my_error_msg);
Packit 284210
                        if ((rc == PCRE_ERROR_MATCHLIMIT) || (rc == PCRE_ERROR_RECURSIONLIMIT)) {
Packit 284210
                            msc_string *s = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
Packit 284210
Packit 284210
                            if (s == NULL) return -1;
Packit 284210
                            s->name = apr_pstrdup(msr->mp, "MSC_PCRE_LIMITS_EXCEEDED");
Packit 284210
                            if (s->name == NULL) return -1;
Packit 284210
                            s->name_len = strlen(s->name);
Packit 284210
                            s->value = apr_pstrdup(msr->mp, "1");
Packit 284210
                            if (s->value == NULL) return -1;
Packit 284210
                            s->value_len = 1;
Packit 284210
                            apr_table_setn(msr->tx_vars, s->name, (void *)s);
Packit 284210
Packit 284210
                            error_msg = apr_psprintf(msr->mp,
Packit 284210
                                    "Execution error - "
Packit 284210
                                    "PCRE limits exceeded for Hash regex [%s] (%d): %s",
Packit 284210
                                    em[i]->param,rc, my_error_msg);
Packit 284210
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
Packit 284210
                            return 0; /* No match. */
Packit 284210
                        }
Packit 284210
                        else if (rc < -1) {
Packit 284210
                            error_msg = apr_psprintf(msr->mp, "Regex execution failed (%d): %s",
Packit 284210
                                    rc, my_error_msg);
Packit 284210
                            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                                msr_log(msr, 4, "%s.", error_msg);
Packit 284210
                            return -1;
Packit 284210
                        }
Packit 284210
                        if (rc != PCRE_ERROR_NOMATCH) { /* Match. */
Packit 284210
                            return 1;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    break;
Packit 284210
            }
Packit 284210
        }
Packit 284210
Packit 284210
    }
Packit 284210
    return 0;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Hash the html elements
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 *
Packit 284210
 * \retval 1 On success
Packit 284210
 * \retval 0 No element was changed
Packit 284210
 * \retval -1 On fail
Packit 284210
 */
Packit 284210
int hash_response_body_links(modsec_rec *msr)   {
Packit 284210
    int lsize = 0, fsize = 0, lcount = 0, fcount = 0, i;
Packit 284210
    int isize = 0, icount = 0, frsize = 0, frcount = 0;
Packit 284210
    int bytes = 0;
Packit 284210
    xmlXPathContextPtr  xpathCtx = NULL;
Packit 284210
    xmlXPathObjectPtr   xpathObj = NULL;
Packit 284210
    xmlChar *content_option = NULL;
Packit 284210
    char *mac_link = NULL;
Packit 284210
    int rc, elts = 0;
Packit 284210
Packit 284210
    if(msr == NULL)
Packit 284210
        return -1;
Packit 284210
Packit 284210
    if (msr->crypto_html_tree == NULL) {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "hash_response_body_links: Cannot parse NULL html tree");
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_href_rx == 0 && msr->txcfg->crypto_hash_href_pm == 0
Packit 284210
            && msr->txcfg->crypto_hash_faction_rx == 0 && msr->txcfg->crypto_hash_faction_pm == 0
Packit 284210
            && msr->txcfg->crypto_hash_iframesrc_rx == 0 && msr->txcfg->crypto_hash_iframesrc_pm == 0
Packit 284210
            && msr->txcfg->crypto_hash_framesrc_rx == 0 && msr->txcfg->crypto_hash_framesrc_pm == 0)
Packit 284210
        return -1;
Packit 284210
Packit 284210
    xpathCtx = xmlXPathNewContext(msr->crypto_html_tree);
Packit 284210
    if(xpathCtx == NULL) {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "hash_response_body_links: Unable to create Xpath context.");
Packit 284210
        goto ctx_error;
Packit 284210
    }
Packit 284210
Packit 284210
    lcount=fcount=0;
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_href_rx == 1 || msr->txcfg->crypto_hash_href_pm == 1)    {
Packit 284210
Packit 284210
        xpathObj = xmlXPathEvalExpression((xmlChar*)"//*[@href]", xpathCtx);
Packit 284210
        if(xpathObj == NULL) {
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4,
Packit 284210
                        "hash_response_body_links: Unable to evaluate xpath expression.");
Packit 284210
            goto obj_error;
Packit 284210
        }
Packit 284210
Packit 284210
        lsize = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
Packit 284210
        for(i = lsize - 1; i >=0; i--) {
Packit 284210
            register xmlNodePtr cur;
Packit 284210
Packit 284210
            cur = xpathObj->nodesetval->nodeTab[i];
Packit 284210
            if(cur != NULL){
Packit 284210
                xmlChar *href = xmlGetProp(cur, (const xmlChar *) "href");
Packit 284210
                char *content_href = normalize_path(msr, (char *)href);
Packit 284210
Packit 284210
                if(content_href != NULL && strstr(content_href,msr->txcfg->crypto_param_name) == NULL) {
Packit 284210
                    if(msr->txcfg->crypto_hash_href_rx == 1)    {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_href, HASH_URL_HREF_HASH_RX);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_href, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "href", (const xmlChar *) mac_link);
Packit 284210
                                lcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(href != NULL)
Packit 284210
                                xmlFree(href);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    if(msr->txcfg->crypto_hash_href_pm == 1)    {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_href, HASH_URL_HREF_HASH_PM);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_href, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "href", (const xmlChar *) mac_link);
Packit 284210
                                lcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(href != NULL)
Packit 284210
                                xmlFree(href);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                }
Packit 284210
Packit 284210
                if(href != NULL)    {
Packit 284210
                    xmlFree(href);
Packit 284210
                    href = NULL;
Packit 284210
                }
Packit 284210
            }
Packit 284210
        }
Packit 284210
Packit 284210
        if(xpathObj != NULL)
Packit 284210
            xmlXPathFreeObject(xpathObj);
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_faction_rx == 1 || msr->txcfg->crypto_hash_faction_pm == 1) {
Packit 284210
        xpathObj = xmlXPathEvalExpression((xmlChar*)"//form", xpathCtx);
Packit 284210
        if(xpathObj == NULL) {
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4,
Packit 284210
                        "hash_response_body_links: Unable to evaluate xpath expression.");
Packit 284210
            goto obj_error;
Packit 284210
        }
Packit 284210
Packit 284210
        fsize = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
Packit 284210
        for(i = fsize - 1; i >=0; i--) {
Packit 284210
            register xmlNodePtr cur;
Packit 284210
Packit 284210
            cur = xpathObj->nodesetval->nodeTab[i];
Packit 284210
            if((cur != NULL)){
Packit 284210
                xmlChar *action = NULL;
Packit 284210
                char *content_action = NULL;
Packit 284210
Packit 284210
                if(content_option)
Packit 284210
                    xmlFree(content_option);
Packit 284210
Packit 284210
                action = xmlGetProp(cur, (const xmlChar *) "action");
Packit 284210
                content_action = normalize_path(msr, (char *)action);
Packit 284210
                content_option = xmlGetProp(cur, (const xmlChar *) "option");
Packit 284210
Packit 284210
                if(content_action != NULL && content_option == NULL && strstr(content_action,msr->txcfg->crypto_param_name) == NULL) {
Packit 284210
                    if(msr->txcfg->crypto_hash_faction_rx == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_action, HASH_URL_FACTION_HASH_RX);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_action, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "action", (const xmlChar *) mac_link);
Packit 284210
                                fcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(action != NULL)
Packit 284210
                                xmlFree(action);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    if(msr->txcfg->crypto_hash_faction_pm == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_action, HASH_URL_FACTION_HASH_PM);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_action, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "action", (const xmlChar *) mac_link);
Packit 284210
                                fcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(action != NULL)
Packit 284210
                                xmlFree(action);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                }
Packit 284210
Packit 284210
                if(action != NULL)  {
Packit 284210
                    xmlFree(action);
Packit 284210
                    action = NULL;
Packit 284210
                }
Packit 284210
Packit 284210
                if(content_option)  {
Packit 284210
                    xmlFree(content_option);
Packit 284210
                    content_option = NULL;
Packit 284210
                }
Packit 284210
            }
Packit 284210
        }
Packit 284210
Packit 284210
        if(xpathObj != NULL)
Packit 284210
            xmlXPathFreeObject(xpathObj);
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_iframesrc_rx == 1 || msr->txcfg->crypto_hash_iframesrc_pm == 1) {
Packit 284210
        xpathObj = xmlXPathEvalExpression((xmlChar*)"//iframe", xpathCtx);
Packit 284210
        if(xpathObj == NULL) {
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4,
Packit 284210
                        "hash_response_body_links: Unable to evaluate xpath expression.");
Packit 284210
            goto obj_error;
Packit 284210
        }
Packit 284210
Packit 284210
        isize = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
Packit 284210
        for(i = isize - 1; i >=0; i--) {
Packit 284210
            register xmlNodePtr cur;
Packit 284210
Packit 284210
            cur = xpathObj->nodesetval->nodeTab[i];
Packit 284210
            if((cur != NULL)){
Packit 284210
Packit 284210
                xmlChar *src = xmlGetProp(cur, (const xmlChar *) "src");
Packit 284210
                char *content_src = normalize_path(msr, (char *)src);
Packit 284210
Packit 284210
                if(content_src != NULL && strstr(content_src,msr->txcfg->crypto_param_name) == NULL) {
Packit 284210
                    if(msr->txcfg->crypto_hash_iframesrc_rx == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_src, HASH_URL_IFRAMESRC_HASH_RX);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_src, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "src", (const xmlChar *) mac_link);
Packit 284210
                                icount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(src != NULL)
Packit 284210
                                xmlFree(src);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    if(msr->txcfg->crypto_hash_iframesrc_pm == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_src, HASH_URL_IFRAMESRC_HASH_PM);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_src, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "src", (const xmlChar *) mac_link);
Packit 284210
                                icount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(src != NULL)
Packit 284210
                                xmlFree(src);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                }
Packit 284210
Packit 284210
                if(src != NULL) {
Packit 284210
                    xmlFree(src);
Packit 284210
                    src = NULL;
Packit 284210
                }
Packit 284210
            }
Packit 284210
        }
Packit 284210
Packit 284210
        if(xpathObj != NULL)
Packit 284210
            xmlXPathFreeObject(xpathObj);
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_framesrc_rx == 1 || msr->txcfg->crypto_hash_framesrc_pm == 1) {
Packit 284210
        xpathObj = xmlXPathEvalExpression((xmlChar*)"//frame", xpathCtx);
Packit 284210
        if(xpathObj == NULL) {
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                msr_log(msr, 4,
Packit 284210
                        "hash_response_body_links: Unable to evaluate xpath expression.");
Packit 284210
            goto obj_error;
Packit 284210
        }
Packit 284210
Packit 284210
        frsize = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
Packit 284210
        for(i = frsize - 1; i >=0; i--) {
Packit 284210
            register xmlNodePtr cur;
Packit 284210
Packit 284210
            cur = xpathObj->nodesetval->nodeTab[i];
Packit 284210
            if((cur != NULL)){
Packit 284210
Packit 284210
                xmlChar *src = xmlGetProp(cur, (const xmlChar *) "src");
Packit 284210
                char *content_src = normalize_path(msr, (char *)src);
Packit 284210
Packit 284210
                if(content_src != NULL && strstr(content_src,msr->txcfg->crypto_param_name) == NULL) {
Packit 284210
                    if(msr->txcfg->crypto_hash_framesrc_rx == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_src, HASH_URL_FRAMESRC_HASH_RX);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_src, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "src", (const xmlChar *) mac_link);
Packit 284210
                                frcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(src != NULL)
Packit 284210
                                xmlFree(src);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                    if(msr->txcfg->crypto_hash_framesrc_pm == 1) {
Packit 284210
                        rc = do_hash_method(msr, (char *)content_src, HASH_URL_FRAMESRC_HASH_PM);
Packit 284210
                        if(rc > 0)  {
Packit 284210
                            mac_link = NULL;
Packit 284210
                            mac_link = do_hash_link(msr, (char *)content_src, FULL_LINK);
Packit 284210
                            if(mac_link != NULL) {
Packit 284210
                                xmlSetProp(cur, (const xmlChar *) "src", (const xmlChar *) mac_link);
Packit 284210
                                frcount++;
Packit 284210
                                bytes += strlen(mac_link);
Packit 284210
                                msr->of_stream_changed = 1;
Packit 284210
                            }
Packit 284210
                            mac_link = NULL;
Packit 284210
                            if(src != NULL)
Packit 284210
                                xmlFree(src);
Packit 284210
                            continue;
Packit 284210
                        }
Packit 284210
                    }
Packit 284210
                }
Packit 284210
Packit 284210
                if(src != NULL) {
Packit 284210
                    xmlFree(src);
Packit 284210
                    src = NULL;
Packit 284210
                }
Packit 284210
            }
Packit 284210
        }
Packit 284210
Packit 284210
        if(xpathObj != NULL)
Packit 284210
            xmlXPathFreeObject(xpathObj);
Packit 284210
    }
Packit 284210
Packit 284210
    if(xpathCtx != NULL)
Packit 284210
        xmlXPathFreeContext(xpathCtx);
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 4)    {
Packit 284210
        msr_log(msr, 4, "hash_response_body_links: Processed [%d] iframe src, [%d] hashed.",isize, icount);
Packit 284210
        msr_log(msr, 4, "hash_response_body_links: Processed [%d] frame src, [%d] hashed.",frsize, frcount);
Packit 284210
        msr_log(msr, 4, "hash_response_body_links: Processed [%d] form actions, [%d] hashed.",fsize, fcount);
Packit 284210
        msr_log(msr, 4, "hash_response_body_links: Processed [%d] links, [%d] hashed.",lsize, lcount);
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->of_stream_changed == 0) {
Packit 284210
        if(msr->crypto_html_tree != NULL)   {
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr->crypto_html_tree = NULL;
Packit 284210
        }
Packit 284210
        return 0;
Packit 284210
    }
Packit 284210
Packit 284210
    elts = (icount+frcount+fcount+lcount);
Packit 284210
Packit 284210
    if((elts >= INT32_MAX) || (elts < 0))
Packit 284210
        return 0;
Packit 284210
Packit 284210
    return bytes;
Packit 284210
Packit 284210
obj_error:
Packit 284210
    if(xpathCtx != NULL)
Packit 284210
    xmlXPathFreeContext(xpathCtx);
Packit 284210
ctx_error:
Packit 284210
    return -1;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Inject the new response body
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 * \param elts Number of hashed elements
Packit 284210
 *
Packit 284210
 * \retval 1 On success
Packit 284210
 * \retval -1 On fail
Packit 284210
 */
Packit 284210
int inject_hashed_response_body(modsec_rec *msr, int elts) {
Packit 284210
    xmlOutputBufferPtr output_buf = NULL;
Packit 284210
    xmlCharEncodingHandlerPtr  handler = NULL;
Packit 284210
    char *p = NULL;
Packit 284210
    const char *ctype = NULL;
Packit 284210
    const char *encoding = NULL;
Packit 284210
    char *new_ct = NULL, *content_value = NULL;
Packit 284210
Packit 284210
    if(msr == NULL) return -1;
Packit 284210
Packit 284210
    if(msr->r == NULL) return -1;
Packit 284210
Packit 284210
    if (msr->crypto_html_tree == NULL) {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Cannot parse NULL html tree");
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
Packit 284210
    if(msr->r->content_type != NULL)
Packit 284210
        ctype = msr->r->content_type;
Packit 284210
Packit 284210
    encoding = (const char *) htmlGetMetaEncoding(msr->crypto_html_tree);
Packit 284210
Packit 284210
    if (ctype && encoding == NULL) {
Packit 284210
        if (ctype && (p = m_strcasestr(ctype, "charset=") , p != NULL)) {
Packit 284210
            p += 8 ;
Packit 284210
            if (encoding = apr_pstrndup(msr->mp, p, strcspn(p, " ;") ), encoding) {
Packit 284210
                xmlCharEncoding enc;
Packit 284210
                enc = xmlParseCharEncoding(encoding);
Packit 284210
                handler = xmlFindCharEncodingHandler(encoding);
Packit 284210
            }
Packit 284210
        }
Packit 284210
    } else  {
Packit 284210
        if(encoding != NULL)    {
Packit 284210
            xmlCharEncoding enc;
Packit 284210
            enc = xmlParseCharEncoding(encoding);
Packit 284210
            handler = xmlFindCharEncodingHandler(encoding);
Packit 284210
        }
Packit 284210
    }
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
        msr_log(msr, 4, "inject_hashed_response_body: Detected encoding type [%s].", encoding);
Packit 284210
Packit 284210
    if (handler == NULL)
Packit 284210
        handler = xmlFindCharEncodingHandler("UTF-8");
Packit 284210
    if (handler == NULL)
Packit 284210
        handler = xmlFindCharEncodingHandler("ISO-8859-1");
Packit 284210
    if (handler == NULL)
Packit 284210
        handler = xmlFindCharEncodingHandler("HTML");
Packit 284210
    if (handler == NULL)
Packit 284210
        handler = xmlFindCharEncodingHandler("ascii");
Packit 284210
Packit 284210
    if(handler == NULL) {
Packit 284210
        xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
Packit 284210
    apr_table_unset(msr->r->headers_out,"Content-Type");
Packit 284210
    new_ct = (char*)apr_psprintf(msr->mp, "text/html;%s",handler->name);
Packit 284210
    apr_table_set(msr->r->err_headers_out,"Content-Type",new_ct);
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
        msr_log(msr, 4, "inject_hashed_response_body: Using content-type [%s].", handler->name);
Packit 284210
Packit 284210
    output_buf = xmlAllocOutputBuffer(handler);
Packit 284210
    if (output_buf == NULL) {
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Unable to allocate memory buffer.");
Packit 284210
        xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
        return -1;
Packit 284210
    }
Packit 284210
Packit 284210
    htmlDocContentDumpFormatOutput(output_buf, msr->crypto_html_tree, NULL, 0);
Packit 284210
    // Not necessary in 2.9.4+
Packit 284210
    //xmlOutputBufferFlush(output_buf);
Packit 284210
Packit 284210
#ifdef  LIBXML2_NEW_BUFFER
Packit 284210
Packit 284210
    if (output_buf->conv == NULL || (output_buf->conv && xmlOutputBufferGetSize(output_buf) == 0)) {
Packit 284210
Packit 284210
        if(output_buf->buffer == NULL || xmlOutputBufferGetSize(output_buf) == 0)  {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr->of_stream_changed = 0;
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: NEW_BUFFER Output buffer is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        if(msr->stream_output_data != NULL) {
Packit 284210
            free(msr->stream_output_data);
Packit 284210
            msr->stream_output_data =  NULL;
Packit 284210
        }
Packit 284210
Packit 284210
        msr->stream_output_length = xmlOutputBufferGetSize(output_buf);
Packit 284210
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);
Packit 284210
Packit 284210
        if (msr->stream_output_data == NULL) {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: NEW BUFFER Stream Output is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
Packit 284210
        memcpy(msr->stream_output_data, xmlOutputBufferGetContent(output_buf), msr->stream_output_length);
Packit 284210
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONTENT to stream buffer [%zu] bytes.", xmlOutputBufferGetSize(output_buf));
Packit 284210
Packit 284210
    } else {
Packit 284210
Packit 284210
        if(output_buf->conv == NULL || xmlOutputBufferGetSize(output_buf) == 0)  {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr->of_stream_changed = 0;
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Conv is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        if(msr->stream_output_data != NULL) {
Packit 284210
            free(msr->stream_output_data);
Packit 284210
            msr->stream_output_data =  NULL;
Packit 284210
        }
Packit 284210
Packit 284210
        msr->stream_output_length = xmlOutputBufferGetSize(output_buf);
Packit 284210
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);
Packit 284210
Packit 284210
        if (msr->stream_output_data == NULL) {
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output data is NULL.");
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
Packit 284210
        memcpy(msr->stream_output_data, xmlOutputBufferGetContent(output_buf), msr->stream_output_length);
Packit 284210
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONV to stream buffer [%zu] bytes.", xmlOutputBufferGetSize(output_buf));
Packit 284210
Packit 284210
    }
Packit 284210
Packit 284210
#else
Packit 284210
Packit 284210
    if (output_buf->conv == NULL || (output_buf->conv && output_buf->conv->use == 0)) {
Packit 284210
Packit 284210
        if(output_buf->buffer == NULL || output_buf->buffer->use == 0)  {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Output buffer is null.");
Packit 284210
            msr->of_stream_changed = 0;
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        if(msr->stream_output_data != NULL) {
Packit 284210
            free(msr->stream_output_data);
Packit 284210
            msr->stream_output_data =  NULL;
Packit 284210
        }
Packit 284210
Packit 284210
        msr->stream_output_length = output_buf->buffer->use;
Packit 284210
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);
Packit 284210
Packit 284210
        if (msr->stream_output_data == NULL) {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
Packit 284210
        memcpy(msr->stream_output_data, (char *)xmlBufferContent(output_buf->buffer), msr->stream_output_length);
Packit 284210
        //memcpy(msr->stream_output_data, output_buf->buffer->content, msr->stream_output_length);
Packit 284210
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONTENT to stream buffer [%d] bytes.", msr->stream_output_length);
Packit 284210
Packit 284210
    } else {
Packit 284210
Packit 284210
        if(output_buf->conv == NULL || output_buf->conv->use == 0)  {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr->of_stream_changed = 0;
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        if(msr->stream_output_data != NULL) {
Packit 284210
            free(msr->stream_output_data);
Packit 284210
            msr->stream_output_data =  NULL;
Packit 284210
        }
Packit 284210
Packit 284210
        msr->stream_output_length = output_buf->conv->use;
Packit 284210
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);
Packit 284210
Packit 284210
        if (msr->stream_output_data == NULL) {
Packit 284210
            xmlOutputBufferClose(output_buf);
Packit 284210
            xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output Data is null.");
Packit 284210
            return -1;
Packit 284210
        }
Packit 284210
Packit 284210
        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
Packit 284210
        memcpy(msr->stream_output_data, (char *)xmlBufferContent(output_buf->conv), msr->stream_output_length);
Packit 284210
        //memcpy(msr->stream_output_data, output_buf->conv->content, msr->stream_output_length);
Packit 284210
Packit 284210
        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONV to stream buffer [%d] bytes.", msr->stream_output_length);
Packit 284210
Packit 284210
    }
Packit 284210
Packit 284210
#endif
Packit 284210
Packit 284210
    xmlOutputBufferClose(output_buf);
Packit 284210
Packit 284210
    content_value = (char*)apr_psprintf(msr->mp, "%"APR_SIZE_T_FMT, msr->stream_output_length);
Packit 284210
    apr_table_unset(msr->r->headers_out,"Content-Length");
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
        msr_log(msr, 4, "inject_hashed_response_body: Setting new content value %s", content_value);
Packit 284210
    apr_table_set(msr->r->headers_out, "Content-Length", content_value);
Packit 284210
Packit 284210
    xmlFreeDoc(msr->crypto_html_tree);
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
        msr_log(msr, 4, "inject_hashed_response_body: Stream buffer [%"APR_SIZE_T_FMT"]. Done",msr->stream_output_length);
Packit 284210
Packit 284210
    return 1;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Parse and MAC html elements
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 * \param link The html attr value to be checked
Packit 284210
 * \param type The hash method type
Packit 284210
 *
Packit 284210
 * \retval mac_link MACed link
Packit 284210
 * \retval NULL on fail
Packit 284210
 */
Packit 284210
char *do_hash_link(modsec_rec *msr, char *link, int type)  {
Packit 284210
    char  *mac_link = NULL;
Packit 284210
    char *path_chunk = NULL;
Packit 284210
    char *hash_value = NULL;
Packit 284210
    char *qm = NULL;
Packit 284210
Packit 284210
    if(msr == NULL) return NULL;
Packit 284210
Packit 284210
    if(strlen(link) > 7 && strncmp("http:",(char*)link,5)==0){
Packit 284210
        path_chunk = strchr(link+7,'/');
Packit 284210
        if(path_chunk != NULL)  {
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)    {
Packit 284210
                msr_log(msr, 4, "Signing data [%s]", path_chunk+1);
Packit 284210
                }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_KEYONLY)
Packit 284210
                hash_value =  hmac(msr, msr->txcfg->crypto_key, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_SESSIONID)  {
Packit 284210
                if(msr->sessionid == NULL || strlen(msr->sessionid) == 0)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Session id is empty. Using REMOTE_IP");
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
                } else {
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->sessionid);
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Using session id [%s]", msr->sessionid);
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
                }
Packit 284210
            }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_REMOTEIP)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
            }
Packit 284210
        } else  {
Packit 284210
            return NULL;
Packit 284210
        }
Packit 284210
    } else
Packit 284210
        if(strlen(link) > 8 && strncmp("https",(char*)link,5)==0){
Packit 284210
            path_chunk = strchr(link+8,'/');
Packit 284210
            if(path_chunk != NULL)  {
Packit 284210
                if (msr->txcfg->debuglog_level >= 4)    {
Packit 284210
                    msr_log(msr, 4, "Signing data [%s]", path_chunk+1);
Packit 284210
                }
Packit 284210
Packit 284210
                if(msr->txcfg->crypto_key_add == HASH_KEYONLY)
Packit 284210
                    hash_value =  hmac(msr, msr->txcfg->crypto_key, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
Packit 284210
                if(msr->txcfg->crypto_key_add == HASH_SESSIONID)  {
Packit 284210
                    if(msr->sessionid == NULL || strlen(msr->sessionid) == 0)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                        const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                        const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                            msr_log(msr, 4, "Session id is empty. Using REMOTE_IP");
Packit 284210
                        msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                        hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
                    } else {
Packit 284210
                        const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->sessionid);
Packit 284210
                        if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                            msr_log(msr, 4, "Using session id [%s]", msr->sessionid);
Packit 284210
                        msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                        hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
                    }
Packit 284210
                }
Packit 284210
Packit 284210
                if(msr->txcfg->crypto_key_add == HASH_REMOTEIP)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) path_chunk+1, strlen((char*)path_chunk)-1);
Packit 284210
                }
Packit 284210
            } else  {
Packit 284210
                return NULL;
Packit 284210
            }
Packit 284210
        }
Packit 284210
        else if(*link=='/'){
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)    {
Packit 284210
                msr_log(msr, 4, "Signing data [%s]", link+1);
Packit 284210
                }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_KEYONLY)
Packit 284210
                hash_value = hmac(msr, msr->txcfg->crypto_key, msr->txcfg->crypto_key_len, (unsigned char *) link+1, strlen((char*)link)-1);
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_SESSIONID)  {
Packit 284210
                if(msr->sessionid == NULL || strlen(msr->sessionid) == 0)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Session id is empty. Using REMOTE_IP");
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) link+1, strlen((char*)link)-1);
Packit 284210
                } else  {
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->sessionid);
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Using session id [%s]", msr->sessionid);
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) link+1, strlen((char*)link)-1);
Packit 284210
                }
Packit 284210
            }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_REMOTEIP)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) link+1, strlen((char*)link)-1);
Packit 284210
            }
Packit 284210
Packit 284210
        }
Packit 284210
        else {
Packit 284210
            char *relative_link = NULL;
Packit 284210
            char *filename = NULL;
Packit 284210
            char *relative_path = NULL;
Packit 284210
            char *relative_uri = NULL;
Packit 284210
Packit 284210
            filename = file_basename(msr->mp, msr->r->parsed_uri.path);
Packit 284210
Packit 284210
            if(filename == NULL || (strlen(msr->r->parsed_uri.path) - strlen(filename) < 0))
Packit 284210
                return NULL;
Packit 284210
Packit 284210
            relative_path = apr_pstrndup(msr->mp, msr->r->parsed_uri.path, strlen(msr->r->parsed_uri.path) - strlen(filename));
Packit 284210
            relative_uri = apr_pstrcat(msr->mp, relative_path, link, NULL);
Packit 284210
Packit 284210
            relative_link = relative_uri+1;
Packit 284210
Packit 284210
            if (msr->txcfg->debuglog_level >= 4)    {
Packit 284210
                msr_log(msr, 4, "Signing data [%s] size %zu", relative_link, strlen(relative_link));
Packit 284210
                }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_KEYONLY)
Packit 284210
                hash_value = hmac(msr, msr->txcfg->crypto_key, msr->txcfg->crypto_key_len, (unsigned char *) relative_link, strlen((char*)relative_link));
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_SESSIONID)  {
Packit 284210
                if(msr->sessionid == NULL || strlen(msr->sessionid) == 0)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Session id is empty. Using REMOTE_IP");
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) relative_link, strlen((char*)relative_link));
Packit 284210
                } else {
Packit 284210
                    const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->sessionid);
Packit 284210
                    if (msr->txcfg->debuglog_level >= 4)
Packit 284210
                        msr_log(msr, 4, "Using session id [%s]", msr->sessionid);
Packit 284210
                    msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                    hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) relative_link, strlen((char*)relative_link));
Packit 284210
                }
Packit 284210
            }
Packit 284210
Packit 284210
            if(msr->txcfg->crypto_key_add == HASH_REMOTEIP)   {
Packit 284210
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->client_ip);
Packit 284210
#else
Packit 284210
                const char *new_pwd = apr_psprintf(msr->mp,"%s%s", msr->txcfg->crypto_key, msr->r->connection->remote_ip);
Packit 284210
#endif
Packit 284210
                msr->txcfg->crypto_key_len = strlen(new_pwd);
Packit 284210
                hash_value = hmac(msr, new_pwd, msr->txcfg->crypto_key_len, (unsigned char *) relative_link, strlen((char*)relative_link));
Packit 284210
            }
Packit 284210
Packit 284210
        link = relative_uri;
Packit 284210
Packit 284210
        }
Packit 284210
Packit 284210
    if(hash_value == NULL) return NULL;
Packit 284210
Packit 284210
    if(type == HASH_ONLY)
Packit 284210
        return hash_value;
Packit 284210
Packit 284210
    qm = strchr((char*)link,'?');
Packit 284210
    if(qm == NULL){
Packit 284210
        mac_link= (char*)apr_psprintf(msr->mp, "%s?%s=%s", link, msr->txcfg->crypto_param_name, (char *)hash_value);
Packit 284210
    }
Packit 284210
    else{
Packit 284210
        mac_link= (char*)apr_psprintf(msr->mp, "%s&%s=%s", link, msr->txcfg->crypto_param_name, (char*)hash_value);
Packit 284210
    }
Packit 284210
Packit 284210
    return mac_link;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * \brief Modify Location in case of status 302 and 301
Packit 284210
 *
Packit 284210
 * \param msr ModSecurity transaction resource
Packit 284210
 *
Packit 284210
 * \retval 1 On Success
Packit 284210
 * \retval 0 on fail
Packit 284210
 */
Packit 284210
int modify_response_header(modsec_rec *msr) {
Packit 284210
    char *mac_link = NULL;
Packit 284210
    const char *location = NULL;
Packit 284210
    int rc = 0;
Packit 284210
Packit 284210
    if(msr == NULL) return 0;
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 9)
Packit 284210
        msr_log(msr, 4, "HTTP status (%d)", msr->response_status);
Packit 284210
Packit 284210
    if(msr->response_status != HTTP_MOVED_TEMPORARILY &&
Packit 284210
            msr->response_status != HTTP_MOVED_PERMANENTLY)    {
Packit 284210
        if (msr->txcfg->debuglog_level >= 9)
Packit 284210
            msr_log(msr, 4, "Skipping status other than 302 an 301");
Packit 284210
        return 0;
Packit 284210
    }
Packit 284210
Packit 284210
    location = apr_table_get(msr->r->headers_out, "Location");
Packit 284210
Packit 284210
    if(location == NULL || strlen(location) == 0)
Packit 284210
        return 0;
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 9)
Packit 284210
        msr_log(msr, 4, "Processing reponse header location [%s]", location);
Packit 284210
Packit 284210
    if(msr->txcfg->crypto_hash_location_rx == 1) {
Packit 284210
        rc = do_hash_method(msr, (char *)location, HASH_URL_LOCATION_HASH_RX);
Packit 284210
Packit 284210
        if(rc > 0)  {
Packit 284210
            mac_link = NULL;
Packit 284210
            mac_link = do_hash_link(msr, (char *)location, FULL_LINK);
Packit 284210
        }   else    {
Packit 284210
            return 0;
Packit 284210
        }
Packit 284210
Packit 284210
    } else if(msr->txcfg->crypto_hash_location_pm == 1) {
Packit 284210
        rc = do_hash_method(msr, (char *)location, HASH_URL_LOCATION_HASH_PM);
Packit 284210
Packit 284210
        if(rc > 0)  {
Packit 284210
            mac_link = NULL;
Packit 284210
            mac_link = do_hash_link(msr, (char *)location, FULL_LINK);
Packit 284210
        }   else    {
Packit 284210
            return 0;
Packit 284210
        }
Packit 284210
Packit 284210
    }
Packit 284210
Packit 284210
    if(mac_link == NULL)
Packit 284210
        return 0;
Packit 284210
Packit 284210
    if (msr->txcfg->debuglog_level >= 9)
Packit 284210
        msr_log(msr, 4, "Setting new reponse header location [%s]", mac_link);
Packit 284210
Packit 284210
    if(rc > 0)  {
Packit 284210
        apr_table_unset(msr->r->headers_out,"Location");
Packit 284210
        apr_table_set(msr->r->headers_out, "Location",(char*)apr_psprintf(msr->mp,"%s", mac_link));
Packit 284210
    }
Packit 284210
Packit 284210
    return 1;
Packit 284210
}