in apache2/re_operators.c [1638:1967]
static int msre_op_gsbLookup_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
msc_regex_t *regex = (msc_regex_t *)rule->op_param_data;
char *my_error_msg = NULL;
int ovector[33];
unsigned int offset = 0;
gsb_db *gsb = msr->txcfg->gsb;
const char *match = NULL;
unsigned int match_length;
unsigned int canon_length;
int rv, i, ret, count_slash;
unsigned int j = 0;
unsigned int size = var->value_len;
char *base = NULL, *domain = NULL, *savedptr = NULL;
char *str = NULL, *canon = NULL, *dot = NULL;
char *data = NULL, *ptr = NULL, *url = NULL;
int capture, domain_len;
int d_pos = -1;
int s_pos = -1;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if(regex == NULL) {
*error_msg = "Internal Error: regex is null.";
return 0;
}
if(gsb == NULL) {
msr_log(msr, 1, "GSB lookup failed without a database. Set SecGsbLookupDB.");
return 0;
}
data = apr_pcalloc(rule->ruleset->mp, var->value_len+1);
if(data == NULL) {
*error_msg = "Internal Error: cannot allocate memory for data.";
return -1;
}
capture = apr_table_get(rule->actionset->actions, "capture") ? 1 : 0;
memcpy(data,var->value,var->value_len);
while (offset < size && (rv = msc_regexec_ex(regex, data, size, offset, PCRE_NOTEMPTY, ovector, 30, &my_error_msg)) >= 0)
{
for(i = 0; i < rv; ++i)
{
match = apr_psprintf(rule->ruleset->mp, "%.*s", ovector[2*i+1] - ovector[2*i], data + ovector[2*i]);
if (match == NULL) {
*error_msg = "Internal Error: cannot allocate memory for match.";
return -1;
}
match = remove_escape(rule->ruleset->mp, match, strlen(match));
match = gsb_replace_tpath(rule->ruleset->mp, match, strlen(match));
match = gsb_reduce_char(rule->ruleset->mp, match);
match_length = strlen(match);
strtolower_inplace((unsigned char *)match);
if((strstr(match,"http") == NULL) && (match_length > 0) && (strchr(match,'.'))) {
/* full url */
if (msr->txcfg->debuglog_level >= 4) {
msr_log(msr, 4, "GSB: Successfully extracted url: %s", match);
}
ret = verify_gsb(gsb, msr, match, match_length);
if(ret > 0) {
set_match_to_tx(msr, capture, match, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, match));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
/* append / in the end of full url */
if ((match[match_length -1] != '/') && (strchr(match,'?') == NULL)) {
canon = apr_psprintf(rule->ruleset->mp, "%s/", match);
if (canon != NULL) {
canon_length = strlen(canon);
ret = verify_gsb(gsb, msr, canon, canon_length);
if(ret > 0) {
set_match_to_tx(msr, capture, match, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, canon));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
}
}
/* Parsing full url */
domain = apr_pstrdup(rule->ruleset->mp, match);
domain_len = strlen(domain);
if(*domain != '/') {
if(domain[domain_len-1] == '.')
domain[domain_len-1] = '\0';
if(domain[domain_len-1] == '/' && domain[domain_len-2] == '.') {
domain[domain_len-2] = '/';
domain[domain_len-1] = '\0';
}
dot = strchr(domain,'.');
if(dot != NULL) {
canon = apr_pstrdup(rule->ruleset->mp, domain);
ret = verify_gsb(gsb, msr, canon, strlen(canon));
if(ret > 0) {
set_match_to_tx(msr, capture, canon, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, canon));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
base = apr_strtok(canon,"?",&savedptr);
if(base != NULL) {
ret = verify_gsb(gsb, msr, base, strlen(base));
if(ret > 0) {
set_match_to_tx(msr, capture, base, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, base));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
}
url = apr_palloc(rule->ruleset->mp, strlen(canon));
count_slash = 0;
while(*canon != '\0') {
switch (*canon) {
case '/':
ptr = apr_psprintf(rule->ruleset->mp,"%s/",url);
ret = verify_gsb(gsb, msr, ptr, strlen(ptr));
if(ret > 0) {
set_match_to_tx(msr, capture, ptr, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, ptr));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
break;
}
url[count_slash] = *canon;
count_slash++;
canon++;
}
}
}
/* Do the same for subdomains */
for(j=0; j<strlen(match); j++) {
if(match[j] == '/') {
s_pos = j;
break;
}
}
str = apr_pstrdup(rule->ruleset->mp, match);
while (*str != '\0') {
switch(*str) {
case '.':
domain++;
domain_len = strlen(domain);
d_pos = strchr(domain,'.') - domain;
if(s_pos >= 0 && d_pos >= 0 && d_pos > s_pos)
break;
if(*domain != '/') {
if(domain[domain_len-1] == '.')
domain[domain_len-1] = '\0';
if(domain[domain_len-1] == '/' && domain[domain_len-2] == '.') {
domain[domain_len-2] = '/';
domain[domain_len-1] = '\0';
}
dot = strchr(domain,'.');
if(dot != NULL) {
canon = apr_pstrdup(rule->ruleset->mp, domain);
ret = verify_gsb(gsb, msr, canon, strlen(canon));
if(ret > 0) {
set_match_to_tx(msr, capture, canon, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, canon));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
base = apr_strtok(canon,"?",&savedptr);
if(base != NULL) {
ret = verify_gsb(gsb, msr, base, strlen(base));
if(ret > 0) {
set_match_to_tx(msr, capture, base, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, base));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
}
url = apr_palloc(rule->ruleset->mp, strlen(canon));
count_slash = 0;
while(*canon != '\0') {
switch (*canon) {
case '/':
ptr = apr_psprintf(rule->ruleset->mp,"%s/",url);
ret = verify_gsb(gsb, msr, ptr, strlen(ptr));
if(ret > 0) {
set_match_to_tx(msr, capture, ptr, 0);
if (! *error_msg) {
*error_msg = apr_psprintf(msr->mp, "Gsb lookup for \"%s\" succeeded.",
log_escape_nq(msr->mp, ptr));
}
str = apr_pstrdup(rule->ruleset->mp,match);
base = apr_strtok(str,"/",&savedptr);
if(base != NULL)
set_match_to_tx(msr, capture, base, 1);
return 1;
}
break;
}
url[count_slash] = *canon;
count_slash++;
canon++;
}
}
}
break;
}
domain = str;
domain++;
str++;
}
}
}
offset = ovector[1];
}
return 0;
}