diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:28:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:28:20 +0000 |
commit | dcc721a95bef6f0d8e6d8775b8efe33e5aecd562 (patch) | |
tree | 66a2774cd0ee294d019efd71d2544c70f42b2842 /runtime/netstrm.c | |
parent | Initial commit. (diff) | |
download | rsyslog-dcc721a95bef6f0d8e6d8775b8efe33e5aecd562.tar.xz rsyslog-dcc721a95bef6f0d8e6d8775b8efe33e5aecd562.zip |
Adding upstream version 8.2402.0.upstream/8.2402.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | runtime/netstrm.c | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/runtime/netstrm.c b/runtime/netstrm.c new file mode 100644 index 0000000..d20957e --- /dev/null +++ b/runtime/netstrm.c @@ -0,0 +1,508 @@ +/* netstrm.c + * + * This class implements a generic netstrmwork stream class. It supports + * sending and receiving data streams over a netstrmwork. The class abstracts + * the transport, though it is a safe assumption that TCP is being used. + * The class has a number of properties, among which are also ones to + * select privacy settings, eg by enabling TLS and/or GSSAPI. In the + * long run, this class shall provide all stream-oriented netstrmwork + * functionality inside rsyslog. + * + * It is a high-level class, which uses a number of helper objects + * to carry out its work (including, and most importantly, transport + * drivers). + * + * Note on processing: + * - Initiating a listener may be driver-specific, but in regard to TLS/non-TLS + * it actually is not. This is because TLS is negotiated after a connection + * has been established. So it is the "acceptConnReq" driver entry where TLS + * params need to be applied. + * + * Work on this module begun 2008-04-17 by Rainer Gerhards. This code + * borrows from librelp's tcp.c/.h code. librelp is dual licensed and + * Rainer Gerhards and Adiscon GmbH have agreed to permit using the code + * under the terms of the GNU Lesser General Public License. + * + * Copyright 2007-2020 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 <http://www.gnu.org/licenses/>. + * + * 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 <stdlib.h> +#include <assert.h> +#include <string.h> + +#include "rsyslog.h" +#include "net.h" +#include "module-template.h" +#include "obj.h" +#include "errmsg.h" +#include "netstrms.h" +#include "netstrm.h" + +/* static data */ +DEFobjStaticHelpers +DEFobjCurrIf(netstrms) + + +/* Standard-Constructor */ +BEGINobjConstruct(netstrm) /* be sure to specify the object type also in END macro! */ +ENDobjConstruct(netstrm) + + +/* destructor for the netstrm object */ +BEGINobjDestruct(netstrm) /* be sure to specify the object type also in END and CODESTART macros! */ +CODESTARTobjDestruct(netstrm) + if(pThis->pDrvrData != NULL) + iRet = pThis->Drvr.Destruct(&pThis->pDrvrData); +ENDobjDestruct(netstrm) + + +/* ConstructionFinalizer */ +static rsRetVal +netstrmConstructFinalize(netstrm_t *pThis) +{ + ISOBJ_TYPE_assert(pThis, netstrm); + return pThis->Drvr.Construct(&pThis->pDrvrData); +} + +/* abort a connection. This is much like Destruct(), but tries + * to discard any unsent data. -- rgerhards, 2008-03-24 + */ +static rsRetVal +AbortDestruct(netstrm_t **ppThis) +{ + DEFiRet; + assert(ppThis != NULL); + ISOBJ_TYPE_assert((*ppThis), netstrm); + + /* we do NOT exit on error, because that would make things worse */ + (*ppThis)->Drvr.Abort((*ppThis)->pDrvrData); + iRet = netstrmDestruct(ppThis); + + RETiRet; +} + + +/* accept an incoming connection request + * The netstrm instance that had the incoming request must be provided. If + * the connection request succeeds, a new netstrm object is created and + * passed back to the caller. The caller is responsible for destructing it. + * pReq is the nsd_t obj that has the accept request. + * rgerhards, 2008-04-21 + */ +static rsRetVal +AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew) +{ + nsd_t *pNewNsd = NULL; + DEFiRet; + + ISOBJ_TYPE_assert(pThis, netstrm); + assert(ppNew != NULL); + + /* accept the new connection */ + CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd)); + /* construct our object so that we can use it... */ + CHKiRet(objUse(netstrms, DONT_LOAD_LIB)); /* use netstrms obj if not already done so */ + CHKiRet(netstrms.CreateStrm(pThis->pNS, ppNew)); + (*ppNew)->pDrvrData = pNewNsd; + +finalize_it: + if(iRet != RS_RET_OK) { + /* the close may be redundant, but that doesn't hurt... */ + if(pNewNsd != NULL) + pThis->Drvr.Destruct(&pNewNsd); + } + + RETiRet; +} + + +/* make the netstrm listen to specified port and IP. + * pLstnIP points to the port to listen to (NULL means "all"), + * iMaxSess has the maximum number of sessions permitted (this ist just a hint). + * pLstnPort must point to a port name or number. NULL is NOT permitted. + * rgerhards, 2008-04-22 + */ +static rsRetVal ATTR_NONNULL(1,3,5) +LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*), + const int iSessMax, const tcpLstnParams_t *const cnf_params) +{ + DEFiRet; + + ISOBJ_TYPE_assert(pNS, netstrms); + assert(fAddLstn != NULL); + assert(cnf_params->pszPort != NULL); + + CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params)); + +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 occurred and + * oserr holds the exact error cause. + * rgerhards, 2008-03-17 + */ +static rsRetVal +Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf, int *const oserr) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.Rcv(pThis->pDrvrData, pBuf, pLenBuf, oserr); + 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 + */ +static rsRetVal +SetDrvrMode(netstrm_t *pThis, int iMode) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetMode(pThis->pDrvrData, iMode); + RETiRet; +} + + +/* 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; +} + + +/* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20 + */ +static rsRetVal +SetDrvrPermitExpiredCerts(netstrm_t *pThis, uchar *mode) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetPermitExpiredCerts(pThis->pDrvrData, mode); + RETiRet; +} + +/* set the driver's permitted peers -- rgerhards, 2008-05-19 */ +static rsRetVal +SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetPermPeers(pThis->pDrvrData, pPermPeers); + RETiRet; +} + +/* Mandate also verification of Extended key usage / purpose field */ +static rsRetVal +SetDrvrCheckExtendedKeyUsage(netstrm_t *pThis, int ChkExtendedKeyUsage) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetCheckExtendedKeyUsage(pThis->pDrvrData, ChkExtendedKeyUsage); + RETiRet; +} + +/* Mandate stricter name checking per RFC 6125 - ignoce CN if any SAN present */ +static rsRetVal +SetDrvrPrioritizeSAN(netstrm_t *pThis, int prioritizeSan) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetPrioritizeSAN(pThis->pDrvrData, prioritizeSan); + RETiRet; +} + +/* tls verify depth */ +static rsRetVal +SetDrvrTlsVerifyDepth(netstrm_t *pThis, int verifyDepth) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetTlsVerifyDepth(pThis->pDrvrData, verifyDepth); + RETiRet; +} + +static rsRetVal +SetDrvrTlsCAFile(netstrm_t *const pThis, const uchar *const file) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetTlsCAFile(pThis->pDrvrData, file); + RETiRet; +} + +static rsRetVal +SetDrvrTlsCRLFile(netstrm_t *const pThis, const uchar *const file) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetTlsCRLFile(pThis->pDrvrData, file); + RETiRet; +} + +static rsRetVal +SetDrvrTlsKeyFile(netstrm_t *const pThis, const uchar *const file) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetTlsKeyFile(pThis->pDrvrData, file); + RETiRet; +} + +static rsRetVal +SetDrvrTlsCertFile(netstrm_t *const pThis, const uchar *const file) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetTlsCertFile(pThis->pDrvrData, file); + 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 + * been written. + * rgerhards, 2008-03-19 + */ +static rsRetVal +Send(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.Send(pThis->pDrvrData, pBuf, pLenBuf); + RETiRet; +} + +/* Enable Keep-Alive handling for those drivers that support it. + * rgerhards, 2009-06-02 + */ +static rsRetVal +EnableKeepAlive(netstrm_t *pThis) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.EnableKeepAlive(pThis->pDrvrData); + RETiRet; +} + +/* Keep-Alive options + */ +static rsRetVal +SetKeepAliveProbes(netstrm_t *pThis, int keepAliveProbes) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetKeepAliveProbes(pThis->pDrvrData, keepAliveProbes); + RETiRet; +} + +/* Keep-Alive options + */ +static rsRetVal +SetKeepAliveTime(netstrm_t *pThis, int keepAliveTime) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetKeepAliveTime(pThis->pDrvrData, keepAliveTime); + RETiRet; +} + +/* Keep-Alive options + */ +static rsRetVal +SetKeepAliveIntvl(netstrm_t *pThis, int keepAliveIntvl) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetKeepAliveIntvl(pThis->pDrvrData, keepAliveIntvl); + RETiRet; +} + +/* gnutls priority string */ +static rsRetVal +SetGnutlsPriorityString(netstrm_t *pThis, uchar *gnutlsPriorityString) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.SetGnutlsPriorityString(pThis->pDrvrData, gnutlsPriorityString); + RETiRet; +} + +/* check connection - slim wrapper for NSD driver function */ +static rsRetVal +CheckConnection(netstrm_t *pThis) +{ + ISOBJ_TYPE_assert(pThis, netstrm); + return pThis->Drvr.CheckConnection(pThis->pDrvrData); +} + + +/* get remote hname - slim wrapper for NSD driver function */ +static rsRetVal +GetRemoteHName(netstrm_t *pThis, uchar **ppsz) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.GetRemoteHName(pThis->pDrvrData, ppsz); + RETiRet; +} + + +/* get remote IP - slim wrapper for NSD driver function */ +static rsRetVal +GetRemoteIP(netstrm_t *pThis, prop_t **ip) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.GetRemoteIP(pThis->pDrvrData, ip); + RETiRet; +} + + +/* get remote addr - slim wrapper for NSD driver function */ +static rsRetVal +GetRemAddr(netstrm_t *pThis, struct sockaddr_storage **ppAddr) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + iRet = pThis->Drvr.GetRemAddr(pThis->pDrvrData, ppAddr); + RETiRet; +} + + +/* open a connection to a remote host (server). + * rgerhards, 2008-03-19 + */ +static rsRetVal +Connect(netstrm_t *pThis, int family, uchar *port, uchar *host, char *device) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + assert(port != NULL); + assert(host != NULL); + iRet = pThis->Drvr.Connect(pThis->pDrvrData, family, port, host, device); + RETiRet; +} + + +/* Provide access to the underlying OS socket. This is dirty + * and scheduled to be removed. Does not work with all nsd drivers. + * See comment in netstrm interface for details. + * rgerhards, 2008-05-05 + */ +static rsRetVal +GetSock(netstrm_t *pThis, int *pSock) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, netstrm); + assert(pSock != NULL); + iRet = pThis->Drvr.GetSock(pThis->pDrvrData, pSock); + RETiRet; +} + + +/* queryInterface function + */ +BEGINobjQueryInterface(netstrm) +CODESTARTobjQueryInterface(netstrm) + if(pIf->ifVersion != netstrmCURR_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 = netstrmConstruct; + pIf->ConstructFinalize = netstrmConstructFinalize; + pIf->Destruct = netstrmDestruct; + pIf->AbortDestruct = AbortDestruct; + pIf->Rcv = Rcv; + pIf->Send = Send; + pIf->Connect = Connect; + pIf->LstnInit = LstnInit; + pIf->AcceptConnReq = AcceptConnReq; + pIf->GetRemoteHName = GetRemoteHName; + pIf->GetRemoteIP = GetRemoteIP; + pIf->GetRemAddr = GetRemAddr; + pIf->SetDrvrMode = SetDrvrMode; + pIf->SetDrvrAuthMode = SetDrvrAuthMode; + pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts; + pIf->SetDrvrPermPeers = SetDrvrPermPeers; + pIf->CheckConnection = CheckConnection; + pIf->GetSock = GetSock; + pIf->EnableKeepAlive = EnableKeepAlive; + pIf->SetKeepAliveProbes = SetKeepAliveProbes; + pIf->SetKeepAliveTime = SetKeepAliveTime; + pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; + pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; + pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; + pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; + pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth; + pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile; + pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile; + pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile; + pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile; +finalize_it: +ENDobjQueryInterface(netstrm) + + +/* exit our class + */ +BEGINObjClassExit(netstrm, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ +CODESTARTObjClassExit(netstrm) + /* release objects we no longer need */ + objRelease(netstrms, DONT_LOAD_LIB); +ENDObjClassExit(netstrm) + + +/* Initialize the netstrm class. Must be called as the very first method + * before anything else is called inside this class. + * rgerhards, 2008-02-19 + */ +BEGINAbstractObjClassInit(netstrm, 1, OBJ_IS_CORE_MODULE) /* class, version */ + /* request objects we use */ + + /* set our own handlers */ +ENDObjClassInit(netstrm) +/* vi:set ai: + */ |