diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | runtime/netstrm.c | 32 | ||||
-rw-r--r-- | runtime/netstrm.h | 4 | ||||
-rw-r--r-- | runtime/nsd.h | 4 | ||||
-rw-r--r-- | runtime/nsd_gtls.c | 73 | ||||
-rw-r--r-- | runtime/nsd_gtls.h | 6 | ||||
-rw-r--r-- | runtime/rsyslog.h | 3 | ||||
-rw-r--r-- | tools/omfwd.c | 69 |
8 files changed, 174 insertions, 23 deletions
@@ -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 |