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 | |
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')
-rw-r--r-- | runtime/net.c | 64 | ||||
-rw-r--r-- | runtime/net.h | 19 | ||||
-rw-r--r-- | runtime/netstrm.c | 34 | ||||
-rw-r--r-- | runtime/netstrm.h | 4 | ||||
-rw-r--r-- | runtime/netstrms.c | 51 | ||||
-rw-r--r-- | runtime/netstrms.h | 9 | ||||
-rw-r--r-- | runtime/nsd.h | 4 | ||||
-rw-r--r-- | runtime/nsd_gtls.c | 158 | ||||
-rw-r--r-- | runtime/nsd_gtls.h | 10 | ||||
-rw-r--r-- | runtime/nsd_ptcp.c | 56 | ||||
-rw-r--r-- | runtime/nsdsel_gtls.c | 5 | ||||
-rw-r--r-- | runtime/rsyslog.h | 7 |
12 files changed, 398 insertions, 23 deletions
diff --git a/runtime/net.c b/runtime/net.c index 7663b1b3..cbff1003 100644 --- a/runtime/net.c +++ b/runtime/net.c @@ -88,6 +88,68 @@ static struct AllowedSenders *pLastAllowedSenders_GSS = NULL; int ACLAddHostnameOnFail = 0; /* add hostname to acl when DNS resolving has failed */ int ACLDontResolve = 0; /* add hostname to acl instead of resolving it to IP(s) */ + +/* ------------------------------ begin permitted peers code ------------------------------ */ + + +/* add a permitted peer. PermittedPeers is an interim solution until we can provide + * access control via enhanced RainerScript methods. + * Note: the provided string is handed over to this function, caller must + * no longer access it. -- rgerhards, 2008-05-19 + */ +static rsRetVal +AddPermittedPeer(permittedPeers_t **ppRootPeer, uchar* pszID) +{ + permittedPeers_t *pNew = NULL; + DEFiRet; + + assert(ppRootPeer != NULL); + assert(pszID != NULL); + + CHKmalloc(pNew = malloc(sizeof(permittedPeers_t))); + CHKmalloc(pNew->pszID = (uchar*)strdup((char*)pszID)); + pNew->pNext = NULL; + + if(*ppRootPeer != NULL) { + pNew->pNext = *ppRootPeer; + } + *ppRootPeer = pNew; + +finalize_it: + if(iRet != RS_RET_OK) { + if(pNew != NULL) + free(pNew); + } + RETiRet; +} + + +/* Destruct a permitted peers list -- rgerhards, 2008-05-19 */ +static rsRetVal +DestructPermittedPeers(permittedPeers_t **ppRootPeer) +{ + permittedPeers_t *pCurr; + permittedPeers_t *pDel; + DEFiRet; + + assert(ppRootPeer != NULL); + + for(pCurr = *ppRootPeer ; pCurr != NULL ; /*EMPTY*/) { + pDel = pCurr; + pCurr = pCurr->pNext; + free(pDel->pszID); + free(pDel); + } + + *ppRootPeer = NULL; + + RETiRet; +} + + +/* ------------------------------ end permitted peers code ------------------------------ */ + + /* Code for handling allowed/disallowed senders */ static inline void MaskIP6 (struct in6_addr *addr, uint8_t bits) { @@ -1095,6 +1157,8 @@ CODESTARTobjQueryInterface(net) pIf->isAllowedSender = isAllowedSender; pIf->should_use_so_bsdcompat = should_use_so_bsdcompat; pIf->getLocalHostname = getLocalHostname; + pIf->AddPermittedPeer = AddPermittedPeer; + pIf->DestructPermittedPeers = DestructPermittedPeers; finalize_it: ENDobjQueryInterface(net) diff --git a/runtime/net.h b/runtime/net.h index 9e471bf9..673f45a9 100644 --- a/runtime/net.h +++ b/runtime/net.h @@ -91,6 +91,20 @@ struct AllowedSenders { }; +/* for fingerprints and hostnames, we need to have a temporary linked list of + * permitted values. Unforutnately, we must also duplicate this in the netstream + * drivers. However, this is the best interim solution (with the least effort). + * A clean implementation requires that we have more capable variables and the + * full-fledged scripting engine available. So we have opted to do the interim + * solution so that our users can begin to enjoy authenticated TLS. The next step + * (hopefully) is to enhance RainerScript. -- rgerhards, 2008-05-19 + */ +struct permittedPeers_s { + uchar *pszID; + permittedPeers_t *pNext; +}; + + /* interfaces */ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ rsRetVal (*cvthname)(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN, uchar *pszIP); @@ -104,7 +118,10 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ int (*isAllowedSender)(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost); rsRetVal (*getLocalHostname)(uchar**); int (*should_use_so_bsdcompat)(void); - /* data memebers - these should go away over time... TODO */ + /* permitted peer handling should be replaced by something better (see comments above) */ + rsRetVal (*AddPermittedPeer)(permittedPeers_t **ppRootPeer, uchar *pszID); + rsRetVal (*DestructPermittedPeers)(permittedPeers_t **ppRootPeer); + /* data members - these should go away over time... TODO */ int *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */ int *pACLDontResolve; /* add hostname to acl instead of resolving it to IP(s) */ struct AllowedSenders *pAllowedSenders_UDP; diff --git a/runtime/netstrm.c b/runtime/netstrm.c index a1384a28..786ba7f8 100644 --- a/runtime/netstrm.c +++ b/runtime/netstrm.c @@ -43,6 +43,7 @@ #include <string.h> #include "rsyslog.h" +#include "net.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" @@ -172,6 +173,10 @@ Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf) RETiRet; } +/* here follows a number of methods that shuffle authentication settings down + * to the drivers. Drivers not supporting these settings may return an error + * state. + * -------------------------------------------------------------------------- */ /* set the driver mode * rgerhards, 2008-04-28 @@ -186,6 +191,33 @@ SetDrvrMode(netstrm_t *pThis, int iMode) } +/* set the driver authentication mode -- rgerhards, 2008-05-16 + */ +static rsRetVal +SetDrvrAuthMode(netstrm_t *pThis, uchar *mode) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetAuthMode(pThis->pDrvrData, mode); + RETiRet; +} + + +/* set the driver's permitted peers -- rgerhards, 2008-05-19 */ +static rsRetVal +SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetPermPeers(pThis->pDrvrData, pPermPeers); + RETiRet; +} + + +/* End of methods to shuffle autentication settings to the driver. + * -------------------------------------------------------------------------- */ + + /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has @@ -280,6 +312,8 @@ CODESTARTobjQueryInterface(netstrm) pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->SetDrvrMode = SetDrvrMode; + pIf->SetDrvrAuthMode = SetDrvrAuthMode; + pIf->SetDrvrPermPeers = SetDrvrPermPeers; pIf->GetSock = GetSock; finalize_it: ENDobjQueryInterface(netstrm) diff --git a/runtime/netstrm.h b/runtime/netstrm.h index a15c1d9b..ae135beb 100644 --- a/runtime/netstrm.h +++ b/runtime/netstrm.h @@ -50,6 +50,8 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */ rsRetVal (*GetRemoteHName)(netstrm_t *pThis, uchar **pszName); rsRetVal (*GetRemoteIP)(netstrm_t *pThis, uchar **pszIP); rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode); + rsRetVal (*SetDrvrAuthMode)(netstrm_t *pThis, uchar*); + rsRetVal (*SetDrvrPermPeers)(netstrm_t *pThis, permittedPeers_t*); /* the GetSock() below is a hack to make imgssapi work. In the long term, * we should migrate imgssapi to a stream driver, which will relieve us of * this problem. Please note that nobody else should use GetSock(). Using it @@ -59,7 +61,7 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */ */ rsRetVal (*GetSock)(netstrm_t *pThis, int *pSock); ENDinterface(netstrm) -#define netstrmCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ +#define netstrmCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(netstrm); diff --git a/runtime/netstrms.c b/runtime/netstrms.c index 03a46329..3e5b7819 100644 --- a/runtime/netstrms.c +++ b/runtime/netstrms.c @@ -146,8 +146,53 @@ finalize_it: } -/* set the driver mode -- rgerhards, 2008-04-30 +/* set the driver's permitted peers -- rgerhards, 2008-05-19 */ +static rsRetVal +SetDrvrPermPeers(netstrms_t *pThis, permittedPeers_t *pPermPeers) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrms); + pThis->pPermPeers = pPermPeers; + RETiRet; +} +/* return the driver's permitted peers + * We use non-standard calling conventions because it makes an awful lot + * of sense here. + * rgerhards, 2008-05-19 + */ +static uchar* +GetDrvrPermPeers(netstrms_t *pThis) +{ + ISOBJ_TYPE_assert(pThis, netstrms); + return pThis->pPermPeers; +} + + +/* set the driver auth mode -- rgerhards, 2008-05-19 */ +static rsRetVal +SetDrvrAuthMode(netstrms_t *pThis, uchar *mode) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrms); +RUNLOG_VAR("%s", mode); + CHKmalloc(pThis->pszDrvrAuthMode = (uchar*)strdup((char*)mode)); +finalize_it: + RETiRet; +} +/* return the driver auth mode + * We use non-standard calling conventions because it makes an awful lot + * of sense here. + * rgerhards, 2008-05-19 */ +static uchar* +GetDrvrAuthMode(netstrms_t *pThis) +{ + ISOBJ_TYPE_assert(pThis, netstrms); + return pThis->pszDrvrAuthMode; +} + + +/* set the driver mode -- rgerhards, 2008-04-30 */ static rsRetVal SetDrvrMode(netstrms_t *pThis, int iMode) { @@ -221,6 +266,10 @@ CODESTARTobjQueryInterface(netstrms) pIf->SetDrvrName = SetDrvrName; pIf->SetDrvrMode = SetDrvrMode; pIf->GetDrvrMode = GetDrvrMode; + pIf->SetDrvrAuthMode = SetDrvrAuthMode; + pIf->GetDrvrAuthMode = GetDrvrAuthMode; + pIf->SetDrvrPermPeers = SetDrvrPermPeers; + pIf->GetDrvrPermPeers = GetDrvrPermPeers; finalize_it: ENDobjQueryInterface(netstrms) diff --git a/runtime/netstrms.h b/runtime/netstrms.h index 1d1cc892..3f686af6 100644 --- a/runtime/netstrms.h +++ b/runtime/netstrms.h @@ -32,6 +32,9 @@ struct netstrms_s { uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */ int iDrvrMode; /**< current default driver mode */ + uchar *pszDrvrAuthMode; /**< current driver authentication mode */ + permittedPeers_t *pPermPeers;/**< current driver's permitted peers */ + nsd_if_t Drvr; /**< our stream driver */ }; @@ -44,7 +47,11 @@ BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */ rsRetVal (*CreateStrm)(netstrms_t *pThis, netstrm_t **ppStrm); rsRetVal (*SetDrvrName)(netstrms_t *pThis, uchar *pszName); rsRetVal (*SetDrvrMode)(netstrms_t *pThis, int iMode); - int (*GetDrvrMode)(netstrms_t *pThis); + rsRetVal (*SetDrvrAuthMode)(netstrms_t *pThis, uchar*); + rsRetVal (*SetDrvrPermPeers)(netstrms_t *pThis, permittedPeers_t*); + int (*GetDrvrMode)(netstrms_t *pThis); + uchar* (*GetDrvrAuthMode)(netstrms_t *pThis); + permittedPeers_t* (*GetDrvrPermPeers)(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 cc06c877..53693b59 100644 --- a/runtime/nsd.h +++ b/runtime/nsd.h @@ -51,6 +51,8 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */ rsRetVal (*GetRemoteHName)(nsd_t *pThis, uchar **pszName); rsRetVal (*GetRemoteIP)(nsd_t *pThis, uchar **pszIP); rsRetVal (*SetMode)(nsd_t *pThis, int mode); /* sets a driver specific mode - see driver doc for details */ + rsRetVal (*SetAuthMode)(nsd_t *pThis, uchar*); /* sets a driver specific mode - see driver doc for details */ + rsRetVal (*SetPermPeers)(nsd_t *pThis, permittedPeers_t*); /* sets driver permitted peers for auth needs */ rsRetVal (*GetSock)(nsd_t *pThis, int *pSock); rsRetVal (*SetSock)(nsd_t *pThis, int sock); /* GetSock() and SetSock() return an error if the driver does not use plain @@ -58,7 +60,7 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */ * those drivers that utilize the nsd_ptcp to do some of their work. */ ENDinterface(nsd) -#define nsdCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ +#define nsdCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* interface for the select call */ BEGINinterface(nsdsel) /* name must also be changed in ENDinterface macro! */ 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: diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h index bbb0eb9e..1f3eb6b1 100644 --- a/runtime/nsd_gtls.h +++ b/runtime/nsd_gtls.h @@ -38,11 +38,21 @@ struct nsd_gtls_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */ int iMode; /* 0 - plain tcp, 1 - TLS */ + int bAbortConn; /* if set, abort conncection (fatal error had happened) */ + enum { + GTLS_AUTH_CERTNAME = 0, + GTLS_AUTH_CERTFINGERPRINT = 1, + GTLS_AUTH_CERTANON = 2 + } authMode; 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 sess; int bHaveSess; /* as we don't know exactly which gnutls_session values are invalid, we use this one to flag whether or not we are in a session (same as -1 for a socket meaning no sess) */ + int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is + * set to 1 and changed to 0 after the first report. It is changed back to 1 after + * one successful authentication. */ + permittedPeers_t *pPermPeers; /* permitted senders */ }; /* interface is defined in nsd.h, we just implement it! */ diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c index c5480a05..14c564a3 100644 --- a/runtime/nsd_ptcp.c +++ b/runtime/nsd_ptcp.c @@ -119,13 +119,61 @@ static rsRetVal SetMode(nsd_t __attribute__((unused)) *pNsd, int mode) { DEFiRet; - if(mode != 0) - ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE); + if(mode != 0) { + errmsg.LogError(NO_ERRCODE, "error: driver mode %d not supported by " + "ptcp netstream driver", mode); + ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE); + } +finalize_it: + RETiRet; +} + + +/* Set the authentication mode. For us, the following is supported: + * anon - no certificate checks whatsoever (discouraged, but supported) + * mode == NULL is valid and defaults to anon + * Actually, we do not even record the mode right now, because we can + * always work in anon mode, only. So there is no point in recording + * something if that's the only choice. What the function does is + * return an error if something is requested that we can not support. + * rgerhards, 2008-05-17 + */ +static rsRetVal +SetAuthMode(nsd_t __attribute__((unused)) *pNsd, uchar *mode) +{ + DEFiRet; + if(mode != NULL && strcasecmp((char*)mode, "anon")) { + errmsg.LogError(NO_ERRCODE, "error: authentication mode '%s' not supported by " + "ptcp netstream driver", mode); + ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); + } + +finalize_it: + RETiRet; +} + + +/* Set the permitted peers. This is a dummy, always returning an + * error because we do not support fingerprint authentication. + * rgerhards, 2008-05-17 + */ +static rsRetVal +SetPermPeers(nsd_t __attribute__((unused)) *pNsd, permittedPeers_t __attribute__((unused)) *pPermPeers) +{ + DEFiRet; + + if(pPermPeers != NULL) { + errmsg.LogError(NO_ERRCODE, "authentication not supported by ptcp netstream driver"); + ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); + } + 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. @@ -435,6 +483,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.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS))); + CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS))); CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm)); pNewStrm->pDrvrData = (nsd_t*) pNewNsd; CHKiRet(fAddLstn(pUsr, pNewStrm)); @@ -625,6 +675,8 @@ CODESTARTobjQueryInterface(nsd_ptcp) pIf->GetSock = GetSock; pIf->SetSock = SetSock; pIf->SetMode = SetMode; + pIf->SetAuthMode = SetAuthMode; + pIf->SetPermPeers = SetPermPeers; pIf->Rcv = Rcv; pIf->Send = Send; pIf->LstnInit = LstnInit; diff --git a/runtime/nsdsel_gtls.c b/runtime/nsdsel_gtls.c index daa38929..96456564 100644 --- a/runtime/nsdsel_gtls.c +++ b/runtime/nsdsel_gtls.c @@ -129,8 +129,9 @@ doRetry(nsd_gtls_t *pNsd) case gtlsRtry_handshake: gnuRet = gnutls_handshake(pNsd->sess); if(gnuRet == 0) { + pNsd->rtryCall = gtlsRtry_None; /* we are done */ /* we got a handshake, now check authorization */ - // TODO: do it! + CHKiRet(gtlsChkFingerprint(pNsd)); } break; default: @@ -154,6 +155,8 @@ doRetry(nsd_gtls_t *pNsd) */ finalize_it: + if(iRet != RS_RET_OK) + pNsd->bAbortConn = 1; /* request abort */ RETiRet; } diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 367a239f..c06b01c3 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -81,6 +81,7 @@ typedef struct interface_s interface_t; typedef struct objInfo_s objInfo_t; typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */ typedef rsRetVal (*errLogFunc_t)(uchar*); /* this is a trick to store a function ptr to a function returning a function ptr... */ +typedef struct permittedPeers_s permittedPeers_t; /* this should go away in the long term -- rgerhards, 2008-05-19 */ typedef struct tcpsrv_s tcpsrv_t; /* some universal 64 bit define... */ @@ -219,11 +220,15 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_GNUTLS_ERR = -2078, /**< (unexpected) error in GnuTLS call */ RS_RET_MAX_SESS_REACHED = -2079, /**< max nbr of sessions reached, can not create more */ RS_RET_MAX_LSTN_REACHED = -2080, /**< max nbr of listeners reached, can not create more */ - RS_RET_INVAID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */ + RS_RET_INVALID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */ RS_RET_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */ RS_RET_TLS_CERT_ERR = -2084, /**< generic TLS certificate error */ RS_RET_TLS_NO_CERT = -2085, /**< no TLS certificate available where one was expected */ + RS_RET_VALUE_NOT_SUPPORTED = -2086, /**< a provided value is not supported */ + RS_RET_VALUE_NOT_IN_THIS_MODE = -2087, /**< a provided value is invalid for the curret mode */ + RS_RET_INVALID_FINGERPRINT = -2088, /**< a fingerprint is not valid for this use case */ + RS_RET_CONNECTION_ABORTREQ = -2089, /**< connection was abort requested due to previous error */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ |