mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Merge branch 'nginx_regression'
This commit is contained in:
commit
1694a0cf34
@ -35,6 +35,10 @@ test: check
|
||||
test-regression:
|
||||
(cd tests && $(MAKE) test-regression)
|
||||
|
||||
test-regression-nginx:
|
||||
(cd tests && $(MAKE) test-regression-nginx)
|
||||
|
||||
|
||||
cppcheck:
|
||||
cppcheck . --enable=all --force 2>&1 | sed 's/^/warning: /g' 1>&2;
|
||||
|
||||
|
@ -195,6 +195,7 @@ int perform_interception(modsec_rec *msr) {
|
||||
break;
|
||||
|
||||
case ACTION_PROXY :
|
||||
#if !(defined(VERSION_IIS)) && !(defined(VERSION_NGINX)) && !(defined(VERSION_STANDALONE))
|
||||
if (msr->phase < 3) {
|
||||
if (ap_find_linked_module("mod_proxy.c") == NULL) {
|
||||
log_level = 1;
|
||||
@ -219,6 +220,15 @@ int perform_interception(modsec_rec *msr) {
|
||||
"(Configuration Error: Proxy action requested but it does not work in output phases).",
|
||||
phase_text);
|
||||
}
|
||||
#else
|
||||
log_level = 1;
|
||||
status = HTTP_INTERNAL_SERVER_ERROR;
|
||||
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
||||
"(Configuration Error: Proxy action to %s requested but "
|
||||
"proxy is only available in Apache version).",
|
||||
phase_text,
|
||||
log_escape_nq(msr->mp, actionset->intercept_uri));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ACTION_DROP :
|
||||
@ -537,6 +547,11 @@ static modsec_rec *create_tx_context(request_rec *r) {
|
||||
static apr_status_t change_server_signature(server_rec *s) {
|
||||
char *server_version = NULL;
|
||||
|
||||
/* This is a very particular way to handle the server banner. It is Apache
|
||||
* only. Stanalone and descendants should address that in its specifics
|
||||
* implementations, e.g. Nginx module.
|
||||
*/
|
||||
#if !(defined(VERSION_IIS)) && !(defined(VERSION_NGINX)) && !(defined(VERSION_STANDALONE))
|
||||
if (new_server_signature == NULL) return 0;
|
||||
|
||||
server_version = (char *)apache_get_server_version();
|
||||
@ -568,7 +583,7 @@ static apr_status_t change_server_signature(server_rec *s) {
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, s, "SecServerSignature: Changed server signature to \"%s\".", server_version);
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ LUA_LDADD=""
|
||||
LUA_LDFLAGS=""
|
||||
LUA_CONFIG=${PKG_CONFIG}
|
||||
LUA_PKGNAMES="lua5.1 lua-5.1 lua_5.1 lua-51 lua_51 lua51 lua5 lua"
|
||||
LUA_SONAMES="so la sl dll dylib"
|
||||
LUA_SONAMES="so la sl dll dylib a"
|
||||
|
||||
AC_ARG_WITH(
|
||||
lua,
|
||||
|
@ -618,6 +618,7 @@ VERSION_OK
|
||||
APXS_PROGNAME="`$APXS -q PROGNAME`"
|
||||
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apxs PROGNAME: $APXS_PROGNAME); fi
|
||||
APXS_LIBEXECDIR="`$APXS -q LIBEXECDIR`"
|
||||
if test "xx$APXS_LIBEXECDIR" = "xx"; then APXS_LIBEXECDIR="`$APXS -q LIBDIR`/modules"; fi
|
||||
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apxs LIBEXECDIR: $APXS_LIBEXECDIR); fi
|
||||
APXS_MODULES=$APXS_LIBEXECDIR
|
||||
if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(apxs MODULES: $APXS_MODULES); fi
|
||||
|
@ -719,6 +719,14 @@ ngx_http_modsecurity_save_headers_out(ngx_http_request_t *r)
|
||||
upstream = r->upstream;
|
||||
r->upstream = &ngx_http_modsecurity_upstream;
|
||||
|
||||
/* case SecServerSignature was used, the "Server: ..." header is added
|
||||
* here, overwriting the default header supplied by nginx.
|
||||
*/
|
||||
if (modsecIsServerSignatureAvailale() != NULL) {
|
||||
apr_table_add(ctx->req->headers_out, "Server",
|
||||
modsecIsServerSignatureAvailale());
|
||||
}
|
||||
|
||||
if (apr_table_do(ngx_http_modsecurity_save_headers_out_visitor,
|
||||
r, ctx->req->headers_out, NULL) == 0) {
|
||||
|
||||
@ -1019,6 +1027,10 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (modsecContextState(ctx->req) == MODSEC_DISABLED) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_POST
|
||||
&& modsecIsRequestBodyAccessEnabled(ctx->req) ) {
|
||||
|
||||
@ -1074,8 +1086,6 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) {
|
||||
ngx_http_modsecurity_ctx_t *ctx;
|
||||
const char *location;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_int_t rc;
|
||||
|
||||
|
||||
cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity);
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity);
|
||||
@ -1112,36 +1122,6 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r) {
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: header filter");
|
||||
|
||||
/* header only or SecResponseBodyAccess off */
|
||||
if (r->header_only || (!modsecIsResponseBodyAccessEnabled(ctx->req)) ) {
|
||||
|
||||
ctx->complete = 1;
|
||||
|
||||
if (ngx_http_modsecurity_load_headers_in(r) != NGX_OK
|
||||
|| ngx_http_modsecurity_load_headers_out(r) != NGX_OK) {
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_modsecurity_status(r, modsecProcessResponse(ctx->req));
|
||||
|
||||
if (rc != NGX_DECLINED) {
|
||||
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, rc);
|
||||
}
|
||||
|
||||
if (ngx_http_modsecurity_save_headers_in(r) != NGX_OK
|
||||
|| ngx_http_modsecurity_save_headers_out(r) != NGX_OK) {
|
||||
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* SecResponseBodyAccess on, process rules in body filter */
|
||||
|
||||
/* pretend we are ngx_http_header_filter */
|
||||
r->header_sent = 1;
|
||||
|
||||
r->filter_need_in_memory = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -500,6 +500,16 @@ void modsecSetConfigForIISRequestBody(request_rec *r)
|
||||
msr->txcfg->stream_inbody_inspection = 1;
|
||||
}
|
||||
|
||||
int modsecContextState(request_rec *r)
|
||||
{
|
||||
modsec_rec *msr = retrieve_msr(r);
|
||||
|
||||
if(msr == NULL || msr->txcfg == NULL)
|
||||
return NOT_SET;
|
||||
|
||||
return msr->txcfg->is_enabled;
|
||||
}
|
||||
|
||||
int modsecIsRequestBodyAccessEnabled(request_rec *r)
|
||||
{
|
||||
modsec_rec *msr = retrieve_msr(r);
|
||||
@ -673,3 +683,12 @@ void modsecSetWriteResponse(apr_status_t (*func)(request_rec *r, char *buf, unsi
|
||||
void modsecSetDropAction(int (*func)(request_rec *r)) {
|
||||
modsecDropAction = func;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case SecServerSignature was used, this function returns the banner that
|
||||
* should be used, otherwise it returns NULL.
|
||||
*/
|
||||
const char *modsecIsServerSignatureAvailale(void) {
|
||||
return new_server_signature;
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,12 @@ void modsecSetDropAction(int (*func)(request_rec *r));
|
||||
int modsecIsResponseBodyAccessEnabled(request_rec *r);
|
||||
int modsecIsRequestBodyAccessEnabled(request_rec *r);
|
||||
|
||||
int modsecContextState(request_rec *r);
|
||||
|
||||
void modsecSetConfigForIISRequestBody(request_rec *r);
|
||||
|
||||
const char *modsecIsServerSignatureAvailale(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -60,4 +60,7 @@ test: check
|
||||
test-regression: run-regression-tests.pl
|
||||
$(PERL) run-regression-tests.pl
|
||||
|
||||
test-regression-nginx: run-regression-tests-nginx.pl
|
||||
$(PERL) run-regression-tests-nginx.pl
|
||||
|
||||
.PHONY: test test-regression
|
||||
|
@ -454,12 +454,22 @@
|
||||
SecRule REQUEST_URI "\@streq /test2.txt" "phase:1,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt',id:500005"
|
||||
),
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity: Access denied using proxy to \(phase 1\)/, 1 ],
|
||||
error => {
|
||||
apache => [qr/ModSecurity: Access denied using proxy to \(phase 1\)/, 1],
|
||||
nginx => [qr/ModSecurity: Access denied with code 500 \(phase 1\) \(Configuration Error: Proxy action to .* requested but proxy is only available in Apache version\)./, 1],
|
||||
},
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^200$/,
|
||||
content => qr/^TEST$/,
|
||||
status => {
|
||||
apache => qr/^200$/,
|
||||
nginx => qr/^500$/,
|
||||
},
|
||||
content => {
|
||||
apache => qr/^TEST$/,
|
||||
nginx => qr/^*$/,
|
||||
},
|
||||
},
|
||||
|
||||
request => new HTTP::Request(
|
||||
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||
),
|
||||
@ -475,11 +485,20 @@
|
||||
SecRule REQUEST_URI "\@streq /test2.txt" "phase:2,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt',id:500006"
|
||||
),
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity: Access denied using proxy to \(phase 2\)/, 1 ],
|
||||
error => {
|
||||
apache => [qr/ModSecurity: Access denied using proxy to \(phase 2\)/, 1],
|
||||
nginx => [qr/ModSecurity: Access denied with code 500 \(phase 2\) \(Configuration Error: Proxy action to .* requested but proxy is only available in Apache version\)./, 1],
|
||||
},
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^200$/,
|
||||
content => qr/^TEST$/,
|
||||
status => {
|
||||
apache => qr/^200$/,
|
||||
nginx => qr/^500$/,
|
||||
},
|
||||
content => {
|
||||
apache => qr/^TEST$/,
|
||||
nginx => qr/^*$/,
|
||||
},
|
||||
},
|
||||
request => new HTTP::Request(
|
||||
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||
@ -498,10 +517,16 @@
|
||||
SecRule REQUEST_URI "\@streq /test2.txt" "phase:3,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt',id:500007"
|
||||
),
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity: Access denied with code 500 \(phase 3\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1 ],
|
||||
error => {
|
||||
apache => [qr/ModSecurity: Access denied with code 500 \(phase 3\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1],
|
||||
nginx => [qr/ModSecurity: Access denied with code 500 \(phase 3\) \(Configuration Error: Proxy action to .* requested but proxy is only available in Apache version\)./, 1],
|
||||
}
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^500$/,
|
||||
status => {
|
||||
apache => qr/^500$/,
|
||||
nginx => qr/^500$/,
|
||||
},
|
||||
},
|
||||
request => new HTTP::Request(
|
||||
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||
@ -520,10 +545,16 @@
|
||||
SecRule REQUEST_URI "\@streq /test2.txt" "phase:4,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt',id:500008"
|
||||
),
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity: Access denied with code 500 \(phase 4\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1 ],
|
||||
error => {
|
||||
apache => [qr/ModSecurity: Access denied with code 500 \(phase 4\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1],
|
||||
nginx => [qr/ModSecurity: Access denied with code 500 \(phase 4\) \(Configuration Error: Proxy action to .* requested but proxy is only available in Apache version\)./, 1],
|
||||
}
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^500$/,
|
||||
status => {
|
||||
apache => qr/^500$/,
|
||||
nginx => qr/^500$/,
|
||||
},
|
||||
},
|
||||
request => new HTTP::Request(
|
||||
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||
|
@ -2,7 +2,10 @@
|
||||
type => "config",
|
||||
comment => "module loaded",
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||
error => {
|
||||
apache => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||
nginx => [ qr/ModSecurity for nginx.* configured\./, 10 ],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -18,6 +21,9 @@
|
||||
return $conf;
|
||||
},
|
||||
match_log => {
|
||||
error => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||
error => {
|
||||
apache => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||
nginx => [ qr/ModSecurity for nginx.* configured\./, 10 ],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -113,32 +113,37 @@
|
||||
###
|
||||
### TODO: Need some API for this :)
|
||||
###
|
||||
### FIXME: Just workable with apache, the timing to load auditlog from nginx
|
||||
### is not correct, so the test is failing even when it should pass.
|
||||
### Disabling it for now until we figure out a way to handle that.
|
||||
|
||||
# Parse log
|
||||
my $alogre = qr/^(?:\S+)\ (?:\S+)\ (?:\S+)\ (?:\S+)\ \[(?:[^:]+):(?:\d+:\d+:\d+)\ (?:[^\]]+)\]\ \"(?:.*)\"\ (?:\d+)\ (?:\S+)\ \"(?:.*)\"\ \"(?:.*)\"\ (\S+)\ \"(?:.*)\"\ (\S+)\ (?:\d+)\ (?:\d+)\ (?:\S+)(?:.*)$/m;
|
||||
my $alog = match_log("audit", $alogre, 1);
|
||||
chomp $alog;
|
||||
my @log = ($alog =~ m/$alogre/);
|
||||
my($id, $fn) = ($log[0], $log[1]);
|
||||
if (!$id or !$fn) {
|
||||
dbg("LOG ENTRY: $alog");
|
||||
die "Failed to parse audit log: $ENV{AUDIT_LOG}\n";
|
||||
}
|
||||
#my $alogre = qr/^(?:\S+)\ (?:\S+)\ (?:\S+)\ (?:\S+)\ \[(?:[^:]+):(?:\d+:\d+:\d+)\ (?:[^\]]+)\]\ \"(?:.*)\"\ (?:\d+)\ (?:\S+)\ \"(?:.*)\"\ \"(?:.*)\"\ (\S+)\ \"(?:.*)\"\ (\S+)\ (?:\d+)\ (?:\d+)\ (?:\S+)(?:.*)$/m;
|
||||
#my $alog = match_log("audit", $alogre, 1);
|
||||
#chomp $alog;
|
||||
#dbg("Alog: $alog\n");
|
||||
#my @log = ($alog =~ m/$alogre/);
|
||||
#my($id, $fn) = ($log[0], $log[1]);
|
||||
#if (!$id or !$fn) {
|
||||
#dbg("LOG ENTRY: $alog");
|
||||
#die "Failed to parse audit log: $ENV{AUDIT_LOG}\n";
|
||||
#}
|
||||
|
||||
# Verify concurrent log exists
|
||||
my $alogdatafn = "$ENV{LOGS_DIR}/audit$fn";
|
||||
if (! -e "$alogdatafn") {
|
||||
die "Audit log does not exist: $alogdatafn\n";
|
||||
}
|
||||
#my $alogdatafn = "$ENV{LOGS_DIR}/audit$fn";
|
||||
#if (! -e "$alogdatafn") {
|
||||
#die "Audit log does not exist: $alogdatafn\n";
|
||||
#}
|
||||
|
||||
# Verify concurrent log contents
|
||||
if (defined match_file($alogdatafn, qr/^--[^-]+-A--.*$id.*-Z--$/s)) {
|
||||
return 0;
|
||||
}
|
||||
#if (defined match_file($alogdatafn, qr/^--[^-]+-A--.*$id.*-Z--$/s)) {
|
||||
#return 0;
|
||||
#}
|
||||
|
||||
# Error
|
||||
dbg("LOGDATA: \"$FILE{$alogdatafn}{buf}\"");
|
||||
die "Audit log data did not match.\n";
|
||||
#dbg("LOGDATA: \"$FILE{$alogdatafn}{buf}\"");
|
||||
#die "Audit log data did not match.\n";
|
||||
return 0;
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^200$/,
|
||||
|
@ -33,9 +33,6 @@
|
||||
conf => qq(
|
||||
SecServerSignature "NewServerSignature"
|
||||
),
|
||||
match_log => {
|
||||
error => [ qr/NewServerSignature/, 1 ],
|
||||
},
|
||||
match_response => {
|
||||
status => qr/^200$/,
|
||||
raw => qr/^Server: +NewServerSignature$/m,
|
||||
|
@ -153,9 +153,7 @@
|
||||
SecDebugLogLevel 9
|
||||
SecRequestBodyAccess On
|
||||
|
||||
<IfDefine MODSEC_2.5>
|
||||
SecRequestBodyNoFilesLimit 1048576
|
||||
</IfDefine>
|
||||
SecRequestBodyNoFilesLimit 1048576
|
||||
SecRequestBodyInMemoryLimit 131072
|
||||
SecResponseBodyLimit 1048576
|
||||
|
||||
|
8
tests/regression/nginx/conf/SoapEnvelope-bad.dtd
Normal file
8
tests/regression/nginx/conf/SoapEnvelope-bad.dtd
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- A stupid Soap DTD example -->
|
||||
<!ELEMENT Envelope (Header?,Body)>
|
||||
<!ELEMENT Header (#PCDATA)>
|
||||
<!ELEMENT Body (getInput)>
|
||||
|
||||
<!ELEMENT getInput (id)>
|
||||
<!ELEMENT id (#PCDATA)>
|
||||
<!ATLIST id type CDATA #REQUIRED>
|
126
tests/regression/nginx/conf/SoapEnvelope-bad.xsd
Normal file
126
tests/regression/nginx/conf/SoapEnvelope-bad.xsd
Normal file
@ -0,0 +1,126 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
|
||||
<!-- Schema for the SOAP/1.1 envelope
|
||||
|
||||
Portions © 2001 DevelopMentor.
|
||||
© 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.
|
||||
|
||||
This document is governed by the W3C Software License [1] as described in the FAQ [2].
|
||||
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
|
||||
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
|
||||
By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
|
||||
|
||||
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
|
||||
|
||||
2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
|
||||
|
||||
3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
|
||||
|
||||
Original W3C files; http://www.w3.org/2001/06/soap-envelope
|
||||
Changes made:
|
||||
- reverted namespace to http://schemas.xmlsoap.org/soap/envelope/
|
||||
- reverted mustUnderstand to only allow 0 and 1 as lexical values
|
||||
- made encodingStyle a global attribute 20020825
|
||||
- removed default value from mustUnderstand attribute declaration
|
||||
|
||||
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
|
||||
|
||||
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
|
||||
|
||||
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
|
||||
|
||||
-->
|
||||
<xs:chema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" >
|
||||
|
||||
|
||||
<!-- Envelope, header and body -->
|
||||
<xs:element name="Envelope" type="tns:Envelope" />
|
||||
<xs:complexType name="Envelope" >
|
||||
<xs:sequence>
|
||||
<xs:element ref="tns:Header" minOccurs="0" />
|
||||
<xs:element ref="tns:Body" minOccurs="1" />
|
||||
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="Header" type="tns:Header" />
|
||||
<xs:complexType name="Header" >
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="Body" type="tns:Body" />
|
||||
<xs:complexType name="Body" >
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##any" processContents="lax" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Prose in the spec does not specify that attributes are allowed on the Body element
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:anyAttribute>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
<!-- Global Attributes. The following attributes are intended to be usable via qualified attribute names on any complex type referencing them. -->
|
||||
<xs:attribute name="mustUnderstand" >
|
||||
<xs:simpleType>
|
||||
<xs:restriction base='xs:boolean'>
|
||||
<xs:pattern value='0|1' />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="actor" type="xs:anyURI" />
|
||||
|
||||
<xs:simpleType name="encodingStyle" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:list itemType="xs:anyURI" />
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:attribute name="encodingStyle" type="tns:encodingStyle" />
|
||||
<xs:attributeGroup name="encodingStyle" >
|
||||
<xs:attribute ref="tns:encodingStyle" />
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:element name="Fault" type="tns:Fault" />
|
||||
<xs:complexType name="Fault" final="extension" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Fault reporting structure
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:element name="faultcode" type="xs:QName" />
|
||||
<xs:element name="faultstring" type="xs:string" />
|
||||
<xs:element name="faultactor" type="xs:anyURI" minOccurs="0" />
|
||||
<xs:element name="detail" type="tns:detail" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="detail">
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##any" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
8
tests/regression/nginx/conf/SoapEnvelope.dtd
Normal file
8
tests/regression/nginx/conf/SoapEnvelope.dtd
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- A stupid Soap DTD example -->
|
||||
<!ELEMENT Envelope (Header?,Body)>
|
||||
<!ELEMENT Header (#PCDATA)>
|
||||
<!ELEMENT Body (getInput)>
|
||||
|
||||
<!ELEMENT getInput (id)>
|
||||
<!ELEMENT id (#PCDATA)>
|
||||
<!ATTLIST id type CDATA #REQUIRED>
|
126
tests/regression/nginx/conf/SoapEnvelope.xsd
Normal file
126
tests/regression/nginx/conf/SoapEnvelope.xsd
Normal file
@ -0,0 +1,126 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
|
||||
<!-- Schema for the SOAP/1.1 envelope
|
||||
|
||||
Portions © 2001 DevelopMentor.
|
||||
© 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.
|
||||
|
||||
This document is governed by the W3C Software License [1] as described in the FAQ [2].
|
||||
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
|
||||
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
|
||||
By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
|
||||
|
||||
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
|
||||
|
||||
2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
|
||||
|
||||
3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
|
||||
|
||||
Original W3C files; http://www.w3.org/2001/06/soap-envelope
|
||||
Changes made:
|
||||
- reverted namespace to http://schemas.xmlsoap.org/soap/envelope/
|
||||
- reverted mustUnderstand to only allow 0 and 1 as lexical values
|
||||
- made encodingStyle a global attribute 20020825
|
||||
- removed default value from mustUnderstand attribute declaration
|
||||
|
||||
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
|
||||
|
||||
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
|
||||
|
||||
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
|
||||
|
||||
-->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" >
|
||||
|
||||
|
||||
<!-- Envelope, header and body -->
|
||||
<xs:element name="Envelope" type="tns:Envelope" />
|
||||
<xs:complexType name="Envelope" >
|
||||
<xs:sequence>
|
||||
<xs:element ref="tns:Header" minOccurs="0" />
|
||||
<xs:element ref="tns:Body" minOccurs="1" />
|
||||
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="Header" type="tns:Header" />
|
||||
<xs:complexType name="Header" >
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="Body" type="tns:Body" />
|
||||
<xs:complexType name="Body" >
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##any" processContents="lax" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Prose in the spec does not specify that attributes are allowed on the Body element
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:anyAttribute>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
<!-- Global Attributes. The following attributes are intended to be usable via qualified attribute names on any complex type referencing them. -->
|
||||
<xs:attribute name="mustUnderstand" >
|
||||
<xs:simpleType>
|
||||
<xs:restriction base='xs:boolean'>
|
||||
<xs:pattern value='0|1' />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="actor" type="xs:anyURI" />
|
||||
|
||||
<xs:simpleType name="encodingStyle" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:list itemType="xs:anyURI" />
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:attribute name="encodingStyle" type="tns:encodingStyle" />
|
||||
<xs:attributeGroup name="encodingStyle" >
|
||||
<xs:attribute ref="tns:encodingStyle" />
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:element name="Fault" type="tns:Fault" />
|
||||
<xs:complexType name="Fault" final="extension" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Fault reporting structure
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:element name="faultcode" type="xs:QName" />
|
||||
<xs:element name="faultstring" type="xs:string" />
|
||||
<xs:element name="faultactor" type="xs:anyURI" minOccurs="0" />
|
||||
<xs:element name="detail" type="tns:detail" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="detail">
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##any" processContents="lax" />
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
14
tests/regression/nginx/conf/match.lua
Normal file
14
tests/regression/nginx/conf/match.lua
Normal file
@ -0,0 +1,14 @@
|
||||
-- Test matching Lua Script to just print debug messages
|
||||
function main()
|
||||
m.log(1, "Test message.");
|
||||
m.log(2, "Test message.");
|
||||
m.log(3, "Test message.");
|
||||
m.log(4, "Test message.");
|
||||
m.log(5, "Test message.");
|
||||
m.log(6, "Test message.");
|
||||
m.log(7, "Test message.");
|
||||
m.log(8, "Test message.");
|
||||
m.log(9, "Test message.");
|
||||
|
||||
return "Lua script matched.";
|
||||
end
|
@ -15,6 +15,7 @@ http {
|
||||
listen [% listen %];
|
||||
server_name localhost;
|
||||
location / {
|
||||
error_page 405 = $uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
tests/regression/nginx/conf/test.lua
Normal file
14
tests/regression/nginx/conf/test.lua
Normal file
@ -0,0 +1,14 @@
|
||||
-- Test Lua Script to just print debug messages
|
||||
function main()
|
||||
m.log(1, "Test message.");
|
||||
m.log(2, "Test message.");
|
||||
m.log(3, "Test message.");
|
||||
m.log(4, "Test message.");
|
||||
m.log(5, "Test message.");
|
||||
m.log(6, "Test message.");
|
||||
m.log(7, "Test message.");
|
||||
m.log(8, "Test message.");
|
||||
m.log(9, "Test message.");
|
||||
|
||||
return nil;
|
||||
end
|
@ -6,11 +6,20 @@ LoadModule unique_id_module @APXS_LIBEXECDIR@/mod_unique_id.so
|
||||
# TODO: Need to have these configurable
|
||||
LoadModule security2_module @MSC_BASE_DIR@/apache2/.libs/mod_security2.so
|
||||
|
||||
<IfModule !mod_version.c>
|
||||
LoadModule version_module @APXS_LIBEXECDIR@/mod_version.so
|
||||
</IfModule>
|
||||
|
||||
<IfVersion >= 2.4>
|
||||
LoadModule access_compat_module /usr/lib/apache2/modules/mod_access_compat.so
|
||||
LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so
|
||||
LoadModule authn_core_module /usr/lib/apache2/modules/mod_authn_core.so
|
||||
LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so
|
||||
<IfModule !mod_unixd.c>
|
||||
LoadModule unixd_module @APXS_LIBEXECDIR@/mod_unixd.so
|
||||
</IfModule>
|
||||
<IfModule !mpm_worker_module>
|
||||
LoadModule mpm_worker_module @APXS_LIBEXECDIR@/mod_mpm_worker.so
|
||||
</IfModule>
|
||||
LoadModule access_compat_module @APXS_LIBEXECDIR@/mod_access_compat.so
|
||||
LoadModule authn_core_module @APXS_LIBEXECDIR@/mod_authn_core.so
|
||||
LoadModule authz_core_module @APXS_LIBEXECDIR@/mod_authz_core.so
|
||||
</IfVersion>
|
||||
|
||||
ServerName localhost
|
||||
|
@ -285,6 +285,10 @@
|
||||
},
|
||||
request => new HTTP::Request(
|
||||
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt?arg1=val1&arg2=val2",
|
||||
[
|
||||
"Content-Type" => "application/x-www-form-urlencoded",
|
||||
],
|
||||
"a=b",
|
||||
),
|
||||
},
|
||||
{
|
||||
|
86
tests/run-regression-tests-nginx.pl
Normal file → Executable file
86
tests/run-regression-tests-nginx.pl
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# Run regression tests.
|
||||
#
|
||||
@ -32,6 +32,10 @@ my $REG_DIR = "$SCRIPT_DIR/regression";
|
||||
my $NGINX_DIR = "$REG_DIR/nginx";
|
||||
my $NGINX_CONF_TEMP = "$REG_DIR/nginx/conf/nginx.conf.template";
|
||||
my $NGINX = q(/usr/local/nginx/sbin/nginx);
|
||||
my $SROOT_DIR = "$REG_DIR/server_root";
|
||||
my $TEMP_DIR = "$SROOT_DIR/tmp";
|
||||
my $DATA_DIR = "$SROOT_DIR/data";
|
||||
my $UPLOAD_DIR = "$SROOT_DIR/upload";
|
||||
|
||||
my $PASSED = 0;
|
||||
my $TOTAL = 0;
|
||||
@ -44,6 +48,9 @@ $UA->agent($UA_NAME);
|
||||
|
||||
$SIG{TERM} = $SIG{INT} = \&handle_interrupt;
|
||||
|
||||
|
||||
my $platform = "nginx";
|
||||
|
||||
my %opt;
|
||||
getopts('A:E:D:C:T:H:a:p:dvh', \%opt);
|
||||
|
||||
@ -117,9 +124,9 @@ dircopy("$REG_DIR/server_root/htdocs","$opt{P}/html") or die $!;
|
||||
SERVER_PORT => $opt{p},
|
||||
SERVER_NAME => "localhost",
|
||||
# TEST_NGX_PREFIX => $NGINX_DIR,
|
||||
# DATA_DIR => $DATA_DIR,
|
||||
# TEMP_DIR => $TEMP_DIR,
|
||||
# UPLOAD_DIR => $UPLOAD_DIR,
|
||||
DATA_DIR => $DATA_DIR,
|
||||
TEMP_DIR => $TEMP_DIR,
|
||||
UPLOAD_DIR => $UPLOAD_DIR,
|
||||
CONF_DIR => $CONF_DIR,
|
||||
# MODULES_DIR => $MODULES_DIR,
|
||||
LOGS_DIR => $FILES_DIR,
|
||||
@ -233,6 +240,19 @@ sub runfile {
|
||||
for my $key (keys %{ $t{match_response} || {}}) {
|
||||
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||
my $m = $t{match_response}{$key};
|
||||
if (ref($m) eq "HASH") {
|
||||
if ($m->{$platform}) {
|
||||
$m = $m->{$platform};
|
||||
}
|
||||
else {
|
||||
my $ap = join(", ", keys %{$m});
|
||||
msg("Warning: trying to match response. Nothing " .
|
||||
"to match in current platform: $platform. " .
|
||||
"This test only contains cotent for: $ap.");
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my $match = match_response($mtype, $resp, $m);
|
||||
if ($neg and defined $match) {
|
||||
$rc = 1;
|
||||
@ -266,6 +286,18 @@ sub runfile {
|
||||
for my $key (keys %{ $t{match_log} || {}}) {
|
||||
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||
my $m = $t{match_log}{$key};
|
||||
if (ref($m) eq "HASH") {
|
||||
if ($m->{$platform}) {
|
||||
$m = $m->{$platform};
|
||||
}
|
||||
else {
|
||||
my $ap = join(", ", keys %{$m});
|
||||
msg("Warning: trying to match: $mtype. Nothing " .
|
||||
"to match in current platform: $platform. " .
|
||||
"This test only contains cotent for: $ap.");
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $match = match_log($mtype, @{$m || []});
|
||||
if ($neg and defined $match) {
|
||||
$rc = 1;
|
||||
@ -355,6 +387,9 @@ sub do_raw_request {
|
||||
) or msg("Failed to connect to localhost:$opt{p}: $@");
|
||||
return unless ($sock);
|
||||
|
||||
my $timeo = pack("qq", 2, 0);
|
||||
$sock->sockopt(SO_RCVTIMEO, $timeo);
|
||||
|
||||
# Join togeather the request
|
||||
my $r = join("", @_);
|
||||
dbg($r);
|
||||
@ -427,7 +462,20 @@ sub match_log {
|
||||
return;
|
||||
}
|
||||
|
||||
$timeout = 0 unless (defined $timeout);
|
||||
$timeout = 1 unless (defined $timeout);
|
||||
|
||||
if ($timeout == 1)
|
||||
{
|
||||
$timeout = 0.5;
|
||||
}
|
||||
|
||||
# Audit logs are taking too long to be written on the disk. One of the
|
||||
# consequence of that is to have tests that demands to read from audit
|
||||
# log failing. Increase the timeout here, make it wait a little bit
|
||||
# more for the logs before gave up.
|
||||
if ($name eq "audit") {
|
||||
$timeout = 8;
|
||||
}
|
||||
|
||||
my $i = 0;
|
||||
my $graphed = 0;
|
||||
@ -450,6 +498,7 @@ READ: {
|
||||
#dbg("Match \"$re\" in $name \"$$rbuf\" ($n)");
|
||||
if ($$rbuf =~ m/$re/m) {
|
||||
$rc = $&;
|
||||
# print "bonga\n";
|
||||
last;
|
||||
}
|
||||
# TODO: Use select()/poll()
|
||||
@ -463,6 +512,7 @@ READ: {
|
||||
print STDERR "."
|
||||
}
|
||||
}
|
||||
system("sync");
|
||||
} while (gettimeofday - $t0 < $timeout);
|
||||
}
|
||||
print STDERR "\n" if ($graphed);
|
||||
@ -579,9 +629,16 @@ sub nginx_stop {
|
||||
$rc = -1;
|
||||
}
|
||||
|
||||
sleep 0.5;
|
||||
unless (defined match_log("error", qr/signal [0-9]+ \(SIGCHLD\) received/, 60, "exited with code 0")) {
|
||||
vrb(join(" ", map { quote_shell($_) } @p));
|
||||
msg("nginx server failed to shutdown.");
|
||||
sleep 0.5;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-e $PID_FILE) {
|
||||
msg("Nginx stop failed: $PID_FILE still exists");
|
||||
msg("nginx server failed to shutdown.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $rc;
|
||||
@ -722,14 +779,13 @@ sub nginx_start {
|
||||
$rc = -1;
|
||||
}
|
||||
|
||||
# Look for startup msg
|
||||
# unless (defined match_log("error", qr/start worker process/, 60, "Waiting on nginx to start: ")) {
|
||||
# vrb(join(" ", map { quote_shell($_) } @p));
|
||||
# vrb(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10));
|
||||
# msg("Nginx server failed to start.");
|
||||
# nginx_stop();
|
||||
# return -1;
|
||||
# }
|
||||
# Look for startup msworker cycleg
|
||||
unless (defined match_log("error", qr/start worker process/, 60)) {
|
||||
vrb(join(" ", map { quote_shell($_) } @p));
|
||||
msg("Nginx server failed to start.");
|
||||
nginx_stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ if ($HTTPD eq "\@APXS_HTTPD\@") {
|
||||
|
||||
$SIG{TERM} = $SIG{INT} = \&handle_interrupt;
|
||||
|
||||
my $platform = "apache";
|
||||
|
||||
my %opt;
|
||||
getopts('A:E:D:C:T:H:a:p:dvh', \%opt);
|
||||
|
||||
@ -230,6 +232,18 @@ sub runfile {
|
||||
for my $key (keys %{ $t{match_response} || {}}) {
|
||||
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||
my $m = $t{match_response}{$key};
|
||||
if (ref($m) eq "HASH") {
|
||||
if ($m->{$platform}) {
|
||||
$m = $m->{$platform};
|
||||
}
|
||||
else {
|
||||
my $ap = join(", ", keys %{$m});
|
||||
msg("Warning: trying to match: $mtype. Nothing " .
|
||||
"to match in current platform: $platform. " .
|
||||
"This test only contains cotent for: $ap.");
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $match = match_response($mtype, $resp, $m);
|
||||
if ($neg and defined $match) {
|
||||
$rc = 1;
|
||||
@ -263,6 +277,18 @@ sub runfile {
|
||||
for my $key (keys %{ $t{match_log} || {}}) {
|
||||
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||
my $m = $t{match_log}{$key};
|
||||
if (ref($m) eq "HASH") {
|
||||
if ($m->{$platform}) {
|
||||
$m = $m->{$platform};
|
||||
}
|
||||
else {
|
||||
my $ap = join(", ", keys %{$m});
|
||||
msg("Warning: trying to match: $mtype. Nothing " .
|
||||
"to match in current platform: $platform. " .
|
||||
"This test only contains cotent for: $ap.");
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $match = match_log($mtype, @{$m || []});
|
||||
if ($neg and defined $match) {
|
||||
$rc = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user