Blame SOURCES/rsyslog-8.37.0-rhbz1733244-TLS-CC-compatibility.patch

763e28
From b15e6ab7242b25311a9e0dcf14187d21a80a44a6 Mon Sep 17 00:00:00 2001
763e28
From: Jiri Vymazal <jvymazal@redhat.com>
763e28
Date: Fri, 16 Aug 2019 15:01:11 +0200
763e28
Subject: [PATCH] Stricter GnuTLS operation
763e28
763e28
This commit adds to new flags which can be set to allow
763e28
1) checking of extendedKeyUsage certificate field
763e28
2) stricter checking of certificate name/adresses
763e28
---
763e28
 plugins/imtcp/imtcp.c | 12 +++++++
763e28
 runtime/netstrm.c     | 22 +++++++++++++
763e28
 runtime/netstrm.h     |  5 ++-
763e28
 runtime/netstrms.c    | 47 +++++++++++++++++++++++++++
763e28
 runtime/netstrms.h    |  6 ++++
763e28
 runtime/nsd.h         |  7 ++--
763e28
 runtime/nsd_gtls.c    | 74 ++++++++++++++++++++++++++++++++++++++++---
763e28
 runtime/nsd_gtls.h    | 12 +++++++
763e28
 runtime/nsd_ossl.c    | 36 +++++++++++++++++++++
763e28
 runtime/nsd_ptcp.c    | 35 ++++++++++++++++++++
763e28
 runtime/tcpsrv.c      | 24 ++++++++++++++
763e28
 runtime/tcpsrv.h      |  7 +++-
763e28
 tools/omfwd.c         | 12 +++++++
763e28
 13 files changed, 291 insertions(+), 8 deletions(-)
763e28
763e28
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
763e28
index 55245842d5..6b3401f8fe 100644
763e28
--- a/plugins/imtcp/imtcp.c
763e28
+++ b/plugins/imtcp/imtcp.c
763e28
@@ -131,6 +131,8 @@ struct modConfData_s {
763e28
 	int iTCPSessMax; /* max number of sessions */
763e28
 	int iTCPLstnMax; /* max number of sessions */
763e28
 	int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
763e28
+	int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */
763e28
+	int iStrmDrvrSANPreference; /* ignore CN when any SAN set */
763e28
 	int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
763e28
 	int maxFrameSize;
763e28
 	int bSuppOctetFram;
763e28
@@ -170,6 +172,8 @@ static struct cnfparamdescr modpdescr[] = {
763e28
 	{ "streamdriver.mode", eCmdHdlrNonNegInt, 0 },
763e28
 	{ "streamdriver.authmode", eCmdHdlrString, 0 },
763e28
 	{ "streamdriver.name", eCmdHdlrString, 0 },
763e28
+	{ "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
763e28
+	{ "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
763e28
 	{ "permittedpeer", eCmdHdlrArray, 0 },
763e28
 	{ "keepalive", eCmdHdlrBinary, 0 },
763e28
 	{ "keepalive.probes", eCmdHdlrPositiveInt, 0 },
763e28
@@ -368,6 +372,8 @@ addListner(modConfData_t *modConf, instanceConf_t *inst)
763e28
 		CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, modConf->iTCPSessMax));
763e28
 		CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, modConf->iTCPLstnMax));
763e28
 		CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, modConf->iStrmDrvrMode));
763e28
+		CHKiRet(tcpsrv.SetDrvrCheckExtendedKeyUsage(pOurTcpsrv, modConf->iStrmDrvrExtendedCertCheck));
763e28
+		CHKiRet(tcpsrv.SetDrvrPrioritizeSAN(pOurTcpsrv, modConf->iStrmDrvrSANPreference));
763e28
 		CHKiRet(tcpsrv.SetUseFlowControl(pOurTcpsrv, modConf->bUseFlowControl));
763e28
 		CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, modConf->iAddtlFrameDelim));
763e28
 		CHKiRet(tcpsrv.SetMaxFrameSize(pOurTcpsrv, modConf->maxFrameSize));
763e28
@@ -479,6 +485,8 @@ CODESTARTbeginCnfLoad
763e28
 	loadModConf->iTCPLstnMax = 20;
763e28
 	loadModConf->bSuppOctetFram = 1;
763e28
 	loadModConf->iStrmDrvrMode = 0;
763e28
+	loadModConf->iStrmDrvrExtendedCertCheck = 0;
763e28
+	loadModConf->iStrmDrvrSANPreference = 0;
763e28
 	loadModConf->bUseFlowControl = 1;
763e28
 	loadModConf->bKeepAlive = 0;
763e28
 	loadModConf->iKeepAliveIntvl = 0;
763e28
@@ -560,6 +568,10 @@ CODESTARTsetModCnf
763e28
 			loadModConf->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
763e28
 		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.mode")) {
763e28
 			loadModConf->iStrmDrvrMode = (int) pvals[i].val.d.n;
763e28
+		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
763e28
+			loadModConf->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n;
763e28
+		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
763e28
+			loadModConf->iStrmDrvrSANPreference = (int) pvals[i].val.d.n;
763e28
 		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.authmode")) {
763e28
 			loadModConf->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
763e28
 		} else if(!strcmp(modpblk.descr[i].name, "streamdriver.name")) {
763e28
diff --git a/runtime/netstrm.c b/runtime/netstrm.c
763e28
index e1df83edee..59aa135997 100644
763e28
--- a/runtime/netstrm.c
763e28
+++ b/runtime/netstrm.c
763e28
@@ -221,6 +221,26 @@ SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers)
763e28
 	RETiRet;
763e28
 }
763e28
 
763e28
+/* Mandate also verification of Extended key usage / purpose field */
763e28
+static rsRetVal
763e28
+SetDrvrCheckExtendedKeyUsage(netstrm_t *pThis, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, netstrm);
763e28
+	iRet = pThis->Drvr.SetCheckExtendedKeyUsage(pThis->pDrvrData, ChkExtendedKeyUsage);
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+/* Mandate stricter name checking per RFC 6125 - ignoce CN if any SAN present */
763e28
+static rsRetVal
763e28
+SetDrvrPrioritizeSAN(netstrm_t *pThis, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, netstrm);
763e28
+	iRet = pThis->Drvr.SetPrioritizeSAN(pThis->pDrvrData, prioritizeSan);
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
 
763e28
 /* End of methods to shuffle autentication settings to the driver.
763e28
  * -------------------------------------------------------------------------- */
763e28
@@ -405,6 +425,8 @@ CODESTARTobjQueryInterface(netstrm)
763e28
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
763e28
 	pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
763e28
 	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
763e28
+	pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
763e28
+	pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(netstrm)
763e28
 
763e28
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
763e28
index 113585d0a5..08b58fd119 100644
763e28
--- a/runtime/netstrm.h
763e28
+++ b/runtime/netstrm.h
763e28
@@ -78,8 +78,11 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
763e28
 	rsRetVal (*SetKeepAliveTime)(netstrm_t *pThis, int keepAliveTime);
763e28
 	rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl);
763e28
 	rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString);
763e28
+	/* v12 -- two new binary flags added to gtls driver enabling stricter operation */
763e28
+	rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrm_t *pThis, int ChkExtendedKeyUsage);
763e28
+	rsRetVal (*SetDrvrPrioritizeSAN)(netstrm_t *pThis, int prioritizeSan);
763e28
 ENDinterface(netstrm)
763e28
-#define netstrmCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */
763e28
+#define netstrmCURR_IF_VERSION 12 /* increment whenever you change the interface structure! */
763e28
 /* interface version 3 added GetRemAddr()
763e28
  * interface version 4 added EnableKeepAlive() -- rgerhards, 2009-06-02
763e28
  * interface version 5 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
763e28
diff --git a/runtime/netstrms.c b/runtime/netstrms.c
763e28
index bd6a06bd7f..a8c342b76b 100644
763e28
--- a/runtime/netstrms.c
763e28
+++ b/runtime/netstrms.c
763e28
@@ -279,6 +279,49 @@ GetDrvrMode(netstrms_t *pThis)
763e28
 }
763e28
 
763e28
 
763e28
+/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */
763e28
+static rsRetVal
763e28
+SetDrvrCheckExtendedKeyUsage(netstrms_t *pThis, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, netstrms);
763e28
+	pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage;
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+
763e28
+/* return the driver cert extended key usage check setting
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static int
763e28
+GetDrvrCheckExtendedKeyUsage(netstrms_t *pThis)
763e28
+{
763e28
+	ISOBJ_TYPE_assert(pThis, netstrms);
763e28
+	return pThis->DrvrChkExtendedKeyUsage;
763e28
+}
763e28
+
763e28
+
763e28
+/* set the driver name checking policy -- jvymazal, 2019-08-16 */
763e28
+static rsRetVal
763e28
+SetDrvrPrioritizeSAN(netstrms_t *pThis, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, netstrms);
763e28
+	pThis->DrvrPrioritizeSan = prioritizeSan;
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+
763e28
+/* return the driver name checking policy
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static int
763e28
+GetDrvrPrioritizeSAN(netstrms_t *pThis)
763e28
+{
763e28
+	ISOBJ_TYPE_assert(pThis, netstrms);
763e28
+	return pThis->DrvrPrioritizeSan;
763e28
+}
763e28
+
763e28
 /* create an instance of a netstrm object. It is initialized with default
763e28
  * values. The current driver is used. The caller may set netstrm properties
763e28
  * and must call ConstructFinalize().
763e28
@@ -337,6 +380,10 @@ CODESTARTobjQueryInterface(netstrms)
763e28
 	pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString;
763e28
 	pIf->SetDrvrPermPeers = SetDrvrPermPeers;
763e28
 	pIf->GetDrvrPermPeers = GetDrvrPermPeers;
763e28
+	pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
763e28
+	pIf->GetDrvrCheckExtendedKeyUsage = GetDrvrCheckExtendedKeyUsage;
763e28
+	pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
763e28
+	pIf->GetDrvrPrioritizeSAN = GetDrvrPrioritizeSAN;
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(netstrms)
763e28
 
763e28
diff --git a/runtime/netstrms.h b/runtime/netstrms.h
763e28
index 440beb20c9..f21bd6a8e2 100644
763e28
--- a/runtime/netstrms.h
763e28
+++ b/runtime/netstrms.h
763e28
@@ -33,6 +33,8 @@ struct netstrms_s {
763e28
 	uchar *pDrvrName;	/**< full base driver name (set when driver is loaded) */
763e28
 	int iDrvrMode;		/**< current default driver mode */
763e28
 	uchar *pszDrvrAuthMode;	/**< current driver authentication mode */
763e28
+	int DrvrChkExtendedKeyUsage;		/**< if true, verify extended key usage in certs */
763e28
+	int DrvrPrioritizeSan;		/**< if true, perform stricter checking of names in certs */
763e28
 	uchar *gnutlsPriorityString; /**< priorityString for connection */
763e28
 	permittedPeers_t *pPermPeers;/**< current driver's permitted peers */
763e28
 
763e28
@@ -58,6 +60,10 @@ BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */
763e28
 	permittedPeers_t* (*GetDrvrPermPeers)(netstrms_t *pThis);
763e28
 	rsRetVal (*SetDrvrGnutlsPriorityString)(netstrms_t *pThis, uchar*);
763e28
 	uchar*   (*GetDrvrGnutlsPriorityString)(netstrms_t *pThis);
763e28
+	rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis, int ChkExtendedKeyUsage);
763e28
+	int      (*GetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis);
763e28
+	rsRetVal (*SetDrvrPrioritizeSAN)(netstrms_t *pThis, int prioritizeSan);
763e28
+	int      (*GetDrvrPrioritizeSAN)(netstrms_t *pThis);
763e28
 ENDinterface(netstrms)
763e28
 #define netstrmsCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
763e28
 
763e28
diff --git a/runtime/nsd.h b/runtime/nsd.h
763e28
index eab53ad6ae..f0cb5bd1aa 100644
763e28
--- a/runtime/nsd.h
763e28
+++ b/runtime/nsd.h
763e28
@@ -85,8 +85,11 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
763e28
 	rsRetVal (*SetKeepAliveProbes)(nsd_t *pThis, int keepAliveProbes);
763e28
 	rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime);
763e28
 	rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString);
763e28
+	/* v13 -- two new binary flags added to gtls driver enabling stricter operation */
763e28
+	rsRetVal (*SetCheckExtendedKeyUsage)(nsd_t *pThis, int ChkExtendedKeyUsage);
763e28
+	rsRetVal (*SetPrioritizeSAN)(nsd_t *pThis, int prioritizeSan);
763e28
 ENDinterface(nsd)
763e28
-#define nsdCURR_IF_VERSION 11 /* increment whenever you change the interface structure! */
763e28
+#define nsdCURR_IF_VERSION 13 /* increment whenever you change the interface structure! */
763e28
 /* interface version 4 added GetRemAddr()
763e28
  * interface version 5 added EnableKeepAlive() -- rgerhards, 2009-06-02
763e28
  * interface version 6 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
763e28
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
763e28
index 56238b9cb4..a3662bedf4 100644
763e28
--- a/runtime/nsd_gtls.c
763e28
+++ b/runtime/nsd_gtls.c
763e28
@@ -1004,6 +1004,7 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert)
763e28
 	int iAltName;
763e28
 	size_t szAltNameLen;
763e28
 	int bFoundPositiveMatch;
763e28
+	int bHaveSAN = 0;
763e28
 	cstr_t *pStr = NULL;
763e28
 	cstr_t *pstrCN = NULL;
763e28
 	int gnuRet;
763e28
@@ -1023,6 +1024,7 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert)
763e28
 		if(gnuRet < 0)
763e28
 			break;
763e28
 		else if(gnuRet == GNUTLS_SAN_DNSNAME) {
763e28
+			bHaveSAN = 1;
763e28
 			dbgprintf("subject alt dnsName: '%s'\n", szAltName);
763e28
 			snprintf((char*)lnBuf, sizeof(lnBuf), "DNSname: %s; ", szAltName);
763e28
 			CHKiRet(rsCStrAppendStr(pStr, lnBuf));
763e28
@@ -1032,8 +1034,8 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert)
763e28
 		++iAltName;
763e28
 	}
763e28
 
763e28
-	if(!bFoundPositiveMatch) {
763e28
-		/* if we did not succeed so far, we try the CN part of the DN... */
763e28
+	/* Check also CN only if not configured per stricter RFC 6125 or no SAN present*/
763e28
+	if(!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) {
763e28
 		CHKiRet(gtlsGetCN(pCert, &pstrCN));
763e28
 		if(pstrCN != NULL) { /* NULL if there was no CN present */
763e28
 			dbgprintf("gtls now checking auth for CN '%s'\n", cstrGetSzStrNoNULL(pstrCN));
763e28
@@ -1044,7 +1044,19 @@  gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
763e28
 		ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
763e28
 	}
763e28
 
763e28
-	CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert));
763e28
+	if (pThis->dataTypeCheck == GTLS_NONE) {
763e28
+		CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert));
763e28
+	} else { /* we have configured data to check in addition to cert */
763e28
+		gnutls_typed_vdata_st data;
763e28
+		data.type = GNUTLS_DT_KEY_PURPOSE_OID;
763e28
+		if (pThis->bIsInitiator) { /* client mode */
763e28
+			data.data = (uchar *)GNUTLS_KP_TLS_WWW_SERVER;
763e28
+		} else { /* server mode */
763e28
+			data.data = (uchar *)GNUTLS_KP_TLS_WWW_CLIENT;
763e28
+		}
763e28
+		data.size = ustrlen(data.data);
763e28
+		CHKgnutls(gnutls_certificate_verify_peers(pThis->sess, &data, 1, &stateCert));
763e28
+	}
763e28
 
763e28
 	if(stateCert & GNUTLS_CERT_INVALID) {
763e28
 		/* provide error details if we have them */
763e28
@@ -1188,6 +1205,8 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
763e28
 			pszErrCause = "insecure algorithm";
763e28
 		} else if(stateCert & GNUTLS_CERT_REVOKED) {
763e28
 			pszErrCause = "certificate revoked";
763e28
+		} else if(stateCert & GNUTLS_CERT_PURPOSE_MISMATCH) {
763e28
+			pszErrCause = "key purpose OID does not match";
763e28
 		} else {
763e28
 			pszErrCause = "GnuTLS returned no specific reason";
763e28
 			dbgprintf("GnuTLS returned no specific reason for GNUTLS_CERT_INVALID, certificate "
763e28
@@ -1499,6 +1516,53 @@ SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString)
763e28
 	RETiRet;
763e28
 }
763e28
 
763e28
+/* Set the driver cert extended key usage check setting
763e28
+ * 0 - ignore contents of extended key usage
763e28
+ * 1 - verify that cert contents is compatible with appropriate OID
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetCheckExtendedKeyUsage(nsd_t *pNsd, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
763e28
+
763e28
+	ISOBJ_TYPE_assert((pThis), nsd_gtls);
763e28
+	if(ChkExtendedKeyUsage != 0 && ChkExtendedKeyUsage != 1) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
763e28
+				"not supported by gtls netstream driver", ChkExtendedKeyUsage);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+
763e28
+	pThis->dataTypeCheck = ChkExtendedKeyUsage;
763e28
+
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+/* Set the driver name checking strictness
763e28
+ * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good
763e28
+ * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored)
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
763e28
+
763e28
+	ISOBJ_TYPE_assert((pThis), nsd_gtls);
763e28
+	if(prioritizeSan != 0 && prioritizeSan != 1) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
763e28
+				"not supported by gtls netstream driver", prioritizeSan);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+
763e28
+	pThis->bSANpriority = prioritizeSan;
763e28
+
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
 
763e28
 /* Provide access to the underlying OS socket. This is primarily
763e28
  * useful for other drivers (like nsd_gtls) who utilize ourselfs
763e28
@@ -2124,6 +2188,8 @@ CODESTARTobjQueryInterface(nsd_gtls)
763e28
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
763e28
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
763e28
 	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
763e28
+	pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage;
763e28
+	pIf->SetPrioritizeSAN = SetPrioritizeSAN;
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(nsd_gtls)
763e28
 
763e28
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
763e28
index 80a86f21d7..d73c0e6a4d 100644
763e28
--- a/runtime/nsd_gtls.h
763e28
+++ b/runtime/nsd_gtls.h
763e28
@@ -54,6 +54,11 @@ struct nsd_gtls_s {
763e28
 		GTLS_AUTH_CERTVALID = 2,
763e28
 		GTLS_AUTH_CERTANON = 3
763e28
 	} authMode;
763e28
+	enum {
763e28
+		GTLS_NONE = 0,
763e28
+		GTLS_PURPOSE = 1
763e28
+	} dataTypeCheck;
763e28
+	int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not cehck CN) */
763e28
 	gtlsRtryCall_t rtryCall;/**< what must we retry? */
763e28
 	int bIsInitiator;	/**< 0 if socket is the server end (listener), 1 if it is the initiator */
763e28
 	gnutls_session_t sess;
763e28
diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
763e28
index 0a474fd744..419e0e97ef 100644
763e28
--- a/runtime/nsd_ossl.c
763e28
+++ b/runtime/nsd_ossl.c
763e28
@@ -1864,6 +1864,40 @@ SetGnutlsPriorityString(__attribute__((unused)) nsd_t *pNsd, __attribute__((unus
763e28
 	RETiRet;
763e28
 }
763e28
 
763e28
+/* Set the driver cert extended key usage check setting, for now it is empty wrapper.
763e28
+ * TODO: implement openSSL version
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	if(ChkExtendedKeyUsage != 0) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
763e28
+				"not supported by ossl netstream driver", ChkExtendedKeyUsage);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+/* Set the driver name checking strictness, for now it is empty wrapper.
763e28
+ * TODO: implement openSSL version
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	if(prioritizeSan != 0) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
763e28
+				"not supported by ossl netstream driver", prioritizeSan);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
 /* queryInterface function */
763e28
 BEGINobjQueryInterface(nsd_ossl)
763e28
 CODESTARTobjQueryInterface(nsd_ossl)
763e28
@@ -1898,6 +1932,8 @@ CODESTARTobjQueryInterface(nsd_ossl)
763e28
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
763e28
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
763e28
 	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; /* we don't NEED this interface! */
763e28
+	pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; /* we don't NEED this interface! */
763e28
+	pIf->SetPrioritizeSAN = SetPrioritizeSAN; /* we don't NEED this interface! */
763e28
 
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(nsd_ossl)
763e28
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
763e28
index 68bed5b9ea..60c40ad444 100644
763e28
--- a/runtime/nsd_ptcp.c
763e28
+++ b/runtime/nsd_ptcp.c
763e28
@@ -150,6 +150,37 @@ SetMode(nsd_t __attribute__((unused)) *pNsd, int mode)
763e28
 	RETiRet;
763e28
 }
763e28
 
763e28
+/* Set the driver cert extended key usage check setting, not supported in ptcp.
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	if(ChkExtendedKeyUsage != 0) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
763e28
+				"not supported by ptcp netstream driver", ChkExtendedKeyUsage);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+/* Set the driver name checking strictness, not supported in ptcp.
763e28
+ * jvymazal, 2019-08-16
763e28
+ */
763e28
+static rsRetVal
763e28
+SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	if(prioritizeSan != 0) {
763e28
+		LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
763e28
+				"not supported by ptcp netstream driver", prioritizeSan);
763e28
+		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
763e28
+	}
763e28
+finalize_it:
763e28
+	RETiRet;
763e28
+}
763e28
 
763e28
 /* Set the authentication mode. For us, the following is supported:
763e28
  * anon - no certificate checks whatsoever (discouraged, but supported)
763e28
@@ -613,6 +644,8 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
763e28
 		CHKiRet(pNS->Drvr.Construct(&pNewNsd));
763e28
 		CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock));
763e28
 		CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS)));
763e28
+		CHKiRet(pNS->Drvr.SetCheckExtendedKeyUsage(pNewNsd, netstrms.GetDrvrCheckExtendedKeyUsage(pNS)));
763e28
+		CHKiRet(pNS->Drvr.SetPrioritizeSAN(pNewNsd, netstrms.GetDrvrPrioritizeSAN(pNS)));
763e28
 		CHKiRet(pNS->Drvr.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS)));
763e28
 		CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS)));
763e28
 		CHKiRet(pNS->Drvr.SetGnutlsPriorityString(pNewNsd, netstrms.GetDrvrGnutlsPriorityString(pNS)));
763e28
@@ -963,6 +996,8 @@ CODESTARTobjQueryInterface(nsd_ptcp)
763e28
 	pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
763e28
 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
763e28
 	pIf->SetKeepAliveTime = SetKeepAliveTime;
763e28
+	pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage;
763e28
+	pIf->SetPrioritizeSAN = SetPrioritizeSAN;
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(nsd_ptcp)
763e28
 
763e28
diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c
763e28
index d7ea2f9f00..43a6687b4a 100644
763e28
--- a/runtime/tcpsrv.c
763e28
+++ b/runtime/tcpsrv.c
763e28
@@ -1013,6 +1013,8 @@ tcpsrvConstructFinalize(tcpsrv_t *pThis)
763e28
 	if(pThis->pszDrvrName != NULL)
763e28
 		CHKiRet(netstrms.SetDrvrName(pThis->pNS, pThis->pszDrvrName));
763e28
 	CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode));
763e28
+	CHKiRet(netstrms.SetDrvrCheckExtendedKeyUsage(pThis->pNS, pThis->DrvrChkExtendedKeyUsage));
763e28
+	CHKiRet(netstrms.SetDrvrPrioritizeSAN(pThis->pNS, pThis->DrvrPrioritizeSan));
763e28
 	if(pThis->pszDrvrAuthMode != NULL)
763e28
 		CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode));
763e28
 	if(pThis->pPermPeers != NULL)
763e28
@@ -1405,6 +1407,26 @@ SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers)
763e28
 	RETiRet;
763e28
 }
763e28
 
763e28
+/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */
763e28
+static rsRetVal
763e28
+SetDrvrCheckExtendedKeyUsage(tcpsrv_t *pThis, int ChkExtendedKeyUsage)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, tcpsrv);
763e28
+	pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage;
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
+/* set the driver name checking policy -- jvymazal, 2019-08-16 */
763e28
+static rsRetVal
763e28
+SetDrvrPrioritizeSAN(tcpsrv_t *pThis, int prioritizeSan)
763e28
+{
763e28
+	DEFiRet;
763e28
+	ISOBJ_TYPE_assert(pThis, tcpsrv);
763e28
+	pThis->DrvrPrioritizeSan = prioritizeSan;
763e28
+	RETiRet;
763e28
+}
763e28
+
763e28
 
763e28
 /* End of methods to shuffle autentication settings to the driver.;
763e28
 
763e28
@@ -1522,6 +1544,8 @@ CODESTARTobjQueryInterface(tcpsrv)
763e28
 	pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters;
763e28
 	pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose;
763e28
 	pIf->SetPreserveCase = SetPreserveCase;
763e28
+	pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
763e28
+	pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
763e28
 
763e28
 finalize_it:
763e28
 ENDobjQueryInterface(tcpsrv)
763e28
diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h
763e28
index 55aa8e9922..79b659013d 100644
763e28
--- a/runtime/tcpsrv.h
763e28
+++ b/runtime/tcpsrv.h
763e28
@@ -61,6 +61,8 @@ struct tcpsrv_s {
763e28
 	int iKeepAliveTime;	/**< socket layer KEEPALIVE timeout */
763e28
 	netstrms_t *pNS;	/**< pointer to network stream subsystem */
763e28
 	int iDrvrMode;		/**< mode of the stream driver to use */
763e28
+	int DrvrChkExtendedKeyUsage;		/**< if true, verify extended key usage in certs */
763e28
+	int DrvrPrioritizeSan;		/**< if true, perform stricter checking of names in certs */
763e28
 	uchar *gnutlsPriorityString;	/**< priority string for gnutls */
763e28
 	uchar *pszDrvrAuthMode;	/**< auth mode of the stream driver to use */
763e28
 	uchar *pszDrvrName;	/**< name of stream driver to use */
763e28
@@ -185,8 +187,11 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
763e28
 	rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*);
763e28
 	/* added v21 -- Preserve case in fromhost, 2018-08-16 */
763e28
 	rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase);
763e28
+	/* added v23 -- Options for stricter driver behavior, 2019-08-16 */
763e28
+	rsRetVal (*SetDrvrCheckExtendedKeyUsage)(tcpsrv_t *pThis, int ChkExtendedKeyUsage);
763e28
+	rsRetVal (*SetDrvrPrioritizeSAN)(tcpsrv_t *pThis, int prioritizeSan);
763e28
 ENDinterface(tcpsrv)
763e28
-#define tcpsrvCURR_IF_VERSION 21 /* increment whenever you change the interface structure! */
763e28
+#define tcpsrvCURR_IF_VERSION 23 /* increment whenever you change the interface structure! */
763e28
 /* change for v4:
763e28
  * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10
763e28
  * - SetInputName() added -- rgerhards, 2008-12-10
763e28
diff --git a/tools/omfwd.c b/tools/omfwd.c
763e28
index cdb74b8d22..96fa68752c 100644
763e28
--- a/tools/omfwd.c
763e28
+++ b/tools/omfwd.c
763e28
@@ -83,6 +83,8 @@ typedef struct _instanceData {
763e28
 	uchar *pszStrmDrvrAuthMode;
763e28
 	permittedPeers_t *pPermPeers;
763e28
 	int iStrmDrvrMode;
763e28
+	int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */
763e28
+	int iStrmDrvrSANPreference; /* ignore CN when any SAN set */
763e28
 	char	*target;
763e28
 	char	*address;
763e28
 	char	*device;
763e28
@@ -189,6 +191,8 @@ static struct cnfparamdescr actpdescr[] = {
763e28
 	{ "streamdrivermode", eCmdHdlrInt, 0 },
763e28
 	{ "streamdriverauthmode", eCmdHdlrGetWord, 0 },
763e28
 	{ "streamdriverpermittedpeers", eCmdHdlrGetWord, 0 },
763e28
+	{ "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
763e28
+	{ "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
763e28
 	{ "resendlastmsgonreconnect", eCmdHdlrBinary, 0 },
763e28
 	{ "udp.sendtoall", eCmdHdlrBinary, 0 },
763e28
 	{ "udp.senddelay", eCmdHdlrInt, 0 },
763e28
@@ -748,6 +752,8 @@ static rsRetVal TCPSendInit(void *pvData)
763e28
 		CHKiRet(netstrms.CreateStrm(pWrkrData->pNS, &pWrkrData->pNetstrm));
763e28
 		CHKiRet(netstrm.ConstructFinalize(pWrkrData->pNetstrm));
763e28
 		CHKiRet(netstrm.SetDrvrMode(pWrkrData->pNetstrm, pData->iStrmDrvrMode));
763e28
+		CHKiRet(netstrm.SetDrvrCheckExtendedKeyUsage(pWrkrData->pNetstrm, pData->iStrmDrvrExtendedCertCheck));
763e28
+		CHKiRet(netstrm.SetDrvrPrioritizeSAN(pWrkrData->pNetstrm, pData->iStrmDrvrSANPreference));
763e28
 		/* now set optional params, but only if they were actually configured */
763e28
 		if(pData->pszStrmDrvrAuthMode != NULL) {
763e28
 			CHKiRet(netstrm.SetDrvrAuthMode(pWrkrData->pNetstrm, pData->pszStrmDrvrAuthMode));
763e28
@@ -1119,6 +1125,8 @@ setInstParamDefaults(instanceData *pData)
763e28
 	pData->pszStrmDrvr = NULL;
763e28
 	pData->pszStrmDrvrAuthMode = NULL;
763e28
 	pData->iStrmDrvrMode = 0;
763e28
+	pData->iStrmDrvrExtendedCertCheck = 0;
763e28
+	pData->iStrmDrvrSANPreference = 0;
763e28
 	pData->iRebindInterval = 0;
763e28
 	pData->bKeepAlive = 0;
763e28
 	pData->iKeepAliveProbes = 0;
763e28
@@ -1220,6 +1228,10 @@ CODESTARTnewActInst
763e28
 			pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
763e28
 		} else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) {
763e28
 			pData->iStrmDrvrMode = pvals[i].val.d.n;
763e28
+		} else if(!strcmp(actpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
763e28
+			pData->iStrmDrvrExtendedCertCheck = pvals[i].val.d.n;
763e28
+		} else if(!strcmp(actpblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
763e28
+			pData->iStrmDrvrSANPreference = pvals[i].val.d.n;
763e28
 		} else if(!strcmp(actpblk.descr[i].name, "streamdriverauthmode")) {
763e28
 			pData->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
763e28
 		} else if(!strcmp(actpblk.descr[i].name, "streamdriverpermittedpeers")) {