cleaup & emergency config system reactivated

This commit is contained in:
Rainer Gerhards 2011-07-09 18:31:50 +02:00
parent 6ebf9ada25
commit 5e2b03a31c
8 changed files with 44 additions and 308 deletions

View File

@ -198,6 +198,29 @@ int fileno(FILE *stream);
<<EOF>> { if(popfile() != 0) yyterminate(); }
%%
int
cnfParseBuffer(char *buf, unsigned lenBuf)
{
struct bufstack *bs;
int r = 0;
/* maintain stack */
if((bs = malloc(sizeof(struct bufstack))) == NULL) {
r = 1;
goto done;
}
if(currbs != NULL)
currbs->lineno = yylineno;
bs->prev = currbs;
bs->fn = strdup("*buffer*");
bs->bs = yy_scan_buffer(buf, lenBuf);
bs->estr = NULL;
currbs = bs;
currfn = bs->fn;
yylineno = 1;
done: return r;
}
/* set a new buffers. Returns 0 on success, something else otherwise. */
int
cnfSetLexFile(char *fname)

View File

@ -166,6 +166,7 @@ struct exprret {
};
int cnfParseBuffer(char *buf, unsigned lenBuf);
void readConfFile(FILE *fp, es_str_t **str);
struct nvlst* nvlstNew(es_str_t *name, es_str_t *value);
void nvlstDestruct(struct nvlst *lst);

View File

@ -79,7 +79,6 @@
/* forward definitions */
static rsRetVal cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr);
static rsRetVal processConfFile(rsconf_t *conf, uchar *pConfFile);
/* static data */
@ -109,146 +108,6 @@ cstr_t *pDfltHostnameCmp = NULL;
cstr_t *pDfltProgNameCmp = NULL;
/* process a directory and include all of its files into
* the current config file. There is no specific order of inclusion,
* files are included in the order they are read from the directory.
* The caller must have make sure that the provided parameter is
* indeed a directory.
* rgerhards, 2007-08-01
*/
static rsRetVal doIncludeDirectory(rsconf_t *conf, uchar *pDirName)
{
DEFiRet;
int iEntriesDone = 0;
DIR *pDir;
union {
struct dirent d;
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
} u;
struct dirent *res;
size_t iDirNameLen;
size_t iFileNameLen;
uchar szFullFileName[MAXFNAME];
ASSERT(pDirName != NULL);
if((pDir = opendir((char*) pDirName)) == NULL) {
errmsg.LogError(errno, RS_RET_FOPEN_FAILURE, "error opening include directory");
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
}
/* prepare file name buffer */
iDirNameLen = strlen((char*) pDirName);
memcpy(szFullFileName, pDirName, iDirNameLen);
/* now read the directory */
iEntriesDone = 0;
while(readdir_r(pDir, &u.d, &res) == 0) {
if(res == NULL)
break; /* this also indicates end of directory */
# ifdef DT_REG
/* TODO: find an alternate way to checking for special files if this is
* not defined. This is currently a known problem on HP UX, but the work-
* around is simple: do not create special files in that directory. So
* fixing this is actually not the most important thing on earth...
* rgerhards, 2008-03-04
*/
if(res->d_type != DT_REG)
continue; /* we are not interested in special files */
# endif
if(res->d_name[0] == '.')
continue; /* these files we are also not interested in */
++iEntriesDone;
/* construct filename */
iFileNameLen = strlen(res->d_name);
if (iFileNameLen > NAME_MAX)
iFileNameLen = NAME_MAX;
memcpy(szFullFileName + iDirNameLen, res->d_name, iFileNameLen);
*(szFullFileName + iDirNameLen + iFileNameLen) = '\0';
dbgprintf("including file '%s'\n", szFullFileName);
processConfFile(conf, szFullFileName);
/* we deliberately ignore the iRet of processConfFile() - this is because
* failure to process one file does not mean all files will fail. By ignoring,
* we retry with the next file, which is the best thing we can do. -- rgerhards, 2007-08-01
*/
}
if(iEntriesDone == 0) {
/* I just make it a debug output, because I can think of a lot of cases where it
* makes sense not to have any files. E.g. a system maintainer may place a $Include
* into the config file just in case, when additional modules be installed. When none
* are installed, the directory will be empty, which is fine. -- rgerhards 2007-08-01
*/
dbgprintf("warning: the include directory contained no files - this may be ok.\n");
}
finalize_it:
if(pDir != NULL)
closedir(pDir);
RETiRet;
}
/* process a $include config line. That type of line requires
* inclusion of another file.
* rgerhards, 2007-08-01
*/
rsRetVal
doIncludeLine(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal)
{
DEFiRet;
char pattern[MAXFNAME];
uchar *cfgFile;
glob_t cfgFiles;
int result;
size_t i = 0;
struct stat fileInfo;
ASSERT(pp != NULL);
ASSERT(*pp != NULL);
if(getSubString(pp, (char*) pattern, sizeof(pattern) / sizeof(char), ' ') != 0) {
errmsg.LogError(0, RS_RET_NOT_FOUND, "could not parse config file name");
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
/* Use GLOB_MARK to append a trailing slash for directories.
* Required by doIncludeDirectory().
*/
result = glob(pattern, GLOB_MARK, NULL, &cfgFiles);
if(result == GLOB_NOSPACE || result == GLOB_ABORTED) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, "error accessing config file or directory '%s': %s",
pattern, errStr);
ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
}
for(i = 0; i < cfgFiles.gl_pathc; i++) {
cfgFile = (uchar*) cfgFiles.gl_pathv[i];
if(stat((char*) cfgFile, &fileInfo) != 0)
continue; /* continue with the next file if we can't stat() the file */
if(S_ISREG(fileInfo.st_mode)) { /* config file */
dbgprintf("requested to include config file '%s'\n", cfgFile);
iRet = processConfFile(conf, cfgFile);
} else if(S_ISDIR(fileInfo.st_mode)) { /* config directory */
dbgprintf("requested to include directory '%s'\n", cfgFile);
iRet = doIncludeDirectory(conf, cfgFile);
} else { /* TODO: shall we handle symlinks or not? */
dbgprintf("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
}
}
globfree(&cfgFiles);
finalize_it:
RETiRet;
}
/* process a $ModLoad config line. */
rsRetVal
doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
@ -389,120 +248,6 @@ finalize_it:
}
/* process a configuration file
* started with code from init() by rgerhards on 2007-07-31
*/
static rsRetVal
processConfFile(rsconf_t *conf, uchar *pConfFile)
{
int iLnNbr = 0;
FILE *cf;
rule_t *pCurrRule = NULL;
uchar *p;
uchar cbuf[CFGLNSIZ];
uchar *cline;
int i;
int bHadAnError = 0;
uchar *pszOrgLine = NULL;
size_t lenLine;
DEFiRet;
ASSERT(pConfFile != NULL);
if((cf = fopen((char*)pConfFile, "r")) == NULL) {
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
}
/* Now process the file.
*/
cline = cbuf;
while (fgets((char*)cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
++iLnNbr;
/* drop LF - TODO: make it better, replace fgets(), but its clean as it is */
lenLine = ustrlen(cline);
if(cline[lenLine-1] == '\n') {
cline[lenLine-1] = '\0';
}
free(pszOrgLine);
pszOrgLine = ustrdup(cline); /* save if needed for errmsg, NULL ptr is OK */
/* check for end-of-section, comments, strip off trailing
* spaces and newline character.
*/
p = cline;
skipWhiteSpace(&p);
if (*p == '\0' || *p == '#')
continue;
/* we now need to copy the characters to the begin of line. As this overlaps,
* we can not use strcpy(). -- rgerhards, 2008-03-20
* TODO: review the code at whole - this is highly suspect (but will go away
* once we do the rest of RainerScript).
*/
for( i = 0 ; p[i] != '\0' ; ++i) {
cline[i] = p[i];
}
cline[i] = '\0';
for (p = (uchar*) strchr((char*)cline, '\0'); isspace((int) *--p);)
/*EMPTY*/;
if (*p == '\\') {
if ((p - cbuf) > CFGLNSIZ - 30) {
/* Oops the buffer is full - what now? */
cline = cbuf;
} else {
*p = 0;
cline = p;
continue;
}
} else
cline = cbuf;
*++p = '\0'; /* TODO: check this */
/* we now have the complete line, and are positioned at the first non-whitespace
* character. So let's process it
*/
if(cfline(conf, cbuf, &pCurrRule) != RS_RET_OK) {
/* we log a message, but otherwise ignore the error. After all, the next
* line can be correct. -- rgerhards, 2007-08-02
*/
uchar szErrLoc[MAXFNAME + 64];
dbgprintf("config line NOT successfully processed\n");
snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
"%s, line %d", pConfFile, iLnNbr);
errmsg.LogError(0, NO_ERRCODE, "the last error occured in %s:\"%s\"", (char*)szErrLoc, (char*)pszOrgLine);
bHadAnError = 1;
}
}
/* we probably have one selector left to be added - so let's do that now */
if(pCurrRule != NULL) {
CHKiRet(ruleset.AddRule(conf, rule.GetAssRuleset(pCurrRule), &pCurrRule));
}
/* close the configuration file */
fclose(cf);
finalize_it:
if(iRet != RS_RET_OK) {
char errStr[1024];
if(pCurrRule != NULL)
rule.Destruct(&pCurrRule);
rs_strerror_r(errno, errStr, sizeof(errStr));
dbgprintf("error %d processing config file '%s'; os error (if any): %s\n",
iRet, pConfFile, errStr);
}
free(pszOrgLine);
if(bHadAnError && (iRet == RS_RET_OK)) { /* a bit dirty, enhance in future releases */
iRet = RS_RET_NONFATAL_CONFIG_ERR;
}
RETiRet;
}
/* Helper to cfline() and its helpers. Parses a template name
* from an "action" line. Must be called with the Line pointer
* pointing to the first character after the semicolon.
@ -1266,9 +1011,7 @@ CODESTARTobjQueryInterface(conf)
pIf->doNameLine = doNameLine;
pIf->cfsysline = cfsysline;
pIf->doModLoad = doModLoad;
pIf->doIncludeLine = doIncludeLine;
pIf->cfline = cfline;
pIf->processConfFile = processConfFile;
pIf->GetNbrActActions = GetNbrActActions;
finalize_it:

View File

@ -37,9 +37,7 @@ BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
rsRetVal (*doNameLine)(uchar **pp, void* pVal);
rsRetVal (*cfsysline)(uchar *p);
rsRetVal (*doModLoad)(uchar **pp, __attribute__((unused)) void* pVal);
rsRetVal (*doIncludeLine)(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal);
rsRetVal (*cfline)(rsconf_t *conf, uchar *line, rule_t **pfCurr);
rsRetVal (*processConfFile)(rsconf_t *conf, uchar *pConfFile);
rsRetVal (*GetNbrActActions)(rsconf_t *conf, int *);
/* version 4 -- 2010-07-23 rgerhards */
/* "just" added global variables

View File

@ -385,7 +385,7 @@ void cnfDoRule(struct cnfrule *cnfrule)
break;
case CNFFILT_SCRIPT:
pRule->f_filter_type = FILTER_EXPR;
pRule->f_filterData.f_expr = cnfrule->filt.expr;
pRule->f_filterData.expr = cnfrule->filt.expr;
break;
}
/* we now check if there are some global (BSD-style) filter conditions
@ -790,19 +790,6 @@ static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int
}
/* this method is needed to shuffle the current conf object down to the
* IncludeConfig handler.
*/
static rsRetVal
doIncludeLine(void *pVal, uchar *pNewVal)
{
DEFiRet;
iRet = conf.doIncludeLine(ourConf, pVal, pNewVal);
free(pNewVal);
RETiRet;
}
/* set the maximum message size */
static rsRetVal setMaxMsgSize(void __attribute__((unused)) *pVal, long iNewVal)
{
@ -1081,8 +1068,6 @@ initLegacyConf(void)
setActionResumeInterval, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler,
conf.doModLoad, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler,
doIncludeLine, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize,
setMaxMsgSize, NULL, NULL, eConfObjGlobal));
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord,
@ -1236,6 +1221,7 @@ load(rsconf_t **cnf, uchar *confFile)
int bHadConfigErr = 0;
char cbuf[BUFSIZ];
int r;
char *emergConf;
DEFiRet;
CHKiRet(rsconfConstruct(&loadConf));
@ -1246,11 +1232,12 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
/* open the configuration file */
r = cnfSetLexFile((char*)confFile);
r = yyparse();
//localRet = conf.processConfFile(loadConf, confFile);
CHKiRet(conf.GetNbrActActions(loadConf, &iNbrActions));
if(r == 0) {
r = yyparse();
conf.GetNbrActActions(loadConf, &iNbrActions);
}
if(localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) {
if(r == 1) {
errmsg.LogError(0, localRet, "CONFIG ERROR: could not interpret master config file '%s'.", confFile);
bHadConfigErr = 1;
} else if(iNbrActions == 0) {
@ -1259,8 +1246,7 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
bHadConfigErr = 1;
}
if((localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) || iNbrActions == 0) {
if(r == 1 || iNbrActions == 0) {
/* rgerhards: this code is executed to set defaults when the
* config file could not be opened. We might think about
* abandoning the run in this case - but this, too, is not
@ -1268,23 +1254,17 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
* We ignore any errors while doing this - we would be lost anyhow...
*/
errmsg.LogError(0, NO_ERRCODE, "EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!");
/* note: we previously used _POSIY_TTY_NAME_MAX+1, but this turned out to be
* too low on linux... :-S -- rgerhards, 2008-07-28
*/
char szTTYNameBuf[128];
rule_t *pRule = NULL; /* initialization to NULL is *vitally* important! */
conf.cfline(loadConf, UCHAR_CONSTANT("*.ERR\t" _PATH_CONSOLE), &pRule);
conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\t" _PATH_CONSOLE), &pRule);
conf.cfline(loadConf, UCHAR_CONSTANT("*.PANIC\t*"), &pRule);
conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\troot"), &pRule);
if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
conf.cfline(loadConf, (uchar*)cbuf, &pRule);
} else {
DBGPRINTF("error %d obtaining controlling terminal, not using that emergency rule\n", errno);
emergConf =
"*.err " _PATH_CONSOLE "\n"
"syslog.*" _PATH_CONSOLE "\n"
"*.panic :omusrmsg:*" "\n"
"syslog.* :omusrmsg:root" "\n";
cnfParseBuffer(emergConf, strlen(emergConf));
r = yyparse();
if(r != 0) {
fprintf(stderr, "rsyslogd: could not even activate emergency conf - terminating\n");
exit(1);
}
ruleset.AddRule(loadConf, ruleset.GetCurrent(loadConf), &pRule);
}
CHKiRet(validateConf());

View File

@ -183,15 +183,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
else
bRet = 1;
} else if(pRule->f_filter_type == FILTER_EXPR) {
#if 0
CHKiRet(vm.Construct(&pVM));
CHKiRet(vm.ConstructFinalize(pVM));
CHKiRet(vm.SetMsg(pVM, pMsg));
CHKiRet(vm.ExecProg(pVM, pRule->f_filterData.f_expr->pVmprg));
CHKiRet(vm.PopBoolFromStack(pVM, &pResult));
/* VM is destructed on function exit */
bRet = (pResult->val.num) ? 1 : 0;
#endif
bRet = cnfexprEvalBool(pRule->f_filterData.expr, pMsg);
dbgprintf("result of rainerscript filter evaluation: %d\n", bRet);
} else {

View File

@ -54,7 +54,6 @@ struct rule_s {
es_str_t *propName; /* name of property for CEE-based filters */
} prop;
struct cnfexpr *expr; /* expression object */
expr_t *f_expr; /* expression object */
} f_filterData;
ruleset_t *pRuleset; /* associated ruleset */

View File

@ -1,7 +1,8 @@
if ENABLE_TESTBENCH
# TODO: reenable TESTRUNS = rt_init rscript
check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker uxsockrcvr syslog_caller syslog_inject inputfilegen
TESTS = $(TESTRUNS) cfg.sh
TESTS = $(TESTRUNS)
#TESTS = $(TESTRUNS) cfg.sh
if ENABLE_IMDIAG
TESTS += \