import rsyslog-8.1911.0-3.el8

This commit is contained in:
CentOS Sources 2020-04-28 04:50:02 -04:00 committed by Andrew Lukoshko
parent 5208615781
commit 4066a6fcea
18 changed files with 296 additions and 3071 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/rsyslog-8.37.0.tar.gz
SOURCES/rsyslog-doc-8.37.0.tar.gz
SOURCES/rsyslog-8.1911.0.tar.gz
SOURCES/rsyslog-doc-8.1911.0.tar.gz

View File

@ -1,2 +1,2 @@
43076e3010fc3fd5178201a916beb93848b5249c SOURCES/rsyslog-8.37.0.tar.gz
4c75f56e2d55c4c87d07781fb6d9deabf63395fb SOURCES/rsyslog-doc-8.37.0.tar.gz
30dfc2b99d73598788e2bd0d0ac45e16e7c3a3d5 SOURCES/rsyslog-8.1911.0.tar.gz
8bcb23571ab8011b712ccf52acee20f8940b7f03 SOURCES/rsyslog-doc-8.1911.0.tar.gz

View File

@ -0,0 +1,28 @@
From fec4535f1c407f39d35ed4f3921662f94710a10e Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <rgerhards@adiscon.com>
Date: Mon, 9 Dec 2019 08:46:27 +0100
Subject: [PATCH] core/config bugfix: false error msg when config.enabled="on"
is used
When the 'config.enabled="on"' config parameter an invalid error message
was emitted that this parameter is not supported. However, it was still
applied properly. This commit removes the invalid error message.
closes https://github.com/rsyslog/rsyslog/issues/4011
---
grammar/rainerscript.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 1b8581b537..fd55360472 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1219,6 +1219,8 @@ nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
for(val = lst; val != NULL ; val = val->next) {
val->bUsed = 1;
}
+ } else {
+ valnode->bUsed = 1;
}
}

View File

@ -2,19 +2,19 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
--- ./plugins/imjournal/imjournal.c.default-tag 2018-05-17 08:50:11.416418022 -0400
+++ ./plugins/imjournal/imjournal.c 2018-05-17 08:53:02.884418022 -0400
@@ -78,6 +78,7 @@ static struct configSettings_s {
int bUseJnlPID;
char *usePid;
int bWorkAroundJournalBug;
int bWorkAroundJournalBug; /* deprecated, left for backwards compatibility only */
int bFsync;
int bRemote;
+ char *dfltTag;
} cs;
static rsRetVal facilityHdlr(uchar **pp, void *pVal);
@@ -93,7 +94,8 @@ static struct cnfparamdescr modpdescr[]
{ "defaultfacility", eCmdHdlrString, 0 },
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
{ "usepid", eCmdHdlrString, 0 },
- { "workaroundjournalbug", eCmdHdlrBinary, 0 }
+ { "workaroundjournalbug", eCmdHdlrBinary, 0 },
{ "workaroundjournalbug", eCmdHdlrBinary, 0 },
{ "fsync", eCmdHdlrBinary, 0 },
- { "remote", eCmdHdlrBinary, 0 }
+ { "remote", eCmdHdlrBinary, 0 },
+ { "defaulttag", eCmdHdlrGetWord, 0 }
};
static struct cnfparamblk modpblk =
@ -34,10 +34,10 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
- char *sys_iden;
+ char *sys_iden = NULL;
char *sys_iden_help = NULL;
char *c = NULL;
const void *get;
@@ -331,7 +334,7 @@ readjournal(void)
if (sd_journal_get_data(j, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
if (journalGetData("SYSLOG_IDENTIFIER", &get, &length) >= 0) {
CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
} else {
- CHKmalloc(sys_iden = strdup("journal"));
@ -58,9 +58,9 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
pidFieldName = "_PID";
bPidFallBack = 0;
@@ -732,6 +740,7 @@ CODESTARTbeginCnfLoad
cs.bUseJnlPID = -1;
cs.usePid = NULL;
cs.bWorkAroundJournalBug = 0;
cs.bWorkAroundJournalBug = 1;
cs.bFsync = 0;
cs.bRemote = 0;
+ cs.dfltTag = NULL;
ENDbeginCnfLoad
@ -70,13 +70,13 @@ diff -up ./plugins/imjournal/imjournal.c.default-tag ./plugins/imjournal/imjourn
free(cs.stateFile);
free(cs.usePid);
+ free(cs.dfltTag);
statsobj.Destruct(&(statsCounter.stats));
free(journalContext.cursor);
statsobj.Destruct(&(statsCounter.stats));
ENDfreeCnf
@@ -832,6 +842,8 @@ CODESTARTsetModCnf
cs.usePid = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if (!strcmp(modpblk.descr[i].name, "workaroundjournalbug")) {
cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
cs.bFsync = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "remote")) {
cs.bRemote = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaulttag")) {
+ cs.dfltTag = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {

View File

@ -0,0 +1,142 @@
From ac30968b7858d4ca3743d2b4d296eca543864fe2 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
Date: Fri, 22 Nov 2019 14:25:59 +0100
Subject: [PATCH] Thorougher state-file renaming and cleaning
Now checking if file-id changes and reanming - cleaning state file
accordingly and always checking and cleaning old inode-only style
state files.
---
plugins/imfile/imfile.c | 66 +++++++++++++++++++++++++++--------------
1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index d9bf0fbb6d..9db2b47ac9 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -182,6 +182,7 @@ struct act_obj_s {
time_t timeoutBase; /* what time to calculate the timeout against? */
/* file dynamic data */
char file_id[FILE_ID_HASH_SIZE]; /* file id for this entry, once we could obtain it */
+ char file_id_prev[FILE_ID_HASH_SIZE]; /* previous file id for this entry, set if changed */
int in_move; /* workaround for inotify move: if set, state file must not be deleted */
ino_t ino; /* current inode nbr */
int fd; /* fd to file in order to obtain file_id (needs to be preserved across move) */
@@ -711,7 +712,7 @@ act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
if (is_file) {
LogError(errno, RS_RET_ERR, "imfile: error accessing file '%s'", name);
} else { /* reporting only in debug for dirs as higher lvl paths are likely blocked by selinux */
- DBGPRINTF("imfile: error accessing file '%s'", name);
+ DBGPRINTF("imfile: error accessing directory '%s'", name);
}
FINALIZE;
}
@@ -727,6 +728,7 @@ act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
act->ino = ino;
act->fd = fd;
act->file_id[0] = '\0';
+ act->file_id_prev[0] = '\0';
act->is_symlink = is_symlink;
if (source) { /* we are target of symlink */
CHKmalloc(act->source_name = strdup(source));
@@ -1256,17 +1258,15 @@ get_file_id_hash(const char *data, size_t lendata,
static void ATTR_NONNULL(1)
getFileID(act_obj_t *const act)
{
- if(act->file_id[0] != '\0') {
- return; /* everything already done */
- }
+ /* save the old id for cleaning purposes */
+ strncpy(act->file_id_prev, (const char*)act->file_id, FILE_ID_HASH_SIZE);
+ act->file_id[0] = '\0';
assert(act->fd >= 0); /* fd must have been opened at act_obj_t creation! */
char filedata[FILE_ID_SIZE];
+ lseek(act->fd, 0, SEEK_SET); /* Seek to beginning of file so we have correct id */
const int r = read(act->fd, filedata, FILE_ID_SIZE);
if(r == FILE_ID_SIZE) {
get_file_id_hash(filedata, sizeof(filedata), act->file_id, sizeof(act->file_id));
- dbgprintf("file_id '%s' obtained, closing monitoring file handle\n", act->file_id);
- close(act->fd); /* we will never go here! */
- act->fd = -1;
} else {
DBGPRINTF("getFileID partial or error read, ret %d\n", r);
}
@@ -1378,28 +1378,13 @@ openFileWithStateFile(act_obj_t *const act)
if(fd < 0) {
if(errno == ENOENT) {
if(act->file_id[0] != '\0') {
- const char *pszSFNamHash = strdup((const char*)pszSFNam);
- CHKmalloc(pszSFNamHash);
DBGPRINTF("state file %s for %s does not exist - trying to see if "
"inode-only file exists\n", pszSFNam, act->name);
getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
if(fd >= 0) {
- dbgprintf("found inode-only state file, renaming it now that we "
- "know the file_id, new name: %s\n", pszSFNamHash);
- /* we now can use identify the file, so let's rename it */
- if(rename((const char*)pszSFNam, pszSFNamHash) != 0) {
- LogError(errno, RS_RET_IO_ERROR,
- "imfile error trying to rename state file for '%s' - "
- "ignoring this error, usually this means a file no "
- "longer file is left over, but this may also cause "
- "some real trouble. Still the best we can do ",
- act->name);
- free((void*) pszSFNamHash);
- ABORT_FINALIZE(RS_RET_IO_ERROR);
- }
+ dbgprintf("found inode-only state file, will be renamed at next persist\n");
}
- free((void*) pszSFNamHash);
}
if(fd < 0) {
DBGPRINTF("state file %s for %s does not exist - trying to see if "
@@ -2609,6 +2594,36 @@ atomicWriteStateFile(const char *fn, const char *content)
RETiRet;
}
+/* This function should be called after any file ID change - that is if
+ * file grown from hash-only statefile, or was truncated, this will ensure
+ * we delete the old file so we do not make garbage in our working dir and
+ * there are no leftover statefiles which can in theory later bind to something
+ * and cause data loss.
+ * jvymazal 2019-11-27
+ */
+static void
+removeOldStatefile(const uchar *statefn, const char *hashToDelete)
+{
+ int ret;
+ uchar statefname[MAXFNAME];
+
+ getFullStateFileName(statefn, hashToDelete, statefname, sizeof(statefname));
+ DBGPRINTF("removing old state file: '%s'\n", statefname);
+ ret = unlink((const char*)statefname);
+ if(ret != 0) {
+ if (errno != ENOENT) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "imfile error trying to delete old state file: '%s' - ignoring this "
+ "error, usually this means a file no longer file is left over, but "
+ "this may also cause some real trouble. Still the best we can do ",
+ statefname);
+ } else {
+ DBGPRINTF("trying to delete no longer valid statefile '%s' which no "
+ "longer exists (probably already deleted)\n", statefname);
+ }
+ }
+}
+
/* This function persists information for a specific file being monitored.
* To do so, it simply persists the stream object. We do NOT abort on error
@@ -2660,6 +2675,11 @@ persistStrmState(act_obj_t *const act)
CHKiRet(atomicWriteStateFile((const char*)statefname, jstr));
json_object_put(json);
+ /* file-id changed remove the old statefile */
+ if (strncmp((const char *)act->file_id_prev, (const char *)act->file_id, FILE_ID_HASH_SIZE)) {
+ removeOldStatefile(statefn, act->file_id_prev);
+ }
+
finalize_it:
if(iRet != RS_RET_OK) {
LogError(0, iRet, "imfile: could not persist state "

View File

@ -0,0 +1,58 @@
From 0de93c9e1597b20f71bb61d5375ded546cfd2fa8 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
Date: Wed, 11 Dec 2019 15:35:26 +0100
Subject: [PATCH] Changed default for permitExpiredCerts to "off"
This is to be conssitent with rsyslog's prior behavior where
expired certs were automatically rejected
---
runtime/nsd_gtls.c | 10 +++++-----
runtime/nsd_ossl.c | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 5df12994d1..2be0ca9c92 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -1461,16 +1461,16 @@ SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode)
nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ISOBJ_TYPE_assert((pThis), nsd_gtls);
- /* default is set to warn! */
- if(mode == NULL || !strcasecmp((char*)mode, "warn")) {
- pThis->permitExpiredCerts = GTLS_EXPIRED_WARN;
- } else if(!strcasecmp((char*) mode, "off")) {
+ /* default is set to off! */
+ if(mode == NULL || !strcasecmp((char*)mode, "off")) {
pThis->permitExpiredCerts = GTLS_EXPIRED_DENY;
+ } else if(!strcasecmp((char*) mode, "warn")) {
+ pThis->permitExpiredCerts = GTLS_EXPIRED_WARN;
} else if(!strcasecmp((char*) mode, "on")) {
pThis->permitExpiredCerts = GTLS_EXPIRED_PERMIT;
} else {
LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by "
- "ossl netstream driver", mode);
+ "gtls netstream driver", mode);
ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
}
diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
index 4f8dd845ab..ebb2537d72 100644
--- a/runtime/nsd_ossl.c
+++ b/runtime/nsd_ossl.c
@@ -1130,11 +1130,11 @@ SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode)
nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
ISOBJ_TYPE_assert((pThis), nsd_ossl);
- /* default is set to warn! */
- if(mode == NULL || !strcasecmp((char*)mode, "warn")) {
- pThis->permitExpiredCerts = OSSL_EXPIRED_WARN;
- } else if(!strcasecmp((char*) mode, "off")) {
+ /* default is set to off! */
+ if(mode == NULL || !strcasecmp((char*)mode, "off")) {
pThis->permitExpiredCerts = OSSL_EXPIRED_DENY;
+ } else if(!strcasecmp((char*) mode, "warn")) {
+ pThis->permitExpiredCerts = OSSL_EXPIRED_WARN;
} else if(!strcasecmp((char*) mode, "on")) {
pThis->permitExpiredCerts = OSSL_EXPIRED_PERMIT;
} else {

View File

@ -8,7 +8,7 @@ diff -up ./rsyslog.service.in.service ./rsyslog.service.in
+Wants=network.target network-online.target
+After=network.target network-online.target
Documentation=man:rsyslogd(8)
Documentation=http://www.rsyslog.com/doc/
Documentation=https://www.rsyslog.com/doc/
[Service]
Type=notify

View File

@ -1,416 +0,0 @@
From 3822da837e4d531e8a9cd78ae76359a410f8d98d Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
Date: Thu, 31 May 2018 16:30:08 +0200
Subject: [PATCH] Symlink support for imfile
this introduces symlink detection and following as well
as monitoring changes on them. Also added test for the new
functionality and ensuring the original symlink behavior
stays as well.
---
plugins/imfile/imfile.c | 182 +++++++++++++++++++++++++++----------
1 file changed, 133 insertions(+), 49 deletions(-)
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index 3c9308bfe..4ca23d2ca 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -152,6 +152,7 @@ struct act_obj_s {
fs_edge_t *edge; /* edge which this object belongs to */
char *name; /* full path name of active object */
char *basename; /* only basename */ //TODO: remove when refactoring rename support
+ char *source_name; /* if this object is target of a symlink, source_name is its name (else NULL) */
//char *statefile; /* base name of state file (for move operations) */
int wd;
#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
@@ -167,6 +168,7 @@ struct act_obj_s {
int nRecords; /**< How many records did we process before persisting the stream? */
ratelimit_t *ratelimiter;
multi_submit_t multiSub;
+ int is_symlink;
};
struct fs_edge_s {
fs_node_t *parent;
@@ -181,7 +182,8 @@ struct act_obj_s {
instanceConf_t **instarr;
};
struct fs_node_s {
- fs_edge_t *edges;
+ fs_edge_t *edges; /* NULL in leaf nodes */
+ fs_node_t *root; /* node one level up (NULL for file system root) */
};
@@ -189,7 +191,7 @@ static rsRetVal persistStrmState(act_obj_t *);
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
static rsRetVal ATTR_NONNULL(1) pollFile(act_obj_t *act);
static int ATTR_NONNULL() getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path);
-static void ATTR_NONNULL() act_obj_unlink(act_obj_t *const act);
+static void ATTR_NONNULL() act_obj_unlink(act_obj_t *act);
static uchar * ATTR_NONNULL(1, 2) getStateFileName(const act_obj_t *, uchar *, const size_t);
static int ATTR_NONNULL() getFullStateFileName(const uchar *const, uchar *const pszout, const size_t ilenout);
@@ -483,14 +485,17 @@ in_setupWatch(act_obj_t *const act, const int is_file)
goto done;
wd = inotify_add_watch(ino_fd, act->name,
- (is_file) ? IN_MODIFY : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
+ (is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
if(wd < 0) {
- LogError(errno, RS_RET_IO_ERROR, "imfile: cannot watch object '%s'",
- act->name);
+ if (errno == EACCES) { /* There is high probability of selinux denial on top-level paths */
+ DBGPRINTF("imfile: permission denied when adding watch for '%s'\n", act->name);
+ } else {
+ LogError(errno, RS_RET_IO_ERROR, "imfile: cannot watch object '%s'", act->name);
+ }
goto done;
}
wdmapAdd(wd, act);
- DBGPRINTF("in_setupDirWatch: watch %d added for dir %s(%p)\n", wd, act->name, act);
+ DBGPRINTF("in_setupWatch: watch %d added for %s(object %p)\n", wd, act->name, act);
done: return wd;
}
@@ -605,7 +610,7 @@ done: return;
static void ATTR_NONNULL()
fen_setupWatch(act_obj_t *const act __attribute__((unused)))
{
- DBGPRINTF("fen_setupWatch: DUMMY CALLED - not on Solaris?");
+ DBGPRINTF("fen_setupWatch: DUMMY CALLED - not on Solaris?\n");
}
#endif /* FEN */
@@ -633,38 +638,48 @@ fs_node_print(const fs_node_t *const node, const int level)
}
}
-
/* add a new file system object if it not yet exists, ignore call
* if it already does.
*/
-static rsRetVal ATTR_NONNULL()
+static rsRetVal ATTR_NONNULL(1,2)
act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
- const ino_t ino)
+ const ino_t ino, const int is_symlink, const char *const source)
{
act_obj_t *act;
char basename[MAXFNAME];
DEFiRet;
- DBGPRINTF("act_obj_add: edge %p, name '%s'\n", edge, name);
+ DBGPRINTF("act_obj_add: edge %p, name '%s' (source '%s')\n", edge, name, source? source : "---");
for(act = edge->active ; act != NULL ; act = act->next) {
if(!strcmp(act->name, name)) {
- DBGPRINTF("active object '%s' already exists in '%s' - no need to add\n",
- name, edge->path);
- FINALIZE;
+ if (!source || !act->source_name || !strcmp(act->source_name, source)) {
+ DBGPRINTF("active object '%s' already exists in '%s' - no need to add\n",
+ name, edge->path);
+ FINALIZE;
+ }
}
}
DBGPRINTF("add new active object '%s' in '%s'\n", name, edge->path);
CHKmalloc(act = calloc(sizeof(act_obj_t), 1));
CHKmalloc(act->name = strdup(name));
- getBasename((uchar*)basename, (uchar*)name);
- CHKmalloc(act->basename = strdup(basename));
+ if (-1 == getBasename((uchar*)basename, (uchar*)name)) {
+ CHKmalloc(act->basename = strdup(name)); /* assume basename is same as name */
+ } else {
+ CHKmalloc(act->basename = strdup(basename));
+ }
act->edge = edge;
act->ino = ino;
+ act->is_symlink = is_symlink;
+ if (source) { /* we are target of symlink */
+ CHKmalloc(act->source_name = strdup(source));
+ } else {
+ act->source_name = NULL;
+ }
#ifdef HAVE_INOTIFY_INIT
act->wd = in_setupWatch(act, is_file);
#endif
fen_setupWatch(act);
- if(is_file) {
+ if(is_file && !is_symlink) {
const instanceConf_t *const inst = edge->instarr[0];// TODO: same file, multiple instances?
CHKiRet(ratelimitNew(&act->ratelimiter, "imfile", name));
CHKmalloc(act->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(smsg_t *)));
@@ -702,27 +717,24 @@ detect_updates(fs_edge_t *const edge)
{
act_obj_t *act;
struct stat fileInfo;
+ int restart = 0;
- for(act = edge->active ; act != NULL ; ) {
+ for(act = edge->active ; act != NULL ; act = act->next) {
DBGPRINTF("detect_updates checking active obj '%s'\n", act->name);
- const int r = stat(act->name, &fileInfo);
+ const int r = lstat(act->name, &fileInfo);
if(r == -1) { /* object gone away? */
DBGPRINTF("object gone away, unlinking: '%s'\n", act->name);
- act_obj_t *toDel = act;
- act = act->next;
- DBGPRINTF("new next act %p\n", act);
- act_obj_unlink(toDel);
- continue;
+ act_obj_unlink(act);
+ restart = 1;
+ break;
}
// TODO: add inode check for change notification!
- /* Note: active nodes may get deleted, so we need to do the
- * pointer advancement at the end of the for loop!
- */
- act = act->next;
}
-
+ if (restart) {
+ detect_updates(edge);
+ }
}
@@ -746,14 +758,52 @@ poll_active_files(fs_edge_t *const edge)
}
}
+static rsRetVal ATTR_NONNULL()
+process_symlink(fs_edge_t *const chld, const char *symlink)
+{
+ DEFiRet;
+ char *target = NULL;
+ CHKmalloc(target = realpath(symlink, target));
+ struct stat fileInfo;
+ if(lstat(target, &fileInfo) != 0) {
+ LogError(errno, RS_RET_ERR, "imfile: process_symlink: cannot stat file '%s' - ignored", target);
+ FINALIZE;
+ }
+ const int is_file = (S_ISREG(fileInfo.st_mode));
+ DBGPRINTF("process_symlink: found '%s', File: %d (config file: %d), symlink: %d\n",
+ target, is_file, chld->is_file, 0);
+ if (act_obj_add(chld, target, is_file, fileInfo.st_ino, 0, symlink) == RS_RET_OK) {
+ /* need to watch parent target as well for proper rotation support */
+ uint idx = ustrlen(chld->active->name) - ustrlen(chld->active->basename);
+ if (idx) { /* basename is different from name */
+ char parent[MAXFNAME];
+ idx--; /* move past trailing slash */
+ memcpy(parent, chld->active->name, idx);
+ parent[idx] = '\0';
+ if(lstat(parent, &fileInfo) != 0) {
+ LogError(errno, RS_RET_ERR,
+ "imfile: process_symlink: cannot stat directory '%s' - ignored", parent);
+ FINALIZE;
+ }
+ if (chld->parent->root->edges) {
+ DBGPRINTF("process_symlink: adding parent '%s' of target '%s'\n", parent, target);
+ act_obj_add(chld->parent->root->edges, parent, 0, fileInfo.st_ino, 0, NULL);
+ }
+ }
+ }
+
+finalize_it:
+ free(target);
+ RETiRet;
+}
-static void ATTR_NONNULL() poll_tree(fs_edge_t *const chld);
static void ATTR_NONNULL()
poll_tree(fs_edge_t *const chld)
{
struct stat fileInfo;
glob_t files;
int need_globfree = 0;
+ int issymlink;
DBGPRINTF("poll_tree: chld %p, name '%s', path: %s\n", chld, chld->name, chld->path);
detect_updates(chld);
const int ret = glob((char*)chld->path, runModConf->sortFiles|GLOB_BRACE, NULL, &files);
@@ -766,18 +803,27 @@ poll_tree(fs_edge_t *const chld)
goto done;
}
char *const file = files.gl_pathv[i];
- if(stat(file, &fileInfo) != 0) {
+ if(lstat(file, &fileInfo) != 0) {
LogError(errno, RS_RET_ERR,
"imfile: poll_tree cannot stat file '%s' - ignored", file);
continue;
}
- const int is_file = S_ISREG(fileInfo.st_mode);
- DBGPRINTF("poll_tree: found '%s', File: %d (config file: %d)\n",
- file, is_file, chld->is_file);
+ if (S_ISLNK(fileInfo.st_mode)) {
+ rsRetVal slink_ret = process_symlink(chld, file);
+ if (slink_ret != RS_RET_OK) {
+ continue;
+ }
+ issymlink = 1;
+ } else {
+ issymlink = 0;
+ }
+ const int is_file = (S_ISREG(fileInfo.st_mode) || issymlink);
+ DBGPRINTF("poll_tree: found '%s', File: %d (config file: %d), symlink: %d\n",
+ file, is_file, chld->is_file, issymlink);
if(!is_file && S_ISREG(fileInfo.st_mode)) {
LogMsg(0, RS_RET_ERR, LOG_WARNING,
- "imfile: '%s' is neither a regular file nor a "
+ "imfile: '%s' is neither a regular file, symlink, nor a "
"directory - ignored", file);
continue;
}
@@ -788,7 +834,7 @@ poll_tree(fs_edge_t *const chld)
(chld->is_file) ? "FILE" : "DIRECTORY");
continue;
}
- act_obj_add(chld, file, is_file, fileInfo.st_ino);
+ act_obj_add(chld, file, is_file, fileInfo.st_ino, issymlink, NULL);
}
}
@@ -829,8 +875,20 @@ act_obj_destroy(act_obj_t *const act, const int is_deleted)
if(act == NULL)
return;
- DBGPRINTF("act_obj_destroy: act %p '%s', wd %d, pStrm %p, is_deleted %d, in_move %d\n",
- act, act->name, act->wd, act->pStrm, is_deleted, act->in_move);
+ DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
+ act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted,
+ act->in_move);
+ if(act->is_symlink && is_deleted) {
+ act_obj_t *target_act;
+ for(target_act = act->edge->active ; target_act != NULL ; target_act = target_act->next) {
+ if(target_act->source_name && !strcmp(target_act->source_name, act->name)) {
+ DBGPRINTF("act_obj_destroy: unlinking slink target %s of %s "
+ "symlink\n", target_act->name, act->name);
+ act_obj_unlink(target_act);
+ break;
+ }
+ }
+ }
if(act->ratelimiter != NULL) {
ratelimitDestruct(act->ratelimiter);
}
@@ -862,6 +920,7 @@ act_obj_destroy(act_obj_t *const act, const int is_deleted)
}
#endif
free(act->basename);
+ free(act->source_name);
//free(act->statefile);
free(act->multiSub.ppMsgs);
#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
@@ -909,7 +968,7 @@ chk_active(const act_obj_t *act, const act_obj_t *const deleted)
* destruct it.
*/
static void //ATTR_NONNULL()
-act_obj_unlink(act_obj_t *const act)
+act_obj_unlink(act_obj_t *act)
{
DBGPRINTF("act_obj_unlink %p: %s\n", act, act->name);
if(act->prev == NULL) {
@@ -921,6 +980,7 @@ act_obj_unlink(act_obj_t *const act)
act->next->prev = act->prev;
}
act_obj_destroy(act, 1);
+ act = NULL;
//dbgprintf("printout of fs tree post unlink\n");
//fs_node_print(runModConf->conf_tree, 0);
//dbg_wdmapPrint("wdmap after");
@@ -1025,6 +1038,7 @@ fs_node_walk(fs_node_t *const node,
*/
static rsRetVal
fs_node_add(fs_node_t *const node,
+ fs_node_t *const source,
const uchar *const toFind,
const size_t pathIdx,
instanceConf_t *const inst)
@@ -1053,6 +1067,7 @@ fs_node_add(fs_node_t *const node,
memcpy(name, toFind+pathIdx, len);
name[len] = '\0';
DBGPRINTF("fs_node_add: name '%s'\n", name);
+ node->root = source;
fs_edge_t *chld;
for(chld = node->edges ; chld != NULL ; chld = chld->next) {
@@ -1064,7 +1079,7 @@ fs_node_add(fs_node_t *const node,
chld->instarr[chld->ninst-1] = inst;
/* recurse */
if(!isFile) {
- CHKiRet(fs_node_add(chld->node, toFind, nextPathIdx, inst));
+ CHKiRet(fs_node_add(chld->node, node, toFind, nextPathIdx, inst));
}
FINALIZE;
}
@@ -1086,7 +1101,7 @@ fs_node_add(fs_node_t *const node,
DBGPRINTF("fs_node_add(%p, '%s') returns %p\n", node, toFind, newchld->node);
if(!isFile) {
- CHKiRet(fs_node_add(newchld->node, toFind, nextPathIdx, inst));
+ CHKiRet(fs_node_add(newchld->node, node, toFind, nextPathIdx, inst));
}
/* link to list */
@@ -1162,7 +1222,11 @@ enqLine(act_obj_t *const act,
msgSetPRI(pMsg, inst->iFacility | inst->iSeverity);
MsgSetRuleset(pMsg, inst->pBindRuleset);
if(inst->addMetadata) {
- metadata_values[0] = (const uchar*)act->name;
+ if (act->source_name) {
+ metadata_values[0] = (const uchar*)act->source_name;
+ } else {
+ metadata_values[0] = (const uchar*)act->name;
+ }
snprintf((char *)file_offset, MAX_OFFSET_REPRESENTATION_NUM_BYTES+1, "%lld", strtOffs);
metadata_values[1] = file_offset;
msgAddMultiMetadata(pMsg, metadata_names, metadata_values, 2);
@@ -1389,13 +1453,16 @@ pollFile(act_obj_t *const act)
{
cstr_t *pCStr = NULL;
DEFiRet;
+ if (act->is_symlink) {
+ FINALIZE; /* no reason to poll symlink file */
+ }
/* Note: we must do pthread_cleanup_push() immediately, because the POSIX macros
* otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14
*/
pthread_cleanup_push(pollFileCancelCleanup, &pCStr);
iRet = pollFileReal(act, &pCStr);
pthread_cleanup_pop(0);
- RETiRet;
+finalize_it: RETiRet;
}
@@ -1931,7 +1946,7 @@ CODESTARTactivateCnf
"be processed. Reason", inst->pszFileName);
}
}
- fs_node_add(runModConf->conf_tree, inst->pszFileName, 0, inst);
+ fs_node_add(runModConf->conf_tree, NULL, inst->pszFileName, 0, inst);
}
if(Debug) {
@@ -2031,6 +2113,9 @@ flag_in_move(fs_edge_t *const edge, const char *name_moved)
DBGPRINTF("name check fails, '%s' != '%s'\n", act->basename, name_moved);
}
}
+ if (!act && edge->next) {
+ flag_in_move(edge->next, name_moved);
+ }
}
static void ATTR_NONNULL(1)
@@ -2057,7 +2145,7 @@ in_processEvent(struct inotify_event *ev)
}
if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) {
fs_node_walk(etry->act->edge->node, poll_tree);
- } else if(etry->act->edge->is_file) {
+ } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
in_handleFileEvent(ev, etry); // esentially poll_file()!
} else {
fs_node_walk(etry->act->edge->node, poll_tree);

View File

@ -1,286 +0,0 @@
From 9ac54f0d7d70b8a9879889b4522a1d552fca1100 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@momo7.localdomain>
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

View File

@ -1,761 +0,0 @@
From 3987cd929d859f900318b393133c3bdde8dfffd5 Mon Sep 17 00:00:00 2001
From: Rich Megginson <rmeggins@redhat.com>
Date: Tue, 28 Aug 2018 12:44:23 -0600
Subject: [PATCH] mmkubertnetes: action fails preparation cycle if kubernetes
API destroys resource during bootup sequence
The plugin was not handling 404 Not Found correctly when looking
up pods and namespaces. In this case, we assume the pod/namespace
was deleted, annotate the record with whatever metadata we have,
and cache the fact that the pod/namespace is missing so we don't
attempt to look it up again.
In addition, the plugin was not handling error 429 Busy correctly.
In this case, it should also annotate the record with whatever
metadata it has, and _not_ cache anything. By default the plugin
will retry every 5 seconds to connect to Kubernetes. This
behavior is controlled by the new config param `busyretryinterval`.
This commit also adds impstats counters so that admins can
view the state of the plugin to see if the lookups are working
or are returning errors. The stats are reported per-instance
or per-action to facilitate using multiple different actions
for different Kubernetes servers.
This commit also adds support for client cert auth to
Kubernetes via the two new config params `tls.mycert` and
`tls.myprivkey`.
---
contrib/mmkubernetes/mmkubernetes.c | 296 ++++++++++++++++++++++++----
7 files changed, 160 insertions(+), 36 deletions(-)
diff --git a/contrib/mmkubernetes/mmkubernetes.c b/contrib/mmkubernetes/mmkubernetes.c
index 422cb2577..5bf5b049d 100644
--- a/contrib/mmkubernetes/mmkubernetes.c
+++ b/contrib/mmkubernetes/mmkubernetes.c
@@ -52,9 +52,12 @@
#include "syslogd-types.h"
#include "module-template.h"
#include "errmsg.h"
+#include "statsobj.h"
#include "regexp.h"
#include "hashtable.h"
#include "srUtils.h"
+#include "unicode-helper.h"
+#include "datetime.h"
/* static data */
MODULE_TYPE_OUTPUT /* this is technically an output plugin */
@@ -62,6 +65,8 @@ MODULE_TYPE_KEEP /* releasing the module would cause a leak through libcurl */
MODULE_CNFNAME("mmkubernetes")
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(regexp)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(datetime)
#define HAVE_LOADSAMPLESFROMSTRING 1
#if defined(NO_LOADSAMPLESFROMSTRING)
@@ -95,12 +100,14 @@ DEFobjCurrIf(regexp)
#define DFLT_CONTAINER_NAME "$!CONTAINER_NAME" /* name of variable holding CONTAINER_NAME value */
#define DFLT_CONTAINER_ID_FULL "$!CONTAINER_ID_FULL" /* name of variable holding CONTAINER_ID_FULL value */
#define DFLT_KUBERNETES_URL "https://kubernetes.default.svc.cluster.local:443"
+#define DFLT_BUSY_RETRY_INTERVAL 5 /* retry every 5 seconds */
static struct cache_s {
const uchar *kbUrl;
struct hashtable *mdHt;
struct hashtable *nsHt;
pthread_mutex_t *cacheMtx;
+ int lastBusyTime;
} **caches;
typedef struct {
@@ -116,6 +123,8 @@ struct modConfData_s {
uchar *srcMetadataPath; /* where to get data for kubernetes queries */
uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
@@ -127,6 +136,7 @@ struct modConfData_s {
uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */
char *contRules; /* lognorm rules for CONTAINER_NAME value match */
uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
};
/* action (instance) configuration data */
@@ -135,6 +145,8 @@ typedef struct _instanceData {
msgPropDescr_t *srcMetadataDescr; /* where to get data for kubernetes queries */
uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
@@ -151,6 +163,7 @@ typedef struct _instanceData {
msgPropDescr_t *contNameDescr; /* CONTAINER_NAME field */
msgPropDescr_t *contIdFullDescr; /* CONTAINER_ID_FULL field */
struct cache_s *cache;
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
} instanceData;
typedef struct wrkrInstanceData {
@@ -159,6 +172,16 @@ typedef struct wrkrInstanceData {
struct curl_slist *curlHdr;
char *curlRply;
size_t curlRplyLen;
+ statsobj_t *stats; /* stats for this instance */
+ STATSCOUNTER_DEF(k8sRecordSeen, mutK8sRecordSeen)
+ STATSCOUNTER_DEF(namespaceMetadataSuccess, mutNamespaceMetadataSuccess)
+ STATSCOUNTER_DEF(namespaceMetadataNotFound, mutNamespaceMetadataNotFound)
+ STATSCOUNTER_DEF(namespaceMetadataBusy, mutNamespaceMetadataBusy)
+ STATSCOUNTER_DEF(namespaceMetadataError, mutNamespaceMetadataError)
+ STATSCOUNTER_DEF(podMetadataSuccess, mutPodMetadataSuccess)
+ STATSCOUNTER_DEF(podMetadataNotFound, mutPodMetadataNotFound)
+ STATSCOUNTER_DEF(podMetadataBusy, mutPodMetadataBusy)
+ STATSCOUNTER_DEF(podMetadataError, mutPodMetadataError)
} wrkrInstanceData_t;
/* module parameters (v6 config format) */
@@ -167,6 +190,8 @@ static struct cnfparamdescr modpdescr[] = {
{ "srcmetadatapath", eCmdHdlrString, 0 },
{ "dstmetadatapath", eCmdHdlrString, 0 },
{ "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
{ "allowunsignedcerts", eCmdHdlrBinary, 0 },
{ "token", eCmdHdlrString, 0 },
{ "tokenfile", eCmdHdlrString, 0 },
@@ -174,7 +199,8 @@ static struct cnfparamdescr modpdescr[] = {
{ "de_dot", eCmdHdlrBinary, 0 },
{ "de_dot_separator", eCmdHdlrString, 0 },
{ "filenamerulebase", eCmdHdlrString, 0 },
- { "containerrulebase", eCmdHdlrString, 0 }
+ { "containerrulebase", eCmdHdlrString, 0 },
+ { "busyretryinterval", eCmdHdlrInt, 0 }
#if HAVE_LOADSAMPLESFROMSTRING == 1
,
{ "filenamerules", eCmdHdlrArray, 0 },
@@ -193,6 +219,8 @@ static struct cnfparamdescr actpdescr[] = {
{ "srcmetadatapath", eCmdHdlrString, 0 },
{ "dstmetadatapath", eCmdHdlrString, 0 },
{ "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
{ "allowunsignedcerts", eCmdHdlrBinary, 0 },
{ "token", eCmdHdlrString, 0 },
{ "tokenfile", eCmdHdlrString, 0 },
@@ -200,7 +228,8 @@ static struct cnfparamdescr actpdescr[] = {
{ "de_dot", eCmdHdlrBinary, 0 },
{ "de_dot_separator", eCmdHdlrString, 0 },
{ "filenamerulebase", eCmdHdlrString, 0 },
- { "containerrulebase", eCmdHdlrString, 0 }
+ { "containerrulebase", eCmdHdlrString, 0 },
+ { "busyretryinterval", eCmdHdlrInt, 0 }
#if HAVE_LOADSAMPLESFROMSTRING == 1
,
{ "filenamerules", eCmdHdlrArray, 0 },
@@ -493,8 +522,9 @@ ENDbeginCnfLoad
BEGINsetModCnf
struct cnfparamvals *pvals = NULL;
int i;
- FILE *fp;
+ FILE *fp = NULL;
int ret;
+ char errStr[1024];
CODESTARTsetModCnf
pvals = nvlstGetParams(lst, &modpblk, NULL);
if(pvals == NULL) {
@@ -509,6 +539,7 @@ CODESTARTsetModCnf
}
loadModConf->de_dot = DFLT_DE_DOT;
+ loadModConf->busyRetryInterval = DFLT_BUSY_RETRY_INTERVAL;
for(i = 0 ; i < modpblk.nParams ; ++i) {
if(!pvals[i].bUsed) {
continue;
@@ -528,15 +559,42 @@ CODESTARTsetModCnf
loadModConf->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)loadModConf->caCertFile, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
- "error: certificate file %s couldn't be accessed: %s\n",
+ "error: 'tls.cacert' file %s couldn't be accessed: %s\n",
loadModConf->caCertFile, errStr);
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "tls.mycert")) {
+ free(loadModConf->myCertFile);
+ loadModConf->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ loadModConf->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "tls.myprivkey")) {
+ loadModConf->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ loadModConf->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
}
} else if(!strcmp(modpblk.descr[i].name, "allowunsignedcerts")) {
loadModConf->allowUnsignedCerts = pvals[i].val.d.n;
@@ -548,7 +606,6 @@ CODESTARTsetModCnf
loadModConf->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)loadModConf->tokenFile, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -557,6 +614,7 @@ CODESTARTsetModCnf
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
} else if(!strcmp(modpblk.descr[i].name, "annotation_match")) {
free_annotationmatch(&loadModConf->annotation_match);
@@ -577,7 +635,6 @@ CODESTARTsetModCnf
loadModConf->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)loadModConf->fnRulebase, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -586,6 +643,7 @@ CODESTARTsetModCnf
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
#if HAVE_LOADSAMPLESFROMSTRING == 1
} else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
@@ -597,7 +655,6 @@ CODESTARTsetModCnf
loadModConf->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)loadModConf->contRulebase, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -606,7 +663,10 @@ CODESTARTsetModCnf
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
+ } else if(!strcmp(modpblk.descr[i].name, "busyretryinterval")) {
+ loadModConf->busyRetryInterval = pvals[i].val.d.n;
} else {
dbgprintf("mmkubernetes: program error, non-handled "
"param '%s' in module() block\n", modpblk.descr[i].name);
@@ -650,6 +710,8 @@ CODESTARTsetModCnf
caches = calloc(1, sizeof(struct cache_s *));
finalize_it:
+ if (fp)
+ fclose(fp);
if(pvals != NULL)
cnfparamvalsDestruct(pvals, &modpblk);
ENDsetModCnf
@@ -667,6 +729,8 @@ CODESTARTfreeInstance
free(pData->srcMetadataDescr);
free(pData->dstMetadataPath);
free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
free(pData->token);
free(pData->tokenFile);
free(pData->fnRules);
@@ -710,6 +774,45 @@ CODESTARTcreateWrkrInstance
char *tokenHdr = NULL;
FILE *fp = NULL;
char *token = NULL;
+ char *statsName = NULL;
+
+ CHKiRet(statsobj.Construct(&(pWrkrData->stats)));
+ if ((-1 == asprintf(&statsName, "mmkubernetes(%s)", pWrkrData->pData->kubernetesUrl)) ||
+ (!statsName)) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ CHKiRet(statsobj.SetName(pWrkrData->stats, (uchar *)statsName));
+ free(statsName);
+ statsName = NULL;
+ CHKiRet(statsobj.SetOrigin(pWrkrData->stats, UCHAR_CONSTANT("mmkubernetes")));
+ STATSCOUNTER_INIT(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("recordseen"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->k8sRecordSeen)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatasuccess"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataSuccess)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataNotFound, pWrkrData->mutNamespaceMetadataNotFound);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatanotfound"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataNotFound)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataBusy, pWrkrData->mutNamespaceMetadataBusy);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatabusy"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataBusy)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataError, pWrkrData->mutNamespaceMetadataError);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadataerror"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataError)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatasuccess"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataSuccess)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatanotfound"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataNotFound)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatabusy"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataBusy)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadataerror"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataError)));
+ CHKiRet(statsobj.ConstructFinalize(pWrkrData->stats));
hdr = curl_slist_append(hdr, "Content-Type: text/json; charset=utf-8");
if (pWrkrData->pData->token) {
@@ -749,12 +852,20 @@ CODESTARTcreateWrkrInstance
curl_easy_setopt(ctx, CURLOPT_WRITEDATA, pWrkrData);
if(pWrkrData->pData->caCertFile)
curl_easy_setopt(ctx, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
+ if(pWrkrData->pData->myCertFile)
+ curl_easy_setopt(ctx, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
+ if(pWrkrData->pData->myPrivKeyFile)
+ curl_easy_setopt(ctx, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
if(pWrkrData->pData->allowUnsignedCerts)
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 0);
pWrkrData->curlCtx = ctx;
finalize_it:
free(token);
+ free(statsName);
+ if ((iRet != RS_RET_OK) && pWrkrData->stats) {
+ statsobj.Destruct(&(pWrkrData->stats));
+ }
if (fp) {
fclose(fp);
}
@@ -765,6 +876,7 @@ BEGINfreeWrkrInstance
CODESTARTfreeWrkrInstance
curl_easy_cleanup(pWrkrData->curlCtx);
curl_slist_free_all(pWrkrData->curlHdr);
+ statsobj.Destruct(&(pWrkrData->stats));
ENDfreeWrkrInstance
@@ -790,6 +902,8 @@ cacheNew(const uchar *const url)
key_equals_string, hashtable_json_object_put);
cache->nsHt = create_hashtable(100, hash_from_string,
key_equals_string, hashtable_json_object_put);
+ dbgprintf("mmkubernetes: created cache mdht [%p] nsht [%p]\n",
+ cache->mdHt, cache->nsHt);
cache->cacheMtx = malloc(sizeof(pthread_mutex_t));
if (!cache->mdHt || !cache->nsHt || !cache->cacheMtx) {
free (cache);
@@ -797,6 +911,7 @@ cacheNew(const uchar *const url)
FINALIZE;
}
pthread_mutex_init(cache->cacheMtx, NULL);
+ cache->lastBusyTime = 0;
finalize_it:
return cache;
@@ -816,9 +931,10 @@ static void cacheFree(struct cache_s *cache)
BEGINnewActInst
struct cnfparamvals *pvals = NULL;
int i;
- FILE *fp;
+ FILE *fp = NULL;
char *rxstr = NULL;
char *srcMetadataPath = NULL;
+ char errStr[1024];
CODESTARTnewActInst
DBGPRINTF("newActInst (mmkubernetes)\n");
@@ -840,6 +956,7 @@ CODESTARTnewActInst
pData->de_dot = loadModConf->de_dot;
pData->allowUnsignedCerts = loadModConf->allowUnsignedCerts;
+ pData->busyRetryInterval = loadModConf->busyRetryInterval;
for(i = 0 ; i < actpblk.nParams ; ++i) {
if(!pvals[i].bUsed) {
continue;
@@ -863,7 +980,6 @@ CODESTARTnewActInst
pData->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)pData->caCertFile, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -872,6 +988,33 @@ CODESTARTnewActInst
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
}
} else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
pData->allowUnsignedCerts = pvals[i].val.d.n;
@@ -883,7 +1026,6 @@ CODESTARTnewActInst
pData->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)pData->tokenFile, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -892,6 +1034,7 @@ CODESTARTnewActInst
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
} else if(!strcmp(actpblk.descr[i].name, "annotation_match")) {
free_annotationmatch(&pData->annotation_match);
@@ -912,7 +1055,6 @@ CODESTARTnewActInst
pData->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)pData->fnRulebase, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -921,6 +1063,7 @@ CODESTARTnewActInst
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
#if HAVE_LOADSAMPLESFROMSTRING == 1
} else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
@@ -932,7 +1075,6 @@ CODESTARTnewActInst
pData->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
fp = fopen((const char*)pData->contRulebase, "r");
if(fp == NULL) {
- char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
iRet = RS_RET_NO_FILE_ACCESS;
LogError(0, iRet,
@@ -941,7 +1083,10 @@ CODESTARTnewActInst
ABORT_FINALIZE(iRet);
} else {
fclose(fp);
+ fp = NULL;
}
+ } else if(!strcmp(actpblk.descr[i].name, "busyretryinterval")) {
+ pData->busyRetryInterval = pvals[i].val.d.n;
} else {
dbgprintf("mmkubernetes: program error, non-handled "
"param '%s' in action() block\n", actpblk.descr[i].name);
@@ -982,6 +1127,10 @@ CODESTARTnewActInst
pData->dstMetadataPath = (uchar *) strdup((char *) loadModConf->dstMetadataPath);
if(pData->caCertFile == NULL && loadModConf->caCertFile)
pData->caCertFile = (uchar *) strdup((char *) loadModConf->caCertFile);
+ if(pData->myCertFile == NULL && loadModConf->myCertFile)
+ pData->myCertFile = (uchar *) strdup((char *) loadModConf->myCertFile);
+ if(pData->myPrivKeyFile == NULL && loadModConf->myPrivKeyFile)
+ pData->myPrivKeyFile = (uchar *) strdup((char *) loadModConf->myPrivKeyFile);
if(pData->token == NULL && loadModConf->token)
pData->token = (uchar *) strdup((char *) loadModConf->token);
if(pData->tokenFile == NULL && loadModConf->tokenFile)
@@ -1018,6 +1167,8 @@ CODESTARTnewActInst
CODE_STD_FINALIZERnewActInst
if(pvals != NULL)
cnfparamvalsDestruct(pvals, &actpblk);
+ if(fp)
+ fclose(fp);
free(rxstr);
free(srcMetadataPath);
ENDnewActInst
@@ -1061,6 +1212,8 @@ CODESTARTfreeCnf
free(pModConf->srcMetadataPath);
free(pModConf->dstMetadataPath);
free(pModConf->caCertFile);
+ free(pModConf->myCertFile);
+ free(pModConf->myPrivKeyFile);
free(pModConf->token);
free(pModConf->tokenFile);
free(pModConf->de_dot_separator);
@@ -1069,8 +1222,11 @@ CODESTARTfreeCnf
free(pModConf->contRules);
free(pModConf->contRulebase);
free_annotationmatch(&pModConf->annotation_match);
- for(i = 0; caches[i] != NULL; i++)
+ for(i = 0; caches[i] != NULL; i++) {
+ dbgprintf("mmkubernetes: freeing cache [%d] mdht [%p] nsht [%p]\n",
+ i, caches[i]->mdHt, caches[i]->nsHt);
cacheFree(caches[i]);
+ }
free(caches);
ENDfreeCnf
@@ -1082,6 +1238,8 @@ CODESTARTdbgPrintInstInfo
dbgprintf("\tsrcMetadataPath='%s'\n", pData->srcMetadataDescr->name);
dbgprintf("\tdstMetadataPath='%s'\n", pData->dstMetadataPath);
dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
dbgprintf("\tallowUnsignedCerts='%d'\n", pData->allowUnsignedCerts);
dbgprintf("\ttoken='%s'\n", pData->token);
dbgprintf("\ttokenFile='%s'\n", pData->tokenFile);
@@ -1093,6 +1251,7 @@ CODESTARTdbgPrintInstInfo
dbgprintf("\tfilenamerules='%s'\n", pData->fnRules);
dbgprintf("\tcontainerrules='%s'\n", pData->contRules);
#endif
+ dbgprintf("\tbusyretryinterval='%d'\n", pData->busyRetryInterval);
ENDdbgPrintInstInfo
@@ -1206,6 +1365,24 @@ queryKB(wrkrInstanceData_t *pWrkrData, char *url, struct json_object **rply)
struct json_object *jo;
long resp_code = 400;
+ if (pWrkrData->pData->cache->lastBusyTime) {
+ time_t now;
+ datetime.GetTime(&now);
+ now -= pWrkrData->pData->cache->lastBusyTime;
+ if (now < pWrkrData->pData->busyRetryInterval) {
+ LogMsg(0, RS_RET_RETRY, LOG_DEBUG,
+ "mmkubernetes: Waited [%ld] of [%d] seconds for the requested url [%s]\n",
+ now, pWrkrData->pData->busyRetryInterval, url);
+ ABORT_FINALIZE(RS_RET_RETRY);
+ } else {
+ LogMsg(0, RS_RET_OK, LOG_DEBUG,
+ "mmkubernetes: Cleared busy status after [%d] seconds - "
+ "will retry the requested url [%s]\n",
+ pWrkrData->pData->busyRetryInterval, url);
+ pWrkrData->pData->cache->lastBusyTime = 0;
+ }
+ }
+
/* query kubernetes for pod info */
ccode = curl_easy_setopt(pWrkrData->curlCtx, CURLOPT_URL, url);
if(ccode != CURLE_OK)
@@ -1238,17 +1415,23 @@ queryKB(wrkrInstanceData_t *pWrkrData, char *url, struct json_object **rply)
ABORT_FINALIZE(RS_RET_ERR);
}
if(resp_code == 404) {
- LogMsg(0, RS_RET_ERR, LOG_ERR,
+ LogMsg(0, RS_RET_NOT_FOUND, LOG_INFO,
"mmkubernetes: Not Found: the resource does not exist at url [%s]\n",
url);
- ABORT_FINALIZE(RS_RET_ERR);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(resp_code == 429) {
- LogMsg(0, RS_RET_ERR, LOG_ERR,
+ if (pWrkrData->pData->busyRetryInterval) {
+ time_t now;
+ datetime.GetTime(&now);
+ pWrkrData->pData->cache->lastBusyTime = now;
+ }
+
+ LogMsg(0, RS_RET_RETRY, LOG_INFO,
"mmkubernetes: Too Many Requests: the server is too heavily loaded "
"to provide the data for the requested url [%s]\n",
url);
- ABORT_FINALIZE(RS_RET_ERR);
+ ABORT_FINALIZE(RS_RET_RETRY);
}
if(resp_code != 200) {
LogMsg(0, RS_RET_ERR, LOG_ERR,
@@ -1299,12 +1482,14 @@ BEGINdoAction
char *mdKey = NULL;
struct json_object *jMetadata = NULL, *jMetadataCopy = NULL, *jMsgMeta = NULL,
*jo = NULL;
- int add_ns_metadata = 0;
+ int add_pod_metadata = 1;
CODESTARTdoAction
CHKiRet_Hdlr(extractMsgMetadata(pMsg, pWrkrData->pData, &jMsgMeta)) {
ABORT_FINALIZE((iRet == RS_RET_NOT_FOUND) ? RS_RET_OK : iRet);
}
+ STATSCOUNTER_INC(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
+
if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo))
podName = json_object_get_string(jo);
if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo))
@@ -1347,28 +1532,49 @@ CODESTARTdoAction
}
iRet = queryKB(pWrkrData, url, &jReply);
free(url);
- /* todo: implement support for the .orphaned namespace */
- if (iRet != RS_RET_OK) {
+ if (iRet == RS_RET_NOT_FOUND) {
+ /* negative cache namespace - make a dummy empty namespace metadata object */
+ jNsMeta = json_object_new_object();
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataNotFound,
+ pWrkrData->mutNamespaceMetadataNotFound);
+ } else if (iRet == RS_RET_RETRY) {
+ /* server is busy - retry or error */
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataBusy,
+ pWrkrData->mutNamespaceMetadataBusy);
+ if (0 == pWrkrData->pData->busyRetryInterval) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ add_pod_metadata = 0; /* don't cache pod metadata either - retry both */
+ } else if (iRet != RS_RET_OK) {
+ /* hard error - something the admin needs to fix e.g. network, config, auth */
json_object_put(jReply);
jReply = NULL;
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataError,
+ pWrkrData->mutNamespaceMetadataError);
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
FINALIZE;
- }
-
- if(fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) {
+ } else if (fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) {
jNsMeta = json_object_get(jNsMeta);
parse_labels_annotations(jNsMeta, &pWrkrData->pData->annotation_match,
pWrkrData->pData->de_dot,
(const char *)pWrkrData->pData->de_dot_separator,
pWrkrData->pData->de_dot_separator_len);
- add_ns_metadata = 1;
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
+ pWrkrData->mutNamespaceMetadataSuccess);
} else {
/* namespace with no metadata??? */
LogMsg(0, RS_RET_ERR, LOG_INFO,
"mmkubernetes: namespace [%s] has no metadata!\n", ns);
- jNsMeta = NULL;
+ /* negative cache namespace - make a dummy empty namespace metadata object */
+ jNsMeta = json_object_new_object();
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
+ pWrkrData->mutNamespaceMetadataSuccess);
}
+ if(jNsMeta) {
+ hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
+ }
json_object_put(jReply);
jReply = NULL;
}
@@ -1381,14 +1587,28 @@ CODESTARTdoAction
}
iRet = queryKB(pWrkrData, url, &jReply);
free(url);
- if(iRet != RS_RET_OK) {
- if(jNsMeta && add_ns_metadata) {
- hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
+ if (iRet == RS_RET_NOT_FOUND) {
+ /* negative cache pod - make a dummy empty pod metadata object */
+ iRet = RS_RET_OK;
+ STATSCOUNTER_INC(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
+ } else if (iRet == RS_RET_RETRY) {
+ /* server is busy - retry or error */
+ STATSCOUNTER_INC(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
+ if (0 == pWrkrData->pData->busyRetryInterval) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_ERR);
}
+ add_pod_metadata = 0; /* do not cache so that we can retry */
+ iRet = RS_RET_OK;
+ } else if(iRet != RS_RET_OK) {
+ /* hard error - something the admin needs to fix e.g. network, config, auth */
json_object_put(jReply);
jReply = NULL;
+ STATSCOUNTER_INC(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
FINALIZE;
+ } else {
+ STATSCOUNTER_INC(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
}
jo = json_object_new_object();
@@ -1435,11 +1655,9 @@ CODESTARTdoAction
json_object_object_add(jo, "container_id", json_object_get(jo2));
json_object_object_add(jMetadata, "docker", jo);
- hashtable_insert(pWrkrData->pData->cache->mdHt, mdKey, jMetadata);
- mdKey = NULL;
- if(jNsMeta && add_ns_metadata) {
- hashtable_insert(pWrkrData->pData->cache->nsHt, strdup(ns), jNsMeta);
- ns = NULL;
+ if (add_pod_metadata) {
+ hashtable_insert(pWrkrData->pData->cache->mdHt, mdKey, jMetadata);
+ mdKey = NULL;
}
}
@@ -1450,6 +1668,11 @@ CODESTARTdoAction
* outside of the cache lock
*/
jMetadataCopy = json_tokener_parse(json_object_get_string(jMetadata));
+ if (!add_pod_metadata) {
+ /* jMetadata object was created from scratch and not cached */
+ json_object_put(jMetadata);
+ jMetadata = NULL;
+ }
pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
/* the +1 is there to skip the leading '$' */
msgAddJSON(pMsg, (uchar *) pWrkrData->pData->dstMetadataPath + 1, jMetadataCopy, 0, 0);
@@ -1470,7 +1693,9 @@ BEGINmodExit
CODESTARTmodExit
curl_global_cleanup();
+ objRelease(datetime, CORE_COMPONENT);
objRelease(regexp, LM_REGEXP_FILENAME);
+ objRelease(statsobj, CORE_COMPONENT);
ENDmodExit
@@ -1489,8 +1714,9 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
DBGPRINTF("mmkubernetes: module compiled with rsyslog version %s.\n", VERSION);
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
CHKiRet(objUse(regexp, LM_REGEXP_FILENAME));
-
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
/* CURL_GLOBAL_ALL initializes more than is needed but the
* libcurl documentation discourages use of other values
*/

View File

@ -1,263 +0,0 @@
From e8d64cbd15fa84907dc23f8b52d6f2f847b46fec Mon Sep 17 00:00:00 2001
From: Rich Megginson <rmeggins@redhat.com>
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);

View File

@ -1,368 +0,0 @@
From f85ef7aabcec84497a5eaf9670616b3402c79d9c Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <rgerhards@adiscon.com>
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 */

View File

@ -1,86 +0,0 @@
From 1255a67fdec2fc44cd49b6ea8c463f4319910812 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
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);

View File

@ -1,60 +0,0 @@
From 920c28ff705aac74f389b4613815b14b9482e497 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
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);
}
}

View File

@ -1,136 +0,0 @@
From 9c22b31cd639911a2faffad02f2ed9f7cc10b9e1 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
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

View File

@ -1,28 +0,0 @@
From f53977817f352ef1c67178687cbfcee849f667fc Mon Sep 17 00:00:00 2001
From: Andre Lorbach <alorbach@adiscon.com>
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;

View File

@ -1,618 +0,0 @@
From b15e6ab7242b25311a9e0dcf14187d21a80a44a6 Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
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")) {

View File

@ -5,8 +5,8 @@
Summary: Enhanced system logging and kernel message trapping daemon
Name: rsyslog
Version: 8.37.0
Release: 13%{?dist}
Version: 8.1911.0
Release: 3%{?dist}
License: (GPLv3+ and ASL 2.0)
Group: System Environment/Daemons
ExcludeArch: i686
@ -44,19 +44,12 @@ Provides: syslog
Obsoletes: sysklogd < 1.5-11
# tweak the upstream service file to honour configuration from /etc/sysconfig/rsyslog
Patch0: rsyslog-8.32.0-service.patch
Patch0: rsyslog-8.1911.0-service.patch
# imjournal: adds "journal" when tag/process name is missing
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
Patch1: rsyslog-8.1911.0-rhbz1659898-imjournal-default-tag.patch
Patch2: rsyslog-8.1911.0-rhbz1763757-imfile-statefiles.patch
Patch3: rsyslog-8.1911.0-rhbz1782353-deny-expired-by-default.patch
Patch4: rsyslog-8.1911.0-rhbz1659383-config-enabled-error.patch
%package crypto
Summary: Encryption support
@ -164,8 +157,8 @@ Elasticsearch.
%description gnutls
The rsyslog-gnutls package contains the rsyslog plugins that provide the
ability to receive syslog messages via upcoming syslog-transport-tls
IETF standard protocol.
ability to send and receive syslog messages via TCP or RELP using TLS
encryption. For details refer to rsyslog doc on imtcp and omfwd modules.
%description gssapi
The rsyslog-gssapi package contains the rsyslog plugins which support GSSAPI
@ -230,16 +223,9 @@ mv build doc
%patch0 -p1 -b .service
%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
%patch2 -p1 -b .imfile-statefiles
%patch3 -p1 -b .deny-expired-certs
%patch4 -p1 -b .config-enabled-on
%build
%ifarch sparc64
@ -276,6 +262,7 @@ autoreconf -if
--enable-mmsnmptrapd \
--enable-mmutf8fix \
--enable-mysql \
--enable-omhttp \
--enable-omjournal \
--enable-omkafka \
--enable-omprog \
@ -367,7 +354,6 @@ done
%{_libdir}/rsyslog/lmnetstrms.so
%{_libdir}/rsyslog/lmnsd_ptcp.so
%{_libdir}/rsyslog/lmregexp.so
%{_libdir}/rsyslog/lmstrmsrv.so
%{_libdir}/rsyslog/lmtcpclt.so
%{_libdir}/rsyslog/lmtcpsrv.so
%{_libdir}/rsyslog/lmzlibw.so
@ -375,6 +361,7 @@ done
%{_libdir}/rsyslog/mmcount.so
%{_libdir}/rsyslog/mmexternal.so
%{_libdir}/rsyslog/mmutf8fix.so
%{_libdir}/rsyslog/omhttp.so
%{_libdir}/rsyslog/omjournal.so
%{_libdir}/rsyslog/ommail.so
%{_libdir}/rsyslog/omprog.so
@ -443,6 +430,38 @@ done
%changelog
* Wed Dec 11 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1911.0-3
RHEL 8.2.0 ERRATUM
- added patch reverting rejecting expired certs by default
resolves: rhbz#1782353
- added patch silencing false errors on config.enabled statement
resolves: rhbz#1659383
* Tue Dec 03 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1911.0-2
RHEL 8.2.0 ERRATUM
- cleaned old patches, fixed patch names
resolves: rhbz#1740683
* Mon Dec 02 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.1911.0-1
RHEL 8.2.0 ERRATUM
- rebased to 8.1911.0 upstream version, removed, previously
upstreamed patches
resolves: rhbz#1740683
resolves: rhbz#1659383
resolves: rhbz#1746876
resolves: rhbz#1676559
resolves: rhbz#1692072
resolves: rhbz#1692073
resolves: rhbz#1692074
resolves: rhbz#1699242
resolves: rhbz#1738213
resolves: rhbz#1744691
resolves: rhbz#1755218
resolves: rhbz#1768321
resolves: rhbz#1768324
- added patch fixing imfile stefiles naming
resolves: rhbz#1763757
* Fri Aug 30 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.37.0-13
RHEL 8.1.0 ERRATUM
- added patch enabling stricter TLS certs checking conforming to