Standalone: added Include command

IIS: added locking, response processing check, fixed file chunk reading bugs
This commit is contained in:
gregwroblewski
2012-10-12 06:27:22 +00:00
parent f00cb1a4e3
commit 6900616faf
7 changed files with 557 additions and 96 deletions

View File

@@ -45,6 +45,12 @@
}
"Entry"
{
"MsmKey" = "8:_3CE93C3FC5AC3E954253889334FBCDA8"
"OwnerKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_51AF671FCA3544DEA3E5756B5D450275"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@@ -141,6 +147,12 @@
}
"Entry"
{
"MsmKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_CEB23D021A2E4EEF9245EEDC143AFBA8"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@@ -187,6 +199,12 @@
"OwnerKey" = "8:_764D5BE911464BEFBCC3BC3B25068987"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_UNDEFINED"
"OwnerKey" = "8:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
"MsmSig" = "8:_UNDEFINED"
}
}
"Configurations"
{
@@ -468,6 +486,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3CE93C3FC5AC3E954253889334FBCDA8"
{
"SourcePath" = "8:nativerd.dll"
"TargetName" = "8:nativerd.dll"
"Tag" = "8:"
"Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_51AF671FCA3544DEA3E5756B5D450275"
{
"SourcePath" = "8:x86\\ModSecurityIIS.dll"
@@ -768,6 +806,37 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_CB8446F7ADCD4E3DA3F2C6246FA844A0"
{
"AssemblyRegister" = "3:1"
"AssemblyIsInGAC" = "11:FALSE"
"AssemblyAsmDisplayName" = "8:Interop.AppHostAdminLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86"
"ScatterAssemblies"
{
"_CB8446F7ADCD4E3DA3F2C6246FA844A0"
{
"Name" = "8:Interop.AppHostAdminLibrary.dll"
"Attributes" = "3:512"
}
}
"SourcePath" = "8:installer project\\bin\\Release\\Interop.AppHostAdminLibrary.dll"
"TargetName" = "8:"
"Tag" = "8:"
"Folder" = "8:_565C3432A64049EAA7CA6E8C007B2188"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEB23D021A2E4EEF9245EEDC143AFBA8"
{
"SourcePath" = "8:amd64\\ModSecurityIIS.dll"
@@ -987,7 +1056,7 @@
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:ModSecurity IIS"
"ProductCode" = "8:{81EE8A4A-5128-4CDB-97B2-06B147E8B4B8}"
"PackageCode" = "8:{0E266CA7-97F3-4DCE-AC7B-5ECCAE18A108}"
"PackageCode" = "8:{B5E59B35-BF44-4075-B9F5-C251002DF58E}"
"UpgradeCode" = "8:{7B32CF94-443C-47BB-91C3-0E9D3D12DF8B}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"

View File

@@ -16,6 +16,10 @@ namespace configure
{
installDir = installDir.Substring(0, installDir.Length - 1);
}
if (installDir.StartsWith("\""))
{
installDir = installDir.Substring(1);
}
Console.WriteLine("Copying 32-bit binaries...");
string dstpath = Environment.ExpandEnvironmentVariables("%windir%\\SysWow64");

View File

@@ -76,8 +76,8 @@ class REQUEST_STORED_CONTEXT : public IHttpStoredContext
IHttpContext *m_pHttpContext;
IHttpEventProvider *m_pProvider;
char *m_pResponseBuffer;
unsigned int m_pResponseLength;
unsigned int m_pResponsePosition;
ULONGLONG m_pResponseLength;
ULONGLONG m_pResponsePosition;
};
//----------------------------------------------------------------------------
@@ -94,39 +94,39 @@ char *GetIpAddr(apr_pool_t *pool, PSOCKADDR pAddr)
apr_sockaddr_t *CopySockAddr(apr_pool_t *pool, PSOCKADDR pAddr)
{
apr_sockaddr_t *addr = (apr_sockaddr_t *)apr_palloc(pool, sizeof(apr_sockaddr_t));
int adrlen = 16, iplen = 4;
if(pAddr->sa_family == AF_INET6)
{
adrlen = 46;
iplen = 16;
}
addr->addr_str_len = adrlen;
addr->family = pAddr->sa_family;
addr->hostname = "unknown";
#ifdef WIN32
addr->ipaddr_len = sizeof(IN_ADDR);
#else
addr->ipaddr_len = sizeof(struct in_addr);
#endif
addr->ipaddr_ptr = &addr->sa.sin.sin_addr;
addr->pool = pool;
addr->port = 80;
#ifdef WIN32
memcpy(&addr->sa.sin.sin_addr.S_un.S_addr, pAddr->sa_data, iplen);
#else
memcpy(&addr->sa.sin.sin_addr.s_addr, pAddr->sa_data, iplen);
#endif
addr->sa.sin.sin_family = pAddr->sa_family;
addr->sa.sin.sin_port = 80;
addr->salen = sizeof(addr->sa);
addr->servname = addr->hostname;
return addr;
}
apr_sockaddr_t *addr = (apr_sockaddr_t *)apr_palloc(pool, sizeof(apr_sockaddr_t));
int adrlen = 16, iplen = 4;
if(pAddr->sa_family == AF_INET6)
{
adrlen = 46;
iplen = 16;
}
addr->addr_str_len = adrlen;
addr->family = pAddr->sa_family;
addr->hostname = "unknown";
#ifdef WIN32
addr->ipaddr_len = sizeof(IN_ADDR);
#else
addr->ipaddr_len = sizeof(struct in_addr);
#endif
addr->ipaddr_ptr = &addr->sa.sin.sin_addr;
addr->pool = pool;
addr->port = 80;
#ifdef WIN32
memcpy(&addr->sa.sin.sin_addr.S_un.S_addr, pAddr->sa_data, iplen);
#else
memcpy(&addr->sa.sin.sin_addr.s_addr, pAddr->sa_data, iplen);
#endif
addr->sa.sin.sin_family = pAddr->sa_family;
addr->sa.sin.sin_port = 80;
addr->salen = sizeof(addr->sa);
addr->servname = addr->hostname;
return addr;
}
//----------------------------------------------------------------------------
@@ -269,7 +269,7 @@ HRESULT CMyHttpModule::ReadFileChunk(HTTP_DATA_CHUNK *chunk, char *buf)
{
OVERLAPPED ovl;
DWORD dwDataStartOffset;
DWORD bytesTotal = 0;
ULONGLONG bytesTotal = 0;
BYTE * pIoBuffer = NULL;
HANDLE hIoEvent = INVALID_HANDLE_VALUE;
HRESULT hr = S_OK;
@@ -332,6 +332,7 @@ HRESULT CMyHttpModule::ReadFileChunk(HTTP_DATA_CHUNK *chunk, char *buf)
TRUE))
{
dwErr = GetLastError();
switch(dwErr)
{
case ERROR_HANDLE_EOF:
@@ -343,7 +344,6 @@ HRESULT CMyHttpModule::ReadFileChunk(HTTP_DATA_CHUNK *chunk, char *buf)
goto Done;
}
}
break;
case ERROR_HANDLE_EOF:
@@ -396,7 +396,9 @@ CMyHttpModule::OnSendResponse(
rsc = (REQUEST_STORED_CONTEXT *)pHttpContext->GetModuleContextContainer()->GetModuleContext(g_pModuleContext);
if(rsc == NULL || rsc->m_pRequestRec == NULL || rsc->m_pResponseBuffer != NULL)
EnterCriticalSection(&m_csLock);
if(rsc == NULL || rsc->m_pRequestRec == NULL || rsc->m_pResponseBuffer != NULL || !modsecIsResponseBodyAccessEnabled(rsc->m_pRequestRec))
{
goto Exit;
}
@@ -408,8 +410,8 @@ CMyHttpModule::OnSendResponse(
HTTP_DATA_CHUNK *pSourceDataChunk = NULL;
LARGE_INTEGER lFileSize;
REQUEST_NOTIFICATION_STATUS ret = RQ_NOTIFICATION_CONTINUE;
ULONG ulTotalLength = 0;
DWORD c, bytesRead;
ULONGLONG ulTotalLength = 0;
DWORD c;
request_rec *r = rsc->m_pRequestRec;
pHttpResponse = pHttpContext->GetResponse();
@@ -430,7 +432,6 @@ CMyHttpModule::OnSendResponse(
// assume HTML if content type not set
// without this output filter would not buffer response and processing would hang
// this needs further investigation (it did not repro on debug build)
//
if(ctz[0] == 0)
ctz = "text/html";
@@ -495,6 +496,9 @@ CMyHttpModule::OnSendResponse(
*(const char **)apr_array_push(r->content_languages) = lng;
}
// here we must check if response body processing is enabled
//
// Disable kernel caching for this response
// Probably we don't have to do it for ModSecurity
@@ -575,6 +579,7 @@ CMyHttpModule::OnSendResponse(
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
goto Finished;
}
ulTotalLength += pFileByteRange->Length.QuadPart;
@@ -639,6 +644,8 @@ Finished:
pHttpContext->SetRequestHandled();
rsc->FinishRequest();
LeaveCriticalSection(&m_csLock);
return RQ_NOTIFICATION_FINISH_REQUEST;
}
@@ -648,6 +655,8 @@ Exit:
if(rsc != NULL)
rsc->FinishRequest();
LeaveCriticalSection(&m_csLock);
return RQ_NOTIFICATION_CONTINUE;
}
@@ -665,7 +674,11 @@ CMyHttpModule::OnPostEndRequest(
//
if(rsc != NULL && rsc->m_pResponseBuffer != NULL)
{
EnterCriticalSection(&m_csLock);
rsc->FinishRequest();
LeaveCriticalSection(&m_csLock);
}
return RQ_NOTIFICATION_CONTINUE;
@@ -683,6 +696,8 @@ CMyHttpModule::OnBeginRequest(
UNREFERENCED_PARAMETER ( pProvider );
EnterCriticalSection(&m_csLock);
if ( pHttpContext == NULL )
{
hr = E_UNEXPECTED;
@@ -996,14 +1011,14 @@ CMyHttpModule::OnBeginRequest(
PSOCKADDR pAddr = pRequest->GetRemoteAddress();
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
c->remote_addr = CopySockAddr(r->pool, pAddr);
c->remote_ip = GetIpAddr(r->pool, pAddr);
#else
c->client_addr = CopySockAddr(r->pool, pAddr);
c->client_ip = GetIpAddr(r->pool, pAddr);
#endif
c->remote_host = NULL;
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
c->remote_addr = CopySockAddr(r->pool, pAddr);
c->remote_ip = GetIpAddr(r->pool, pAddr);
#else
c->client_addr = CopySockAddr(r->pool, pAddr);
c->client_ip = GetIpAddr(r->pool, pAddr);
#endif
c->remote_host = NULL;
int status = modsecProcessRequest(r);
@@ -1012,10 +1027,12 @@ CMyHttpModule::OnBeginRequest(
pHttpContext->GetResponse()->SetStatus(status, "ModSecurity Action");
pHttpContext->SetRequestHandled();
return RQ_NOTIFICATION_FINISH_REQUEST;
hr = E_FAIL;
goto Finished;
}
Finished:
LeaveCriticalSection(&m_csLock);
if ( FAILED( hr ) )
{
@@ -1201,6 +1218,8 @@ CMyHttpModule::CMyHttpModule()
GetSystemInfo(&sysInfo);
m_dwPageSize = sysInfo.dwPageSize;
InitializeCriticalSection(&m_csLock);
modsecSetLogHook(this, Log);
modsecSetReadBody(ReadBodyCallback);
@@ -1238,6 +1257,8 @@ CMyHttpModule::~CMyHttpModule()
// Close the handle to the Event Viewer.
DeregisterEventSource( m_hEventLog );
m_hEventLog = NULL;
DeleteCriticalSection(&m_csLock);
}
}

View File

@@ -22,8 +22,9 @@
class CMyHttpModule : public CHttpModule
{
public:
HANDLE m_hEventLog;
DWORD m_dwPageSize;
HANDLE m_hEventLog;
DWORD m_dwPageSize;
CRITICAL_SECTION m_csLock;
REQUEST_NOTIFICATION_STATUS
OnBeginRequest(

View File

@@ -422,6 +422,16 @@ int modsecProcessRequest(request_rec *r) {
return status;
}
int modsecIsResponseBodyAccessEnabled(request_rec *r)
{
modsec_rec *msr = retrieve_msr(r);
if(msr == NULL || msr->txcfg == NULL)
return 0;
return msr->txcfg->resbody_access;
}
int modsecProcessResponse(request_rec *r) {
int status = DECLINED;

View File

@@ -71,6 +71,8 @@ void modsecSetReadResponse(apr_status_t (*func)(request_rec *r, char *buf, unsig
void modsecSetWriteBody(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length));
void modsecSetWriteResponse(apr_status_t (*func)(request_rec *r, char *buf, unsigned int length));
int modsecIsResponseBodyAccessEnabled(request_rec *r);
#ifdef __cplusplus
}
#endif

View File

@@ -37,7 +37,7 @@
#include "apr_lib.h"
#include "ap_config.h"
#include "http_config.h"
#include "apr_fnmatch.h"
AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
{
@@ -702,6 +702,281 @@ static cmd_parms default_parms =
{NULL, 0, 0, NULL, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
#endif
typedef struct {
const char *fname;
} fnames;
AP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
{
apr_finfo_t finfo;
if (apr_stat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
return 0; /* in error condition, just return no */
return (finfo.filetype == APR_DIR);
}
AP_DECLARE(char *) ap_make_full_path(apr_pool_t *a, const char *src1,
const char *src2)
{
apr_size_t len1, len2;
char *path;
len1 = strlen(src1);
len2 = strlen(src2);
/* allocate +3 for '/' delimiter, trailing NULL and overallocate
* one extra byte to allow the caller to add a trailing '/'
*/
path = (char *)apr_palloc(a, len1 + len2 + 3);
if (len1 == 0) {
*path = '/';
memcpy(path + 1, src2, len2 + 1);
}
else {
char *next;
memcpy(path, src1, len1);
next = path + len1;
if (next[-1] != '/') {
*next++ = '/';
}
memcpy(next, src2, len2 + 1);
}
return path;
}
static int fname_alphasort(const void *fn1, const void *fn2)
{
const fnames *f1 = fn1;
const fnames *f2 = fn2;
return strcmp(f1->fname,f2->fname);
}
AP_DECLARE(const char *) ap_process_resource_config(const char *fname,
apr_array_header_t *ari,
apr_pool_t *ptemp)
{
*(char **)apr_array_push(ari) = (char *)fname;
return NULL;
}
static const char *process_resource_config_nofnmatch(const char *fname,
apr_array_header_t *ari,
apr_pool_t *p,
apr_pool_t *ptemp,
unsigned depth,
int optional)
{
const char *error;
apr_status_t rv;
if (ap_is_directory(ptemp, fname)) {
apr_dir_t *dirp;
apr_finfo_t dirent;
int current;
apr_array_header_t *candidates = NULL;
fnames *fnew;
char *path = apr_pstrdup(ptemp, fname);
if (++depth > 100) {
return apr_psprintf(p, "Directory %s exceeds the maximum include "
"directory nesting level of %u. You have "
"probably a recursion somewhere.", path,
100);
}
/*
* first course of business is to grok all the directory
* entries here and store 'em away. Recall we need full pathnames
* for this.
*/
rv = apr_dir_open(&dirp, path, ptemp);
if (rv != APR_SUCCESS) {
char errmsg[120];
return apr_psprintf(p, "Could not open config directory %s: %s",
path, apr_strerror(rv, errmsg, sizeof errmsg));
}
candidates = apr_array_make(ptemp, 1, sizeof(fnames));
while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
/* strip out '.' and '..' */
if (strcmp(dirent.name, ".")
&& strcmp(dirent.name, "..")) {
fnew = (fnames *) apr_array_push(candidates);
fnew->fname = ap_make_full_path(ptemp, path, dirent.name);
}
}
apr_dir_close(dirp);
if (candidates->nelts != 0) {
qsort((void *) candidates->elts, candidates->nelts,
sizeof(fnames), fname_alphasort);
/*
* Now recurse these... we handle errors and subdirectories
* via the recursion, which is nice
*/
for (current = 0; current < candidates->nelts; ++current) {
fnew = &((fnames *) candidates->elts)[current];
error = process_resource_config_nofnmatch(fnew->fname,
ari, p, ptemp,
depth, optional);
if (error) {
return error;
}
}
}
return NULL;
}
return ap_process_resource_config(fname, ari, ptemp);
}
static const char *process_resource_config_fnmatch(const char *path,
const char *fname,
apr_array_header_t *ari,
apr_pool_t *p,
apr_pool_t *ptemp,
unsigned depth,
int optional)
{
const char *rest;
apr_status_t rv;
apr_dir_t *dirp;
apr_finfo_t dirent;
apr_array_header_t *candidates = NULL;
fnames *fnew;
int current;
/* find the first part of the filename */
rest = ap_strchr_c(fname, '/');
if (rest) {
fname = apr_pstrndup(ptemp, fname, rest - fname);
rest++;
}
/* optimisation - if the filename isn't a wildcard, process it directly */
if (!apr_fnmatch_test(fname)) {
path = ap_make_full_path(ptemp, path, fname);
if (!rest) {
return process_resource_config_nofnmatch(path,
ari, p,
ptemp, 0, optional);
}
else {
return process_resource_config_fnmatch(path, rest,
ari, p,
ptemp, 0, optional);
}
}
/*
* first course of business is to grok all the directory
* entries here and store 'em away. Recall we need full pathnames
* for this.
*/
rv = apr_dir_open(&dirp, path, ptemp);
if (rv != APR_SUCCESS) {
char errmsg[120];
return apr_psprintf(p, "Could not open config directory %s: %s",
path, apr_strerror(rv, errmsg, sizeof errmsg));
}
candidates = apr_array_make(ptemp, 1, sizeof(fnames));
while (apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_TYPE, dirp) == APR_SUCCESS) {
/* strip out '.' and '..' */
if (strcmp(dirent.name, ".")
&& strcmp(dirent.name, "..")
&& (apr_fnmatch(fname, dirent.name,
APR_FNM_PERIOD) == APR_SUCCESS)) {
const char *full_path = ap_make_full_path(ptemp, path, dirent.name);
/* If matching internal to path, and we happen to match something
* other than a directory, skip it
*/
if (rest && (rv == APR_SUCCESS) && (dirent.filetype != APR_DIR)) {
continue;
}
fnew = (fnames *) apr_array_push(candidates);
fnew->fname = full_path;
}
}
apr_dir_close(dirp);
if (candidates->nelts != 0) {
const char *error;
qsort((void *) candidates->elts, candidates->nelts,
sizeof(fnames), fname_alphasort);
/*
* Now recurse these... we handle errors and subdirectories
* via the recursion, which is nice
*/
for (current = 0; current < candidates->nelts; ++current) {
fnew = &((fnames *) candidates->elts)[current];
if (!rest) {
error = process_resource_config_nofnmatch(fnew->fname,
ari, p,
ptemp, 0, optional);
}
else {
error = process_resource_config_fnmatch(fnew->fname, rest,
ari, p,
ptemp, 0, optional);
}
if (error) {
return error;
}
}
}
else {
if (!optional) {
return apr_psprintf(p, "No matches for the wildcard '%s' in '%s', failing "
"(use IncludeOptional if required)", fname, path);
}
}
return NULL;
}
AP_DECLARE(const char *) ap_process_fnmatch_configs(apr_array_header_t *ari,
const char *fname,
apr_pool_t *p,
apr_pool_t *ptemp,
int optional)
{
if (!apr_fnmatch_test(fname)) {
return ap_process_resource_config(fname, ari, p);
}
else {
apr_status_t status;
const char *rootpath, *filepath = fname;
/* locate the start of the directories proper */
status = apr_filepath_root(&rootpath, &filepath, APR_FILEPATH_TRUENAME, ptemp);
/* we allow APR_SUCCESS and APR_EINCOMPLETE */
if (APR_ERELATIVE == status) {
return apr_pstrcat(p, "Include must have an absolute path, ", fname, NULL);
}
else if (APR_EBADPATH == status) {
return apr_pstrcat(p, "Include has a bad path, ", fname, NULL);
}
/* walk the filepath */
return process_resource_config_fnmatch(rootpath, filepath, ari, p, ptemp,
0, optional);
}
}
const char *populate_include_files(apr_pool_t *p, apr_pool_t *ptemp, apr_array_header_t *ari, const char *fname, int optional)
{
return ap_process_fnmatch_configs(ari, fname, p, ptemp, optional);
}
const char *process_command_config(server_rec *s,
void *mconfig,
apr_pool_t *p,
@@ -709,74 +984,153 @@ const char *process_command_config(server_rec *s,
const char *filename)
{
const char *errmsg;
cmd_parms parms;
char *l = apr_palloc (ptemp, MAX_STRING_LEN);
const char *args = l;
char *cmd_name;
char *cmd_name, *w;
const command_rec *cmd;
apr_array_header_t *arr = apr_array_make(p, 1, sizeof(char *));
apr_array_header_t *arr = apr_array_make(p, 1, sizeof(cmd_parms));
apr_array_header_t *ari = apr_array_make(p, 1, sizeof(char *));
cmd_parms *parms;
apr_status_t status;
ap_directive_t *newdir;
int optional;
parms = default_parms;
parms.pool = p;
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
//*(char **)apr_array_push(ari) = (char *)filename;
errmsg = populate_include_files(p, ptemp, ari, filename, 0);
status = ap_pcfg_openfile(&parms.config_file, p, filename);
if(errmsg != NULL)
goto Exit;
if(status != APR_SUCCESS)
while(ari->nelts != 0 || arr->nelts != 0)
{
// cannot open config file
//
}
while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms.config_file))) {
if (*l == '#' || *l == '\0')
continue;
args = l;
cmd_name = ap_getword_conf(p, &args);
if (*cmd_name == '\0')
continue;
cmd = ap_find_command(cmd_name, security2_module.cmds);
if(cmd == NULL)
if(ari->nelts > 0)
{
// unknown command, should error
//
printf("Unknown command: %s\n", cmd_name);
continue;
char *fn = *(char **)apr_array_pop(ari);
parms = (cmd_parms *)apr_array_push(arr);
*parms = default_parms;
parms->pool = p;
parms->temp_pool = ptemp;
parms->server = s;
parms->override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
parms->override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
status = ap_pcfg_openfile(&parms->config_file, p, fn);
if(status != APR_SUCCESS)
{
apr_array_pop(arr);
errmsg = apr_pstrcat(p, "Cannot open config file: ", fn, NULL);
goto Exit;
}
}
newdir = apr_pcalloc(p, sizeof(ap_directive_t));
newdir->filename = parms.config_file->name;
newdir->line_num = parms.config_file->line_number;
newdir->directive = cmd_name;
newdir->args = apr_pstrdup(p, args);
if (arr->nelts > 1024) {
errmsg = "Exceeded the maximum include directory nesting level. You have "
"probably a recursion somewhere.";
goto Exit;
}
parms.directive = newdir;
parms = (cmd_parms *)apr_array_pop(arr);
errmsg = invoke_cmd(cmd, &parms, mconfig, args);
if(parms == NULL)
break;
while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
if (*l == '#' || *l == '\0')
continue;
args = l;
cmd_name = ap_getword_conf(p, &args);
if (*cmd_name == '\0')
continue;
if (!strcasecmp(cmd_name, "IncludeOptional"))
{
optional = 1;
goto ProcessInclude;
}
if (!strcasecmp(cmd_name, "Include"))
{
optional = 0;
ProcessInclude:
w = ap_getword_conf(parms->pool, &args);
if (*w == '\0' || *args != 0)
{
ap_cfg_closefile(parms->config_file);
errmsg = apr_pstrcat(parms->pool, "Include takes one argument", NULL);
goto Exit;
}
errmsg = populate_include_files(p, ptemp, ari, w, optional);
*(cmd_parms *)apr_array_push(arr) = *parms;
if(errmsg != NULL)
goto Exit;
// we don't want to close the current file yet
//
parms = NULL;
break;
}
cmd = ap_find_command(cmd_name, security2_module.cmds);
if(cmd == NULL)
{
// unknown command, should error
//
ap_cfg_closefile(parms->config_file);
errmsg = apr_pstrcat(p, "Unknown command in config: ", cmd_name, NULL);
goto Exit;
}
newdir = apr_pcalloc(p, sizeof(ap_directive_t));
newdir->filename = parms->config_file->name;
newdir->line_num = parms->config_file->line_number;
newdir->directive = cmd_name;
newdir->args = apr_pstrdup(p, args);
parms->directive = newdir;
errmsg = invoke_cmd(cmd, parms, mconfig, args);
if(errmsg != NULL)
break;
}
if(parms != NULL)
ap_cfg_closefile(parms->config_file);
if(errmsg != NULL)
break;
}
ap_cfg_closefile(parms.config_file);
while((parms = (cmd_parms *)apr_array_pop(arr)) != NULL)
{
ap_cfg_closefile(parms->config_file);
}
if (errmsg) {
char *err = (char *)apr_palloc(p, 1024);
apr_snprintf(err, 1024, "Syntax error in config file %s, line %d: %s", parms.config_file->name,
parms.config_file->line_number, errmsg);
apr_snprintf(err, 1024, "Syntax error in config file %s, line %d: %s", parms->config_file->name,
parms->config_file->line_number, errmsg);
return err;
}
return NULL;
Exit:
while((parms = (cmd_parms *)apr_array_pop(arr)) != NULL)
{
ap_cfg_closefile(parms->config_file);
}
return errmsg;
}