summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-16 18:26:25 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-16 18:26:25 +0200
commit6ea98ec5fff21c362e28a0121b78b8e6bb3b2528 (patch)
tree3b4f434a5b8329acd82ef77d3d5d0144218b9e79
parent29ebd4ab3e391aea53b6e337061d226359aeb993 (diff)
downloadrsyslog-6ea98ec5fff21c362e28a0121b78b8e6bb3b2528.tar.gz
rsyslog-6ea98ec5fff21c362e28a0121b78b8e6bb3b2528.tar.xz
rsyslog-6ea98ec5fff21c362e28a0121b78b8e6bb3b2528.zip
added first rough ability to authenticate the server against its certificate
This is very experimental and needs some more work. It probably even segfaults - but the base code is there and running. The rest is refinement. While working on this, I did these two bugfixes: - bugfix: small mem leak in omfwd on exit (strmdriver name was not freed) - bugfix: $ActionSendStreamDriver had no effect
-rw-r--r--ChangeLog6
-rw-r--r--runtime/netstrm.c32
-rw-r--r--runtime/netstrm.h4
-rw-r--r--runtime/nsd.h4
-rw-r--r--runtime/nsd_gtls.c73
-rw-r--r--runtime/nsd_gtls.h6
-rw-r--r--runtime/rsyslog.h3
-rw-r--r--tools/omfwd.c69
8 files changed, 174 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index ffe66f8f..cc599b52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
---------------------------------------------------------------------------
Version 3.19.3 (rgerhards), 2008-05-??
+- added ability to authenticate the server against its certificate
+ fingerprint
+- bugfix: small mem leak in omfwd on exit (strmdriver name was not freed)
+- bugfix: $ActionSendStreamDriver had no effect
+- added ability for client to provide its fingerprint
+- added ability for server to obtain client cert's fingerprint
---------------------------------------------------------------------------
Version 3.19.2 (rgerhards), 2008-05-16
- bugfix: TCP input modules did incorrectly set fromhost property
diff --git a/runtime/netstrm.c b/runtime/netstrm.c
index a1384a28..899cb3bf 100644
--- a/runtime/netstrm.c
+++ b/runtime/netstrm.c
@@ -172,6 +172,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 +190,32 @@ 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;
+}
+
+
+/* add an accepted fingerprint -- rgerhards, 2008-05-16
+ */
+static rsRetVal
+AddDrvrPermittedFingerprint(netstrm_t *pThis, uchar *fingerprint)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.AddPermFingerprint(pThis->pDrvrData, fingerprint);
+ 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 +310,8 @@ CODESTARTobjQueryInterface(netstrm)
pIf->GetRemoteHName = GetRemoteHName;
pIf->GetRemoteIP = GetRemoteIP;
pIf->SetDrvrMode = SetDrvrMode;
+ pIf->SetDrvrAuthMode = SetDrvrAuthMode;
+ pIf->AddDrvrPermittedFingerprint = AddDrvrPermittedFingerprint;
pIf->GetSock = GetSock;
finalize_it:
ENDobjQueryInterface(netstrm)
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
index a15c1d9b..ffdb392e 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 (*AddDrvrPermittedFingerprint)(netstrm_t *pThis, uchar*);
/* 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/nsd.h b/runtime/nsd.h
index cc06c877..1dc9efe9 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 (*AddPermFingerprint)(nsd_t *pThis, uchar*); /* sets a driver specific mode - see driver doc for details */
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 60685de7..131a3679 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -225,9 +225,6 @@ finalize_it:
static rsRetVal
gtlsGlblInitLstn(void)
{
- int gnuRet;
- uchar *keyFile;
- uchar *certFile;
DEFiRet;
if(bGlblSrvrInitDone == 0) {
@@ -290,6 +287,14 @@ gtlsChkFingerprint(nsd_gtls_t *pThis)
CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint));
dbgprintf("peer's certificate SHA1 fingerprint: %s\n", rsCStrGetSzStr(pstrFingerprint));
+ if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT)
+ FINALIZE;
+
+ if(pThis->authIDs == NULL || rsCStrSzStrCmp(pstrFingerprint, pThis->authIDs, strlen((char*) pThis->authIDs))) {
+ // TODO: logerror
+ dbgprintf("invalid server fingerprint, not authorized\n");
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
finalize_it:
dbgprintf("exit fingerprint check, iRet %d\n", iRet);
@@ -397,6 +402,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);
+RUNLOG_VAR("%s", mode);
+ 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 {
+ // TODO: logerror()?
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+/* TODO: clear stored IDs! */
+
+finalize_it:
+dbgprintf("gtls auth mode %d set\n", pThis->authMode);
+ RETiRet;
+}
+
+
+/* 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
+ */
+static rsRetVal
+AddPermFingerprint(nsd_t *pNsd, uchar *pszFingerprint)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT)
+ 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);
+
+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
@@ -689,6 +754,8 @@ CODESTARTobjQueryInterface(nsd_gtls)
pIf->Connect = Connect;
pIf->SetSock = SetSock;
pIf->SetMode = SetMode;
+ pIf->SetAuthMode = SetAuthMode;
+ pIf->AddPermFingerprint = AddPermFingerprint;
pIf->GetRemoteHName = GetRemoteHName;
pIf->GetRemoteIP = GetRemoteIP;
finalize_it:
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
index bbb0eb9e..885a8b30 100644
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -38,11 +38,17 @@ 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 */
+ 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) */
+ uchar *authIDs; /* TODO: make linked list, currently just a single fingerprint, must also support names */
};
/* interface is defined in nsd.h, we just implement it! */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 367a239f..088a14db 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -224,6 +224,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
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 */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/tools/omfwd.c b/tools/omfwd.c
index 59245536..e0b6db01 100644
--- a/tools/omfwd.c
+++ b/tools/omfwd.c
@@ -78,6 +78,8 @@ typedef struct _instanceData {
netstrms_t *pNS; /* netstream subsystem */
netstrm_t *pNetstrm; /* our output netstream */
uchar *pszStrmDrvr;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrFingerprint;
int iStrmDrvrMode;
char *f_hname;
int *pSockArray; /* sockets to use for UDP */
@@ -96,6 +98,8 @@ 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 */
/* get the syslog forward port from selector_t. The passed in
@@ -146,7 +150,12 @@ CODESTARTfreeInstance
if(pData->f_hname != NULL)
free(pData->f_hname);
-
+ if(pData->pszStrmDrvr != NULL)
+ free(pData->pszStrmDrvr);
+ if(pData->pszStrmDrvrAuthMode != NULL)
+ free(pData->pszStrmDrvrAuthMode);
+ if(pData->pszStrmDrvrFingerprint != NULL)
+ free(pData->pszStrmDrvrFingerprint);
ENDfreeInstance
@@ -268,6 +277,9 @@ static rsRetVal TCPSendInit(void *pvData)
CHKiRet(netstrms.CreateStrm(pData->pNS, &pData->pNetstrm));
CHKiRet(netstrm.ConstructFinalize(pData->pNetstrm));
CHKiRet(netstrm.SetDrvrMode(pData->pNetstrm, pData->iStrmDrvrMode));
+ CHKiRet(netstrm.SetDrvrAuthMode(pData->pNetstrm, pData->pszStrmDrvrAuthMode));
+ CHKiRet(netstrm.AddDrvrPermittedFingerprint(pData->pNetstrm,
+ pData->pszStrmDrvrFingerprint));
CHKiRet(netstrm.Connect(pData->pNetstrm, glbl.GetDefPFFamily(),
(uchar*)pData->port, (uchar*)pData->f_hname));
}
@@ -567,14 +579,45 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendPrepRetry));
CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing));
pData->iStrmDrvrMode = iStrmDrvrMode;
- if(pData->pszStrmDrvr != NULL)
+ if(pszStrmDrvr != NULL)
CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)pszStrmDrvr));
+ if(pszStrmDrvrAuthMode != NULL)
+ CHKmalloc(pData->pszStrmDrvrAuthMode =
+ (uchar*)strdup((char*)pszStrmDrvrAuthMode));
+ if(pszStrmDrvrFingerprint != NULL)
+ CHKmalloc(pData->pszStrmDrvrFingerprint =
+ (uchar*)strdup((char*)pszStrmDrvrFingerprint));
}
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
+/* a common function to free our configuration variables - used both on exit
+ * and on $ResetConfig processing. -- rgerhards, 2008-05-16
+ */
+static void
+freeConfigVars(void)
+{
+ if(pszTplName != NULL) {
+ free(pszTplName);
+ pszTplName = NULL;
+ }
+ if(pszStrmDrvr != NULL) {
+ free(pszStrmDrvr);
+ pszStrmDrvr = NULL;
+ }
+ if(pszStrmDrvrAuthMode != NULL) {
+ free(pszStrmDrvrAuthMode);
+ pszStrmDrvrAuthMode = NULL;
+ }
+ if(pszStrmDrvrFingerprint != NULL) {
+ free(pszStrmDrvrFingerprint);
+ pszStrmDrvrFingerprint = NULL;
+ }
+}
+
+
BEGINmodExit
CODESTARTmodExit
/* release what we no longer need */
@@ -585,14 +628,7 @@ CODESTARTmodExit
objRelease(netstrms, LM_NETSTRMS_FILENAME);
objRelease(tcpclt, LM_TCPCLT_FILENAME);
- if(pszTplName != NULL) {
- free(pszTplName);
- pszTplName = NULL;
- }
- if(pszStrmDrvr != NULL) {
- free(pszStrmDrvr);
- pszStrmDrvr = NULL;
- }
+ freeConfigVars();
ENDmodExit
@@ -607,14 +643,9 @@ ENDqueryEtryPt
*/
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
- if(pszTplName != NULL) {
- free(pszTplName);
- pszTplName = NULL;
- }
- if(pszStrmDrvr != NULL) {
- free(pszStrmDrvr);
- pszStrmDrvr = NULL;
- }
+ freeConfigVars();
+
+ /* we now must reset all non-string values */
iStrmDrvrMode = 0;
return RS_RET_OK;
@@ -632,6 +663,8 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
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(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit