summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-21 12:23:41 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-21 12:23:41 +0200
commitff446070be16b18e119873ed56e2c96e28b98514 (patch)
tree4639428c29cf604a3955ea487813027141a585db /runtime
parent275595cdf8d5e18e665bfd4189f8061441595cce (diff)
parent8cb6ec4cee79d41c30d7df38b58ab1f198ac8581 (diff)
downloadrsyslog-ff446070be16b18e119873ed56e2c96e28b98514.tar.gz
rsyslog-ff446070be16b18e119873ed56e2c96e28b98514.tar.xz
rsyslog-ff446070be16b18e119873ed56e2c96e28b98514.zip
Merge branch 'ietf-tls'
Conflicts: ChangeLog
Diffstat (limited to 'runtime')
-rw-r--r--runtime/net.c64
-rw-r--r--runtime/net.h19
-rw-r--r--runtime/netstrm.c34
-rw-r--r--runtime/netstrm.h4
-rw-r--r--runtime/netstrms.c51
-rw-r--r--runtime/netstrms.h9
-rw-r--r--runtime/nsd.h4
-rw-r--r--runtime/nsd_gtls.c158
-rw-r--r--runtime/nsd_gtls.h10
-rw-r--r--runtime/nsd_ptcp.c56
-rw-r--r--runtime/nsdsel_gtls.c5
-rw-r--r--runtime/rsyslog.h7
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) */