diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-05-21 12:23:41 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-05-21 12:23:41 +0200 |
commit | ff446070be16b18e119873ed56e2c96e28b98514 (patch) | |
tree | 4639428c29cf604a3955ea487813027141a585db /runtime/nsd_gtls.c | |
parent | 275595cdf8d5e18e665bfd4189f8061441595cce (diff) | |
parent | 8cb6ec4cee79d41c30d7df38b58ab1f198ac8581 (diff) | |
download | rsyslog-ff446070be16b18e119873ed56e2c96e28b98514.tar.gz rsyslog-ff446070be16b18e119873ed56e2c96e28b98514.tar.bz2 rsyslog-ff446070be16b18e119873ed56e2c96e28b98514.zip |
Merge branch 'ietf-tls'
Conflicts:
ChangeLog
Diffstat (limited to 'runtime/nsd_gtls.c')
-rw-r--r-- | runtime/nsd_gtls.c | 158 |
1 files changed, 144 insertions, 14 deletions
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c index 5ea7ceb9..fd7a502a 100644 --- a/runtime/nsd_gtls.c +++ b/runtime/nsd_gtls.c @@ -39,6 +39,7 @@ #include "obj.h" #include "stringbuf.h" #include "errmsg.h" +#include "net.h" #include "nsd_ptcp.h" #include "nsdsel_gtls.h" #include "nsd_gtls.h" @@ -85,12 +86,18 @@ GenFingerprintStr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr) cstr_t *pStr = NULL; uchar buf[4]; size_t i; + int bAddColon = 0; /* do we need to add a colon to the fingerprint string? */ DEFiRet; CHKiRet(rsCStrConstruct(&pStr)); for(i = 0 ; i < sizeFingerprint ; ++i) { - snprintf((char*)buf, sizeof(buf), "%2.2X:", pFingerprint[i]); - CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3)); + if(bAddColon) { + CHKiRet(rsCStrAppendChar(pStr, ':')); + } else { + bAddColon = 1; /* all but the first need a colon added */ + } + snprintf((char*)buf, sizeof(buf), "%2.2X", pFingerprint[i]); + CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 2)); } CHKiRet(rsCStrFinish(pStr)); @@ -120,6 +127,31 @@ uchar *gtlsStrerror(int error) } +/* add our own certificate to the certificate set, so that the peer + * can identify us. Please note that we try to use mutual authentication, + * so we always add a cert, even if we are in the client role (later, + * this may be controlled by a config setting). + * rgerhards, 2008-05-15 + */ +static rsRetVal +gtlsAddOurCert(void) +{ + int gnuRet; + uchar *keyFile; + uchar *certFile; + DEFiRet; + + certFile = glbl.GetDfltNetstrmDrvrCertFile(); + keyFile = glbl.GetDfltNetstrmDrvrKeyFile(); + dbgprintf("GTLS certificate file: '%s'\n", certFile); + dbgprintf("GTLS key file: '%s'\n", keyFile); + CHKgnutls(gnutls_certificate_set_x509_key_file(xcred, (char*)certFile, (char*)keyFile, GNUTLS_X509_FMT_PEM)); + +finalize_it: + RETiRet; +} + + /* globally initialize GnuTLS */ static rsRetVal gtlsGlblInit(void) @@ -200,9 +232,6 @@ finalize_it: static rsRetVal gtlsGlblInitLstn(void) { - int gnuRet; - uchar *keyFile; - uchar *certFile; DEFiRet; if(bGlblSrvrInitDone == 0) { @@ -210,11 +239,7 @@ gtlsGlblInitLstn(void) * considered legacy. -- rgerhards, 2008-05-05 */ /*CHKgnutls(gnutls_certificate_set_x509_crl_file(xcred, CRLFILE, GNUTLS_X509_FMT_PEM));*/ - certFile = glbl.GetDfltNetstrmDrvrCertFile(); - keyFile = glbl.GetDfltNetstrmDrvrKeyFile(); - dbgprintf("GTLS certificate file: '%s'\n", certFile); - dbgprintf("GTLS key file: '%s'\n", keyFile); - CHKgnutls(gnutls_certificate_set_x509_key_file(xcred, (char*)certFile, (char*)keyFile, GNUTLS_X509_FMT_PEM)); + //CHKiRet(gtlsAddOurCert()); CHKiRet(generate_dh_params()); gnutls_certificate_set_dh_params(xcred, dh_params); /* this is void */ bGlblSrvrInitDone = 1; /* we are all set now */ @@ -228,7 +253,7 @@ finalize_it: /* check the fingerprint of the remote peer's certificate. * rgerhards, 2008-05-08 */ -static rsRetVal +rsRetVal gtlsChkFingerprint(nsd_gtls_t *pThis) { cstr_t *pstrFingerprint = NULL; @@ -239,10 +264,18 @@ gtlsChkFingerprint(nsd_gtls_t *pThis) gnutls_x509_crt cert; int bMustDeinitCert = 0; int gnuRet; + int bFoundPositiveMatch; + permittedPeers_t *pPeer; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); + /* first check if we need to do fingerprint authentication - if not, we + * are already set ;) -- rgerhards, 2008-05-21 + */ + if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT) + FINALIZE; + /* This function only works for X.509 certificates. */ if(gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509) return RS_RET_TLS_CERT_ERR; @@ -268,8 +301,30 @@ gtlsChkFingerprint(nsd_gtls_t *pThis) CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint)); dbgprintf("peer's certificate SHA1 fingerprint: %s\n", rsCStrGetSzStr(pstrFingerprint)); + /* now search through the permitted peers to see if we can find a permitted one */ + bFoundPositiveMatch = 0; + pPeer = pThis->pPermPeers; + while(pPeer != NULL && !bFoundPositiveMatch) { + if(!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char*) pPeer->pszID))) { + bFoundPositiveMatch = 1; + } else { + pPeer = pPeer->pNext; + } + } + + if(!bFoundPositiveMatch) { + dbgprintf("invalid peer fingerprint, not permitted to talk to it\n"); + if(pThis->bReportAuthErr == 1) { + errno = 0; + errmsg.LogError(NO_ERRCODE, "error: peer fingerprint '%s' unknown - we are " + "not permitted to talk to it", rsCStrGetSzStr(pstrFingerprint)); + pThis->bReportAuthErr = 0; + } + ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); + } finalize_it: +dbgprintf("exit fingerprint check, iRet %d\n", iRet); if(pstrFingerprint != NULL) rsCStrDestruct(&pstrFingerprint); if(bMustDeinitCert) @@ -333,6 +388,9 @@ gtlsSetTransportPtr(nsd_gtls_t *pThis, int sock) /* Standard-Constructor */ BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */ iRet = nsd_ptcp.Construct(&pThis->pTcp); + pThis->bReportAuthErr = 1; +CHKiRet(gtlsAddOurCert()); +finalize_it: ENDobjConstruct(nsd_gtls) @@ -360,10 +418,12 @@ SetMode(nsd_t *pNsd, int mode) DEFiRet; nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; -dbgprintf("SetMode tries to set mode %d\n", mode); ISOBJ_TYPE_assert((pThis), nsd_gtls); - if(mode != 0 && mode != 1) - ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE); + if(mode != 0 && mode != 1) { + errmsg.LogError(NO_ERRCODE, "error: driver mode %d not supported by " + "gtls netstream driver", mode); + ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE); + } pThis->iMode = mode; @@ -372,6 +432,66 @@ finalize_it: } +/* Set the authentication mode. For us, the following is supported: + * anon - no certificate checks whatsoever (discouraged, but supported) + * x509/fingerprint - certificate fingerprint + * x509/name - cerfificate name check + * mode == NULL is valid and defaults to x509/name + * rgerhards, 2008-05-16 + */ +static rsRetVal +SetAuthMode(nsd_t *pNsd, uchar *mode) +{ + DEFiRet; + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + + ISOBJ_TYPE_assert((pThis), nsd_gtls); + if(mode == NULL || !strcasecmp((char*)mode, "x509/name")) { + pThis->authMode = GTLS_AUTH_CERTNAME; + } else if(!strcasecmp((char*) mode, "x509/fingerprint")) { + pThis->authMode = GTLS_AUTH_CERTFINGERPRINT; + } else if(!strcasecmp((char*) mode, "anon")) { + pThis->authMode = GTLS_AUTH_CERTANON; + } else { + errmsg.LogError(NO_ERRCODE, "error: authentication mode '%s' not supported by " + "gtls netstream driver", mode); + ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); + } + +/* TODO: clear stored IDs! */ + +finalize_it: +dbgprintf("gtls auth mode %d set\n", pThis->authMode); + RETiRet; +} + + +/* Set permitted peers. It is depending on the auth mode if this are + * fingerprints or names. -- rgerhards, 2008-05-19 + */ +static rsRetVal +SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers) +{ + DEFiRet; + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + + ISOBJ_TYPE_assert((pThis), nsd_gtls); + if(pPermPeers == NULL) + FINALIZE; + + if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT && pThis->authMode != GTLS_AUTH_CERTNAME) { + errmsg.LogError(NO_ERRCODE, "authentication not supported by " + "gtls netstream driver in the configured authentication mode - ignored"); + ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); + } + + pThis->pPermPeers = pPermPeers; + +finalize_it: + RETiRet; +} + + /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_gtls) who utilize ourselfs * for some of their functionality. -- rgerhards, 2008-04-18 @@ -484,6 +604,8 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew) /* if we reach this point, we are in TLS mode */ CHKiRet(gtlsInitSession(pNew)); gtlsSetTransportPtr(pNew, ((nsd_ptcp_t*) (pNew->pTcp))->sock); + pNew->authMode = pThis->authMode; + pNew->pPermPeers = pThis->pPermPeers; /* we now do the handshake. This is a bit complicated, because we are * on non-blocking sockets. Usually, the handshake will not complete @@ -527,6 +649,9 @@ Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsd_gtls); + if(pThis->bAbortConn) + ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); + if(pThis->iMode == 0) { CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf)); FINALIZE; @@ -561,6 +686,9 @@ Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); + if(pThis->bAbortConn) + ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); + if(pThis->iMode == 0) { CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf)); FINALIZE; @@ -664,6 +792,8 @@ CODESTARTobjQueryInterface(nsd_gtls) pIf->Connect = Connect; pIf->SetSock = SetSock; pIf->SetMode = SetMode; + pIf->SetAuthMode = SetAuthMode; + pIf->SetPermPeers =SetPermPeers; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; finalize_it: |