Blame SOURCES/rsyslog-8.24.0-rhbz1627799-cert-chains.patch

ff08e8
diff -up rsyslog-8.24.0/plugins/imtcp/imtcp.c.v36tls rsyslog-8.24.0/plugins/imtcp/imtcp.c
ff08e8
--- rsyslog-8.24.0/plugins/imtcp/imtcp.c.v36tls	2019-08-19 17:37:07.872166694 +0100
ff08e8
+++ rsyslog-8.24.0/plugins/imtcp/imtcp.c	2019-08-19 17:37:07.876166693 +0100
ff08e8
@@ -100,6 +100,7 @@ static struct configSettings_s {
ff08e8
 	int bDisableLFDelim;
ff08e8
 	int bUseFlowControl;
ff08e8
 	int bPreserveCase;
ff08e8
+	uchar *gnutlsPriorityString;
ff08e8
 	uchar *pszStrmDrvrAuthMode;
ff08e8
 	uchar *pszInputName;
ff08e8
 	uchar *pszBindRuleset;
ff08e8
@@ -136,6 +137,7 @@ struct modConfData_s {
ff08e8
 	int iKeepAliveProbes;
ff08e8
 	int iKeepAliveTime;
ff08e8
 	sbool bEmitMsgOnClose; /* emit an informational message on close by remote peer */
ff08e8
+	uchar *gnutlsPriorityString;
ff08e8
 	uchar *pszStrmDrvrName; /* stream driver to use */
ff08e8
 	uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
ff08e8
 	struct cnfarray *permittedPeers;
ff08e8
@@ -164,7 +166,8 @@ static struct cnfparamdescr modpdescr[]
ff08e8
 	{ "keepalive.probes", eCmdHdlrPositiveInt, 0 },
ff08e8
 	{ "keepalive.time", eCmdHdlrPositiveInt, 0 },
ff08e8
 	{ "keepalive.interval", eCmdHdlrPositiveInt, 0 },
ff08e8
-	{ "preservecase", eCmdHdlrBinary, 0 }
ff08e8
+	{ "preservecase", eCmdHdlrBinary, 0 },
ff08e8
+	{ "gnutlsprioritystring", eCmdHdlrString, 0 }
ff08e8
 };
ff08e8
 static struct cnfparamblk modpblk =
ff08e8
 	{ CNFPARAMBLK_VERSION,
ff08e8
@@ -354,6 +357,7 @@ addListner(modConfData_t *modConf, insta
ff08e8
 		CHKiRet(tcpsrv.SetKeepAliveIntvl(pOurTcpsrv, modConf->iKeepAliveIntvl));
ff08e8
 		CHKiRet(tcpsrv.SetKeepAliveProbes(pOurTcpsrv, modConf->iKeepAliveProbes));
ff08e8
 		CHKiRet(tcpsrv.SetKeepAliveTime(pOurTcpsrv, modConf->iKeepAliveTime));
ff08e8
+		CHKiRet(tcpsrv.SetGnutlsPriorityString(pOurTcpsrv, modConf->gnutlsPriorityString));
ff08e8
 		CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, modConf->iTCPSessMax));
ff08e8
 		CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, modConf->iTCPLstnMax));
ff08e8
 		CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, modConf->iStrmDrvrMode));
ff08e8
@@ -463,6 +467,7 @@ CODESTARTbeginCnfLoad
ff08e8
 	loadModConf->bEmitMsgOnClose = 0;
ff08e8
 	loadModConf->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
ff08e8
 	loadModConf->bDisableLFDelim = 0;
ff08e8
+	loadModConf->gnutlsPriorityString = NULL;
ff08e8
 	loadModConf->pszStrmDrvrName = NULL;
ff08e8
 	loadModConf->pszStrmDrvrAuthMode = NULL;
ff08e8
 	loadModConf->permittedPeers = NULL;
ff08e8
@@ -517,6 +522,8 @@ CODESTARTsetModCnf
ff08e8
 			loadModConf->iKeepAliveTime = (int) pvals[i].val.d.n;
ff08e8
 		} else if(!strcmp(modpblk.descr[i].name, "keepalive.interval")) {
ff08e8
 			loadModConf->iKeepAliveIntvl = (int) pvals[i].val.d.n;
ff08e8
+		} else if(!strcmp(modpblk.descr[i].name, "gnutlsprioritystring")) {
ff08e8
+			loadModConf->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
ff08e8
 		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.mode")) {
ff08e8
 			loadModConf->iStrmDrvrMode = (int) pvals[i].val.d.n;
ff08e8
 		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.authmode")) {
ff08e8
diff -up rsyslog-8.24.0/runtime/netstrm.c.v36tls rsyslog-8.24.0/runtime/netstrm.c
ff08e8
--- rsyslog-8.24.0/runtime/netstrm.c.v36tls	2017-01-10 09:00:04.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/netstrm.c	2019-08-19 17:37:07.876166693 +0100
ff08e8
@@ -280,6 +280,16 @@ SetKeepAliveIntvl(netstrm_t *pThis, int
ff08e8
 	RETiRet;
ff08e8
 }
ff08e8
 
ff08e8
+/* gnutls priority string */
ff08e8
+static rsRetVal
ff08e8
+SetGnutlsPriorityString(netstrm_t *pThis, uchar *gnutlsPriorityString)
ff08e8
+{
ff08e8
+	DEFiRet;
ff08e8
+	ISOBJ_TYPE_assert(pThis, netstrm);
ff08e8
+	iRet = pThis->Drvr.SetGnutlsPriorityString(pThis->pDrvrData, gnutlsPriorityString);
ff08e8
+	RETiRet;
ff08e8
+}
ff08e8
+
ff08e8
 /* check connection - slim wrapper for NSD driver function */
ff08e8
 static rsRetVal
ff08e8
 CheckConnection(netstrm_t *pThis)
ff08e8
@@ -387,6 +397,7 @@ CODESTARTobjQueryInterface(netstrm)
ff08e8
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
ff08e8
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
ff08e8
 	pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
ff08e8
+	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
ff08e8
 finalize_it:
ff08e8
 ENDobjQueryInterface(netstrm)
ff08e8
 
ff08e8
diff -up rsyslog-8.24.0/runtime/netstrm.h.v36tls rsyslog-8.24.0/runtime/netstrm.h
ff08e8
--- rsyslog-8.24.0/runtime/netstrm.h.v36tls	2017-01-10 09:00:04.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/netstrm.h	2019-08-19 17:37:07.876166693 +0100
ff08e8
@@ -75,14 +75,16 @@ BEGINinterface(netstrm) /* name must als
ff08e8
 	rsRetVal (*SetKeepAliveProbes)(netstrm_t *pThis, int keepAliveProbes);
ff08e8
 	rsRetVal (*SetKeepAliveTime)(netstrm_t *pThis, int keepAliveTime);
ff08e8
 	rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl);
ff08e8
+	rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString);
ff08e8
 ENDinterface(netstrm)
ff08e8
-#define netstrmCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */
ff08e8
+#define netstrmCURR_IF_VERSION 9 /* increment whenever you change the interface structure! */
ff08e8
 /* interface version 3 added GetRemAddr()
ff08e8
  * interface version 4 added EnableKeepAlive() -- rgerhards, 2009-06-02
ff08e8
  * interface version 5 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
ff08e8
  * interface version 6 changed signature of GetRemoteIP() -- rgerhards, 2013-01-21
ff08e8
  * interface version 7 added KeepAlive parameter set functions
ff08e8
  * interface version 8 changed signature of Connect() -- dsa, 2016-11-14
ff08e8
+ * interface version 9 added SetGnutlsPriorityString -- PascalWithopf, 2017-08-08
ff08e8
  * */
ff08e8
 
ff08e8
 /* prototypes */
ff08e8
diff -up rsyslog-8.24.0/runtime/netstrms.c.v36tls rsyslog-8.24.0/runtime/netstrms.c
ff08e8
--- rsyslog-8.24.0/runtime/netstrms.c.v36tls	2016-12-03 17:41:03.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/netstrms.c	2019-08-19 17:37:07.876166693 +0100
ff08e8
@@ -113,6 +113,10 @@ CODESTARTobjDestruct(netstrms)
ff08e8
 		free(pThis->pBaseDrvrName);
ff08e8
 		pThis->pBaseDrvrName = NULL;
ff08e8
 	}
ff08e8
+	if(pThis->gnutlsPriorityString != NULL) {
ff08e8
+		free(pThis->gnutlsPriorityString);
ff08e8
+		pThis->gnutlsPriorityString = NULL;
ff08e8
+	}
ff08e8
 ENDobjDestruct(netstrms)
ff08e8
 
ff08e8
 
ff08e8
@@ -196,6 +200,31 @@ GetDrvrAuthMode(netstrms_t *pThis)
ff08e8
 }
ff08e8
 
ff08e8
 
ff08e8
+/* Set the priorityString for GnuTLS
ff08e8
+ * PascalWithopf 2017-08-16
ff08e8
+ */
ff08e8
+static rsRetVal
ff08e8
+SetDrvrGnutlsPriorityString(netstrms_t *pThis, uchar *iVal)
ff08e8
+{
ff08e8
+	DEFiRet;
ff08e8
+	ISOBJ_TYPE_assert(pThis, netstrms);
ff08e8
+	CHKmalloc(pThis->gnutlsPriorityString = (uchar*)strdup((char*)iVal));
ff08e8
+finalize_it:
ff08e8
+	RETiRet;
ff08e8
+}
ff08e8
+
ff08e8
+
ff08e8
+/* return the priorityString for GnuTLS
ff08e8
+ * PascalWithopf, 2017-08-16
ff08e8
+ */
ff08e8
+static uchar*
ff08e8
+GetDrvrGnutlsPriorityString(netstrms_t *pThis)
ff08e8
+{
ff08e8
+	ISOBJ_TYPE_assert(pThis, netstrms);
ff08e8
+	return pThis->gnutlsPriorityString;
ff08e8
+}
ff08e8
+
ff08e8
+
ff08e8
 /* set the driver mode -- rgerhards, 2008-04-30 */
ff08e8
 static rsRetVal
ff08e8
 SetDrvrMode(netstrms_t *pThis, int iMode)
ff08e8
@@ -272,6 +301,8 @@ CODESTARTobjQueryInterface(netstrms)
ff08e8
 	pIf->GetDrvrMode = GetDrvrMode;
ff08e8
 	pIf->SetDrvrAuthMode = SetDrvrAuthMode;
ff08e8
 	pIf->GetDrvrAuthMode = GetDrvrAuthMode;
ff08e8
+	pIf->SetDrvrGnutlsPriorityString = SetDrvrGnutlsPriorityString;
ff08e8
+	pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString;
ff08e8
 	pIf->SetDrvrPermPeers = SetDrvrPermPeers;
ff08e8
 	pIf->GetDrvrPermPeers = GetDrvrPermPeers;
ff08e8
 finalize_it:
ff08e8
diff -up rsyslog-8.24.0/runtime/netstrms.h.v36tls rsyslog-8.24.0/runtime/netstrms.h
ff08e8
--- rsyslog-8.24.0/runtime/netstrms.h.v36tls	2016-12-03 17:41:03.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/netstrms.h	2019-08-19 17:37:07.876166693 +0100
ff08e8
@@ -33,6 +33,7 @@ struct netstrms_s {
ff08e8
 	uchar *pDrvrName;	/**< full base driver name (set when driver is loaded) */
ff08e8
 	int iDrvrMode;		/**< current default driver mode */
ff08e8
 	uchar *pszDrvrAuthMode;	/**< current driver authentication mode */
ff08e8
+	uchar *gnutlsPriorityString; /**< priorityString for connection */
ff08e8
 	permittedPeers_t *pPermPeers;/**< current driver's permitted peers */
ff08e8
 
ff08e8
 	nsd_if_t Drvr;		/**< our stream driver */
ff08e8
@@ -52,6 +53,8 @@ BEGINinterface(netstrms) /* name must al
ff08e8
 	int      (*GetDrvrMode)(netstrms_t *pThis);
ff08e8
 	uchar*   (*GetDrvrAuthMode)(netstrms_t *pThis);
ff08e8
 	permittedPeers_t* (*GetDrvrPermPeers)(netstrms_t *pThis);
ff08e8
+	rsRetVal (*SetDrvrGnutlsPriorityString)(netstrms_t *pThis, uchar*);
ff08e8
+	uchar*   (*GetDrvrGnutlsPriorityString)(netstrms_t *pThis);
ff08e8
 ENDinterface(netstrms)
ff08e8
 #define netstrmsCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
ff08e8
 
ff08e8
diff -up rsyslog-8.24.0/runtime/nsd_gtls.c.v36tls rsyslog-8.24.0/runtime/nsd_gtls.c
ff08e8
--- rsyslog-8.24.0/runtime/nsd_gtls.c.v36tls	2017-01-10 09:00:04.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/nsd_gtls.c	2019-08-19 17:39:30.576158227 +0100
ff08e8
@@ -73,8 +73,20 @@ DEFobjCurrIf(nsd_ptcp)
ff08e8
 
ff08e8
 static int bGlblSrvrInitDone = 0;	/**< 0 - server global init not yet done, 1 - already done */
ff08e8
 
ff08e8
-static pthread_mutex_t mutGtlsStrerror; /**< a mutex protecting the potentially non-reentrant gtlStrerror() function */
ff08e8
+static pthread_mutex_t mutGtlsStrerror;
ff08e8
+/*< a mutex protecting the potentially non-reentrant gtlStrerror() function */
ff08e8
 
ff08e8
+/* a macro to abort if GnuTLS error is not acceptable. We split this off from
ff08e8
+ * CHKgnutls() to avoid some Coverity report in cases where we know GnuTLS
ff08e8
+ * failed. Note: gnuRet must already be set accordingly!
ff08e8
+ */
ff08e8
+#define ABORTgnutls { \
ff08e8
+		uchar *pErr = gtlsStrerror(gnuRet); \
ff08e8
+		LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n", \
ff08e8
+	gnuRet, __FILE__, __LINE__, pErr); \
ff08e8
+		free(pErr); \
ff08e8
+		ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
ff08e8
+}
ff08e8
 /* a macro to check GnuTLS calls against unexpected errors */
ff08e8
 #define CHKgnutls(x) { \
ff08e8
 	gnuRet = (x); \
ff08e8
@@ -82,10 +94,7 @@ static pthread_mutex_t mutGtlsStrerror;
ff08e8
 		errmsg.LogError(0, RS_RET_GNUTLS_ERR, "error reading file - a common cause is that the file  does not exist"); \
ff08e8
 		ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
ff08e8
 	} else if(gnuRet != 0) { \
ff08e8
-		uchar *pErr = gtlsStrerror(gnuRet); \
ff08e8
-		errmsg.LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); \
ff08e8
-		free(pErr); \
ff08e8
-		ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
ff08e8
+		ABORTgnutls; \
ff08e8
 	} \
ff08e8
 }
ff08e8
 
70d005
@@ -192,9 +201,13 @@ gtlsLoadOurCertKey(nsd_gtls_t *pThis)
ff08e8
 
ff08e8
 	/* try load certificate */
ff08e8
 	CHKiRet(readFile(certFile, &data));
ff08e8
-	CHKgnutls(gnutls_x509_crt_init(&pThis->ourCert));
70d005
	pThis->bOurCertIsInit = 1;
ff08e8
-	CHKgnutls(gnutls_x509_crt_import(pThis->ourCert, &data, GNUTLS_X509_FMT_PEM));
ff08e8
+	pThis->nOurCerts = sizeof(pThis->pOurCerts) / sizeof(gnutls_x509_crt_t);
ff08e8
+	gnuRet = gnutls_x509_crt_list_import(pThis->pOurCerts, &pThis->nOurCerts,
ff08e8
+		&data, GNUTLS_X509_FMT_PEM,  GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
ff08e8
+	if(gnuRet < 0) {
ff08e8
+		ABORTgnutls;
ff08e8
+	}
ff08e8
 	free(data.data);
ff08e8
 	data.data = NULL;
ff08e8
 
ff08e8
@@ -210,7 +222,9 @@ finalize_it:
ff08e8
 		if(data.data != NULL)
ff08e8
 			free(data.data);
ff08e8
 		if(pThis->bOurCertIsInit) {
ff08e8
-			gnutls_x509_crt_deinit(pThis->ourCert);
ff08e8
+			for(unsigned i=0; i<pThis->nOurCerts; ++i) {
ff08e8
+				gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
ff08e8
+			}
ff08e8
 			pThis->bOurCertIsInit = 0;
ff08e8
 		}
ff08e8
 		if(pThis->bOurKeyIsInit) {
ff08e8
@@ -255,8 +269,8 @@ gtlsClientCertCallback(gnutls_session_t
ff08e8
 #else
ff08e8
 	st->type = GNUTLS_CRT_X509;
ff08e8
 #endif
ff08e8
-	st->ncerts = 1;
ff08e8
-	st->cert.x509 = &pThis->ourCert;
ff08e8
+	st->ncerts = pThis->nOurCerts;
ff08e8
+	st->cert.x509 = pThis->pOurCerts;
ff08e8
 	st->key.x509 = pThis->ourKey;
ff08e8
 	st->deinit_all = 0;
ff08e8
 
ff08e8
@@ -532,8 +546,8 @@ gtlsRecordRecv(nsd_gtls_t *pThis)
ff08e8
 		dbgprintf("GnuTLS receive requires a retry (this most probably is OK and no error condition)\n");
ff08e8
 		ABORT_FINALIZE(RS_RET_RETRY);
ff08e8
 	} else {
ff08e8
-		int gnuRet; /* TODO: build a specific function for GnuTLS error reporting */
ff08e8
-		CHKgnutls(lenRcvd); /* this will abort the function */
ff08e8
+		int gnuRet = lenRcvd;
ff08e8
+		ABORTgnutls;
ff08e8
 	}
ff08e8
 
ff08e8
 finalize_it:
ff08e8
@@ -646,7 +660,7 @@ gtlsInitSession(nsd_gtls_t *pThis)
ff08e8
 	pThis->bIsInitiator = 0;
ff08e8
 
ff08e8
 	/* avoid calling all the priority functions, since the defaults are adequate. */
ff08e8
-	CHKgnutls(gnutls_set_default_priority(session));
ff08e8
+
ff08e8
 	CHKgnutls(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred));
ff08e8
 
ff08e8
 	/* request client certificate if any.  */
ff08e8
@@ -1204,7 +1218,9 @@ CODESTARTobjDestruct(nsd_gtls)
ff08e8
 	}
ff08e8
 
ff08e8
 	if(pThis->bOurCertIsInit)
ff08e8
-		gnutls_x509_crt_deinit(pThis->ourCert);
ff08e8
+                for(unsigned i=0; i<pThis->nOurCerts; ++i) {
ff08e8
+			gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
ff08e8
+                }
ff08e8
 	if(pThis->bOurKeyIsInit)
ff08e8
 		gnutls_x509_privkey_deinit(pThis->ourKey);
ff08e8
 	if(pThis->bHaveSess)
ff08e8
@@ -1299,6 +1315,21 @@ finalize_it:
ff08e8
 }
ff08e8
 
ff08e8
 
ff08e8
+/* gnutls priority string
ff08e8
+ * PascalWithopf 2017-08-16
ff08e8
+ */
ff08e8
+static rsRetVal
ff08e8
+SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString)
ff08e8
+{
ff08e8
+	DEFiRet;
ff08e8
+	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ff08e8
+
ff08e8
+	ISOBJ_TYPE_assert((pThis), nsd_gtls);
ff08e8
+	pThis->gnutlsPriorityString = gnutlsPriorityString;
ff08e8
+	RETiRet;
ff08e8
+}
ff08e8
+
ff08e8
+
ff08e8
 /* Provide access to the underlying OS socket. This is primarily
ff08e8
  * useful for other drivers (like nsd_gtls) who utilize ourselfs
ff08e8
  * for some of their functionality. -- rgerhards, 2008-04-18
ff08e8
@@ -1476,6 +1507,7 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew
ff08e8
 	int gnuRet;
ff08e8
 	nsd_gtls_t *pNew = NULL;
ff08e8
 	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ff08e8
+	const char *error_position;
ff08e8
 
ff08e8
 	ISOBJ_TYPE_assert((pThis), nsd_gtls);
ff08e8
 	CHKiRet(nsd_gtlsConstruct(&pNew)); // TODO: prevent construct/destruct!
ff08e8
@@ -1493,6 +1525,19 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew
ff08e8
 	gtlsSetTransportPtr(pNew, ((nsd_ptcp_t*) (pNew->pTcp))->sock);
ff08e8
 	pNew->authMode = pThis->authMode;
ff08e8
 	pNew->pPermPeers = pThis->pPermPeers;
ff08e8
+	pNew->gnutlsPriorityString = pThis->gnutlsPriorityString;
ff08e8
+	/* here is the priorityString set */
ff08e8
+	if(pNew->gnutlsPriorityString != NULL) {
ff08e8
+		if(gnutls_priority_set_direct(pNew->sess,
ff08e8
+					(const char*) pNew->gnutlsPriorityString,
ff08e8
+					&error_position)==GNUTLS_E_INVALID_REQUEST) {
ff08e8
+			LogError(0, RS_RET_GNUTLS_ERR, "Syntax Error in"
ff08e8
+					" Priority String: \"%s\"\n", error_position);
ff08e8
+		}
ff08e8
+	} else {
ff08e8
+		/* Use default priorities */
ff08e8
+		CHKgnutls(gnutls_set_default_priority(pNew->sess));
ff08e8
+	}
ff08e8
 
ff08e8
 	/* we now do the handshake. This is a bit complicated, because we are 
ff08e8
 	 * on non-blocking sockets. Usually, the handshake will not complete
ff08e8
@@ -1673,6 +1718,31 @@ EnableKeepAlive(nsd_t *pNsd)
ff08e8
 	return nsd_ptcp.EnableKeepAlive(pThis->pTcp);
ff08e8
 }
ff08e8
 
ff08e8
+/*
ff08e8
+ * SNI should not be used if the hostname is a bare IP address
ff08e8
+ */
ff08e8
+static int
ff08e8
+SetServerNameIfPresent(nsd_gtls_t *pThis, uchar *host) {
ff08e8
+	struct sockaddr_in sa;
ff08e8
+	struct sockaddr_in6 sa6;
ff08e8
+
ff08e8
+	int inet_pton_ret = inet_pton(AF_INET, CHAR_CONVERT(host), &(sa.sin_addr));
ff08e8
+
ff08e8
+	if (inet_pton_ret == 0) { // host wasn't a bare IPv4 address: try IPv6
ff08e8
+		inet_pton_ret = inet_pton(AF_INET6, CHAR_CONVERT(host), &(sa6.sin6_addr));
ff08e8
+	}
ff08e8
+
ff08e8
+	switch(inet_pton_ret) {
ff08e8
+		case 1: // host is a valid IP address: don't use SNI
ff08e8
+			return 0;
ff08e8
+		case 0: // host isn't a valid IP address: assume it's a domain name, use SNI
ff08e8
+			return gnutls_server_name_set(pThis->sess, GNUTLS_NAME_DNS, host, ustrlen(host));
ff08e8
+		default: // unexpected error
ff08e8
+			return -1;
ff08e8
+	}
ff08e8
+
ff08e8
+}
ff08e8
+
ff08e8
 /* open a connection to a remote host (server). With GnuTLS, we always
ff08e8
  * open a plain tcp socket and then, if in TLS mode, do a handshake on it.
ff08e8
  * rgerhards, 2008-03-19
ff08e8
@@ -1685,6 +1755,7 @@ Connect(nsd_t *pNsd, int family, uchar *
ff08e8
 	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ff08e8
 	int sock;
ff08e8
 	int gnuRet;
ff08e8
+	const char *error_position;
ff08e8
 #	ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY
ff08e8
 	static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 };
ff08e8
 #	endif
ff08e8
@@ -1704,6 +1775,8 @@ Connect(nsd_t *pNsd, int family, uchar *
ff08e8
 	pThis->bHaveSess = 1;
ff08e8
 	pThis->bIsInitiator = 1;
ff08e8
 
ff08e8
+	CHKgnutls(SetServerNameIfPresent(pThis, host));
ff08e8
+
ff08e8
 	/* in the client case, we need to set a callback that ensures our certificate
ff08e8
 	 * will be presented to the server even if it is not signed by one of the server's
ff08e8
 	 * trusted roots. This is necessary to support fingerprint authentication.
ff08e8
@@ -1721,8 +1794,19 @@ Connect(nsd_t *pNsd, int family, uchar *
ff08e8
 		FINALIZE; /* we have an error case! */
ff08e8
 	}
ff08e8
 
ff08e8
-	/* Use default priorities */
ff08e8
-	CHKgnutls(gnutls_set_default_priority(pThis->sess));
ff08e8
+	/*priority string setzen*/
ff08e8
+	if(pThis->gnutlsPriorityString != NULL) {
ff08e8
+		if(gnutls_priority_set_direct(pThis->sess,
ff08e8
+					(const char*) pThis->gnutlsPriorityString,
ff08e8
+					&error_position)==GNUTLS_E_INVALID_REQUEST) {
ff08e8
+			LogError(0, RS_RET_GNUTLS_ERR, "Syntax Error in"
ff08e8
+					" Priority String: \"%s\"\n", error_position);
ff08e8
+		}
ff08e8
+	} else {
ff08e8
+		/* Use default priorities */
ff08e8
+		CHKgnutls(gnutls_set_default_priority(pThis->sess));
ff08e8
+	}
ff08e8
+
ff08e8
 #	ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY
ff08e8
 	/* The gnutls_certificate_type_set_priority function is deprecated
ff08e8
 	 * and not available in recent GnuTLS versions. However, there is no
ff08e8
@@ -1806,6 +1890,7 @@ CODESTARTobjQueryInterface(nsd_gtls)
ff08e8
 	pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
ff08e8
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
ff08e8
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
ff08e8
+	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
ff08e8
 finalize_it:
ff08e8
 ENDobjQueryInterface(nsd_gtls)
ff08e8
 
ff08e8
diff -up rsyslog-8.24.0/runtime/nsd_gtls.h.v36tls rsyslog-8.24.0/runtime/nsd_gtls.h
ff08e8
--- rsyslog-8.24.0/runtime/nsd_gtls.h.v36tls	2016-12-03 17:41:03.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/nsd_gtls.h	2019-08-19 17:37:07.878166693 +0100
ff08e8
@@ -25,6 +25,7 @@
ff08e8
 #include "nsd.h"
ff08e8
 
ff08e8
 #define NSD_GTLS_MAX_RCVBUF 8 * 1024 /* max size of buffer for message reception */
ff08e8
+#define NSD_GTLS_MAX_CERT 10 /* max number of certs in our chain */
ff08e8
 
ff08e8
 typedef enum {
ff08e8
 	gtlsRtry_None = 0,	/**< no call needs to be retried */
ff08e8
@@ -56,7 +57,10 @@ struct nsd_gtls_s {
ff08e8
 				 * set to 1 and changed to 0 after the first report. It is changed back to 1 after
ff08e8
 				 * one successful authentication. */
ff08e8
 	permittedPeers_t *pPermPeers; /* permitted peers */
ff08e8
-	gnutls_x509_crt_t ourCert;	/**< our certificate, if in client mode (unused in server mode) */
ff08e8
+	uchar *gnutlsPriorityString;	/* gnutls priority string */
ff08e8
+	gnutls_x509_crt_t pOurCerts[NSD_GTLS_MAX_CERT];	/**< our certificate, if in client mode
ff08e8
+							(unused in server mode) */
ff08e8
+	unsigned int nOurCerts;  /* number of certificates in our chain */
ff08e8
 	gnutls_x509_privkey_t ourKey;	/**< our private key, if in client mode (unused in server mode) */
ff08e8
 	short	bOurCertIsInit;	/**< 1 if our certificate is initialized and must be deinit on destruction */
ff08e8
 	short	bOurKeyIsInit;	/**< 1 if our private key is initialized and must be deinit on destruction */
ff08e8
diff -up rsyslog-8.24.0/runtime/nsd.h.v36tls rsyslog-8.24.0/runtime/nsd.h
ff08e8
--- rsyslog-8.24.0/runtime/nsd.h.v36tls	2017-01-10 09:00:04.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/nsd.h	2019-08-19 17:37:07.878166693 +0100
ff08e8
@@ -83,14 +83,17 @@ BEGINinterface(nsd) /* name must also be
ff08e8
 	rsRetVal (*SetKeepAliveIntvl)(nsd_t *pThis, int keepAliveIntvl);
ff08e8
 	rsRetVal (*SetKeepAliveProbes)(nsd_t *pThis, int keepAliveProbes);
ff08e8
 	rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime);
ff08e8
+	/* v10 */
ff08e8
+	rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString);
ff08e8
 ENDinterface(nsd)
ff08e8
-#define nsdCURR_IF_VERSION 9 /* increment whenever you change the interface structure! */
ff08e8
+#define nsdCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */
ff08e8
 /* interface version 4 added GetRemAddr()
ff08e8
  * interface version 5 added EnableKeepAlive() -- rgerhards, 2009-06-02
ff08e8
  * interface version 6 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
ff08e8
  * interface version 7 changed signature ofGetRempoteIP() -- rgerhards, 2013-01-21
ff08e8
  * interface version 8 added keep alive parameter set functions
ff08e8
  * interface version 9 changed signature of Connect() -- dsa, 2016-11-14
ff08e8
+ * interface version 10 added SetGnutlsPriorityString() -- PascalWithopf, 2017-08-08
ff08e8
  */
ff08e8
 
ff08e8
 /* interface  for the select call */
ff08e8
diff -up rsyslog-8.24.0/runtime/nsd_ptcp.c.v36tls rsyslog-8.24.0/runtime/nsd_ptcp.c
ff08e8
--- rsyslog-8.24.0/runtime/nsd_ptcp.c.v36tls	2017-01-10 09:00:04.000000000 +0000
ff08e8
+++ rsyslog-8.24.0/runtime/nsd_ptcp.c	2019-08-19 17:37:07.879166693 +0100
ff08e8
@@ -176,6 +176,23 @@ finalize_it:
ff08e8
 }
ff08e8
 
ff08e8
 
ff08e8
+/* Set priorityString
ff08e8
+ * PascalWithopf 2017-08-18 */
ff08e8
+static rsRetVal
ff08e8
+SetGnutlsPriorityString(nsd_t __attribute__((unused)) *pNsd, uchar *iVal)
ff08e8
+{
ff08e8
+	DEFiRet;
ff08e8
+	if(iVal != NULL) {
ff08e8
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: "
ff08e8
+		"gnutlsPriorityString '%s' not supported by ptcp netstream "
ff08e8
+		"driver", iVal);
ff08e8
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
ff08e8
+	}
ff08e8
+finalize_it:
ff08e8
+	RETiRet;
ff08e8
+}
ff08e8
+
ff08e8
+
ff08e8
 /* Set the permitted peers. This is a dummy, always returning an
ff08e8
  * error because we do not support fingerprint authentication.
ff08e8
  * rgerhards, 2008-05-17
ff08e8
@@ -535,6 +552,7 @@ LstnInit(netstrms_t *pNS, void *pUsr, rs
ff08e8
 		CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS)));
ff08e8
 		CHKiRet(pNS->Drvr.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS)));
ff08e8
 		CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS)));
ff08e8
+		CHKiRet(pNS->Drvr.SetGnutlsPriorityString(pNewNsd, netstrms.GetDrvrGnutlsPriorityString(pNS)));
ff08e8
 		CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm));
ff08e8
 		pNewStrm->pDrvrData = (nsd_t*) pNewNsd;
ff08e8
 		pNewNsd = NULL;
ff08e8
@@ -854,6 +872,7 @@ CODESTARTobjQueryInterface(nsd_ptcp)
ff08e8
 	pIf->SetSock = SetSock;
ff08e8
 	pIf->SetMode = SetMode;
ff08e8
 	pIf->SetAuthMode = SetAuthMode;
ff08e8
+	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
ff08e8
 	pIf->SetPermPeers = SetPermPeers;
ff08e8
 	pIf->Rcv = Rcv;
ff08e8
 	pIf->Send = Send;
ff08e8
diff -up rsyslog-8.24.0/runtime/tcpsrv.c.v36tls rsyslog-8.24.0/runtime/tcpsrv.c
ff08e8
--- rsyslog-8.24.0/runtime/tcpsrv.c.v36tls	2019-08-19 17:37:07.874166693 +0100
ff08e8
+++ rsyslog-8.24.0/runtime/tcpsrv.c	2019-08-19 17:37:07.880166693 +0100
ff08e8
@@ -470,6 +470,9 @@ SessAccept(tcpsrv_t *pThis, tcpLstnPortL
ff08e8
 	}
ff08e8
 
ff08e8
 	/* we found a free spot and can construct our session object */
ff08e8
+	if(pThis->gnutlsPriorityString != NULL) {
ff08e8
+		CHKiRet(netstrm.SetGnutlsPriorityString(pNewStrm, pThis->gnutlsPriorityString));
ff08e8
+	}
ff08e8
 	CHKiRet(tcps_sess.Construct(&pSess));
ff08e8
 	CHKiRet(tcps_sess.SetTcpsrv(pSess, pThis));
ff08e8
 	CHKiRet(tcps_sess.SetLstnInfo(pSess, pLstnInfo));
ff08e8
@@ -1001,6 +1004,8 @@ tcpsrvConstructFinalize(tcpsrv_t *pThis)
ff08e8
 		CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode));
ff08e8
 	if(pThis->pPermPeers != NULL)
ff08e8
 		CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers));
ff08e8
+	if(pThis->gnutlsPriorityString != NULL)
ff08e8
+		CHKiRet(netstrms.SetDrvrGnutlsPriorityString(pThis->pNS, pThis->gnutlsPriorityString));
ff08e8
 	CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
ff08e8
 
ff08e8
 	/* set up listeners */
ff08e8
@@ -1173,6 +1178,16 @@ SetKeepAliveTime(tcpsrv_t *pThis, int iV
ff08e8
 }
ff08e8
 
ff08e8
 static rsRetVal
ff08e8
+SetGnutlsPriorityString(tcpsrv_t *pThis, uchar *iVal)
ff08e8
+{
ff08e8
+	DEFiRet;
ff08e8
+	DBGPRINTF("tcpsrv: gnutlsPriorityString set to %s\n",
ff08e8
+		(iVal == NULL) ? "(null)" : (const char*) iVal);
ff08e8
+	pThis->gnutlsPriorityString = iVal;
ff08e8
+	RETiRet;
ff08e8
+}
ff08e8
+
ff08e8
+static rsRetVal
ff08e8
 SetOnMsgReceive(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int))
ff08e8
 {
ff08e8
 	DEFiRet;
ff08e8
@@ -1414,6 +1429,7 @@ CODESTARTobjQueryInterface(tcpsrv)
ff08e8
 	pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
ff08e8
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
ff08e8
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
ff08e8
+	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
ff08e8
 	pIf->SetUsrP = SetUsrP;
ff08e8
 	pIf->SetInputName = SetInputName;
ff08e8
 	pIf->SetOrigin = SetOrigin;
ff08e8
diff -up rsyslog-8.24.0/runtime/tcpsrv.h.v36tls rsyslog-8.24.0/runtime/tcpsrv.h
ff08e8
--- rsyslog-8.24.0/runtime/tcpsrv.h.v36tls	2019-08-19 17:37:07.874166693 +0100
ff08e8
+++ rsyslog-8.24.0/runtime/tcpsrv.h	2019-08-19 17:37:07.880166693 +0100
ff08e8
@@ -61,6 +61,7 @@ struct tcpsrv_s {
ff08e8
 	int iKeepAliveTime;	/**< socket layer KEEPALIVE timeout */
ff08e8
 	netstrms_t *pNS;	/**< pointer to network stream subsystem */
ff08e8
 	int iDrvrMode;		/**< mode of the stream driver to use */
ff08e8
+	uchar *gnutlsPriorityString;	/**< priority string for gnutls */
ff08e8
 	uchar *pszDrvrAuthMode;	/**< auth mode of the stream driver to use */
ff08e8
 	uchar *pszDrvrName;	/**< name of stream driver to use */
ff08e8
 	uchar *pszInputName;	/**< value to be used as input name */
ff08e8
@@ -169,6 +170,8 @@ BEGINinterface(tcpsrv) /* name must also
ff08e8
 	rsRetVal (*SetKeepAliveTime)(tcpsrv_t*, int);
ff08e8
 	/* added v18 */
ff08e8
 	rsRetVal (*SetbSPFramingFix)(tcpsrv_t*, sbool);
ff08e8
+	/* added v19 -- PascalWithopf, 2017-08-08 */
ff08e8
+	rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*);
ff08e8
 	/* added v21 -- Preserve case in fromhost, 2018-08-16 */
ff08e8
 	rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase);
ff08e8
 ENDinterface(tcpsrv)
ff08e8
diff -up rsyslog-8.24.0/tools/omfwd.c.v36tls rsyslog-8.24.0/tools/omfwd.c
ff08e8
--- rsyslog-8.24.0/tools/omfwd.c.v36tls	2019-08-19 17:37:07.848166695 +0100
ff08e8
+++ rsyslog-8.24.0/tools/omfwd.c	2019-08-19 17:37:07.881166693 +0100
ff08e8
@@ -91,6 +91,7 @@ typedef struct _instanceData {
ff08e8
 	int iKeepAliveIntvl;
ff08e8
 	int iKeepAliveProbes;
ff08e8
 	int iKeepAliveTime;
ff08e8
+	uchar *gnutlsPriorityString;
ff08e8
 
ff08e8
 #	define	FORW_UDP 0
ff08e8
 #	define	FORW_TCP 1
ff08e8
@@ -138,6 +139,7 @@ typedef struct configSettings_s {
ff08e8
 	int iKeepAliveIntvl;
ff08e8
 	int iKeepAliveProbes;
ff08e8
 	int iKeepAliveTime;
ff08e8
+	uchar *gnutlsPriorityString;
ff08e8
 	permittedPeers_t *pPermPeers;
ff08e8
 } configSettings_t;
ff08e8
 static configSettings_t cs;
ff08e8
@@ -169,6 +171,7 @@ static struct cnfparamdescr actpdescr[]
ff08e8
 	{ "keepalive.probes", eCmdHdlrPositiveInt, 0 },
ff08e8
 	{ "keepalive.time", eCmdHdlrPositiveInt, 0 },
ff08e8
 	{ "keepalive.interval", eCmdHdlrPositiveInt, 0 },
ff08e8
+	{ "gnutlsprioritystring", eCmdHdlrString, 0 },
ff08e8
 	{ "streamdriver", eCmdHdlrGetWord, 0 },
ff08e8
 	{ "streamdrivermode", eCmdHdlrInt, 0 },
ff08e8
 	{ "streamdriverauthmode", eCmdHdlrGetWord, 0 },
ff08e8
@@ -717,6 +720,9 @@ static rsRetVal TCPSendInit(void *pvData
ff08e8
 			CHKiRet(netstrm.SetDrvrPermPeers(pWrkrData->pNetstrm, pData->pPermPeers));
ff08e8
 		}
ff08e8
 		/* params set, now connect */
ff08e8
+		if(pData->gnutlsPriorityString != NULL) {
ff08e8
+			CHKiRet(netstrm.SetGnutlsPriorityString(pWrkrData->pNetstrm, pData->gnutlsPriorityString));
ff08e8
+		}
ff08e8
 		CHKiRet(netstrm.Connect(pWrkrData->pNetstrm, glbl.GetDefPFFamily(),
ff08e8
 			(uchar*)pData->port, (uchar*)pData->target, pData->device));
ff08e8
 
ff08e8
@@ -960,6 +966,7 @@ setInstParamDefaults(instanceData *pData
ff08e8
 	pData->iKeepAliveProbes = 0;
ff08e8
 	pData->iKeepAliveIntvl = 0;
ff08e8
 	pData->iKeepAliveTime = 0;
ff08e8
+	pData->gnutlsPriorityString = NULL;
ff08e8
 	pData->bResendLastOnRecon = 0; 
ff08e8
 	pData->bSendToAll = -1;  /* unspecified */
ff08e8
 	pData->iUDPSendDelay = 0;
ff08e8
@@ -1046,6 +1053,8 @@ CODESTARTnewActInst
ff08e8
 			pData->iKeepAliveIntvl = (int) pvals[i].val.d.n;
ff08e8
 		} else if(!strcmp(actpblk.descr[i].name, "keepalive.time")) {
ff08e8
 			pData->iKeepAliveTime = (int) pvals[i].val.d.n;
ff08e8
+		} else if(!strcmp(actpblk.descr[i].name, "gnutlsprioritystring")) {
ff08e8
+			pData->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
ff08e8
 		} else if(!strcmp(actpblk.descr[i].name, "streamdriver")) {
ff08e8
 			pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
ff08e8
 		} else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) {