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