summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-26 11:01:42 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-26 11:01:42 +0200
commit7b604269c725eaa6120ddbece6a1ec0b67d9cf82 (patch)
tree1e2416798213053f67f1ea4c4b18117ed7f628db
parentf31a0537c649b0ecf40986e5dc8fea6386e6bcb0 (diff)
downloadrsyslog-7b604269c725eaa6120ddbece6a1ec0b67d9cf82.tar.gz
rsyslog-7b604269c725eaa6120ddbece6a1ec0b67d9cf82.tar.xz
rsyslog-7b604269c725eaa6120ddbece6a1ec0b67d9cf82.zip
added capability to auto-configure tls auth rule for client connecting to server
must match hostname in send action
-rw-r--r--runtime/nsd_gtls.c64
-rw-r--r--runtime/nsd_gtls.h1
2 files changed, 52 insertions, 13 deletions
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 54fbecd2..fab400fc 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -504,6 +504,45 @@ finalize_it:
}
+/* Perform a match on ONE peer name obtained from the certificate. This name
+ * is checked against the set of configured credentials. *pbFoundPositiveMatch is
+ * set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized
+ * to 0 by the caller (this is a performance enhancement as we expect to be
+ * called multiple times)
+ * rgerhards, 2008-05-26
+ */
+static rsRetVal
+gtlsChkOnePeerName(nsd_gtls_t *pThis, uchar *pszPeerID, int *pbFoundPositiveMatch)
+{
+ permittedPeers_t *pPeer;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ assert(pszPeerID != NULL);
+ assert(pbFoundPositiveMatch != NULL);
+
+ if(pThis->pPermPeers) { /* do we have configured peer IDs? */
+ pPeer = pThis->pPermPeers;
+ while(pPeer != NULL && !*pbFoundPositiveMatch) {
+ if(!strcmp((char*)pszPeerID, (char*)pPeer->pszID)) {
+ *pbFoundPositiveMatch = 1;
+ } else {
+ pPeer = pPeer->pNext;
+ }
+ }
+ } else {
+ /* we do not have configured peer IDs, so we use defaults */
+RUNLOG_VAR("%s", pThis->pszConnectHost);
+ if( pThis->pszConnectHost
+ && !strcmp((char*)pszPeerID, (char*)pThis->pszConnectHost)) {
+ *pbFoundPositiveMatch = 1;
+ }
+ }
+
+ RETiRet;
+}
+
+
/* Check the peer's ID in name auth mode.
* rgerhards, 2008-05-22
*/
@@ -515,7 +554,6 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt *pCert)
int iAltName;
size_t szAltNameLen;
int bFoundPositiveMatch;
- permittedPeers_t *pPeer;
cstr_t *pStr = NULL;
int gnuRet;
DEFiRet;
@@ -537,18 +575,7 @@ gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt *pCert)
dbgprintf("subject alt dnsName: '%s'\n", szAltName);
snprintf((char*)lnBuf, sizeof(lnBuf), "DNSname: %s; ", szAltName);
CHKiRet(rsCStrAppendStr(pStr, lnBuf));
- /* we found it - now we need to loop through the list of permitted
- * peer IDs. As soon as we have a positive match, we are all set.
- */
- pPeer = pThis->pPermPeers;
- while(pPeer != NULL && !bFoundPositiveMatch) {
-RUNLOG_VAR("%s", pPeer->pszID);
- if(!strcmp(szAltName, (char*)pPeer->pszID)) {
- bFoundPositiveMatch = 1;
- } else {
- pPeer = pPeer->pNext;
- }
- }
+ CHKiRet(gtlsChkOnePeerName(pThis, (uchar*)szAltName, &bFoundPositiveMatch));
/* do NOT break, because there may be multiple dNSName's! */
}
++iAltName;
@@ -647,6 +674,7 @@ gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
ISOBJ_TYPE_assert(pThis, nsd_gtls);
gnuRet = gnutls_certificate_verify_peers(pThis->sess);
if(gnuRet == GNUTLS_E_NO_CERTIFICATE_FOUND) {
+ errno = 0;
errmsg.LogError(NO_ERRCODE, "peer did not provide a certificate, not permitted to talk to it");
ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
} else if(gnuRet < 1)
@@ -781,6 +809,10 @@ CODESTARTobjDestruct(nsd_gtls)
if(pThis->pTcp != NULL) {
nsd_ptcp.Destruct(&pThis->pTcp);
}
+
+ if(pThis->pszConnectHost != NULL) {
+ free(pThis->pszConnectHost);
+ }
ENDobjDestruct(nsd_gtls)
@@ -1131,6 +1163,12 @@ Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock));
gtlsSetTransportPtr(pThis, sock);
+ /* we need to store the hostname as an alternate mean of authentication if no
+ * permitted peer names are given. Using the hostname is quite useful. It permits
+ * auto-configuration of security if a commen root cert is present. -- rgerhards, 2008-05-26
+ */
+ CHKmalloc(pThis->pszConnectHost = (uchar*)strdup((char*)host));
+
/* and perform the handshake */
CHKgnutls(gnutls_handshake(pThis->sess));
dbgprintf("GnuTLS handshake succeeded\n");
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
index 59109e68..a88e34fc 100644
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -37,6 +37,7 @@ typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
struct nsd_gtls_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
nsd_t *pTcp; /**< our aggregated nsd_ptcp data */
+ uchar *pszConnectHost; /**< hostname used for connect - may be used to authenticate peer if no other name given */
int iMode; /* 0 - plain tcp, 1 - TLS */
int bAbortConn; /* if set, abort conncection (fatal error had happened) */
enum {