From fd6c3bc36a5a32f873299f7ae2dfc184e6e3c658 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 18 Apr 2008 14:25:29 +0200 Subject: set stage for TLS client implementation --- configure.ac | 40 +++++++- runtime/Makefile.am | 16 +++- runtime/glbl.c | 4 +- runtime/nsd.h | 1 - runtime/nsd_gtls.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++ runtime/nsd_gtls.h | 47 ++++++++++ runtime/nsd_ptcp.h | 3 +- runtime/rsyslog.h | 3 + 8 files changed, 366 insertions(+), 7 deletions(-) create mode 100644 runtime/nsd_gtls.c create mode 100644 runtime/nsd_gtls.h diff --git a/configure.ac b/configure.ac index 2ae3401c..060a3854 100644 --- a/configure.ac +++ b/configure.ac @@ -462,6 +462,44 @@ AC_SUBST(snmp_cflags) AC_SUBST(snmp_libs) +# GNUtls support +AC_ARG_ENABLE(gnutls, + [AS_HELP_STRING([--enable-gnutls],[Enable GNU TLS support @<:@default=yes@:>@])], + [case "${enableval}" in + yes) enable_gnutls="yes" ;; + no) enable_gnutls="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-gnutls) ;; + esac], + [enable_gnutls=no] +) +if test "x$enable_gnutls" = "xyes"; then + AC_CHECK_HEADERS( + [gnutls/gnutls.h],, + [AC_MSG_FAILURE([GNUTls is missing])] + ) + AC_CHECK_PROG( + [HAVE_GNUTLS_CONFIG], + [libgnutls-config], + [yes],,, + ) + if test "x${HAVE_GNUTLS_CONFIG}" != "xyes"; then + AC_MSG_FAILURE([libgnutls-config not found in PATH]) + fi + AC_CHECK_LIB( + [gnutls], + [gnutls_check_version], + [tls_cflags=`libgnutls-config --cflags` + tls_libs=`libgnutls-config --libs` + ], + [AC_MSG_FAILURE([GNU TLS library is missing])], + [`libgnutls-config --libs`] + ) +fi +AM_CONDITIONAL(ENABLE_GNUTLS, test x$enable_gnutls = xyes) +AC_SUBST(tls_cflags) +AC_SUBST(tls_libs) + + # support for building the rsyslogd runtime AC_ARG_ENABLE(rsyslogrt, [AS_HELP_STRING([--enable-rsyslogrt],[Build rsyslogrt @<:@default=yes@:>@])], @@ -525,7 +563,6 @@ AC_SUBST(RELP_CFLAGS) AC_SUBST(RELP_LIBS) # RFC 3195 support -# WARNING: THIS IS NOT REALLY PRESENT YET - needs to be build manually! AC_ARG_ENABLE(rfc3195, [AS_HELP_STRING([--enable-rfc3195],[Enable RFC3195 support @<:@default=no@:>@])], [case "${enableval}" in @@ -624,6 +661,7 @@ echo "file input module enabled: $enable_imfile" echo "input template module will be compiled: $enable_imtemplate" echo "Large file support enabled: $enable_largefile" echo "Networking support enabled: $enable_inet" +echo "GnuTLS network stream driver enabled: $enable_gnutls" echo "Enable GSSAPI Kerberos 5 support: $want_gssapi_krb5" echo "Debug mode enabled: $enable_debug" echo "Runtime Instrumentation enabled: $enable_rtinst" diff --git a/runtime/Makefile.am b/runtime/Makefile.am index 077310c6..23e62deb 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -96,12 +96,22 @@ lmnetstrm_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) lmnetstrm_la_LDFLAGS = -module -avoid-version lmnetstrm_la_LIBADD = -# netstream drivers - -# plain tcp driver +# plain tcp netstream driver pkglib_LTLIBRARIES += lmnsd_ptcp.la lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h lmnsd_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) lmnsd_ptcp_la_LDFLAGS = -module -avoid-version lmnsd_ptcp_la_LIBADD = endif # if ENABLE_INET + +# +# GnuTLS netstream driver +# +if ENABLE_GNUTLS +pkglib_LTLIBRARIES += lmnsd_gtls.la +lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h +lmnsd_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) +lmnsd_gtls_la_LDFLAGS = -module -avoid-version +lmnsd_gtls_la_LIBADD = +endif + diff --git a/runtime/glbl.c b/runtime/glbl.c index 1e51b0e0..787b6ab7 100644 --- a/runtime/glbl.c +++ b/runtime/glbl.c @@ -40,7 +40,9 @@ /* some defaults */ #ifndef DFLT_NETSTRM_DRVR -# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_ptcp") +// TESTING ONLY# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_ptcp") +#warning "define must be restored for non-testing!" +# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_gtls") #endif /* static data */ diff --git a/runtime/nsd.h b/runtime/nsd.h index 52c36dcf..c8bc95d0 100644 --- a/runtime/nsd.h +++ b/runtime/nsd.h @@ -24,7 +24,6 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ - #ifndef INCLUDED_NSD_H #define INCLUDED_NSD_H diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c new file mode 100644 index 00000000..6fe0cd8a --- /dev/null +++ b/runtime/nsd_gtls.c @@ -0,0 +1,259 @@ +/* nsd_gtls.c + * + * An implementation of the nsd interface for GnuTLS. + * + * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of the rsyslog runtime library. + * + * The rsyslog runtime library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The rsyslog runtime library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the rsyslog runtime library. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. + */ +#include "config.h" + +#include "rsyslog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rsyslog.h" +#include "syslogd-types.h" +#include "module-template.h" +#include "parse.h" +#include "srUtils.h" +#include "obj.h" +#include "errmsg.h" +#include "nsd_ptcp.h" +#include "nsd_gtls.h" + +MODULE_TYPE_LIB + +/* static data */ +DEFobjStaticHelpers +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(nsd_ptcp) + + +/* Standard-Constructor */ +BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */ + iRet = nsd_ptcp.Construct(&pThis->pTcp); +ENDobjConstruct(nsd_gtls) + + +/* destructor for the nsd_gtls object */ +BEGINobjDestruct(nsd_gtls) /* be sure to specify the object type also in END and CODESTART macros! */ +CODESTARTobjDestruct(nsd_gtls) + if(pThis->pTcp != NULL) + nsd_ptcp.Destruct(&pThis->pTcp); +ENDobjDestruct(nsd_gtls) + + +/* abort a connection. This is meant to be called immediately + * before the Destruct call. -- rgerhards, 2008-03-24 + */ +static rsRetVal +Abort(nsd_t *pNsd) +{ + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + DEFiRet; + + ISOBJ_TYPE_assert((pThis), nsd_gtls); + + if(pThis->iMode == 0) { + nsd_ptcp.Abort(pThis->pTcp); + } + + RETiRet; +} + + + +/* initialize the tcp socket for a listner + * pLstnPort must point to a port name or number. NULL is NOT permitted + * (hint: we need to be careful when we use this module together with librelp, + * there NULL indicates the default port + * default is used. + * gerhards, 2008-03-17 + */ +static rsRetVal +LstnInit(nsd_t *pNsd, uchar *pLstnPort) +{ + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + DEFiRet; + + ISOBJ_TYPE_assert(pThis, nsd_gtls); + assert(pLstnPort != NULL); + + if(pThis->iMode == 0) { + CHKiRet(nsd_ptcp.LstnInit(pThis->pTcp, pLstnPort)); + } + +finalize_it: + RETiRet; +} + + +/* receive data from a tcp socket + * The lenBuf parameter must contain the max buffer size on entry and contains + * the number of octets read (or -1 in case of error) on exit. This function + * never blocks, not even when called on a blocking socket. That is important + * for client sockets, which are set to block during send, but should not + * block when trying to read data. If *pLenBuf is -1, an error occured and + * errno holds the exact error cause. + * rgerhards, 2008-03-17 + */ +static rsRetVal +Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) +{ + DEFiRet; + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + ISOBJ_TYPE_assert(pThis, nsd_gtls); + + if(pThis->iMode == 0) { + CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf)); + } + +finalize_it: + RETiRet; +} + + +/* 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 + * been written. + * rgerhards, 2008-03-19 + */ +static rsRetVal +Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) +{ + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + DEFiRet; + ISOBJ_TYPE_assert(pThis, nsd_gtls); + + if(pThis->iMode == 0) { + CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf)); + } +finalize_it: + RETiRet; +} + + +/* open a connection to a remote host (server). + * rgerhards, 2008-03-19 + */ +static rsRetVal +Connect(nsd_t *pNsd, int family, uchar *port, uchar *host) +{ + nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd; + DEFiRet; + + ISOBJ_TYPE_assert(pThis, nsd_gtls); + assert(port != NULL); + assert(host != NULL); + if(pThis->iMode == 0) { + CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host)); + } + + +finalize_it: + RETiRet; +} + + +/* queryInterface function */ +BEGINobjQueryInterface(nsd_gtls) +CODESTARTobjQueryInterface(nsd_gtls) + if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */ + ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); + } + + /* ok, we have the right interface, so let's fill it + * Please note that we may also do some backwards-compatibility + * work here (if we can support an older interface version - that, + * of course, also affects the "if" above). + */ + pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_gtlsConstruct; + pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_gtlsDestruct; + pIf->Abort = Abort; + pIf->LstnInit = LstnInit; + //pIf->AcceptConnReq = AcceptConnReq; + pIf->Rcv = Rcv; + pIf->Send = Send; + pIf->Connect = Connect; +finalize_it: +ENDobjQueryInterface(nsd_gtls) + + +/* exit our class + */ +BEGINObjClassExit(nsd_gtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ +CODESTARTObjClassExit(nsd_gtls) + /* release objects we no longer need */ + objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME); + objRelease(glbl, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); +ENDObjClassExit(nsd_gtls) + + +/* Initialize the nsd_gtls class. Must be called as the very first method + * before anything else is called inside this class. + * rgerhards, 2008-02-19 + */ +BEGINObjClassInit(nsd_gtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ + /* request objects we use */ + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME)); + + /* set our own handlers */ +ENDObjClassInit(nsd_gtls) + + +/* --------------- here now comes the plumbing that makes as a library module --------------- */ + + +BEGINmodExit +CODESTARTmodExit + nsd_gtlsClassExit(); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_LIB_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ + + /* Initialize all classes that are in our module - this includes ourselfs */ + CHKiRet(nsd_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ +ENDmodInit +/* vi:set ai: + */ diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h new file mode 100644 index 00000000..ddd561de --- /dev/null +++ b/runtime/nsd_gtls.h @@ -0,0 +1,47 @@ +/* An implementation of the nsd interface for GnuTLS. + * + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of the rsyslog runtime library. + * + * The rsyslog runtime library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The rsyslog runtime library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the rsyslog runtime library. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. + */ + +#ifndef INCLUDED_NSD_GTLS_H +#define INCLUDED_NSD_GTLS_H + +#include "nsd.h" + +typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */ + +/* the nsd_gtls object */ +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 */ +}; + +/* interface is defined in nsd.h, we just implement it! */ +#define nsd_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION + +/* prototypes */ +PROTOTYPEObj(nsd_gtls); + +/* the name of our library binary */ +#define LM_NSD_GTLS_FILENAME "lmnsd_gtls" + +#endif /* #ifndef INCLUDED_NSD_GTLS_H */ diff --git a/runtime/nsd_ptcp.h b/runtime/nsd_ptcp.h index d4848314..36725799 100644 --- a/runtime/nsd_ptcp.h +++ b/runtime/nsd_ptcp.h @@ -29,7 +29,7 @@ typedef nsd_if_t nsd_ptcp_if_t; /* we just *implement* this interface */ /* the nsd_ptcp object */ struct nsd_ptcp_s { - BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ + BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ uchar *pRemHostIP; /**< IP address of remote peer (currently used in server mode, only) */ uchar *pRemHostName; /**< host name of remote peer (currently used in server mode, only) */ int sock; /**< the socket we use for regular, single-socket, operations */ @@ -38,6 +38,7 @@ struct nsd_ptcp_s { }; /* interface is defined in nsd.h, we just implement it! */ +#define nsd_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsd_ptcp); diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index f7824006..ad2a543a 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -66,6 +66,9 @@ typedef struct filed selector_t;/* TODO: this so far resides in syslogd.c, think typedef struct NetAddr netAddr_t; typedef struct netstrm_s netstrm_t; typedef struct nsd_ptcp_s nsd_ptcp_t; +typedef struct nsd_gtls_s nsd_gtls_t; +typedef struct nsd_gsspi_s nsd_gsspi_t; +typedef struct nsd_nss_s nsd_nss_t; typedef obj_t nsd_t; typedef struct msg msg_t; typedef struct interface_s interface_t; -- cgit