619 lines
26 KiB
Diff
619 lines
26 KiB
Diff
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")) {
|