diff --git a/SOURCES/rsyslog-8.37.0-rhbz1614181-imtcp-imudp-preservecase-option.patch b/SOURCES/rsyslog-8.37.0-rhbz1614181-imtcp-imudp-preservecase-option.patch new file mode 100644 index 0000000..e4c6e50 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1614181-imtcp-imudp-preservecase-option.patch @@ -0,0 +1,286 @@ +From 9ac54f0d7d70b8a9879889b4522a1d552fca1100 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 12 Jul 2018 11:52:04 -0700 +Subject: [PATCH] Introducing an option preservecase to imudp and imtcp module + for managing the case of FROMHOST value. + +Usage: +module(load="imudp" [preservecase="on"|"off"]) +module(load="imtdp" [preservecase="on"|"off"]) + +If preservecase="on", FROMHOST value is handled in the case sensitive manner. +If preservecase="off", FROMHOST value is handled in the case insensitive manner. + +To maintain the current behaviour, the default value of preservecase is +"on" for imtcp and "off" for imudp. + +Incremented tcpsrvCURR_IF_VERSION by 1. + +References: +https://github.com/rsyslog/rsyslog/pull/2774 +https://bugzilla.redhat.com/show_bug.cgi?id=1309698 +--- + plugins/imtcp/imtcp.c | 14 ++++++++++++-- + plugins/imudp/imudp.c | 15 ++++++++++++--- + runtime/msg.c | 6 +++++- + runtime/msg.h | 2 ++ + runtime/net.c | 2 +- + runtime/tcpsrv.c | 21 +++++++++++++++++++++ + runtime/tcpsrv.h | 5 ++++- + 7 files changed, 57 insertions(+), 8 deletions(-) + +diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c +index 8e3dcc0a2..45fa240b5 100644 +--- a/plugins/imtcp/imtcp.c ++++ b/plugins/imtcp/imtcp.c +@@ -100,6 +100,7 @@ static struct configSettings_s { + int bDisableLFDelim; + int discardTruncatedMsg; + int bUseFlowControl; ++ int bPreserveCase; + uchar *gnutlsPriorityString; + uchar *pszStrmDrvrAuthMode; + uchar *pszInputName; +@@ -144,6 +145,7 @@ struct modConfData_s { + uchar *pszStrmDrvrAuthMode; /* authentication mode to use */ + struct cnfarray *permittedPeers; + sbool configSetViaV2Method; ++ sbool bPreserveCase; /* preserve case of fromhost; true by default */ + }; + + static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +@@ -169,7 +171,8 @@ static struct cnfparamdescr modpdescr[] = { + { "keepalive.probes", eCmdHdlrPositiveInt, 0 }, + { "keepalive.time", eCmdHdlrPositiveInt, 0 }, + { "keepalive.interval", eCmdHdlrPositiveInt, 0 }, +- { "gnutlsprioritystring", eCmdHdlrString, 0 } ++ { "gnutlsprioritystring", eCmdHdlrString, 0 }, ++ { "preservecase", eCmdHdlrBinary, 0 } + }; + static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, +@@ -375,6 +378,7 @@ addListner(modConfData_t *modConf, instanceConf_t *inst) + if(pPermPeersRoot != NULL) { + CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot)); + } ++ CHKiRet(tcpsrv.SetPreserveCase(pOurTcpsrv, modConf->bPreserveCase)); + } + + /* initialized, now add socket and listener params */ +@@ -473,6 +477,7 @@ CODESTARTbeginCnfLoad + loadModConf->pszStrmDrvrAuthMode = NULL; + loadModConf->permittedPeers = NULL; + loadModConf->configSetViaV2Method = 0; ++ loadModConf->bPreserveCase = 1; /* default to true */ + bLegacyCnfModGlobalsPermitted = 1; + /* init legacy config variables */ + cs.pszStrmDrvrAuthMode = NULL; +@@ -543,6 +548,8 @@ CODESTARTsetModCnf + loadModConf->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(modpblk.descr[i].name, "permittedpeer")) { + loadModConf->permittedPeers = cnfarrayDup(pvals[i].val.d.ar); ++ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) { ++ loadModConf->bPreserveCase = (int) pvals[i].val.d.n; + } else { + dbgprintf("imtcp: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); +@@ -584,6 +591,7 @@ CODESTARTendCnfLoad + loadModConf->pszStrmDrvrAuthMode = cs.pszStrmDrvrAuthMode; + cs.pszStrmDrvrAuthMode = NULL; + } ++ pModConf->bPreserveCase = cs.bPreserveCase; + } + free(cs.pszStrmDrvrAuthMode); + cs.pszStrmDrvrAuthMode = NULL; +@@ -731,6 +739,7 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus + cs.pszInputName = NULL; + free(cs.pszStrmDrvrAuthMode); + cs.pszStrmDrvrAuthMode = NULL; ++ cs.bPreserveCase = 1; + return RS_RET_OK; + } + +@@ -797,7 +806,8 @@ CODEmodInit_QueryRegCFSLineHdlr + NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted)); + CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0, eCmdHdlrInt, + NULL, &cs.iStrmDrvrMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted)); +- ++ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverpreservecase"), 1, eCmdHdlrBinary, ++ NULL, &cs.bPreserveCase, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted)); + CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler, + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); + ENDmodInit +diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c +index 51a9d712a..74437781c 100644 +--- a/plugins/imudp/imudp.c ++++ b/plugins/imudp/imudp.c +@@ -152,6 +152,7 @@ struct modConfData_s { + int batchSize; /* max nbr of input batch --> also recvmmsg() max count */ + int8_t wrkrMax; /* max nbr of worker threads */ + sbool configSetViaV2Method; ++ sbool bPreserveCase; /* preserves the case of fromhost; "off" by default */ + }; + static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ + static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ +@@ -162,7 +163,8 @@ static struct cnfparamdescr modpdescr[] = { + { "schedulingpriority", eCmdHdlrInt, 0 }, + { "batchsize", eCmdHdlrInt, 0 }, + { "threads", eCmdHdlrPositiveInt, 0 }, +- { "timerequery", eCmdHdlrInt, 0 } ++ { "timerequery", eCmdHdlrInt, 0 }, ++ { "preservecase", eCmdHdlrBinary, 0 } + }; + static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, +@@ -447,8 +449,12 @@ processPacket(struct lstn_s *lstn, struct sockaddr_storage *frominetPrev, int *p + if(lstn->dfltTZ != NULL) + MsgSetDfltTZ(pMsg, (char*) lstn->dfltTZ); + pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME | NEEDS_DNSRESOL; +- if(*pbIsPermitted == 2) +- pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */ ++ if(*pbIsPermitted == 2) { ++ pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */ ++ } ++ if(runModConf->bPreserveCase) { ++ pMsg->msgFlags |= PRESERVE_CASE; /* preserve case of fromhost */ ++ } + CHKiRet(msgSetFromSockinfo(pMsg, frominet)); + CHKiRet(ratelimitAddMsg(lstn->ratelimiter, multiSub, pMsg)); + STATSCOUNTER_INC(lstn->ctrSubmit, lstn->mutCtrSubmit); +@@ -1030,6 +1036,7 @@ CODESTARTbeginCnfLoad + loadModConf->iTimeRequery = TIME_REQUERY_DFLT; + loadModConf->iSchedPrio = SCHED_PRIO_UNSET; + loadModConf->pszSchedPolicy = NULL; ++ loadModConf->bPreserveCase = 0; /* off */ + bLegacyCnfModGlobalsPermitted = 1; + /* init legacy config vars */ + cs.pszBindRuleset = NULL; +@@ -1079,6 +1086,8 @@ CODESTARTsetModCnf + } else { + loadModConf->wrkrMax = wrkrMax; + } ++ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) { ++ loadModConf->bPreserveCase = (int) pvals[i].val.d.n; + } else { + dbgprintf("imudp: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); +diff --git a/runtime/msg.c b/runtime/msg.c +index c43f81314..9ed4eaf84 100644 +--- a/runtime/msg.c ++++ b/runtime/msg.c +@@ -506,7 +506,11 @@ resolveDNS(smsg_t * const pMsg) { + MsgLock(pMsg); + CHKiRet(objUse(net, CORE_COMPONENT)); + if(pMsg->msgFlags & NEEDS_DNSRESOL) { +- localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip); ++ if (pMsg->msgFlags & PRESERVE_CASE) { ++ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, NULL, &localName, &ip); ++ } else { ++ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip); ++ } + if(localRet == RS_RET_OK) { + /* we pass down the props, so no need for AddRef */ + MsgSetRcvFromWithoutAddRef(pMsg, localName); +diff --git a/runtime/msg.h b/runtime/msg.h +index cd530aca3..1287cb7a4 100644 +--- a/runtime/msg.h ++++ b/runtime/msg.h +@@ -156,6 +156,8 @@ struct msg { + /* check UDP ACLs after DNS resolution has been done in main queue consumer */ + #define NO_PRI_IN_RAW 0x100 + /* rawmsg does not include a PRI (Solaris!), but PRI is already set correctly in the msg object */ ++#define PRESERVE_CASE 0x200 ++/* preserve case in fromhost */ + + /* (syslog) protocol types */ + #define MSG_LEGACY_PROTOCOL 0 +diff --git a/runtime/net.c b/runtime/net.c +index d6ff8a3d4..aef906601 100644 +--- a/runtime/net.c ++++ b/runtime/net.c +@@ -1152,7 +1152,7 @@ cvthname(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t * + { + DEFiRet; + assert(f != NULL); +- iRet = dnscacheLookup(f, NULL, fqdn, localName, ip); ++ iRet = dnscacheLookup(f, fqdn, NULL, localName, ip); + RETiRet; + } + +diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c +index 61e9ff4d2..d5993b4f0 100644 +--- a/runtime/tcpsrv.c ++++ b/runtime/tcpsrv.c +@@ -495,6 +495,15 @@ SessAccept(tcpsrv_t *pThis, tcpLstnPortList_t *pLstnInfo, tcps_sess_t **ppSess, + + /* get the host name */ + CHKiRet(netstrm.GetRemoteHName(pNewStrm, &fromHostFQDN)); ++ if (!pThis->bPreserveCase) { ++ /* preserve_case = off */ ++ uchar *p; ++ for(p = fromHostFQDN; *p; p++) { ++ if (isupper((int) *p)) { ++ *p = tolower((int) *p); ++ } ++ } ++ } + CHKiRet(netstrm.GetRemoteIP(pNewStrm, &fromHostIP)); + CHKiRet(netstrm.GetRemAddr(pNewStrm, &addr)); + /* TODO: check if we need to strip the domain name here -- rgerhards, 2008-04-24 */ +@@ -1001,6 +1010,7 @@ BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macr + pThis->ratelimitBurst = 10000; + pThis->bUseFlowControl = 1; + pThis->pszDrvrName = NULL; ++ pThis->bPreserveCase = 1; /* preserve case in fromhost; default to true. */ + ENDobjConstruct(tcpsrv) + + +@@ -1433,6 +1443,16 @@ SetSessMax(tcpsrv_t *pThis, int iMax) + } + + ++static rsRetVal ++SetPreserveCase(tcpsrv_t *pThis, int bPreserveCase) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, tcpsrv); ++ pThis-> bPreserveCase = bPreserveCase; ++ RETiRet; ++} ++ ++ + /* queryInterface function + * rgerhards, 2008-02-29 + */ +@@ -1491,6 +1511,7 @@ CODESTARTobjQueryInterface(tcpsrv) + pIf->SetRuleset = SetRuleset; + pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters; + pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose; ++ pIf->SetPreserveCase = SetPreserveCase; + + finalize_it: + ENDobjQueryInterface(tcpsrv) +diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h +index 22a65c20a..f17b1b438 100644 +--- a/runtime/tcpsrv.h ++++ b/runtime/tcpsrv.h +@@ -85,6 +85,7 @@ struct tcpsrv_s { + int maxFrameSize; /**< max frame size for octet counted*/ + int bDisableLFDelim; /**< if 1, standard LF frame delimiter is disabled (*very dangerous*) */ + int discardTruncatedMsg;/**< discard msg part that has been truncated*/ ++ sbool bPreserveCase; /**< preserve case in fromhost */ + int ratelimitInterval; + int ratelimitBurst; + tcps_sess_t **pSessions;/**< array of all of our sessions */ +@@ -177,8 +178,10 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ + rsRetVal (*SetbSPFramingFix)(tcpsrv_t*, sbool); + /* added v19 -- PascalWithopf, 2017-08-08 */ + rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*); ++ /* added v21 -- Preserve case in fromhost, 2018-08-16 */ ++ rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase); + ENDinterface(tcpsrv) +-#define tcpsrvCURR_IF_VERSION 20 /* increment whenever you change the interface structure! */ ++#define tcpsrvCURR_IF_VERSION 21 /* increment whenever you change the interface structure! */ + /* change for v4: + * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10 + * - SetInputName() added -- rgerhards, 2008-12-10 diff --git a/SOURCES/rsyslog-8.37.0-rhbz1627941-imfile-support-for-endmsg.regex.patch b/SOURCES/rsyslog-8.37.0-rhbz1627941-imfile-support-for-endmsg.regex.patch new file mode 100644 index 0000000..0a4acc7 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1627941-imfile-support-for-endmsg.regex.patch @@ -0,0 +1,263 @@ +From e8d64cbd15fa84907dc23f8b52d6f2f847b46fec Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Mon, 10 Sep 2018 17:25:38 -0600 +Subject: [PATCH] imfile: support for endmsg.regex + +This adds support for endmsg.regex. It is similar to +startmsg.regex except that it matches the line that denotes +the end of the message, rather than the start of the next message. +This is primarily for container log file use cases such as this: + + date stdout P start of message + date stdout P middle of message + date stdout F end of message + +The `F` means this is the line which contains the final part of +the message. The fully assembled message should be +`start of message middle of message end of message`. +`startmsg.regex="^[^ ]+ stdout F "` will match. + +(cherry picked from commit c902a0938fe163b5351829d2b72001d024895c16) +(cherry picked from commit dd4a72c4d52d8da98ed6b86114868e1a450ccb41) +--- + plugins/imfile/imfile.c | 44 ++++-- + plugins/imptcp/imptcp.c | 10 +- + runtime/stream.c | 28 +++- + runtime/stream.h | 2 +- + 4 files changed, 62 insertions(+), 20 deletions(-) + +diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c +index 7767c9f02..87706082f 100644 +--- a/plugins/imfile/imfile.c ++++ b/plugins/imfile/imfile.c +@@ -126,7 +126,9 @@ struct instanceConf_s { + sbool bRMStateOnDel; + uint8_t readMode; + uchar *startRegex; +- regex_t end_preg; /* compiled version of startRegex */ ++ uchar *endRegex; ++ regex_t start_preg; /* compiled version of startRegex */ ++ regex_t end_preg; /* compiled version of endRegex */ + sbool discardTruncatedMsg; + sbool msgDiscardingError; + sbool escapeLF; +@@ -281,6 +283,7 @@ static struct cnfparamdescr inppdescr[] = { + { "ruleset", eCmdHdlrString, 0 }, + { "readmode", eCmdHdlrInt, 0 }, + { "startmsg.regex", eCmdHdlrString, 0 }, ++ { "endmsg.regex", eCmdHdlrString, 0 }, + { "discardtruncatedmsg", eCmdHdlrBinary, 0 }, + { "msgdiscardingerror", eCmdHdlrBinary, 0 }, + { "escapelf", eCmdHdlrBinary, 0 }, +@@ -1421,6 +1424,7 @@ pollFileReal(act_obj_t *act, cstr_t **pCStr) + int64 strtOffs; + DEFiRet; + int nProcessed = 0; ++ regex_t *start_preg = NULL, *end_preg = NULL; + + DBGPRINTF("pollFileReal enter, pStrm %p, name '%s'\n", act->pStrm, act->name); + DBGPRINTF("pollFileReal enter, edge %p\n", act->edge); +@@ -1432,15 +1436,18 @@ pollFileReal(act_obj_t *act, cstr_t **pCStr) + CHKiRet(openFile(act)); /* open file */ + } + ++ start_preg = (inst->startRegex == NULL) ? NULL : &inst->start_preg; ++ end_preg = (inst->endRegex == NULL) ? NULL : &inst->end_preg; ++ + /* loop below will be exited when strmReadLine() returns EOF */ + while(glbl.GetGlobalInputTermState() == 0) { + if(inst->maxLinesAtOnce != 0 && nProcessed >= inst->maxLinesAtOnce) + break; +- if(inst->startRegex == NULL) { ++ if((start_preg == NULL) && (end_preg == NULL)) { + CHKiRet(strm.ReadLine(act->pStrm, pCStr, inst->readMode, inst->escapeLF, + inst->trimLineOverBytes, &strtOffs)); + } else { +- CHKiRet(strmReadMultiLine(act->pStrm, pCStr, &inst->end_preg, ++ CHKiRet(strmReadMultiLine(act->pStrm, pCStr, start_preg, end_preg, + inst->escapeLF, inst->discardTruncatedMsg, inst->msgDiscardingError, &strtOffs)); + } + ++nProcessed; +@@ -1506,6 +1513,7 @@ createInstance(instanceConf_t **const pinst) + inst->iPersistStateInterval = 0; + inst->readMode = 0; + inst->startRegex = NULL; ++ inst->endRegex = NULL; + inst->discardTruncatedMsg = 0; + inst->msgDiscardingError = 1; + inst->bRMStateOnDel = 1; +@@ -1713,6 +1721,8 @@ CODESTARTnewInpInst + inst->readMode = (sbool) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "startmsg.regex")) { + inst->startRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); ++ } else if(!strcmp(inppblk.descr[i].name, "endmsg.regex")) { ++ inst->endRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) { + inst->discardTruncatedMsg = (sbool) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "msgdiscardingerror")) { +@@ -1753,19 +1763,31 @@ CODESTARTnewInpInst + "param '%s'\n", inppblk.descr[i].name); + } + } +- if(inst->readMode != 0 && inst->startRegex != NULL) { ++ i = (inst->readMode > 0) ? 1 : 0; ++ i = (NULL != inst->startRegex) ? (i+1) : i; ++ i = (NULL != inst->endRegex) ? (i+1) : i; ++ if(i > 1) { + LogError(0, RS_RET_PARAM_NOT_PERMITTED, +- "readMode and startmsg.regex cannot be set " +- "at the same time --- remove one of them"); ++ "only one of readMode or startmsg.regex or endmsg.regex can be set " ++ "at the same time"); + ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED); + } + + if(inst->startRegex != NULL) { +- const int errcode = regcomp(&inst->end_preg, (char*)inst->startRegex, REG_EXTENDED); ++ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED); ++ if(errcode != 0) { ++ char errbuff[512]; ++ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff)); ++ parser_errmsg("imfile: error in startmsg.regex expansion: %s", errbuff); ++ ABORT_FINALIZE(RS_RET_ERR); ++ } ++ } ++ if(inst->endRegex != NULL) { ++ const int errcode = regcomp(&inst->end_preg, (char*)inst->endRegex, REG_EXTENDED); + if(errcode != 0) { + char errbuff[512]; + regerror(errcode, &inst->end_preg, errbuff, sizeof(errbuff)); +- parser_errmsg("imfile: error in regex expansion: %s", errbuff); ++ parser_errmsg("imfile: error in endmsg.regex expansion: %s", errbuff); + ABORT_FINALIZE(RS_RET_ERR); + } + } +@@ -1970,9 +1992,13 @@ CODESTARTfreeCnf + free(inst->pszStateFile); + free(inst->pszFileName_forOldStateFile); + if(inst->startRegex != NULL) { +- regfree(&inst->end_preg); ++ regfree(&inst->start_preg); + free(inst->startRegex); + } ++ if(inst->endRegex != NULL) { ++ regfree(&inst->end_preg); ++ free(inst->endRegex); ++ } + del = inst; + inst = inst->next; + free(del); +diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c +index 9b6be0f40..a94b97f41 100644 +--- a/plugins/imptcp/imptcp.c ++++ b/plugins/imptcp/imptcp.c +@@ -162,7 +162,7 @@ struct instanceConf_s { + int ratelimitInterval; + int ratelimitBurst; + uchar *startRegex; +- regex_t end_preg; /* compiled version of startRegex */ ++ regex_t start_preg; /* compiled version of startRegex */ + struct instanceConf_s *next; + }; + +@@ -961,7 +961,7 @@ processDataRcvd_regexFraming(ptcpsess_t *const __restrict__ pThis, + if(c == '\n') { + pThis->iCurrLine = pThis->iMsg; + } else { +- const int isMatch = !regexec(&inst->end_preg, (char*)pThis->pMsg+pThis->iCurrLine, 0, NULL, 0); ++ const int isMatch = !regexec(&inst->start_preg, (char*)pThis->pMsg+pThis->iCurrLine, 0, NULL, 0); + if(isMatch) { + DBGPRINTF("regex match (%d), framing line: %s\n", pThis->iCurrLine, pThis->pMsg); + strcpy((char*)pThis->pMsg_save, (char*) pThis->pMsg+pThis->iCurrLine); +@@ -2188,10 +2188,10 @@ CODESTARTnewInpInst + } + + if(inst->startRegex != NULL) { +- const int errcode = regcomp(&inst->end_preg, (char*)inst->startRegex, REG_EXTENDED); ++ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED); + if(errcode != 0) { + char errbuff[512]; +- regerror(errcode, &inst->end_preg, errbuff, sizeof(errbuff)); ++ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff)); + parser_errmsg("imptcp: error in framing.delimiter.regex expansion: %s", errbuff); + ABORT_FINALIZE(RS_RET_ERR); + } +@@ -2348,7 +2348,7 @@ CODESTARTfreeCnf + free(inst->pszInputName); + free(inst->dfltTZ); + if(inst->startRegex != NULL) { +- regfree(&inst->end_preg); ++ regfree(&inst->start_preg); + free(inst->startRegex); + } + del = inst; +diff --git a/runtime/stream.c b/runtime/stream.c +index 6b7e7028e..0f4197103 100644 +--- a/runtime/stream.c ++++ b/runtime/stream.c +@@ -942,12 +942,12 @@ strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis) + + /* read a multi-line message from a strm file. + * The multi-line message is terminated based on the user-provided +- * startRegex (Posix ERE). For performance reasons, the regex ++ * startRegex or endRegex (Posix ERE). For performance reasons, the regex + * must already have been compiled by the user. + * added 2015-05-12 rgerhards + */ + rsRetVal +-strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEscapeLF, ++strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, const sbool bEscapeLF, + const sbool discardTruncatedMsg, const sbool msgDiscardingError, int64 *const strtOffs) + { + uchar c; +@@ -979,9 +979,14 @@ strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEs + cstrFinalize(thisLine); + + /* we have a line, now let's assemble the message */ +- const int isMatch = !regexec(preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0); +- +- if(isMatch) { ++ const int isStartMatch = start_preg ? ++ !regexec(start_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) : ++ 0; ++ const int isEndMatch = end_preg ? ++ !regexec(end_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) : ++ 0; ++ ++ if(isStartMatch) { + /* in this case, the *previous* message is complete and we are + * at the start of a new one. + */ +@@ -1047,6 +1052,19 @@ strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, const sbool bEs + } + } + } ++ if(isEndMatch) { ++ /* in this case, the *current* message is complete and we are ++ * at the end of it. ++ */ ++ if(pThis->ignoringMsg == 0) { ++ if(pThis->prevMsgSegment != NULL) { ++ finished = 1; ++ *ppCStr = pThis->prevMsgSegment; ++ pThis->prevMsgSegment= NULL; ++ } ++ } ++ pThis->ignoringMsg = 0; ++ } + cstrDestruct(&thisLine); + } while(finished == 0); + +diff --git a/runtime/stream.h b/runtime/stream.h +index 71596879e..7dc597ff5 100644 +--- a/runtime/stream.h ++++ b/runtime/stream.h +@@ -225,7 +225,7 @@ ENDinterface(strm) + /* prototypes */ + PROTOTYPEObjClassInit(strm); + rsRetVal strmMultiFileSeek(strm_t *pThis, unsigned int fileNum, off64_t offs, off64_t *bytesDel); +-rsRetVal strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *preg, ++rsRetVal strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, + sbool bEscapeLF, sbool discardTruncatedMsg, sbool msgDiscardingError, int64 *const strtOffs); + int strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis); + void strmDebugOutBuf(const strm_t *const pThis); diff --git a/SOURCES/rsyslog-8.37.0-rhbz1674471-imfile-log-rotation.patch b/SOURCES/rsyslog-8.37.0-rhbz1674471-imfile-log-rotation.patch new file mode 100644 index 0000000..e721782 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1674471-imfile-log-rotation.patch @@ -0,0 +1,368 @@ +From f85ef7aabcec84497a5eaf9670616b3402c79d9c Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards +Date: Sun, 23 Sep 2018 13:19:31 +0200 +Subject: File rotation with imfile broken + +Previously, truncation was only detected at end of file. Especially with +busy files that could cause loss of data and possibly also stall imfile +reading. The new code now also checks during each read. Obviously, there +is some additional overhead associated with that, but this is unavoidable. + +It still is highly recommended NOT to turn on "reopenOnTruncate" in imfile. +Note that there are also inherant reliability issues. There is no way to +"fix" these, as they are caused by races between the process(es) who truncate +and rsyslog reading the file. But with the new code, the "problem window" +should be much smaller and, more importantly, imfile should not stall. + +A change in the inode was not detected under all circumstances, +most importantly not in some logrotate cases. + +Includes new tests made by Andre Lorbach. They now use the +logrotate tool natively to reproduce the issue. +--- + runtime/rsyslog.h | 6 ++-- + plugins/imfile/imfile.c | 17 +++- + runtime/stream.c | 122 ++++++++---- + runtime/stream.h | 7 ++ + 4 files changed, 126 insertions(+), 36 deletions(-) + +diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h +index 61d0af623..22a1c46d1 100644 +--- a/runtime/rsyslog.h ++++ b/runtime/rsyslog.h +@@ -221,9 +221,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth + /* begin regular error codes */ + RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */ + RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */ +- RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, +-/*< the caller provided a buffer, but the called function sees the size of this buffer is too small - +-operation not carried out */ ++ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, /*< the caller provided a buffer, but the called function sees ++ the size of this buffer is too small - operation not carried out */ ++ RS_RET_FILE_TRUNCATED = -51, /**< (input) file was truncated, not an error but a status */ + RS_RET_TRUE = -3, /**< to indicate a true state (can be used as TRUE, legacy) */ + RS_RET_FALSE = -2, /**< to indicate a false state (can be used as FALSE, legacy) */ + RS_RET_NO_IRET = -8, /**< This is a trick for the debuging system - it means no iRet is provided */ +diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c +index f4a4ef9b7..6be8b2999 100644 +--- a/plugins/imfile/imfile.c ++++ b/plugins/imfile/imfile.c +@@ -740,8 +740,19 @@ detect_updates(fs_edge_t *const edge) + act_obj_unlink(act); + restart = 1; + break; ++ } else if(fileInfo.st_ino != act->ino) { ++ DBGPRINTF("file '%s' inode changed from %llu to %llu, unlinking from " ++ "internal lists\n", act->name, (long long unsigned) act->ino, ++ (long long unsigned) fileInfo.st_ino); ++ if(act->pStrm != NULL) { ++ /* we do no need to re-set later, as act_obj_unlink ++ * will destroy the strm obj */ ++ strmSet_checkRotation(act->pStrm, STRM_ROTATION_DO_NOT_CHECK); ++ } ++ act_obj_unlink(act); ++ restart = 1; ++ break; + } +- // TODO: add inode check for change notification! + + } + +@@ -993,10 +1004,10 @@ chk_active(const act_obj_t *act, const act_obj_t *const deleted) + /* unlink act object from linked list and then + * destruct it. + */ +-static void //ATTR_NONNULL() ++static void ATTR_NONNULL() + act_obj_unlink(act_obj_t *act) + { +- DBGPRINTF("act_obj_unlink %p: %s\n", act, act->name); ++ DBGPRINTF("act_obj_unlink %p: %s, pStrm %p\n", act, act->name, act->pStrm); + if(act->prev == NULL) { + act->edge->active = act->next; + } else { +diff --git a/runtime/stream.c b/runtime/stream.c +index 0f4197103..32a12b256 100644 +--- a/runtime/stream.c ++++ b/runtime/stream.c +@@ -400,6 +400,7 @@ static rsRetVal strmOpenFile(strm_t *pThis) + CHKiRet(doPhysOpen(pThis)); + + pThis->iCurrOffs = 0; ++ pThis->iBufPtrMax = 0; + CHKiRet(getFileSize(pThis->pszCurrFName, &offset)); + if(pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) { + pThis->iCurrOffs = offset; +@@ -636,6 +637,78 @@ strmHandleEOF(strm_t *pThis) + RETiRet; + } + ++ ++/* helper to checkTruncation */ ++static rsRetVal ATTR_NONNULL() ++rereadTruncated(strm_t *const pThis, const char *const reason) ++{ ++ DEFiRet; ++ ++ LogMsg(errno, RS_RET_FILE_TRUNCATED, LOG_WARNING, "file '%s': truncation detected, " ++ "(%s) - re-start reading from beginning", ++ pThis->pszCurrFName, reason); ++ DBGPRINTF("checkTruncation, file %s last buffer CHANGED\n", pThis->pszCurrFName); ++ CHKiRet(strmCloseFile(pThis)); ++ CHKiRet(strmOpenFile(pThis)); ++ iRet = RS_RET_FILE_TRUNCATED; ++ ++finalize_it: ++ RETiRet; ++} ++/* helper to read: ++ * Check if file has been truncated since last read and, if so, re-set reading ++ * to begin of file. To detect truncation, we try to re-read the last block. ++ * If that does not succeed or different data than from the original read is ++ * returned, truncation is assumed. ++ * NOTE: this function must be called only if truncation is enabled AND ++ * when the previous read buffer still is valid (aka "before the next read"). ++ * It is ok to call with a 0-size buffer, which we than assume as begin of ++ * reading. In that case, no truncation will be detected. ++ * rgerhards, 2018-09-20 ++ */ ++static rsRetVal ATTR_NONNULL() ++checkTruncation(strm_t *const pThis) ++{ ++ DEFiRet; ++ int ret; ++ off64_t backseek; ++ assert(pThis->bReopenOnTruncate); ++ ++ DBGPRINTF("checkTruncation, file %s, iBufPtrMax %zd\n", pThis->pszCurrFName, pThis->iBufPtrMax); ++ if(pThis->iBufPtrMax == 0) { ++ FINALIZE; ++ } ++ ++ int currpos = lseek64(pThis->fd, 0, SEEK_CUR); ++ backseek = -1 * (off64_t) pThis->iBufPtrMax; ++ dbgprintf("checkTruncation in actual processing, currpos %d, backseek is %d\n", (int)currpos, (int) backseek); ++ ret = lseek64(pThis->fd, backseek, SEEK_CUR); ++ if(ret < 0) { ++ iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block"); ++ FINALIZE; ++ } ++dbgprintf("checkTruncation seek backwrds: %d\n", ret); ++currpos = lseek64(pThis->fd, 0, SEEK_CUR); ++dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek); ++ ++ const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax); ++ dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead); ++ if(lenRead < 0) { ++ iRet = rereadTruncated(pThis, "last block could not be re-read"); ++ FINALIZE; ++ } ++ ++ if(!memcmp(pThis->pIOBuf_truncation, pThis->pIOBuf, pThis->iBufPtrMax)) { ++ DBGPRINTF("checkTruncation, file %s last buffer unchanged\n", pThis->pszCurrFName); ++ } else { ++ iRet = rereadTruncated(pThis, "last block data different"); ++ } ++ ++finalize_it: ++ RETiRet; ++} ++ ++ + /* read the next buffer from disk + * rgerhards, 2008-02-13 + */ +@@ -668,6 +741,13 @@ strmReadBuf(strm_t *pThis, int *padBytes) + toRead = (size_t) bytesLeft; + } + } ++ if(pThis->bReopenOnTruncate) { ++ rsRetVal localRet = checkTruncation(pThis); ++ if(localRet == RS_RET_FILE_TRUNCATED) { ++ continue; ++ } ++ CHKiRet(localRet); ++ } + iLenRead = read(pThis->fd, pThis->pIOBuf, toRead); + DBGOPRINT((obj_t*) pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead); + /* end crypto */ +@@ -1184,6 +1264,7 @@ static rsRetVal strmConstructFinalize(strm_t *pThis) + } else { + /* we work synchronously, so we need to alloc a fixed pIOBuf */ + CHKmalloc(pThis->pIOBuf = (uchar*) MALLOC(pThis->sIOBufSize)); ++ CHKmalloc(pThis->pIOBuf_truncation = (char*) MALLOC(pThis->sIOBufSize)); + } + + finalize_it: +@@ -1231,6 +1312,7 @@ CODESTARTobjDestruct(strm) + } + } else { + free(pThis->pIOBuf); ++ free(pThis->pIOBuf_truncation); + } + + /* Finally, we can free the resources. +diff --git a/runtime/stream.c b/runtime/stream.c +index 2d494c612..5b52591ef 100644 +--- a/runtime/stream.c ++++ b/runtime/stream.c +@@ -360,8 +360,8 @@ CheckFileChange(strm_t *pThis) + CHKiRet(strmSetCurrFName(pThis)); + if(stat((char*) pThis->pszCurrFName, &statName) == -1) + ABORT_FINALIZE(RS_RET_IO_ERROR); +- DBGPRINTF("stream/after deserialize checking for file change on '%s', " +- "inode %u/%u, size/currOffs %llu/%llu\n", ++ DBGPRINTF("CheckFileChange: stream/after deserialize checking for file change " ++ "on '%s', inode %u/%u, size/currOffs %llu/%llu\n", + pThis->pszCurrFName, (unsigned) pThis->inode, + (unsigned) statName.st_ino, + (long long unsigned) statName.st_size, +@@ -574,8 +574,8 @@ strmNextFile(strm_t *pThis) + * circumstances). So starting as of now, we only check the inode number and + * a file change is detected only if the inode changes. -- rgerhards, 2011-01-10 + */ +-static rsRetVal +-strmHandleEOFMonitor(strm_t *pThis) ++static rsRetVal ATTR_NONNULL() ++strmHandleEOFMonitor(strm_t *const pThis) + { + DEFiRet; + struct stat statName; +@@ -611,8 +611,8 @@ strmHandleEOFMonitor(strm_t *pThis) + * try to open the next one. + * rgerhards, 2008-02-13 + */ +-static rsRetVal +-strmHandleEOF(strm_t *pThis) ++static rsRetVal ATTR_NONNULL() ++strmHandleEOF(strm_t *const pThis) + { + DEFiRet; + +@@ -629,7 +629,13 @@ strmHandleEOF(strm_t *pThis) + CHKiRet(strmNextFile(pThis)); + break; + case STREAMTYPE_FILE_MONITOR: +- CHKiRet(strmHandleEOFMonitor(pThis)); ++ DBGOPRINT((obj_t*) pThis, "file '%s' (%d) EOF, rotationCheck %d\n", ++ pThis->pszCurrFName, pThis->fd, pThis->rotationCheck); ++ if(pThis->rotationCheck == STRM_ROTATION_DO_CHECK) { ++ CHKiRet(strmHandleEOFMonitor(pThis)); ++ } else { ++ ABORT_FINALIZE(RS_RET_EOF); ++ } + break; + } + +@@ -687,9 +693,6 @@ checkTruncation(strm_t *const pThis) + iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block"); + FINALIZE; + } +-dbgprintf("checkTruncation seek backwrds: %d\n", ret); +-currpos = lseek64(pThis->fd, 0, SEEK_CUR); +-dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek); + + const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax); + dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead); +@@ -861,7 +864,7 @@ static rsRetVal strmUnreadChar(strm_t *pThis, uchar c) + * a line, but following lines that are indented are part of the same log entry + */ + static rsRetVal +-strmReadLine(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF, ++strmReadLine(strm_t *const pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF, + uint32_t trimLineOverBytes, int64 *const strtOffs) + { + uchar c; +@@ -2147,14 +2150,25 @@ DEFpropSetMeth(strm, cryprov, cryprov_if_t*) + DEFpropSetMeth(strm, cryprovData, void*) + + /* sets timeout in seconds */ +-void ++void ATTR_NONNULL() + strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val) + { ++ ISOBJ_TYPE_assert(pThis, strm); + pThis->readTimeout = val; + } + +-static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val) ++void ATTR_NONNULL() ++strmSet_checkRotation(strm_t *const pThis, const int val) { ++ ISOBJ_TYPE_assert(pThis, strm); ++ assert(val == STRM_ROTATION_DO_CHECK || val == STRM_ROTATION_DO_NOT_CHECK); ++ pThis->rotationCheck = val; ++} ++ ++ ++static rsRetVal ATTR_NONNULL() ++strmSetbDeleteOnClose(strm_t *const pThis, const int val) + { ++ ISOBJ_TYPE_assert(pThis, strm); + pThis->bDeleteOnClose = val; + if(pThis->cryprov != NULL) { + pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose); +@@ -2162,15 +2176,19 @@ static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val) + return RS_RET_OK; + } + +-static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal) ++static rsRetVal ATTR_NONNULL() ++strmSetiMaxFiles(strm_t *const pThis, const int iNewVal) + { ++ ISOBJ_TYPE_assert(pThis, strm); + pThis->iMaxFiles = iNewVal; + pThis->iFileNumDigits = getNumberDigits(iNewVal); + return RS_RET_OK; + } + +-static rsRetVal strmSetFileNotFoundError(strm_t *pThis, int pFileNotFoundError) ++static rsRetVal ATTR_NONNULL() ++strmSetFileNotFoundError(strm_t *const pThis, const int pFileNotFoundError) + { ++ ISOBJ_TYPE_assert(pThis, strm); + pThis->fileNotFoundError = pFileNotFoundError; + return RS_RET_OK; + } +diff --git a/runtime/stream.h b/runtime/stream.h +index 7dc597ff5..e3d6c2372 100644 +--- a/runtime/stream.h ++++ b/runtime/stream.h +@@ -124,6 +124,7 @@ typedef struct strm_s { + ino_t inode; /* current inode for files being monitored (undefined else) */ + uchar *pszCurrFName; /* name of current file (if open) */ + uchar *pIOBuf; /* the iobuffer currently in use to gather data */ ++ char *pIOBuf_truncation; /* iobuffer used during trucation detection block re-reads */ + size_t iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */ + size_t iBufPtr; /* pointer into current buffer */ + int iUngetC; /* char set via UngetChar() call or -1 if none set */ + +diff --git a/runtime/stream.h b/runtime/stream.h +index e3d6c2372..f6f48378a 100644 +--- a/runtime/stream.h ++++ b/runtime/stream.h +@@ -91,6 +91,10 @@ typedef enum { /* when extending, do NOT change existing modes! */ + STREAMMODE_WRITE_APPEND = 4 + } strmMode_t; + ++/* settings for stream rotation (applies not to all processing modes!) */ ++#define STRM_ROTATION_DO_CHECK 0 ++#define STRM_ROTATION_DO_NOT_CHECK 1 ++ + #define STREAM_ASYNC_NUMBUFS 2 /* must be a power of 2 -- TODO: make configurable */ + /* The strm_t data structure */ + typedef struct strm_s { +@@ -114,6 +118,7 @@ typedef struct strm_s { + sbool bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */ + sbool bSync; /* sync this file after every write? */ + sbool bReopenOnTruncate; ++ int rotationCheck; /* rotation check mode */ + size_t sIOBufSize;/* size of IO buffer */ + uchar *pszDir; /* Directory */ + int lenDir; +@@ -234,5 +239,6 @@ void strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val); + const uchar * ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis); + const uchar * ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis); + int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis); ++void ATTR_NONNULL() strmSet_checkRotation(strm_t *const pThis, const int val); + + #endif /* #ifndef STREAM_H_INCLUDED */ diff --git a/SOURCES/rsyslog-8.37.0-rhbz1677037-short-offMsg-overrun-crash.patch b/SOURCES/rsyslog-8.37.0-rhbz1677037-short-offMsg-overrun-crash.patch new file mode 100644 index 0000000..c9f7455 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1677037-short-offMsg-overrun-crash.patch @@ -0,0 +1,86 @@ +From 1255a67fdec2fc44cd49b6ea8c463f4319910812 Mon Sep 17 00:00:00 2001 +From: Jiri Vymazal +Date: Wed, 27 Feb 2019 11:57:49 +0100 +Subject: [PATCH] Enlarged msg offset types for bigger structured messages + +using a large enough (dozens of kBs) structured message +it is possible to overflow the signed short type which leads +to rsyslog crash. +--- + runtime/msg.c | 12 ++++++------ + runtime/msg.h | 8 ++++---- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/runtime/msg.c b/runtime/msg.c +index b82c38b9ee..96306bbeab 100644 +--- a/runtime/msg.c ++++ b/runtime/msg.c +@@ -839,7 +839,7 @@ msgBaseConstruct(smsg_t **ppThis) + pM->iFacility = LOG_INVLD; + pM->iLenPROGNAME = -1; + pM->offAfterPRI = 0; +- pM->offMSG = -1; ++ pM->offMSG = 0; + pM->iProtocolVersion = 0; + pM->msgFlags = 0; + pM->iLenRawMsg = 0; +@@ -2167,7 +2167,7 @@ MsgSetFlowControlType(smsg_t * const pMsg, flowControl_t eFlowCtl) + * rgerhards, 2009-06-16 + */ + rsRetVal +-MsgSetAfterPRIOffs(smsg_t * const pMsg, short offs) ++MsgSetAfterPRIOffs(smsg_t * const pMsg, uint32_t offs) + { + assert(pMsg != NULL); + pMsg->offAfterPRI = offs; +@@ -2819,12 +2819,12 @@ void MsgSetHOSTNAME(smsg_t *pThis, const uchar* pszHOSTNAME, const int lenHOSTNA + * (exactly by one). This can happen if we have a message that does not + * contain any MSG part. + */ +-void MsgSetMSGoffs(smsg_t * const pMsg, short offs) ++void MsgSetMSGoffs(smsg_t * const pMsg, uint32_t offs) + { + ISOBJ_TYPE_assert(pMsg, msg); + pMsg->offMSG = offs; +- if(offs > pMsg->iLenRawMsg) { +- assert(offs - 1 == pMsg->iLenRawMsg); ++ if(offs > (uint32_t)pMsg->iLenRawMsg) { ++ assert((int)offs - 1 == pMsg->iLenRawMsg); + pMsg->iLenMSG = 0; + } else { + pMsg->iLenMSG = pMsg->iLenRawMsg - offs; +@@ -2920,7 +2920,7 @@ MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMs + memcpy(pThis->pszRawMsg, pszRawMsg, pThis->iLenRawMsg); + pThis->pszRawMsg[pThis->iLenRawMsg] = '\0'; /* this also works with truncation! */ + /* correct other information */ +- if(pThis->iLenRawMsg > pThis->offMSG) ++ if((uint32_t)pThis->iLenRawMsg > pThis->offMSG) + pThis->iLenMSG += deltaSize; + else + pThis->iLenMSG = 0; +diff --git a/runtime/msg.h b/runtime/msg.h +index 74439275b1..722cca6e8a 100644 +--- a/runtime/msg.h ++++ b/runtime/msg.h +@@ -67,8 +67,8 @@ struct msg { + sbool bParseSuccess; /* set to reflect state of last executed higher level parser */ + unsigned short iSeverity;/* the severity */ + unsigned short iFacility;/* Facility code */ +- short offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */ +- short offMSG; /* offset at which the MSG part starts in pszRawMsg */ ++ uint32_t offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */ ++ uint32_t offMSG; /* offset at which the MSG part starts in pszRawMsg */ + short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */ + int msgFlags; /* flags associated with this message */ + int iLenRawMsg; /* length of raw message */ +@@ -194,8 +194,8 @@ void MsgSetRcvFromStr(smsg_t *const pMsg, const uchar* pszRcvFrom, const int, pr + rsRetVal MsgSetRcvFromIP(smsg_t *pMsg, prop_t*); + rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp); + void MsgSetHOSTNAME(smsg_t *pMsg, const uchar* pszHOSTNAME, const int lenHOSTNAME); +-rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, short offs); +-void MsgSetMSGoffs(smsg_t *pMsg, short offs); ++rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, uint32_t offs); ++void MsgSetMSGoffs(smsg_t *pMsg, uint32_t offs); + void MsgSetRawMsgWOSize(smsg_t *pMsg, char* pszRawMsg); + void ATTR_NONNULL() MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMsg); + rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar* pszMSG, int lenMSG); diff --git a/SOURCES/rsyslog-8.37.0-rhbz1716867-imjournal-memleak.patch b/SOURCES/rsyslog-8.37.0-rhbz1716867-imjournal-memleak.patch new file mode 100644 index 0000000..56d414c --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1716867-imjournal-memleak.patch @@ -0,0 +1,60 @@ +From 920c28ff705aac74f389b4613815b14b9482e497 Mon Sep 17 00:00:00 2001 +From: Jiri Vymazal +Date: Mon, 21 Jan 2019 10:58:03 +0100 +Subject: [PATCH] Added missing free() calls of received journal cursor + +--- + plugins/imjournal/imjournal.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c +index a85e521003..f5c2be4b6e 100644 +--- a/plugins/imjournal/imjournal.c ++++ b/plugins/imjournal/imjournal.c +@@ -442,8 +437,7 @@ readjournal(void) + + if (cs.bWorkAroundJournalBug) { + /* save journal cursor (at this point we can be sure it is valid) */ +- sd_journal_get_cursor(j, &c); +- if (c) { ++ if (!sd_journal_get_cursor(j, &c)) { + free(last_cursor); + last_cursor = c; + } +@@ -470,6 +471,7 @@ persistJournalState(void) + } + } else { + int ret; ++ free(last_cursor); + if ((ret = sd_journal_get_cursor(j, &last_cursor))) { + LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed"); + ABORT_FINALIZE(RS_RET_ERR); +@@ -630,6 +632,7 @@ loadJournalState(void) + iRet = RS_RET_ERR; + } + } ++ free(tmp_cursor); + } + } else { + LogError(0, RS_RET_IO_ERROR, "imjournal: " +@@ -843,6 +846,7 @@ BEGINfreeCnf + free(cs.stateFile); + free(cs.usePid); + free(cs.dfltTag); ++ free(last_cursor); + statsobj.Destruct(&(statsCounter.stats)); + ENDfreeCnf + +diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c +index f5c2be4b6e..7225fae1ab 100644 +--- a/plugins/imjournal/imjournal.c ++++ b/plugins/imjournal/imjournal.c +@@ -474,6 +474,7 @@ persistJournalState(void) + free(last_cursor); + if ((ret = sd_journal_get_cursor(j, &last_cursor))) { + LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed"); ++ last_cursor = NULL; + ABORT_FINALIZE(RS_RET_ERR); + } + } + diff --git a/SOURCES/rsyslog-8.37.0-rhbz1722165-imjournal-flooding-errors.patch b/SOURCES/rsyslog-8.37.0-rhbz1722165-imjournal-flooding-errors.patch new file mode 100644 index 0000000..35f2185 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1722165-imjournal-flooding-errors.patch @@ -0,0 +1,136 @@ +From 9c22b31cd639911a2faffad02f2ed9f7cc10b9e1 Mon Sep 17 00:00:00 2001 +From: Jiri Vymazal +Date: Fri, 15 Mar 2019 09:29:04 +0100 +Subject: [PATCH] Fetching journal cursor only for valid journal + +The sd_journal_get_cursor() got called regradless of previous +retcodes from other jorunal calls which flooded logs with journald +errors. Now skipping the call in case of previous journal call +non-zero result. Fixed success checking of get_cursor() call +to eliminate double-free possibility. + +Also, making WorkAroundJournalBug true by default, as there were no +confirmed performance regressions for a quite long time. +--- + plugins/imjournal/imjournal.c | 43 ++++++++++++++++++++++------------ + 1 file changed, 28 insertions(+), 15 deletions(-) + +diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c +index 7225fae1ab..5419762cf1 100644 +--- a/plugins/imjournal/imjournal.c ++++ b/plugins/imjournal/imjournal.c +@@ -135,7 +135,7 @@ static char *last_cursor = NULL; + + #define J_PROCESS_PERIOD 1024 /* Call sd_journal_process() every 1,024 records */ + +-static rsRetVal persistJournalState(void); ++static rsRetVal persistJournalState(int trySave); + static rsRetVal loadJournalState(void); + + static rsRetVal openJournal(void) { +@@ -158,9 +158,9 @@ static rsRetVal openJournal(void) { + RETiRet; + } + +-static void closeJournal(void) { ++static void closeJournal(int trySave) { + if (cs.stateFile) { /* can't persist without a state file */ +- persistJournalState(); ++ persistJournalState(trySave); + } + sd_journal_close(j); + j_inotify_fd = 0; +@@ -461,7 +461,7 @@ readjournal(void) + /* This function gets journal cursor and saves it into state file + */ + static rsRetVal +-persistJournalState(void) ++persistJournalState(int trySave) + { + DEFiRet; + FILE *sf; /* state file */ +@@ -469,7 +470,7 @@ persistJournalState(void) + if (!last_cursor) { + ABORT_FINALIZE(RS_RET_OK); + } +- } else { ++ } else if (trySave) { + int ret; + free(last_cursor); + if ((ret = sd_journal_get_cursor(j, &last_cursor))) { +@@ -477,6 +478,8 @@ persistJournalState(void) + last_cursor = NULL; + ABORT_FINALIZE(RS_RET_ERR); + } ++ } else { /* not trying to get cursor out of invalid journal state */ ++ ABORT_FINALIZE(RS_RET_OK); + } + + /* we create a temporary name by adding a ".tmp" +@@ -535,14 +535,24 @@ pollJournal(void) + err = sd_journal_wait(j, POLL_TIMEOUT); + if (err == SD_JOURNAL_INVALIDATE) { + STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations); +- closeJournal(); ++ closeJournal(0); + + iRet = openJournal(); + if (iRet != RS_RET_OK) { + ABORT_FINALIZE(RS_RET_ERR); + } + +- if (cs.stateFile) { ++ /* If we have locally saved cursor there is no need to read it from state file */ ++ if (cs.bWorkAroundJournalBug && last_cursor) ++ { ++ if (sd_journal_seek_cursor(j, last_cursor) != 0) { ++ LogError(0, RS_RET_ERR, "imjournal: " ++ "couldn't seek to cursor `%s'\n", last_cursor); ++ iRet = RS_RET_ERR; ++ } ++ sd_journal_next(j); ++ } ++ else if (cs.stateFile) { + iRet = loadJournalState(); + } + LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal reloaded..."); +@@ -668,10 +680,9 @@ loadJournalState(void) + + static void + tryRecover(void) { +- LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from unexpected " +- "journal error"); ++ LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from journal error"); + STATSCOUNTER_INC(statsCounter.ctrRecoveryAttempts, statsCounter.mutCtrRecoveryAttempts); +- closeJournal(); ++ closeJournal(0); + srSleep(10, 0); // do not hammer machine with too-frequent retries + openJournal(); + } +@@ -768,7 +779,7 @@ CODESTARTrunInput + if (cs.stateFile) { /* can't persist without a state file */ + /* TODO: This could use some finer metric. */ + if ((count % cs.iPersistStateInterval) == 0) { +- persistJournalState(); ++ persistJournalState(1); + } + } + } +@@ -790,7 +801,7 @@ CODESTARTbeginCnfLoad + cs.iDfltFacility = DFLT_FACILITY; + cs.bUseJnlPID = -1; + cs.usePid = NULL; +- cs.bWorkAroundJournalBug = 0; ++ cs.bWorkAroundJournalBug = 1; + cs.dfltTag = NULL; + ENDbeginCnfLoad + +@@ -860,7 +871,7 @@ ENDwillRun + /* close journal */ + BEGINafterRun + CODESTARTafterRun +- closeJournal(); ++ closeJournal(1); + ratelimitDestruct(ratelimiter); + ENDafterRun + diff --git a/SOURCES/rsyslog-8.37.0-rhbz1724218-imrelp-old-syntax.patch b/SOURCES/rsyslog-8.37.0-rhbz1724218-imrelp-old-syntax.patch new file mode 100644 index 0000000..1ad9dc3 --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1724218-imrelp-old-syntax.patch @@ -0,0 +1,28 @@ +From f53977817f352ef1c67178687cbfcee849f667fc Mon Sep 17 00:00:00 2001 +From: Andre Lorbach +Date: Tue, 9 Oct 2018 14:31:52 +0200 +Subject: [PATCH] imrelp: Fixed issue with oldstyle configuration caused by + commit: + +https://github.com/rsyslog/rsyslog/commit/32b71daa8aadb8f16fe0ca2945e54d593f47a824 + +Fixed by setting bEnableLstn in addInstance(). + +Closes https://github.com/rsyslog/rsyslog/issues/3106 +--- + plugins/imrelp/imrelp.c | 2 ++ + 1 files changed, 2 insertions(+) + +diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c +index c2134e5165..076dd64900 100644 +--- a/plugins/imrelp/imrelp.c ++++ b/plugins/imrelp/imrelp.c +@@ -346,6 +346,8 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) + CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset)); + } + inst->pBindRuleset = NULL; ++ ++ inst->bEnableLstn = -1; /* all ok, ready to start up */ + finalize_it: + free(pNewVal); + RETiRet; diff --git a/SOURCES/rsyslog-8.37.0-rhbz1733244-TLS-CC-compatibility.patch b/SOURCES/rsyslog-8.37.0-rhbz1733244-TLS-CC-compatibility.patch new file mode 100644 index 0000000..5dc9d7f --- /dev/null +++ b/SOURCES/rsyslog-8.37.0-rhbz1733244-TLS-CC-compatibility.patch @@ -0,0 +1,618 @@ +From b15e6ab7242b25311a9e0dcf14187d21a80a44a6 Mon Sep 17 00:00:00 2001 +From: Jiri Vymazal +Date: Fri, 16 Aug 2019 15:01:11 +0200 +Subject: [PATCH] Stricter GnuTLS operation + +This commit adds to new flags which can be set to allow +1) checking of extendedKeyUsage certificate field +2) stricter checking of certificate name/adresses +--- + plugins/imtcp/imtcp.c | 12 +++++++ + runtime/netstrm.c | 22 +++++++++++++ + runtime/netstrm.h | 5 ++- + runtime/netstrms.c | 47 +++++++++++++++++++++++++++ + runtime/netstrms.h | 6 ++++ + runtime/nsd.h | 7 ++-- + runtime/nsd_gtls.c | 74 ++++++++++++++++++++++++++++++++++++++++--- + runtime/nsd_gtls.h | 12 +++++++ + runtime/nsd_ossl.c | 36 +++++++++++++++++++++ + runtime/nsd_ptcp.c | 35 ++++++++++++++++++++ + runtime/tcpsrv.c | 24 ++++++++++++++ + runtime/tcpsrv.h | 7 +++- + tools/omfwd.c | 12 +++++++ + 13 files changed, 291 insertions(+), 8 deletions(-) + +diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c +index 55245842d5..6b3401f8fe 100644 +--- a/plugins/imtcp/imtcp.c ++++ b/plugins/imtcp/imtcp.c +@@ -131,6 +131,8 @@ struct modConfData_s { + int iTCPSessMax; /* max number of sessions */ + int iTCPLstnMax; /* max number of sessions */ + int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */ ++ int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */ ++ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */ + int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */ + int maxFrameSize; + int bSuppOctetFram; +@@ -170,6 +172,8 @@ static struct cnfparamdescr modpdescr[] = { + { "streamdriver.mode", eCmdHdlrNonNegInt, 0 }, + { "streamdriver.authmode", eCmdHdlrString, 0 }, + { "streamdriver.name", eCmdHdlrString, 0 }, ++ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 }, ++ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 }, + { "permittedpeer", eCmdHdlrArray, 0 }, + { "keepalive", eCmdHdlrBinary, 0 }, + { "keepalive.probes", eCmdHdlrPositiveInt, 0 }, +@@ -368,6 +372,8 @@ addListner(modConfData_t *modConf, instanceConf_t *inst) + CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, modConf->iTCPSessMax)); + CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, modConf->iTCPLstnMax)); + CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, modConf->iStrmDrvrMode)); ++ CHKiRet(tcpsrv.SetDrvrCheckExtendedKeyUsage(pOurTcpsrv, modConf->iStrmDrvrExtendedCertCheck)); ++ CHKiRet(tcpsrv.SetDrvrPrioritizeSAN(pOurTcpsrv, modConf->iStrmDrvrSANPreference)); + CHKiRet(tcpsrv.SetUseFlowControl(pOurTcpsrv, modConf->bUseFlowControl)); + CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, modConf->iAddtlFrameDelim)); + CHKiRet(tcpsrv.SetMaxFrameSize(pOurTcpsrv, modConf->maxFrameSize)); +@@ -479,6 +485,8 @@ CODESTARTbeginCnfLoad + loadModConf->iTCPLstnMax = 20; + loadModConf->bSuppOctetFram = 1; + loadModConf->iStrmDrvrMode = 0; ++ loadModConf->iStrmDrvrExtendedCertCheck = 0; ++ loadModConf->iStrmDrvrSANPreference = 0; + loadModConf->bUseFlowControl = 1; + loadModConf->bKeepAlive = 0; + loadModConf->iKeepAliveIntvl = 0; +@@ -560,6 +568,10 @@ CODESTARTsetModCnf + loadModConf->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(modpblk.descr[i].name, "streamdriver.mode")) { + loadModConf->iStrmDrvrMode = (int) pvals[i].val.d.n; ++ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) { ++ loadModConf->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n; ++ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.PrioritizeSAN")) { ++ loadModConf->iStrmDrvrSANPreference = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "streamdriver.authmode")) { + loadModConf->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(modpblk.descr[i].name, "streamdriver.name")) { +diff --git a/runtime/netstrm.c b/runtime/netstrm.c +index e1df83edee..59aa135997 100644 +--- a/runtime/netstrm.c ++++ b/runtime/netstrm.c +@@ -221,6 +221,26 @@ SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers) + RETiRet; + } + ++/* Mandate also verification of Extended key usage / purpose field */ ++static rsRetVal ++SetDrvrCheckExtendedKeyUsage(netstrm_t *pThis, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, netstrm); ++ iRet = pThis->Drvr.SetCheckExtendedKeyUsage(pThis->pDrvrData, ChkExtendedKeyUsage); ++ RETiRet; ++} ++ ++/* Mandate stricter name checking per RFC 6125 - ignoce CN if any SAN present */ ++static rsRetVal ++SetDrvrPrioritizeSAN(netstrm_t *pThis, int prioritizeSan) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, netstrm); ++ iRet = pThis->Drvr.SetPrioritizeSAN(pThis->pDrvrData, prioritizeSan); ++ RETiRet; ++} ++ + + /* End of methods to shuffle autentication settings to the driver. + * -------------------------------------------------------------------------- */ +@@ -405,6 +425,8 @@ CODESTARTobjQueryInterface(netstrm) + pIf->SetKeepAliveTime = SetKeepAliveTime; + pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; + pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; ++ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; ++ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; + finalize_it: + ENDobjQueryInterface(netstrm) + +diff --git a/runtime/netstrm.h b/runtime/netstrm.h +index 113585d0a5..08b58fd119 100644 +--- a/runtime/netstrm.h ++++ b/runtime/netstrm.h +@@ -78,8 +78,11 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */ + rsRetVal (*SetKeepAliveTime)(netstrm_t *pThis, int keepAliveTime); + rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl); + rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString); ++ /* v12 -- two new binary flags added to gtls driver enabling stricter operation */ ++ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrm_t *pThis, int ChkExtendedKeyUsage); ++ rsRetVal (*SetDrvrPrioritizeSAN)(netstrm_t *pThis, int prioritizeSan); + ENDinterface(netstrm) +-#define netstrmCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */ ++#define netstrmCURR_IF_VERSION 12 /* increment whenever you change the interface structure! */ + /* interface version 3 added GetRemAddr() + * interface version 4 added EnableKeepAlive() -- rgerhards, 2009-06-02 + * interface version 5 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06 +diff --git a/runtime/netstrms.c b/runtime/netstrms.c +index bd6a06bd7f..a8c342b76b 100644 +--- a/runtime/netstrms.c ++++ b/runtime/netstrms.c +@@ -279,6 +279,49 @@ GetDrvrMode(netstrms_t *pThis) + } + + ++/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */ ++static rsRetVal ++SetDrvrCheckExtendedKeyUsage(netstrms_t *pThis, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, netstrms); ++ pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage; ++ RETiRet; ++} ++ ++ ++/* return the driver cert extended key usage check setting ++ * jvymazal, 2019-08-16 ++ */ ++static int ++GetDrvrCheckExtendedKeyUsage(netstrms_t *pThis) ++{ ++ ISOBJ_TYPE_assert(pThis, netstrms); ++ return pThis->DrvrChkExtendedKeyUsage; ++} ++ ++ ++/* set the driver name checking policy -- jvymazal, 2019-08-16 */ ++static rsRetVal ++SetDrvrPrioritizeSAN(netstrms_t *pThis, int prioritizeSan) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, netstrms); ++ pThis->DrvrPrioritizeSan = prioritizeSan; ++ RETiRet; ++} ++ ++ ++/* return the driver name checking policy ++ * jvymazal, 2019-08-16 ++ */ ++static int ++GetDrvrPrioritizeSAN(netstrms_t *pThis) ++{ ++ ISOBJ_TYPE_assert(pThis, netstrms); ++ return pThis->DrvrPrioritizeSan; ++} ++ + /* create an instance of a netstrm object. It is initialized with default + * values. The current driver is used. The caller may set netstrm properties + * and must call ConstructFinalize(). +@@ -337,6 +380,10 @@ CODESTARTobjQueryInterface(netstrms) + pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString; + pIf->SetDrvrPermPeers = SetDrvrPermPeers; + pIf->GetDrvrPermPeers = GetDrvrPermPeers; ++ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; ++ pIf->GetDrvrCheckExtendedKeyUsage = GetDrvrCheckExtendedKeyUsage; ++ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; ++ pIf->GetDrvrPrioritizeSAN = GetDrvrPrioritizeSAN; + finalize_it: + ENDobjQueryInterface(netstrms) + +diff --git a/runtime/netstrms.h b/runtime/netstrms.h +index 440beb20c9..f21bd6a8e2 100644 +--- a/runtime/netstrms.h ++++ b/runtime/netstrms.h +@@ -33,6 +33,8 @@ struct netstrms_s { + uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */ + int iDrvrMode; /**< current default driver mode */ + uchar *pszDrvrAuthMode; /**< current driver authentication mode */ ++ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */ ++ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */ + uchar *gnutlsPriorityString; /**< priorityString for connection */ + permittedPeers_t *pPermPeers;/**< current driver's permitted peers */ + +@@ -58,6 +60,10 @@ BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */ + permittedPeers_t* (*GetDrvrPermPeers)(netstrms_t *pThis); + rsRetVal (*SetDrvrGnutlsPriorityString)(netstrms_t *pThis, uchar*); + uchar* (*GetDrvrGnutlsPriorityString)(netstrms_t *pThis); ++ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis, int ChkExtendedKeyUsage); ++ int (*GetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis); ++ rsRetVal (*SetDrvrPrioritizeSAN)(netstrms_t *pThis, int prioritizeSan); ++ int (*GetDrvrPrioritizeSAN)(netstrms_t *pThis); + ENDinterface(netstrms) + #define netstrmsCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ + +diff --git a/runtime/nsd.h b/runtime/nsd.h +index eab53ad6ae..f0cb5bd1aa 100644 +--- a/runtime/nsd.h ++++ b/runtime/nsd.h +@@ -85,8 +85,11 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */ + rsRetVal (*SetKeepAliveProbes)(nsd_t *pThis, int keepAliveProbes); + rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime); + rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString); ++ /* v13 -- two new binary flags added to gtls driver enabling stricter operation */ ++ rsRetVal (*SetCheckExtendedKeyUsage)(nsd_t *pThis, int ChkExtendedKeyUsage); ++ rsRetVal (*SetPrioritizeSAN)(nsd_t *pThis, int prioritizeSan); + ENDinterface(nsd) +-#define nsdCURR_IF_VERSION 11 /* increment whenever you change the interface structure! */ ++#define nsdCURR_IF_VERSION 13 /* increment whenever you change the interface structure! */ + /* interface version 4 added GetRemAddr() + * interface version 5 added EnableKeepAlive() -- rgerhards, 2009-06-02 + * interface version 6 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06 +diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c +index 56238b9cb4..a3662bedf4 100644 +--- a/runtime/nsd_gtls.c ++++ b/runtime/nsd_gtls.c +@@ -1004,6 +1004,7 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert) + int iAltName; + size_t szAltNameLen; + int bFoundPositiveMatch; ++ int bHaveSAN = 0; + cstr_t *pStr = NULL; + cstr_t *pstrCN = NULL; + int gnuRet; +@@ -1023,6 +1024,7 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert) + if(gnuRet < 0) + break; + else if(gnuRet == GNUTLS_SAN_DNSNAME) { ++ bHaveSAN = 1; + dbgprintf("subject alt dnsName: '%s'\n", szAltName); + snprintf((char*)lnBuf, sizeof(lnBuf), "DNSname: %s; ", szAltName); + CHKiRet(rsCStrAppendStr(pStr, lnBuf)); +@@ -1032,8 +1034,8 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert) + ++iAltName; + } + +- if(!bFoundPositiveMatch) { +- /* if we did not succeed so far, we try the CN part of the DN... */ ++ /* Check also CN only if not configured per stricter RFC 6125 or no SAN present*/ ++ if(!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) { + CHKiRet(gtlsGetCN(pCert, &pstrCN)); + if(pstrCN != NULL) { /* NULL if there was no CN present */ + dbgprintf("gtls now checking auth for CN '%s'\n", cstrGetSzStrNoNULL(pstrCN)); +@@ -1044,7 +1044,19 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis) + ABORT_FINALIZE(RS_RET_TLS_NO_CERT); + } + +- CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert)); ++ if (pThis->dataTypeCheck == GTLS_NONE) { ++ CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert)); ++ } else { /* we have configured data to check in addition to cert */ ++ gnutls_typed_vdata_st data; ++ data.type = GNUTLS_DT_KEY_PURPOSE_OID; ++ if (pThis->bIsInitiator) { /* client mode */ ++ data.data = (uchar *)GNUTLS_KP_TLS_WWW_SERVER; ++ } else { /* server mode */ ++ data.data = (uchar *)GNUTLS_KP_TLS_WWW_CLIENT; ++ } ++ data.size = ustrlen(data.data); ++ CHKgnutls(gnutls_certificate_verify_peers(pThis->sess, &data, 1, &stateCert)); ++ } + + if(stateCert & GNUTLS_CERT_INVALID) { + /* provide error details if we have them */ +@@ -1188,6 +1205,8 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis) + pszErrCause = "insecure algorithm"; + } else if(stateCert & GNUTLS_CERT_REVOKED) { + pszErrCause = "certificate revoked"; ++ } else if(stateCert & GNUTLS_CERT_PURPOSE_MISMATCH) { ++ pszErrCause = "key purpose OID does not match"; + } else { + pszErrCause = "GnuTLS returned no specific reason"; + dbgprintf("GnuTLS returned no specific reason for GNUTLS_CERT_INVALID, certificate " +@@ -1499,6 +1516,53 @@ SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString) + RETiRet; + } + ++/* Set the driver cert extended key usage check setting ++ * 0 - ignore contents of extended key usage ++ * 1 - verify that cert contents is compatible with appropriate OID ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetCheckExtendedKeyUsage(nsd_t *pNsd, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; ++ ++ ISOBJ_TYPE_assert((pThis), nsd_gtls); ++ if(ChkExtendedKeyUsage != 0 && ChkExtendedKeyUsage != 1) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " ++ "not supported by gtls netstream driver", ChkExtendedKeyUsage); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++ ++ pThis->dataTypeCheck = ChkExtendedKeyUsage; ++ ++finalize_it: ++ RETiRet; ++} ++ ++/* Set the driver name checking strictness ++ * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good ++ * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored) ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan) ++{ ++ DEFiRet; ++ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; ++ ++ ISOBJ_TYPE_assert((pThis), nsd_gtls); ++ if(prioritizeSan != 0 && prioritizeSan != 1) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " ++ "not supported by gtls netstream driver", prioritizeSan); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++ ++ pThis->bSANpriority = prioritizeSan; ++ ++finalize_it: ++ RETiRet; ++} + + /* Provide access to the underlying OS socket. This is primarily + * useful for other drivers (like nsd_gtls) who utilize ourselfs +@@ -2124,6 +2188,8 @@ CODESTARTobjQueryInterface(nsd_gtls) + pIf->SetKeepAliveProbes = SetKeepAliveProbes; + pIf->SetKeepAliveTime = SetKeepAliveTime; + pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; ++ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; ++ pIf->SetPrioritizeSAN = SetPrioritizeSAN; + finalize_it: + ENDobjQueryInterface(nsd_gtls) + +diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h +index 80a86f21d7..d73c0e6a4d 100644 +--- a/runtime/nsd_gtls.h ++++ b/runtime/nsd_gtls.h +@@ -54,6 +54,11 @@ struct nsd_gtls_s { + GTLS_AUTH_CERTVALID = 2, + GTLS_AUTH_CERTANON = 3 + } authMode; ++ enum { ++ GTLS_NONE = 0, ++ GTLS_PURPOSE = 1 ++ } dataTypeCheck; ++ int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not cehck CN) */ + gtlsRtryCall_t rtryCall;/**< what must we retry? */ + int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */ + gnutls_session_t sess; +diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c +index 0a474fd744..419e0e97ef 100644 +--- a/runtime/nsd_ossl.c ++++ b/runtime/nsd_ossl.c +@@ -1864,6 +1864,40 @@ SetGnutlsPriorityString(__attribute__((unused)) nsd_t *pNsd, __attribute__((unus + RETiRet; + } + ++/* Set the driver cert extended key usage check setting, for now it is empty wrapper. ++ * TODO: implement openSSL version ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ if(ChkExtendedKeyUsage != 0) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " ++ "not supported by ossl netstream driver", ChkExtendedKeyUsage); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++finalize_it: ++ RETiRet; ++} ++ ++/* Set the driver name checking strictness, for now it is empty wrapper. ++ * TODO: implement openSSL version ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan) ++{ ++ DEFiRet; ++ if(prioritizeSan != 0) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " ++ "not supported by ossl netstream driver", prioritizeSan); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++finalize_it: ++ RETiRet; ++} ++ + /* queryInterface function */ + BEGINobjQueryInterface(nsd_ossl) + CODESTARTobjQueryInterface(nsd_ossl) +@@ -1898,6 +1932,8 @@ CODESTARTobjQueryInterface(nsd_ossl) + pIf->SetKeepAliveProbes = SetKeepAliveProbes; + pIf->SetKeepAliveTime = SetKeepAliveTime; + pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; /* we don't NEED this interface! */ ++ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; /* we don't NEED this interface! */ ++ pIf->SetPrioritizeSAN = SetPrioritizeSAN; /* we don't NEED this interface! */ + + finalize_it: + ENDobjQueryInterface(nsd_ossl) +diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c +index 68bed5b9ea..60c40ad444 100644 +--- a/runtime/nsd_ptcp.c ++++ b/runtime/nsd_ptcp.c +@@ -150,6 +150,37 @@ SetMode(nsd_t __attribute__((unused)) *pNsd, int mode) + RETiRet; + } + ++/* Set the driver cert extended key usage check setting, not supported in ptcp. ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ if(ChkExtendedKeyUsage != 0) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " ++ "not supported by ptcp netstream driver", ChkExtendedKeyUsage); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++finalize_it: ++ RETiRet; ++} ++ ++/* Set the driver name checking strictness, not supported in ptcp. ++ * jvymazal, 2019-08-16 ++ */ ++static rsRetVal ++SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan) ++{ ++ DEFiRet; ++ if(prioritizeSan != 0) { ++ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " ++ "not supported by ptcp netstream driver", prioritizeSan); ++ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); ++ } ++finalize_it: ++ RETiRet; ++} + + /* Set the authentication mode. For us, the following is supported: + * anon - no certificate checks whatsoever (discouraged, but supported) +@@ -613,6 +644,8 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*), + CHKiRet(pNS->Drvr.Construct(&pNewNsd)); + CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock)); + CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS))); ++ CHKiRet(pNS->Drvr.SetCheckExtendedKeyUsage(pNewNsd, netstrms.GetDrvrCheckExtendedKeyUsage(pNS))); ++ CHKiRet(pNS->Drvr.SetPrioritizeSAN(pNewNsd, netstrms.GetDrvrPrioritizeSAN(pNS))); + CHKiRet(pNS->Drvr.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS))); + CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS))); + CHKiRet(pNS->Drvr.SetGnutlsPriorityString(pNewNsd, netstrms.GetDrvrGnutlsPriorityString(pNS))); +@@ -963,6 +996,8 @@ CODESTARTobjQueryInterface(nsd_ptcp) + pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; + pIf->SetKeepAliveProbes = SetKeepAliveProbes; + pIf->SetKeepAliveTime = SetKeepAliveTime; ++ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; ++ pIf->SetPrioritizeSAN = SetPrioritizeSAN; + finalize_it: + ENDobjQueryInterface(nsd_ptcp) + +diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c +index d7ea2f9f00..43a6687b4a 100644 +--- a/runtime/tcpsrv.c ++++ b/runtime/tcpsrv.c +@@ -1013,6 +1013,8 @@ tcpsrvConstructFinalize(tcpsrv_t *pThis) + if(pThis->pszDrvrName != NULL) + CHKiRet(netstrms.SetDrvrName(pThis->pNS, pThis->pszDrvrName)); + CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode)); ++ CHKiRet(netstrms.SetDrvrCheckExtendedKeyUsage(pThis->pNS, pThis->DrvrChkExtendedKeyUsage)); ++ CHKiRet(netstrms.SetDrvrPrioritizeSAN(pThis->pNS, pThis->DrvrPrioritizeSan)); + if(pThis->pszDrvrAuthMode != NULL) + CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode)); + if(pThis->pPermPeers != NULL) +@@ -1405,6 +1407,26 @@ SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers) + RETiRet; + } + ++/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */ ++static rsRetVal ++SetDrvrCheckExtendedKeyUsage(tcpsrv_t *pThis, int ChkExtendedKeyUsage) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, tcpsrv); ++ pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage; ++ RETiRet; ++} ++ ++/* set the driver name checking policy -- jvymazal, 2019-08-16 */ ++static rsRetVal ++SetDrvrPrioritizeSAN(tcpsrv_t *pThis, int prioritizeSan) ++{ ++ DEFiRet; ++ ISOBJ_TYPE_assert(pThis, tcpsrv); ++ pThis->DrvrPrioritizeSan = prioritizeSan; ++ RETiRet; ++} ++ + + /* End of methods to shuffle autentication settings to the driver.; + +@@ -1522,6 +1544,8 @@ CODESTARTobjQueryInterface(tcpsrv) + pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters; + pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose; + pIf->SetPreserveCase = SetPreserveCase; ++ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; ++ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; + + finalize_it: + ENDobjQueryInterface(tcpsrv) +diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h +index 55aa8e9922..79b659013d 100644 +--- a/runtime/tcpsrv.h ++++ b/runtime/tcpsrv.h +@@ -61,6 +61,8 @@ struct tcpsrv_s { + int iKeepAliveTime; /**< socket layer KEEPALIVE timeout */ + netstrms_t *pNS; /**< pointer to network stream subsystem */ + int iDrvrMode; /**< mode of the stream driver to use */ ++ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */ ++ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */ + uchar *gnutlsPriorityString; /**< priority string for gnutls */ + uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */ + uchar *pszDrvrName; /**< name of stream driver to use */ +@@ -185,8 +187,11 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ + rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*); + /* added v21 -- Preserve case in fromhost, 2018-08-16 */ + rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase); ++ /* added v23 -- Options for stricter driver behavior, 2019-08-16 */ ++ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(tcpsrv_t *pThis, int ChkExtendedKeyUsage); ++ rsRetVal (*SetDrvrPrioritizeSAN)(tcpsrv_t *pThis, int prioritizeSan); + ENDinterface(tcpsrv) +-#define tcpsrvCURR_IF_VERSION 21 /* increment whenever you change the interface structure! */ ++#define tcpsrvCURR_IF_VERSION 23 /* increment whenever you change the interface structure! */ + /* change for v4: + * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10 + * - SetInputName() added -- rgerhards, 2008-12-10 +diff --git a/tools/omfwd.c b/tools/omfwd.c +index cdb74b8d22..96fa68752c 100644 +--- a/tools/omfwd.c ++++ b/tools/omfwd.c +@@ -83,6 +83,8 @@ typedef struct _instanceData { + uchar *pszStrmDrvrAuthMode; + permittedPeers_t *pPermPeers; + int iStrmDrvrMode; ++ int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */ ++ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */ + char *target; + char *address; + char *device; +@@ -189,6 +191,8 @@ static struct cnfparamdescr actpdescr[] = { + { "streamdrivermode", eCmdHdlrInt, 0 }, + { "streamdriverauthmode", eCmdHdlrGetWord, 0 }, + { "streamdriverpermittedpeers", eCmdHdlrGetWord, 0 }, ++ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 }, ++ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 }, + { "resendlastmsgonreconnect", eCmdHdlrBinary, 0 }, + { "udp.sendtoall", eCmdHdlrBinary, 0 }, + { "udp.senddelay", eCmdHdlrInt, 0 }, +@@ -748,6 +752,8 @@ static rsRetVal TCPSendInit(void *pvData) + CHKiRet(netstrms.CreateStrm(pWrkrData->pNS, &pWrkrData->pNetstrm)); + CHKiRet(netstrm.ConstructFinalize(pWrkrData->pNetstrm)); + CHKiRet(netstrm.SetDrvrMode(pWrkrData->pNetstrm, pData->iStrmDrvrMode)); ++ CHKiRet(netstrm.SetDrvrCheckExtendedKeyUsage(pWrkrData->pNetstrm, pData->iStrmDrvrExtendedCertCheck)); ++ CHKiRet(netstrm.SetDrvrPrioritizeSAN(pWrkrData->pNetstrm, pData->iStrmDrvrSANPreference)); + /* now set optional params, but only if they were actually configured */ + if(pData->pszStrmDrvrAuthMode != NULL) { + CHKiRet(netstrm.SetDrvrAuthMode(pWrkrData->pNetstrm, pData->pszStrmDrvrAuthMode)); +@@ -1119,6 +1125,8 @@ setInstParamDefaults(instanceData *pData) + pData->pszStrmDrvr = NULL; + pData->pszStrmDrvrAuthMode = NULL; + pData->iStrmDrvrMode = 0; ++ pData->iStrmDrvrExtendedCertCheck = 0; ++ pData->iStrmDrvrSANPreference = 0; + pData->iRebindInterval = 0; + pData->bKeepAlive = 0; + pData->iKeepAliveProbes = 0; +@@ -1220,6 +1228,10 @@ CODESTARTnewActInst + pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) { + pData->iStrmDrvrMode = pvals[i].val.d.n; ++ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) { ++ pData->iStrmDrvrExtendedCertCheck = pvals[i].val.d.n; ++ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.PrioritizeSAN")) { ++ pData->iStrmDrvrSANPreference = pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "streamdriverauthmode")) { + pData->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(actpblk.descr[i].name, "streamdriverpermittedpeers")) { diff --git a/SPECS/rsyslog.spec b/SPECS/rsyslog.spec index b1e9b23..3aafa6b 100644 --- a/SPECS/rsyslog.spec +++ b/SPECS/rsyslog.spec @@ -6,7 +6,7 @@ Summary: Enhanced system logging and kernel message trapping daemon Name: rsyslog Version: 8.37.0 -Release: 9%{?dist} +Release: 13%{?dist} License: (GPLv3+ and ASL 2.0) Group: System Environment/Daemons ExcludeArch: i686 @@ -49,6 +49,14 @@ Patch0: rsyslog-8.32.0-service.patch Patch1: rsyslog-8.37.0-rhbz1659898-imjournal-default-tag.patch Patch2: rsyslog-8.37.0-rhbz1614179-imfile-symlink-support.patch Patch3: rsyslog-8.37.0-rhbz1622768-kubernetes-404-handling.patch +Patch4: rsyslog-8.37.0-rhbz1627941-imfile-support-for-endmsg.regex.patch +Patch5: rsyslog-8.37.0-rhbz1674471-imfile-log-rotation.patch +Patch6: rsyslog-8.37.0-rhbz1677037-short-offMsg-overrun-crash.patch +Patch7: rsyslog-8.37.0-rhbz1614181-imtcp-imudp-preservecase-option.patch +Patch8: rsyslog-8.37.0-rhbz1716867-imjournal-memleak.patch +Patch9: rsyslog-8.37.0-rhbz1722165-imjournal-flooding-errors.patch +Patch10: rsyslog-8.37.0-rhbz1724218-imrelp-old-syntax.patch +Patch11: rsyslog-8.37.0-rhbz1733244-TLS-CC-compatibility.patch %package crypto Summary: Encryption support @@ -224,6 +232,14 @@ mv build doc %patch1 -p1 -b .default-tag %patch2 -p1 -b .imfile-symlink %patch3 -p1 -b .mmkubernetes-404 +%patch4 -p1 -b .endmsg-regex +%patch5 -p1 -b .rotation-detection +%patch6 -p1 -b .short-offmsg-crash +%patch7 -p1 -b .preservecase-option +%patch8 -p1 -b .imjournal-memleak +%patch9 -p1 -b .imjournal-err-flood +%patch10 -p1 -b .imrelp-old-syntax +%patch11 -p1 -b .tls-CC %build %ifarch sparc64 @@ -427,6 +443,39 @@ done %changelog +* Fri Aug 30 2019 Jiri Vymazal - 8.37.0-13 + RHEL 8.1.0 ERRATUM +- added patch enabling stricter TLS certs checking conforming to + common criteria requirements + resolves: rhbz#1733244 + +* Mon Jul 22 2019 Jiri Vymazal - 8.37.0-12 + RHEL 8.1.0 ERRATUM +- edited imjournal memleak patch to not cause double-free crash + resolves: rhbz#1729995 +- added patch calling journald API only when there are no + preceeding errors + resolves: rhbz#1722165 +- added patch fixing imrelp module when invoked with old syntax + resolves: rhbz#1724218 + +* Wed Jun 05 2019 Jiri Vymazal - 8.37.0-11 + RHEL 8.1.0 ERRATUM +- fixed memory leak in imjournal by proper cursor releasing + resolves: rhbz#1716867 + +* Fri May 10 2019 Jiri Vymazal - 8.37.0-10 + RHEL 8.1.0 ERRATUM +- added option for imfile endmsg.regex + resolves: rhbz#1627941 +- added patch enhancing imfile rotation detection + resolves: rhbz#1674471 +- added patch fixing msgOffset datatype preventing crash on + message with too long other fields + resolves: rhbz#1677037 +- added patch introducing "preservecase" option for imudp/imtcp + resolves: rhbz#1614181 + * Mon Dec 17 2018 Jiri Vymazal - 8.37.0-9 RHEL 8.0.0 ERRATUM - added back legacy option for imjournal default tag