summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-19 18:52:44 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-19 18:52:44 +0200
commit85b587f93d7f1294fae78317c0841a30aaa03583 (patch)
treefcfcf000d37b873cf385782fe8c411fb21f1b1c0
parent48684ceac5d57f2c3bc9e8afce98d2026ab51958 (diff)
downloadrsyslog-85b587f93d7f1294fae78317c0841a30aaa03583.tar.gz
rsyslog-85b587f93d7f1294fae78317c0841a30aaa03583.tar.xz
rsyslog-85b587f93d7f1294fae78317c0841a30aaa03583.zip
first implementation of TLS server client authentication check
The TLS server now checks the client fingerprint. This works, but is highly experimental. Needs to be refined for practice. Also: - implemented permittedPeers helper construct to store names - changed omfwd implementation to use new permittedPeers
-rw-r--r--plugins/imtcp/imtcp.c48
-rw-r--r--runtime/net.c64
-rw-r--r--runtime/net.h19
-rw-r--r--runtime/netstrm.c12
-rw-r--r--runtime/netstrm.h2
-rw-r--r--runtime/netstrms.c51
-rw-r--r--runtime/netstrms.h9
-rw-r--r--runtime/nsd.h2
-rw-r--r--runtime/nsd_gtls.c55
-rw-r--r--runtime/nsd_gtls.h3
-rw-r--r--runtime/nsd_ptcp.c20
-rw-r--r--runtime/nsdsel_gtls.c9
-rw-r--r--runtime/rsyslog.h2
-rw-r--r--tcpsrv.c53
-rw-r--r--tcpsrv.h6
-rw-r--r--tools/omfwd.c50
16 files changed, 347 insertions, 58 deletions
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
index 971d3aec..d8363151 100644
--- a/plugins/imtcp/imtcp.c
+++ b/plugins/imtcp/imtcp.c
@@ -23,6 +23,20 @@
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
+/* This note shall explain the calling sequence while we do not have
+ * have full RainerScript support for (TLS) sender authentication:
+ *
+ * imtcp --> tcpsrv --> netstrms (this sequence stored pPermPeers in netstrms class)
+ * then a callback (doOpenLstnSocks) into imtcp happens, which in turn calls
+ * into tcpsrv.create_tcp_socket(),
+ * which calls into netstrm.LstnInit(), which receives a pointer to netstrms obj
+ * which calls into the driver function LstnInit (again, netstrms obj passed)
+ * which finally calls back into netstrms obj's get functions to obtain the auth
+ * parameters and then applies them to the driver object instance
+ *
+ * rgerhards, 2008-05-19
+ */
+
#include "config.h"
#include <stdlib.h>
#include <assert.h>
@@ -46,6 +60,7 @@
#include "netstrm.h"
#include "errmsg.h"
#include "tcpsrv.h"
+#include "net.h" /* for permittedPeers, may be removed when this is removed */
MODULE_TYPE_INPUT
@@ -59,10 +74,13 @@ DEFobjCurrIf(errmsg)
/* Module static data */
static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
+static permittedPeers_t *pPermPeersRoot = NULL;
+
/* config settings */
static int iTCPSessMax = 200; /* max number of sessions */
static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
/* callbacks */
@@ -122,9 +140,22 @@ onErrClose(tcps_sess_t *pSess)
/* ------------------------------ end callbacks ------------------------------ */
+/* set permitted peer -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRoot, pszID));
+finalize_it:
+ RETiRet;
+}
+
+
static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
{
DEFiRet;
+
if(pOurTcpsrv == NULL) {
CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
@@ -133,6 +164,15 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa
CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode));
+ /* now set optional params, but only if they were actually configured */
+ if(pszStrmDrvrAuthMode != NULL) {
+RUNLOG_VAR("%s", pszStrmDrvrAuthMode);
+ CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode));
+ }
+ if(pPermPeersRoot != NULL) {
+ CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot));
+ }
+ /* most params set, now start listener */
tcpsrv.configureTCPListen(pOurTcpsrv, (char *) pNewVal);
CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
}
@@ -183,6 +223,10 @@ CODESTARTmodExit
if(pOurTcpsrv != NULL)
iRet = tcpsrv.Destruct(&pOurTcpsrv);
+ if(pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&pPermPeersRoot);
+ }
+
/* release objects we used */
objRelease(net, LM_NET_FILENAME);
objRelease(netstrm, LM_NETSTRMS_FILENAME);
@@ -227,6 +271,10 @@ CODEmodInit_QueryRegCFSLineHdlr
NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdrivermode", 0,
eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverauthmode", 0,
+ eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverpermittedpeer", 0,
+ eCmdHdlrGetWord, setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
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 899cb3bf..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"
@@ -202,20 +203,21 @@ SetDrvrAuthMode(netstrm_t *pThis, uchar *mode)
}
-/* add an accepted fingerprint -- rgerhards, 2008-05-16
- */
+/* set the driver's permitted peers -- rgerhards, 2008-05-19 */
static rsRetVal
-AddDrvrPermittedFingerprint(netstrm_t *pThis, uchar *fingerprint)
+SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers)
{
DEFiRet;
ISOBJ_TYPE_assert(pThis, netstrm);
- iRet = pThis->Drvr.AddPermFingerprint(pThis->pDrvrData, fingerprint);
+ 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
@@ -311,7 +313,7 @@ CODESTARTobjQueryInterface(netstrm)
pIf->GetRemoteIP = GetRemoteIP;
pIf->SetDrvrMode = SetDrvrMode;
pIf->SetDrvrAuthMode = SetDrvrAuthMode;
- pIf->AddDrvrPermittedFingerprint = AddDrvrPermittedFingerprint;
+ pIf->SetDrvrPermPeers = SetDrvrPermPeers;
pIf->GetSock = GetSock;
finalize_it:
ENDobjQueryInterface(netstrm)
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
index ffdb392e..ae135beb 100644
--- a/runtime/netstrm.h
+++ b/runtime/netstrm.h
@@ -51,7 +51,7 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
rsRetVal (*GetRemoteIP)(netstrm_t *pThis, uchar **pszIP);
rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode);
rsRetVal (*SetDrvrAuthMode)(netstrm_t *pThis, uchar*);
- rsRetVal (*AddDrvrPermittedFingerprint)(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
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 1dc9efe9..53693b59 100644
--- a/runtime/nsd.h
+++ b/runtime/nsd.h
@@ -52,7 +52,7 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
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 (*AddPermFingerprint)(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
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 4e7fa3b6..ff162754 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"
@@ -252,7 +253,6 @@ finalize_it:
/* check the fingerprint of the remote peer's certificate.
* rgerhards, 2008-05-08
*/
-//static rsRetVal
rsRetVal
gtlsChkFingerprint(nsd_gtls_t *pThis)
{
@@ -264,6 +264,8 @@ 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);
@@ -296,11 +298,23 @@ gtlsChkFingerprint(nsd_gtls_t *pThis)
if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT)
FINALIZE;
- if(pThis->authIDs == NULL || rsCStrSzStrCmp(pstrFingerprint, pThis->authIDs, strlen((char*) pThis->authIDs))) {
- dbgprintf("invalid server fingerprint, not permitted to talk to us\n");
+ /* 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) {
- errmsg.LogError(NO_ERRCODE, "error: server fingerprint '%s' unknown - we are "
- "not permitted to talk to this server", rsCStrGetSzStr(pstrFingerprint));
+ 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);
@@ -401,7 +415,6 @@ 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) {
errmsg.LogError(NO_ERRCODE, "error: driver mode %d not supported by "
@@ -450,28 +463,26 @@ dbgprintf("gtls auth mode %d set\n", pThis->authMode);
}
-/* Add a permitted fingerprint. Only useful to call if we are using
- * fingerprint authentication. Results in error if we are not in this mode.
- * rgerhards, 2008-05-16
+/* Set permitted peers. It is depending on the auth mode if this are
+ * fingerprints or names. -- rgerhards, 2008-05-19
*/
static rsRetVal
-AddPermFingerprint(nsd_t *pNsd, uchar *pszFingerprint)
+SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers)
{
DEFiRet;
nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ISOBJ_TYPE_assert((pThis), nsd_gtls);
- if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT) {
- errmsg.LogError(NO_ERRCODE, "fingerprint authentication not supported by "
+ 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);
}
- // TODO: proper handling - but we need to redo this when we do the
- // linked list. So for now, this is good enough (but MUST BE CHANGED!).
-
- pThis->authIDs = pszFingerprint;
-dbgprintf("gtls fingerprint '%s' set\n", pThis->authIDs);
+ pThis->pPermPeers = pPermPeers;
finalize_it:
RETiRet;
@@ -590,6 +601,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
@@ -633,6 +646,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;
@@ -667,6 +683,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;
@@ -771,7 +790,7 @@ CODESTARTobjQueryInterface(nsd_gtls)
pIf->SetSock = SetSock;
pIf->SetMode = SetMode;
pIf->SetAuthMode = SetAuthMode;
- pIf->AddPermFingerprint = AddPermFingerprint;
+ pIf->SetPermPeers =SetPermPeers;
pIf->GetRemoteHName = GetRemoteHName;
pIf->GetRemoteIP = GetRemoteIP;
finalize_it:
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
index 0576a993..1f3eb6b1 100644
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -38,6 +38,7 @@ 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,
@@ -51,7 +52,7 @@ struct nsd_gtls_s {
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. */
- uchar *authIDs; /* TODO: make linked list, currently just a single fingerprint, must also support names */
+ 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 6702e118..14c564a3 100644
--- a/runtime/nsd_ptcp.c
+++ b/runtime/nsd_ptcp.c
@@ -153,16 +153,22 @@ finalize_it:
}
-/* Add a permitted fingerprint. This is a dummy, always returning an
+/* 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
-AddPermFingerprint(nsd_t __attribute__((unused)) *pNsd, uchar __attribute__((unused)) *pszFingerprint)
+SetPermPeers(nsd_t __attribute__((unused)) *pNsd, permittedPeers_t __attribute__((unused)) *pPermPeers)
{
- errmsg.LogError(NO_ERRCODE, "fingerprint authentication not supported by "
- "ptcp netstream driver");
- return RS_RET_VALUE_NOT_IN_THIS_MODE;
+ 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;
}
@@ -477,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));
@@ -668,7 +676,7 @@ CODESTARTobjQueryInterface(nsd_ptcp)
pIf->SetSock = SetSock;
pIf->SetMode = SetMode;
pIf->SetAuthMode = SetAuthMode;
- pIf->AddPermFingerprint = AddPermFingerprint;
+ 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 e54693dc..082a044b 100644
--- a/runtime/nsdsel_gtls.c
+++ b/runtime/nsdsel_gtls.c
@@ -128,12 +128,10 @@ doRetry(nsd_gtls_t *pNsd)
switch(pNsd->rtryCall) {
case gtlsRtry_handshake:
gnuRet = gnutls_handshake(pNsd->sess);
- dbgprintf("handshake ret %d\n", gnuRet);
if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
/* we got a handshake, now check authorization */
- // TODO: do it!
- dbgprintf("handshake done\n");
- gtlsChkFingerprint(pNsd);
+ CHKiRet(gtlsChkFingerprint(pNsd));
}
break;
default:
@@ -157,6 +155,9 @@ doRetry(nsd_gtls_t *pNsd)
*/
finalize_it:
+ if(iRet != RS_RET_OK)
+ pNsd->bAbortConn = 1; /* request abort */
+RUNLOG_VAR("%d", pNsd->bAbortConn);
RETiRet;
}
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index fe26bb44..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... */
@@ -227,6 +228,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
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) */
diff --git a/tcpsrv.c b/tcpsrv.c
index 6db2fee7..9b3553f1 100644
--- a/tcpsrv.c
+++ b/tcpsrv.c
@@ -457,6 +457,7 @@ Run(tcpsrv_t *pThis)
pThis->pOnRegularClose(pThis->pSessions[iTCPSess]);
tcps_sess.Destruct(&pThis->pSessions[iTCPSess]);
} else if(state == -1) {
+ errno = 0;
errmsg.LogError(NO_ERRCODE, "netstream session %p will be closed, error ignored\n",
pThis->pSessions[iTCPSess]->pStrm);
pThis->pOnErrClose(pThis->pSessions[iTCPSess]);
@@ -478,12 +479,18 @@ Run(tcpsrv_t *pThis)
iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
}
CHKiRet(nssel.Destruct(&pSel));
+finalize_it: /* this is a very special case - this time only we do not exit the function,
+ * because that would not help us either. So we simply retry it. Let's see
+ * if that actually is a better idea. Exiting the loop wasn't we always
+ * crashed, which made sense (the rest of the engine was not prepared for
+ * that) -- rgerhards, 2008-05-19
+ */
+ /*EMPTY*/;
}
/* note that this point is usually not reached */
pthread_cleanup_pop(0); /* remove cleanup handler */
-finalize_it: // TODO: think: is it really good to exit the loop?
RETiRet;
}
@@ -504,6 +511,10 @@ tcpsrvConstructFinalize(tcpsrv_t *pThis)
/* prepare network stream subsystem */
CHKiRet(netstrms.Construct(&pThis->pNS));
CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode));
+ if(pThis->pszDrvrAuthMode != NULL)
+ CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode));
+ if(pThis->pPermPeers != NULL)
+ CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers));
// TODO: set driver!
CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
@@ -530,6 +541,8 @@ CODESTARTobjDestruct(tcpsrv)
if(pThis->pNS != NULL)
netstrms.Destruct(&pThis->pNS);
+ if(pThis->pszDrvrAuthMode != NULL)
+ free(pThis->pszDrvrAuthMode);
if(pThis->ppLstn != NULL)
free(pThis->ppLstn);
ENDobjDestruct(tcpsrv)
@@ -628,8 +641,14 @@ SetUsrP(tcpsrv_t *pThis, void *pUsr)
pThis->pUsr = pUsr;
RETiRet;
}
-/* set the driver mode -- rgerhards, 2008-04-30
- */
+
+
+/* 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-30 */
static rsRetVal
SetDrvrMode(tcpsrv_t *pThis, int iMode)
{
@@ -640,6 +659,32 @@ SetDrvrMode(tcpsrv_t *pThis, int iMode)
}
+/* set the driver authentication mode -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrAuthMode(tcpsrv_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ CHKmalloc(pThis->pszDrvrAuthMode = (uchar*)strdup((char*)mode));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the driver's permitted peers -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->pPermPeers = pPermPeers;
+ RETiRet;
+}
+
+
+/* End of methods to shuffle autentication settings to the driver.;
+
+ * -------------------------------------------------------------------------- */
/* queryInterface function
@@ -668,6 +713,8 @@ CODESTARTobjQueryInterface(tcpsrv)
pIf->SetUsrP = SetUsrP;
pIf->SetDrvrMode = SetDrvrMode;
+ pIf->SetDrvrAuthMode = SetDrvrAuthMode;
+ pIf->SetDrvrPermPeers = SetDrvrPermPeers;
pIf->SetCBIsPermittedHost = SetCBIsPermittedHost;
pIf->SetCBOpenLstnSocks = SetCBOpenLstnSocks;
pIf->SetCBRcvData = SetCBRcvData;
diff --git a/tcpsrv.h b/tcpsrv.h
index 07826125..0feb62f3 100644
--- a/tcpsrv.h
+++ b/tcpsrv.h
@@ -30,6 +30,8 @@ struct tcpsrv_s {
BEGINobjInstance; /**< Data to implement generic object - MUST be the first data element! */
netstrms_t *pNS; /**< pointer to network stream subsystem */
int iDrvrMode; /**< mode of the stream driver to use */
+ uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */
+ permittedPeers_t *pPermPeers;/**< driver's permitted peers */
int iLstnMax; /**< max nbr of listeners currently supported */
netstrm_t **ppLstn; /**< our netstream listners */
int iSessMax; /**< max number of sessions supported */
@@ -71,12 +73,14 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SetCBOnRegularClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
rsRetVal (*SetCBOnErrClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
rsRetVal (*SetDrvrMode)(tcpsrv_t *pThis, int iMode);
+ rsRetVal (*SetDrvrAuthMode)(tcpsrv_t *pThis, uchar *pszMode);
+ rsRetVal (*SetDrvrPermPeers)(tcpsrv_t *pThis, permittedPeers_t*);
/* session specifics */
rsRetVal (*SetCBOnSessAccept)(tcpsrv_t*, rsRetVal (*) (tcpsrv_t*, tcps_sess_t*));
rsRetVal (*SetCBOnSessDestruct)(tcpsrv_t*, rsRetVal (*) (void*));
rsRetVal (*SetCBOnSessConstructFinalize)(tcpsrv_t*, rsRetVal (*) (void*));
ENDinterface(tcpsrv)
-#define tcpsrvCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
+#define tcpsrvCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
/* prototypes */
diff --git a/tools/omfwd.c b/tools/omfwd.c
index 43f601e3..a902fe3b 100644
--- a/tools/omfwd.c
+++ b/tools/omfwd.c
@@ -79,7 +79,8 @@ typedef struct _instanceData {
netstrm_t *pNetstrm; /* our output netstream */
uchar *pszStrmDrvr;
uchar *pszStrmDrvrAuthMode;
- uchar *pszStrmDrvrFingerprint;
+ permittedPeers_t *pPermPeersRootFingerprint;
+ permittedPeers_t *pPermPeersRootNames;
int iStrmDrvrMode;
char *f_hname;
int *pSockArray; /* sockets to use for UDP */
@@ -98,9 +99,10 @@ typedef struct _instanceData {
static uchar *pszTplName = NULL; /* name of the default template to use */
static uchar *pszStrmDrvr = NULL; /* name of the stream driver to use */
static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
-static uchar *pszStrmDrvrAuthMode = NULL; /* name of the default template to use */
-static uchar *pszStrmDrvrFingerprint = NULL; /* name of the default template to use */
+static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
+static permittedPeers_t *pPermPeersRootFingerprint = NULL;
+static permittedPeers_t *pPermPeersRootNames = NULL;
/* get the syslog forward port from selector_t. The passed in
* struct must be one that is setup for forwarding.
@@ -154,8 +156,10 @@ CODESTARTfreeInstance
free(pData->pszStrmDrvr);
if(pData->pszStrmDrvrAuthMode != NULL)
free(pData->pszStrmDrvrAuthMode);
- if(pData->pszStrmDrvrFingerprint != NULL)
- free(pData->pszStrmDrvrFingerprint);
+ if(pData->pPermPeersRootFingerprint != NULL)
+ net.DestructPermittedPeers(&pData->pPermPeersRootFingerprint);
+ if(pData->pPermPeersRootNames != NULL)
+ net.DestructPermittedPeers(&pData->pPermPeersRootNames);
ENDfreeInstance
@@ -212,6 +216,19 @@ static rsRetVal UDPSend(instanceData *pData, char *msg, size_t len)
}
+/* set the cert fingerprint -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setFingerprint(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRootFingerprint, pszID));
+finalize_it:
+ RETiRet;
+}
+
+
+
/* CODE FOR SENDING TCP MESSAGES */
@@ -281,9 +298,8 @@ static rsRetVal TCPSendInit(void *pvData)
if(pData->pszStrmDrvrAuthMode != NULL) {
CHKiRet(netstrm.SetDrvrAuthMode(pData->pNetstrm, pData->pszStrmDrvrAuthMode));
}
- if(pData->pszStrmDrvrFingerprint != NULL) {
- CHKiRet(netstrm.AddDrvrPermittedFingerprint(pData->pNetstrm,
- pData->pszStrmDrvrFingerprint));
+ if(pData->pPermPeersRootFingerprint != NULL) {
+ CHKiRet(netstrm.SetDrvrPermPeers(pData->pNetstrm, pData->pPermPeersRootFingerprint));
}
/* params set, now connect */
CHKiRet(netstrm.Connect(pData->pNetstrm, glbl.GetDefPFFamily(),
@@ -590,9 +606,14 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
if(pszStrmDrvrAuthMode != NULL)
CHKmalloc(pData->pszStrmDrvrAuthMode =
(uchar*)strdup((char*)pszStrmDrvrAuthMode));
- if(pszStrmDrvrFingerprint != NULL)
- CHKmalloc(pData->pszStrmDrvrFingerprint =
- (uchar*)strdup((char*)pszStrmDrvrFingerprint));
+ if(pPermPeersRootFingerprint != NULL) {
+ pData->pPermPeersRootFingerprint = pPermPeersRootFingerprint;
+ pPermPeersRootFingerprint = NULL;
+ }
+ if(pPermPeersRootNames != NULL) {
+ pData->pPermPeersRootNames = pPermPeersRootNames;
+ pPermPeersRootNames = NULL;
+ }
}
CODE_STD_FINALIZERparseSelectorAct
@@ -617,9 +638,8 @@ freeConfigVars(void)
free(pszStrmDrvrAuthMode);
pszStrmDrvrAuthMode = NULL;
}
- if(pszStrmDrvrFingerprint != NULL) {
- free(pszStrmDrvrFingerprint);
- pszStrmDrvrFingerprint = NULL;
+ if(pPermPeersRootFingerprint != NULL) {
+ free(pPermPeersRootFingerprint);
}
}
@@ -670,7 +690,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvr, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt, NULL, &iStrmDrvrMode, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivercertfingerprint", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvrFingerprint, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivercertfingerprint", 0, eCmdHdlrGetWord, setFingerprint, NULL, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit