summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-30 16:35:35 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-30 16:35:35 +0200
commitc370fc6305af0fc9c37f818d8b88726b899b0d0a (patch)
treed07339f8fab9125240d11ca67aa4679e0018956e
parentb0d63ea8f26f525bbfd177aaa6a1294b0d94f1f9 (diff)
downloadrsyslog-c370fc6305af0fc9c37f818d8b88726b899b0d0a.tar.gz
rsyslog-c370fc6305af0fc9c37f818d8b88726b899b0d0a.tar.xz
rsyslog-c370fc6305af0fc9c37f818d8b88726b899b0d0a.zip
server handshake now works with nonblocking sockets
-rw-r--r--runtime/Makefile.am2
-rw-r--r--runtime/nsd_gtls.c9
-rw-r--r--runtime/nsd_gtls.h3
-rw-r--r--runtime/nsd_ptcp.c3
-rw-r--r--runtime/nsdsel_gtls.c72
-rw-r--r--runtime/rsyslog.h1
6 files changed, 82 insertions, 8 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 571d36ac..381c3ae5 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -128,6 +128,6 @@ pkglib_LTLIBRARIES += lmnsdsel_gtls.la
lmnsdsel_gtls_la_SOURCES = nsdsel_gtls.c nsdsel_gtls.h
lmnsdsel_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmnsdsel_gtls_la_LDFLAGS = -module -avoid-version
-lmnsdsel_gtls_la_LIBADD =
+lmnsdsel_gtls_la_LIBADD = $(gnutls_libs)
endif
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 51d32b6c..d8279aaa 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -365,7 +365,14 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
* on non-blocking sockets. Usually, the handshake will not complete
* immediately, so that we need to retry it some time later.
*/
- CHKgnutls(gnutls_handshake(pNew->sess));
+ gnuRet = gnutls_handshake(pNew->sess);
+ if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+ pNew->rtryCall = gtlsRtry_handshake;
+ dbgprintf("GnuTLS handshake does not complete immediately - setting to retry (this is OK and normal)\n");
+ } else if(gnuRet != 0) {
+ ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
+ }
+
pThis->iMode = 1; /* this session is now in TLS mode! */
*ppNew = (nsd_t*) pNew;
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
index 492a2da1..83e15f29 100644
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -27,7 +27,8 @@
#include "nsd.h"
typedef enum {
- gtlsRtry_None = 0 /**< no call needs to be retried */
+ gtlsRtry_None = 0, /**< no call needs to be retried */
+ gtlsRtry_handshake = 1
} gtlsRtryCall_t; /**< IDs of calls that needs to be retried */
typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
index c4fb1cf1..e26347c3 100644
--- a/runtime/nsd_ptcp.c
+++ b/runtime/nsd_ptcp.c
@@ -273,8 +273,6 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
CHKiRet(FillRemHost(pNew, (struct sockaddr*) &addr));
-#warning "socket set to blocking for tls testing - re-enable non-blocking mode!"
-#if 0
/* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */
if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
sockflags |= O_NONBLOCK;
@@ -287,7 +285,6 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket %d", errno, iNewSock);
ABORT_FINALIZE(RS_RET_IO_ERROR);
}
-#endif
pNew->sock = iNewSock;
*ppNew = (nsd_t*) pNew;
diff --git a/runtime/nsdsel_gtls.c b/runtime/nsdsel_gtls.c
index 7cafec49..ab52999c 100644
--- a/runtime/nsdsel_gtls.c
+++ b/runtime/nsdsel_gtls.c
@@ -74,7 +74,21 @@ Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
- iRet = nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ if(gnutls_record_get_direction(pNsdGTLS->sess) == 0) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_RD));
+ } else {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_WR));
+ }
+ FINALIZE;
+ }
+ }
+
+ /* if we reach this point, we need no special handling */
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp));
+
+finalize_it:
RETiRet;
}
@@ -94,6 +108,47 @@ Select(nsdsel_t *pNsdsel, int *piNumReady)
}
+/* retry an interrupted GTLS operation
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+doRetry(nsd_gtls_t *pNsd)
+{
+ DEFiRet;
+ int gnuRet;
+
+ dbgprintf("GnuTLS requested retry of %d operation - executing\n", pNsd->rtryCall);
+
+ /* We follow a common scheme here: first, we do the systen call and
+ * then we check the result. So far, the result is checked after the
+ * switch, because the result check is the same for all calls. Note that
+ * this may change once we deal with the read and write calls (but
+ * probably this becomes an issue only when we begin to work on TLS
+ * for relp). -- rgerhards, 2008-04-30
+ */
+ switch(pNsd->rtryCall) {
+ case gtlsRtry_handshake:
+ gnuRet = gnutls_handshake(pNsd->sess);
+ break;
+ default:
+ assert(0); /* this shall not happen! */
+ break;
+ }
+
+ if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
+ } else if(gnuRet != GNUTLS_E_AGAIN && gnuRet != GNUTLS_E_INTERRUPTED) {
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ /* if we are interrupted once again (else case), we do not need to
+ * change our status because we are already setup for retries.
+ */
+
+finalize_it:
+ RETiRet;
+}
+
+
/* check if a socket is ready for IO */
static rsRetVal
IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
@@ -104,7 +159,20 @@ IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
- iRet = nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ CHKiRet(doRetry(pNsdGTLS));
+ /* we used this up for our own internal processing, so the socket
+ * is not ready from the upper layer point of view.
+ */
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady));
+
+finalize_it:
RETiRet;
}
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 41f4f0c2..c32e190c 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -221,6 +221,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
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_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */
+ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */