diff options
-rw-r--r-- | plugins/imgssapi/imgssapi.c | 467 | ||||
-rw-r--r-- | plugins/imtcp/imtcp.c | 20 | ||||
-rw-r--r-- | tcps_sess.c | 49 | ||||
-rw-r--r-- | tcps_sess.h | 10 | ||||
-rw-r--r-- | tcpsrv.c | 150 | ||||
-rw-r--r-- | tcpsrv.h | 34 |
6 files changed, 505 insertions, 225 deletions
diff --git a/plugins/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c index 215adfa0..bfda9dc4 100644 --- a/plugins/imgssapi/imgssapi.c +++ b/plugins/imgssapi/imgssapi.c @@ -30,6 +30,20 @@ */ #include "config.h" +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <stdarg.h> +#include <ctype.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif #include <gssapi/gssapi.h> #include "rsyslog.h" #include "syslogd.h" @@ -39,65 +53,115 @@ #include "srUtils.h" #include "gss-misc.h" #include "tcpsrv.h" +#include "tcps_sess.h" + + +MODULE_TYPE_INPUT + +int bEnableTCP; + +/* defines */ +#define ALLOWEDMETHOD_GSS 2 +#define ALLOWEDMETHOD_TCP 1 + /* some forward definitions - they may go away when we no longer include imtcp.c */ static rsRetVal addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal); -int TCPSessGSSAccept(int fd); -int TCPSessGSSInit(void); -void TCPSessGSSClose(int iSess); -void TCPSessGSSDeinit(void); -int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len); +static int TCPSessGSSInit(void); +static void TCPSessGSSClose(tcps_sess_t* pSess); +static int TCPSessGSSRecv(tcps_sess_t *pSess, void *buf, size_t buf_len); +static rsRetVal onSessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd); +static rsRetVal OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd); /* static data */ +DEF_IMOD_STATIC_DATA +DEFobjCurrIf(obj) DEFobjCurrIf(tcpsrv) +DEFobjCurrIf(tcps_sess) + +typedef struct _instanceData { +} instanceData; + +static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */ static gss_cred_id_t gss_server_creds = GSS_C_NO_CREDENTIAL; -typedef struct GSSTCPSession_s { +/* our usr structure for the tcpsrv object */ +typedef struct gsssrv_s { + char allowedMethods; +} gsssrv_t; + +/* our usr structure for the session object */ +typedef struct gss_sess_s { OM_uint32 gss_flags; gss_ctx_id_t gss_context; char allowedMethods; -} GSSTCPSession_t; +} gss_sess_t; /* config variables */ +static int iTCPSessMax = 200; /* max number of sessions */ static char *gss_listen_service_name = NULL; static int bPermitPlainTcp = 0; /* plain tcp syslog allowed on GSSAPI port? */ /* methods */ /* callbacks */ -static rsRetVal onTCPSessInit(GSSTCPSession_t *pGSS) +static rsRetVal OnSessConstructFinalize(void *ppUsr) { DEFiRet; - assert(pGSS != NULL) - pGSS->gss_flags = 0; - pGSS->gss_context = GSS_C_NO_CONTEXT; - pGSS->allowedMethods = 0; + gss_sess_t **ppGSess = (gss_sess_t**) ppUsr; + gss_sess_t *pGSess; + + assert(ppGSess != NULL); + + if((pGSess = calloc(1, sizeof(gss_sess_t))) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + + pGSess->gss_flags = 0; + pGSess->gss_context = GSS_C_NO_CONTEXT; + pGSess->allowedMethods = 0; + + *ppGSess = pGSess; + +finalize_it: RETiRet; } static rsRetVal -onListenDeinit(GSSTCPSession_t *pGSS) +OnSessDestruct(void *ppUsr) { DEFiRet; - assert(pGSS != NULL) - if(bEnableTCP & ALLOWEDMETHOD_GSS) { + gss_sess_t **ppGSess = (gss_sess_t**) ppUsr; + + assert(ppGSess != NULL); + assert(*ppGSess != NULL); + + if((*ppGSess)->allowedMethods & ALLOWEDMETHOD_GSS) { OM_uint32 maj_stat, min_stat; - maj_stat = gss_delete_sec_context(&min_stat, &pTCPSessions[iTCPSess].gss_context, GSS_C_NO_BUFFER); + maj_stat = gss_delete_sec_context(&min_stat, &(*ppGSess)->gss_context, GSS_C_NO_BUFFER); if (maj_stat != GSS_S_COMPLETE) display_status("deleting context", maj_stat, min_stat); } + + free(*ppGSess); + *ppGSess = NULL; + RETiRet; } static int -isPermittedHost(TCPSession_t *pSess) +isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void *pUsrSrv, void*pUsrSess) { + gsssrv_t *pGSrv; + gss_sess_t *pGSess; char allowedMethods = 0; - assert(pSess != NULL); + assert(pUsrSrv != NULL); + assert(pUsrSess != NULL); + pGSrv = (gsssrv_t*) pUsrSrv; + pGSess = (gss_sess_t*) pUsrSess; if((bEnableTCP & ALLOWEDMETHOD_TCP) && isAllowedSender(pAllowedSenders_TCP, (struct sockaddr *)&addr, (char*)fromHostFQDN)) @@ -106,66 +170,113 @@ isPermittedHost(TCPSession_t *pSess) isAllowedSender(pAllowedSenders_GSS, (struct sockaddr *)&addr, (char*)fromHostFQDN)) allowedMethods |= ALLOWEDMETHOD_GSS; if(allowedMethods) - pSess->allowedMethods = allowedMethods; + pGSess->allowedMethods = allowedMethods; return allowedMethods; } static rsRetVal -onTCPSessAccept(int fd) +onSessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd) { DEFiRet; - assert(pSess != NULL); + gsssrv_t *pGSrv; + + pGSrv = (gsssrv_t*) pThis->pUsr; - if(bEnableTCP & ALLOWEDMETHOD_GSS) - TCPSessGSSAccept(fd); + if(pGSrv->allowedMethods & ALLOWEDMETHOD_GSS) + iRet = OnSessAcceptGSS(pThis, ppSess, fd); else - TCPSessAccept(fd); + iRet = tcpsrv.SessAccept(pThis, ppSess, fd); + RETiRet; } + static rsRetVal -onRegularClose(TCPSession_t *pSess) +onRegularClose(tcps_sess_t *pSess) { DEFiRet; - assert(pSess != NULL); + gss_sess_t *pGSess; + assert(pSess != NULL); + assert(pSess->pUsr != NULL); + pGSess = (gss_sess_t*) pSess->pUsr; - if(allowedMethods & ALLOWEDMETHOD_GSS) + if(pGSess->allowedMethods & ALLOWEDMETHOD_GSS) TCPSessGSSClose(pSess); else { /* process any incomplete frames left over */ - TCPSessPrepareClose(pSess); + tcps_sess.PrepareClose(pSess); /* Session closed */ - TCPSessClose(pSess); + tcps_sess.Close(pSess); } RETiRet; } static rsRetVal -onErrClose(TCPSession_t *pSess) +onErrClose(tcps_sess_t *pSess) { DEFiRet; + gss_sess_t *pGSess; + assert(pSess != NULL); + assert(pSess->pUsr != NULL); + pGSess = (gss_sess_t*) pSess->pUsr; - if(allowedMethods & ALLOWEDMETHOD_GSS) + if(pGSess->allowedMethods & ALLOWEDMETHOD_GSS) TCPSessGSSClose(pSess); else - TCPSessClose(pSess); + tcps_sess.Close(pSess); + RETiRet; } +/* open the listen sockets */ +static int* +doOpenLstnSocks(tcpsrv_t *pSrv) +{ + int *pRet; + gsssrv_t *pGSrv; + + ISOBJ_TYPE_assert(pSrv, tcpsrv); + pGSrv = pSrv->pUsr; + assert(pGSrv != NULL); + + /* first apply some config settings */ + if(pGSrv->allowedMethods) { + if(pGSrv->allowedMethods & ALLOWEDMETHOD_GSS) { + if(TCPSessGSSInit()) { + logerror("GSS-API initialization failed\n"); + pGSrv->allowedMethods &= ~(ALLOWEDMETHOD_GSS); + } + } + if(pGSrv->allowedMethods) { + /* fallback to plain TCP */ + if((pRet = tcpsrv.create_tcp_socket(pSrv)) != NULL) { + dbgprintf("Opened %d syslog TCP port(s).\n", *pRet); + } + } + } + + return pRet; +} + -static int pRcvData(TCPSession_t *pSess, char *buf, size_t lenBuf) +static int +doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf) { int state; int allowedMethods; + gss_sess_t *pGSess; + assert(pSess != NULL); + assert(pSess->pUsr != NULL); + pGSess = (gss_sess_t*) pSess->pUsr; - allowedMethods = pSess->allowedMethods; + allowedMethods = pGSess->allowedMethods; if(allowedMethods & ALLOWEDMETHOD_GSS) - state = TCPSessGSSRecv(iTCPSess, buf, lenBuf); + state = TCPSessGSSRecv(pSess, buf, lenBuf); //XXX else state = recv(pSess->sock, buf, lenBuf, 0); return state; @@ -174,18 +285,44 @@ static int pRcvData(TCPSession_t *pSess, char *buf, size_t lenBuf) /* end callbacks */ -static rsRetVal addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal) +static rsRetVal +addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal) { - if (!bEnableTCP) - tcpsrv.configureTCPListen((char *) pNewVal); - bEnableTCP |= ALLOWEDMETHOD_GSS; + DEFiRet; + gsssrv_t *pGSrv; + + if(pOurTcpsrv == NULL) { + /* first create/init the gsssrv "object" */ + if((pGSrv = calloc(1, sizeof(gsssrv_t))) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + + pGSrv->allowedMethods = ALLOWEDMETHOD_GSS; + if(bPermitPlainTcp) + pGSrv->allowedMethods |= ALLOWEDMETHOD_TCP; + /* gsssrv initialized */ + + CHKiRet(tcpsrv.Construct(&pOurTcpsrv)); + CHKiRet(tcpsrv.SetUsrP(pOurTcpsrv, pGSrv)); + CHKiRet(tcpsrv.SetCBOnSessConstructFinalize(pOurTcpsrv, OnSessConstructFinalize)); + CHKiRet(tcpsrv.SetCBOnSessDestruct(pOurTcpsrv, OnSessDestruct)); + CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost)); + CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData)); + CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks)); + //CHKiRet(tcpsrv.SetCBOnListenDeinit(pOurTcpsrv, )); + CHKiRet(tcpsrv.SetCBOnSessAccept(pOurTcpsrv, onSessAccept)); + CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose)); + CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose)); + tcpsrv.configureTCPListen(pOurTcpsrv, (char *) pNewVal); + CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv)); + } - return RS_RET_OK; +finalize_it: + RETiRet; } /* returns 0 if all went OK, -1 if it failed */ -int TCPSessGSSInit(void) +static int TCPSessGSSInit(void) { gss_buffer_desc name_buf; gss_name_t server_name; @@ -217,11 +354,13 @@ int TCPSessGSSInit(void) /* returns 0 if all went OK, -1 if it failed - * Calls TCPSessAccept() and then tries to guess if the connection uses + * Calls tcpsrv's SessAccept() and then tries to guess if the connection uses * gssapi. */ -int TCPSessGSSAccept(int fd) +static rsRetVal +OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd) { + DEFiRet; gss_buffer_desc send_tok, recv_tok; gss_name_t client; OM_uint32 maj_stat, min_stat, acc_sec_min_stat; @@ -230,12 +369,19 @@ int TCPSessGSSAccept(int fd) OM_uint32 *sess_flags; int fdSess; char allowedMethods; + gsssrv_t *pGSrv; + tcps_sess_t *pSess; + gss_sess_t *pGSess; - if ((iSess = TCPSessAccept(fd)) == -1) - return -1; + assert(ppSess != NULL); + + if((iSess = tcpsrv.SessAccept(pThis, &pSess, fd)) == -1) + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes - allowedMethods = pTCPSessions[iSess].allowedMethods; - if (allowedMethods & ALLOWEDMETHOD_GSS) { + pGSrv = (gsssrv_t*) pThis->pUsr; + pGSess = (gss_sess_t*) pSess->pUsr; + allowedMethods = pGSrv->allowedMethods; + if(allowedMethods & ALLOWEDMETHOD_GSS) { /* Buffer to store raw message in case that * gss authentication fails halfway through. */ @@ -244,7 +390,7 @@ int TCPSessGSSAccept(int fd) dbgprintf("GSS-API Trying to accept TCP session %d\n", iSess); - fdSess = pTCPSessions[iSess].sock; + fdSess = pSess->sock; // TODO: method access! if (allowedMethods & ALLOWEDMETHOD_TCP) { int len; fd_set fds; @@ -259,12 +405,14 @@ int TCPSessGSSAccept(int fd) } while (ret < 0 && errno == EINTR); if (ret < 0) { logerrorInt("TCP session %d will be closed, error ignored\n", iSess); - TCPSessClose(iSess); - return -1; + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + // was: return -1; } else if (ret == 0) { dbgprintf("GSS-API Reverting to plain TCP\n"); - pTCPSessions[iSess].allowedMethods = ALLOWEDMETHOD_TCP; - return 0; + pGSess->allowedMethods = ALLOWEDMETHOD_TCP; + ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes + // was: return 0; } do { @@ -274,20 +422,22 @@ int TCPSessGSSAccept(int fd) if (ret == 0) dbgprintf("GSS-API Connection closed by peer\n"); else - logerrorInt("TCP session %d will be closed, error ignored\n", iSess); - TCPSessClose(iSess); - return -1; + logerrorInt("TCP(GSS) session %d will be closed, error ignored\n", iSess); + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + // was: return -1; } if (ret < 4) { dbgprintf("GSS-API Reverting to plain TCP\n"); - pTCPSessions[iSess].allowedMethods = ALLOWEDMETHOD_TCP; - return 0; + pGSess->allowedMethods = ALLOWEDMETHOD_TCP; + ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes + // was: return 0; } else if (ret == 4) { /* The client might has been interupted after sending * the data length (4B), give him another chance. */ - sleep(1); + sleep(1); // TODO: bad, bad, fix... do { ret = recv(fdSess, buf, sizeof (buf), MSG_PEEK); } while (ret < 0 && errno == EINTR); @@ -296,30 +446,34 @@ int TCPSessGSSAccept(int fd) dbgprintf("GSS-API Connection closed by peer\n"); else logerrorInt("TCP session %d will be closed, error ignored\n", iSess); - TCPSessClose(iSess); - return -1; + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + //was: return -1; } } + /* TODO: how does this work together with IPv6? Does it? */ len = ntohl((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); if ((ret - 4) < len || len == 0) { dbgprintf("GSS-API Reverting to plain TCP\n"); - pTCPSessions[iSess].allowedMethods = ALLOWEDMETHOD_TCP; - return 0; + pGSess->allowedMethods = ALLOWEDMETHOD_TCP; + ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes + // was: return 0; } } - context = &pTCPSessions[iSess].gss_context; + context = &pGSess->gss_context; *context = GSS_C_NO_CONTEXT; - sess_flags = &pTCPSessions[iSess].gss_flags; + sess_flags = &pGSess->gss_flags; do { if (recv_token(fdSess, &recv_tok) <= 0) { - logerrorInt("TCP session %d will be closed, error ignored\n", iSess); - TCPSessClose(iSess); - return -1; + logerrorVar("TCP session %d will be closed, error ignored\n", iSess); + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + //was: return -1; } maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, gss_server_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, @@ -328,8 +482,7 @@ int TCPSessGSSAccept(int fd) free(recv_tok.value); recv_tok.value = NULL; } - if (maj_stat != GSS_S_COMPLETE - && maj_stat != GSS_S_CONTINUE_NEEDED) { + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { gss_release_buffer(&min_stat, &send_tok); if (*context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER); @@ -337,29 +490,32 @@ int TCPSessGSSAccept(int fd) (GSS_ROUTINE_ERROR(maj_stat) == GSS_S_DEFECTIVE_TOKEN)) { dbgprintf("GSS-API Reverting to plain TCP\n"); dbgprintf("tcp session socket with new data: #%d\n", fdSess); - if(TCPSessDataRcvd(iSess, buf, ret) == 0) { - logerrorInt("Tearing down TCP Session %d - see " + if(tcps_sess.DataRcvd(pSess, buf, ret) == 0) { + logerrorVar("Tearing down TCP Session %d - see " "previous messages for reason(s)\n", iSess); - TCPSessClose(iSess); - return -1; + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + //was: return -1; } - pTCPSessions[iSess].allowedMethods = ALLOWEDMETHOD_TCP; - return 0; + pGSess->allowedMethods = ALLOWEDMETHOD_TCP; + ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes + // was: return 0; } - display_status("accepting context", maj_stat, - acc_sec_min_stat); - TCPSessClose(iSess); - return -1; + display_status("accepting context", maj_stat, acc_sec_min_stat); + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + //was: return -1; } if (send_tok.length != 0) { if (send_token(fdSess, &send_tok) < 0) { gss_release_buffer(&min_stat, &send_tok); - logerrorInt("TCP session %d will be closed, error ignored\n", iSess); + logerrorVar("TCP session %d will be closed, error ignored\n", iSess); if (*context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER); - TCPSessClose(iSess); - return -1; + tcps_sess.Close(pSess); + ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes + //was: return -1; } gss_release_buffer(&min_stat, &send_tok); } @@ -375,17 +531,20 @@ int TCPSessGSSAccept(int fd) dbgprintf("GSS-API Provided context flags:\n"); display_ctx_flags(*sess_flags); - pTCPSessions[iSess].allowedMethods = ALLOWEDMETHOD_GSS; + pGSess->allowedMethods = ALLOWEDMETHOD_GSS; } + + *ppSess = pSess; - return 0; +finalize_it: + RETiRet; } /* returns: ? * Replaces recv() for gssapi connections. */ -int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len) +int TCPSessGSSRecv(tcps_sess_t *pSess, void *buf, size_t buf_len) { gss_buffer_desc xmit_buf, msg_buf; gss_ctx_id_t *context; @@ -393,17 +552,21 @@ int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len) int fdSess; int conf_state; int state, len; + gss_sess_t *pGSess; - fdSess = pTCPSessions[iSess].sock; + assert(pSess->pUsr != NULL); + pGSess = (gss_sess_t*) pSess->pUsr; + + fdSess = pSess->sock; if ((state = recv_token(fdSess, &xmit_buf)) <= 0) return state; - context = &pTCPSessions[iSess].gss_context; + context = &pGSess->gss_context; maj_stat = gss_unwrap(&min_stat, *context, &xmit_buf, &msg_buf, &conf_state, (gss_qop_t *) NULL); - if (maj_stat != GSS_S_COMPLETE) { + if(maj_stat != GSS_S_COMPLETE) { display_status("unsealing message", maj_stat, min_stat); - if (xmit_buf.value) { + if(xmit_buf.value) { free(xmit_buf.value); xmit_buf.value = 0; } @@ -425,93 +588,123 @@ int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len) /* Takes care of cleaning up gssapi stuff and then calls * TCPSessClose(). */ -void TCPSessGSSClose(int iSess) { +void TCPSessGSSClose(tcps_sess_t* pSess) +{ OM_uint32 maj_stat, min_stat; gss_ctx_id_t *context; + gss_sess_t *pGSess; - if(iSess < 0 || iSess > iTCPSessMax) { - errno = 0; - logerror("internal error, trying to close an invalid TCP session!"); - return; - } + assert(pSess->pUsr != NULL); + pGSess = (gss_sess_t*) pSess->pUsr; - context = &pTCPSessions[iSess].gss_context; + context = &pGSess->gss_context; maj_stat = gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER); if (maj_stat != GSS_S_COMPLETE) display_status("deleting context", maj_stat, min_stat); *context = GSS_C_NO_CONTEXT; - pTCPSessions[iSess].gss_flags = 0; - pTCPSessions[iSess].allowedMethods = 0; + pGSess->gss_flags = 0; + pGSess->allowedMethods = 0; - TCPSessClose(iSess); + tcps_sess.Close(pSess); } -/* Counterpart of TCPSessGSSInit() */ -void TCPSessGSSDeinit(void) { +/* Counterpart of TCPSessGSSInit(). This is called to exit the GSS system + * at all. It is a server-based session exit. + */ +static rsRetVal +TCPSessGSSDeinit(void) +{ + DEFiRet; OM_uint32 maj_stat, min_stat; maj_stat = gss_release_cred(&min_stat, &gss_server_creds); if (maj_stat != GSS_S_COMPLETE) display_status("releasing credentials", maj_stat, min_stat); + RETiRet; } - -static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) -{ - if (gss_listen_service_name != NULL) { - free(gss_listen_service_name); - gss_listen_service_name = NULL; - } - bPermitPlainTcp = 0; - return RS_RET_OK; -} - - /* This function is called to gather input. */ BEGINrunInput CODESTARTrunInput - iRet = tcpsrv.RunInput(); - return iRet; + iRet = tcpsrv.Run(pOurTcpsrv); ENDrunInput /* initialize and return if will run or not */ BEGINwillRun CODESTARTwillRun - /* first check if we must support plain TCP, too. If so, set mode - * accordingly. -- rgerhards, 2008-02-26 - */ - if(bPermitPlainTcp) - bEnableTCP |= ALLOWEDMETHOD_TCP; + if(pOurTcpsrv == NULL) + ABORT_FINALIZE(RS_RET_NO_RUN); - /* first apply some config settings */ PrintAllowedSenders(2); /* TCP */ PrintAllowedSenders(3); /* GSS */ - if (bEnableTCP) { - if(sockTCPLstn == NULL) { - if(bEnableTCP & ALLOWEDMETHOD_GSS) { - if(TCPSessGSSInit()) { - logerror("GSS-API initialization failed\n"); - bEnableTCP &= ~(ALLOWEDMETHOD_GSS); - } - } - // TODO: do we still need this here? I don't think - // so... - if(bEnableTCP) - if((sockTCPLstn = create_tcp_socket()) != NULL) { - dbgprintf("Opened %d syslog TCP port(s).\n", *sockTCPLstn); - } - } - } +finalize_it: ENDwillRun + +BEGINmodExit +CODESTARTmodExit + iRet = tcpsrv.Destruct(&pOurTcpsrv); + TCPSessGSSDeinit(); +ENDmodExit + + +BEGINafterRun +CODESTARTafterRun + /* do cleanup here */ + if (pAllowedSenders_TCP != NULL) { + clearAllowedSenders (pAllowedSenders_TCP); + pAllowedSenders_TCP = NULL; + } + if (pAllowedSenders_GSS != NULL) { + clearAllowedSenders (pAllowedSenders_GSS); + pAllowedSenders_GSS = NULL; + } +ENDafterRun + + + +BEGINfreeInstance +CODESTARTfreeInstance +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo +ENDdbgPrintInstInfo + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + + +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + if (gss_listen_service_name != NULL) { + free(gss_listen_service_name); + gss_listen_service_name = NULL; + } + bPermitPlainTcp = 0; + iTCPSessMax = 200; + return RS_RET_OK; +} + + BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = 1; /* so far, we only support the initial definition */ CODEmodInit_QueryRegCFSLineHdlr + pOurTcpsrv = NULL; + /* request objects we use */ +CHKiRet(objGetObjInterface(&obj)); /* get ourselves ;) */ // TODO: framework must do this + CHKiRet(objUse(tcps_sess, "tcps_sess")); + CHKiRet(objUse(tcpsrv, "tcpsrv")); + CHKiRet(objUse(tcpsrv, "tcpsrv")); /* register config file handlers */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"permitplaintcp", 0, eCmdHdlrBinary, diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c index 9ad85044..efdc3e9c 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -62,28 +62,35 @@ static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change fo /* config settings */ static int iTCPSessMax = 200; /* max number of sessions */ -static char *TCPLstnPort = "0"; /* read-only after startup */ /* callbacks */ /* this shall go into a specific ACL module! */ static int -isPermittedHost(struct sockaddr *addr, char *fromHostFQDN) +isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void __attribute__((unused)) *pUsrSrv, + void __attribute__((unused)) *pUsrSess) { return isAllowedSender(pAllowedSenders_TCP, addr, fromHostFQDN); } static rsRetVal -onSessAccept(tcpsrv_t *pThis, int fd) +onSessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd) { DEFiRet; - - tcpsrv.SessAccept(pThis, fd); + tcpsrv.SessAccept(pThis, ppSess, fd); RETiRet; } +static int* +doOpenLstnSocks(tcpsrv_t *pSrv) +{ + ISOBJ_TYPE_assert(pSrv, tcpsrv); + return tcpsrv.create_tcp_socket(pSrv); +} + + static int doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf) { @@ -129,6 +136,7 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa /* TODO: fill params! */ CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost)); CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData)); + CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks)); //CHKiRet(tcpsrv.SetCBOnListenDeinit(pOurTcpsrv, )); CHKiRet(tcpsrv.SetCBOnSessAccept(pOurTcpsrv, onSessAccept)); CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose)); @@ -149,7 +157,6 @@ CODESTARTrunInput * do that in ConstructFinalize */ iRet = tcpsrv.Run(pOurTcpsrv); - return iRet; ENDrunInput @@ -173,6 +180,7 @@ CODESTARTafterRun } ENDafterRun + BEGINmodExit CODESTARTmodExit iRet = tcpsrv.Destruct(&pOurTcpsrv); diff --git a/tcps_sess.c b/tcps_sess.c index 0cff9d88..56b7d9a5 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -47,6 +47,7 @@ #include "syslogd.h" #include "module-template.h" #include "net.h" +#include "tcpsrv.h" #include "tcps_sess.h" #include "obj.h" @@ -61,11 +62,6 @@ BEGINobjConstruct(tcps_sess) /* be sure to specify the object type also in END m pThis->iMsg = 0; /* just make sure... */ pThis->bAtStrtOfFram = 1; /* indicate frame header expected */ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */ - if(pThis->pOnTCPSessConstruct != NULL) { - // TODO: return value! Supply user pointer or whole - // object? - pThis->pOnTCPSessConstruct(pThis->pUsr); - } ENDobjConstruct(tcps_sess) @@ -76,11 +72,11 @@ tcps_sessConstructFinalize(tcps_sess_t __attribute__((unused)) *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); - if(pThis->pOnTCPSessConstructFinalize != NULL) { - // TODO: return value! Supply user pointer or whole - // object? - pThis->pOnTCPSessConstructFinalize(pThis->pUsr); + if(pThis->pSrv->OnSessConstructFinalize != NULL) { + CHKiRet(pThis->pSrv->OnSessConstructFinalize(&pThis->pUsr)); } + +finalize_it: RETiRet; } @@ -88,11 +84,13 @@ tcps_sessConstructFinalize(tcps_sess_t __attribute__((unused)) *pThis) /* destructor for the tcps_sess object */ BEGINobjDestruct(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(tcps_sess) - if(pThis->pOnTCPSessDestruct != NULL) { - // TODO: return value! Supply user pointer or whole - // object? - pThis->pOnTCPSessDestruct(pThis->pUsr); + if(pThis->pSrv->pOnSessDestruct != NULL) { + pThis->pSrv->pOnSessDestruct(&pThis->pUsr); } + /* now destruct our own properties */ + if(pThis->fromHost != NULL) + free(pThis->fromHost); + close(pThis->sock); ENDobjDestruct(tcps_sess) @@ -110,17 +108,14 @@ SetHost(tcps_sess_t *pThis, uchar *pszHost) ISOBJ_TYPE_assert(pThis, tcps_sess); -RUNLOG_VAR("%p", pThis->fromHost); if(pThis->fromHost != NULL) { free(pThis->fromHost); pThis->fromHost = NULL; } -RUNLOG; if((pThis->fromHost = strdup((char*)pszHost)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); -RUNLOG; finalize_it: RETiRet; } @@ -144,6 +139,26 @@ SetMsgIdx(tcps_sess_t *pThis, int idx) } +/* set out parent, the tcpsrv object */ +static rsRetVal +SetTcpsrv(tcps_sess_t *pThis, tcpsrv_t *pSrv) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, tcps_sess); + ISOBJ_TYPE_assert(pSrv, tcpsrv); + pThis->pSrv = pSrv; + RETiRet; +} + + +static rsRetVal +SetUsrP(tcps_sess_t *pThis, void *pUsr) +{ + DEFiRet; + pThis->pUsr = pUsr; + RETiRet; +} + /* This should be called before a normal (non forced) close * of a TCP session. This function checks if there is any unprocessed @@ -394,6 +409,8 @@ CODESTARTobjQueryInterface(tcps_sess) pIf->Close = Close; pIf->DataRcvd = DataRcvd; + pIf->SetUsrP = SetUsrP; + pIf->SetTcpsrv = SetTcpsrv; pIf->SetHost = SetHost; pIf->SetSock = SetSock; pIf->SetMsgIdx = SetMsgIdx; diff --git a/tcps_sess.h b/tcps_sess.h index d3dc9c6d..2bdee80b 100644 --- a/tcps_sess.h +++ b/tcps_sess.h @@ -25,6 +25,9 @@ #include "obj.h" +/* a forward-definition, we are somewhat cyclic */ +struct tcpsrv_s; + /* framing modes for TCP */ typedef enum _TCPFRAMINGMODE { TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */ @@ -34,6 +37,7 @@ typedef enum _TCPFRAMINGMODE { /* the tcps_sess object */ typedef struct tcps_sess_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ + struct tcpsrv_s *pSrv; /* pointer back to my server (e.g. for callbacks) */ int sock; int iMsg; /* index of next char to store in msg */ int bAtStrtOfFram; /* are we at the very beginning of a new frame? */ @@ -42,10 +46,6 @@ typedef struct tcps_sess_s { char msg[MAXLINE+1]; char *fromHost; void *pUsr; /* a user-pointer */ - /* callbacks */ - rsRetVal (*pOnTCPSessConstruct)(void*); - rsRetVal (*pOnTCPSessConstructFinalize)(void*); - rsRetVal (*pOnTCPSessDestruct)(void*); } tcps_sess_t; @@ -59,6 +59,8 @@ BEGINinterface(tcps_sess) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Close)(tcps_sess_t *pThis); rsRetVal (*DataRcvd)(tcps_sess_t *pThis, char *pData, size_t iLen); /* set methods */ + rsRetVal (*SetTcpsrv)(tcps_sess_t *pThis, struct tcpsrv_s *pSrv); + rsRetVal (*SetUsrP)(tcps_sess_t*, void*); rsRetVal (*SetHost)(tcps_sess_t *pThis, uchar*); rsRetVal (*SetSock)(tcps_sess_t *pThis, int); rsRetVal (*SetMsgIdx)(tcps_sess_t *pThis, int); @@ -72,10 +72,6 @@ DEFobjStaticHelpers DEFobjCurrIf(conf) DEFobjCurrIf(tcps_sess) -static char *TCPLstnPort = "0"; /* read-only after startup */ -static tcps_sess_t **pTCPSessions; -/* The thread-safeness of the sesion table is doubtful */ - /* code to free all sockets within a socket table. @@ -129,10 +125,10 @@ configureTCPListen(tcpsrv_t *pThis, char *cOptarg) } if( i >= 0 && i <= 65535) { - TCPLstnPort = cOptarg; + pThis->TCPLstnPort = cOptarg; } else { logerrorSz("Invalid TCP listen port %s - changed to 514.\n", cOptarg); - TCPLstnPort = "514"; + pThis->TCPLstnPort = "514"; } } @@ -172,10 +168,10 @@ TCPSessTblInit(tcpsrv_t *pThis) DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); - assert(pTCPSessions == NULL); + assert(pThis->pSessions == NULL); dbgprintf("Allocating buffer for %d TCP sessions.\n", pThis->iSessMax); - if((pTCPSessions = (tcps_sess_t **) calloc(pThis->iSessMax, sizeof(tcps_sess_t *))) == NULL) { + if((pThis->pSessions = (tcps_sess_t **) calloc(pThis->iSessMax, sizeof(tcps_sess_t *))) == NULL) { dbgprintf("Error: TCPSessInit() could not alloc memory for TCP session table.\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } @@ -197,7 +193,7 @@ TCPSessTblFindFreeSpot(tcpsrv_t *pThis) ISOBJ_TYPE_assert(pThis, tcpsrv); for(i = 0 ; i < pThis->iSessMax ; ++i) { - if(pTCPSessions[i] == NULL) + if(pThis->pSessions[i] == NULL) break; } @@ -220,7 +216,7 @@ TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr) ISOBJ_TYPE_assert(pThis, tcpsrv); for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) - if(pTCPSessions[i] != NULL) + if(pThis->pSessions[i] != NULL) break; return((i < pThis->iSessMax) ? i : -1); @@ -238,20 +234,20 @@ static void deinit_tcp_listener(tcpsrv_t *pThis) int iTCPSess; ISOBJ_TYPE_assert(pThis, tcpsrv); - assert(pTCPSessions != NULL); + assert(pThis->pSessions != NULL); /* close all TCP connections! */ iTCPSess = TCPSessGetNxtSess(pThis, -1); while(iTCPSess != -1) { - tcps_sess.Destruct(&pTCPSessions[iTCPSess]); + tcps_sess.Destruct(&pThis->pSessions[iTCPSess]); /* now get next... */ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } /* we are done with the session table - so get rid of it... */ - free(pTCPSessions); - pTCPSessions = NULL; /* just to make sure... */ + free(pThis->pSessions); + pThis->pSessions = NULL; /* just to make sure... */ /* finally close the listen sockets themselfs */ freeAllSockets(&pThis->pSocksLstn); @@ -274,30 +270,28 @@ static int *create_tcp_socket(tcpsrv_t *pThis) { struct addrinfo hints, *res, *r; int error, maxs, *s, *socks, on = 1; -DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); - if(!strcmp(TCPLstnPort, "0")) - TCPLstnPort = "514"; + if(!strcmp(pThis->TCPLstnPort, "0")) + pThis->TCPLstnPort = "514"; /* use default - we can not do service db update, because there is * no IANA-assignment for syslog/tcp. In the long term, we might * re-use RFC 3195 port of 601, but that would probably break to * many existing configurations. * rgerhards, 2007-06-28 */ - dbgprintf("creating tcp socket on port %s\n", TCPLstnPort); + dbgprintf("creating tcp socket on port %s\n", pThis->TCPLstnPort); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - error = getaddrinfo(NULL, TCPLstnPort, &hints, &res); + error = getaddrinfo(NULL, pThis->TCPLstnPort, &hints, &res); if(error) { logerror((char*) gai_strerror(error)); return NULL; } -RUNLOG; /* Count max number of sockets we may open */ for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++) @@ -308,7 +302,6 @@ RUNLOG; freeaddrinfo(res); return NULL; } -RUNLOG; *socks = 0; /* num of sockets counter at start of array */ s = socks + 1; @@ -346,7 +339,6 @@ RUNLOG; /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ -RUNLOG; #ifndef BSD if (should_use_so_bsdcompat()) { if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, @@ -369,7 +361,6 @@ RUNLOG; *s = -1; continue; } -RUNLOG; if( listen(*s,pThis->iSessMax / 10 + 5) < 0) { /* If the listen fails, it most probably fails because we ask @@ -390,7 +381,6 @@ RUNLOG; (*socks)++; s++; } -RUNLOG; if(res != NULL) freeaddrinfo(res); @@ -406,7 +396,6 @@ RUNLOG; return(NULL); } -RUNLOG; /* OK, we had success. Now it is also time to * initialize our connections */ @@ -420,7 +409,6 @@ RUNLOG; return(NULL); } -dbgprintf("TCP socket(s) successfully created.\n"); return(socks); } @@ -428,9 +416,12 @@ dbgprintf("TCP socket(s) successfully created.\n"); /* Accept new TCP connection; make entry in session table. If there * is no more space left in the connection table, the new TCP * connection is immediately dropped. + * ppSess has a pointer to the newly created session, if it succeds. + * If it does not succeed, no session is created and ppSess is + * undefined. -- rgerhards, 2008-03-02 */ static int -SessAccept(tcpsrv_t *pThis, int fd) +SessAccept(tcpsrv_t *pThis, tcps_sess_t **ppSess, int fd) { DEFiRet; @@ -456,8 +447,13 @@ SessAccept(tcpsrv_t *pThis, int fd) logerror("too many tcp sessions - dropping incoming request"); close(newConn); return -1; + } else { + /* we found a free spot and can construct our session object */ + CHKiRet(tcps_sess.Construct(&pThis->pSessions[iSess])); } + *ppSess = pThis->pSessions[iSess]; + /* OK, we have a "good" index... */ /* get the host name */ if(cvthname(&addr, fromHost, fromHostFQDN) != RS_RET_OK) { @@ -475,7 +471,8 @@ SessAccept(tcpsrv_t *pThis, int fd) * configured to do this). * rgerhards, 2005-09-26 */ - if(!pThis->pIsPermittedHost((struct sockaddr*) &addr, (char*) fromHostFQDN)) + if(!pThis->pIsPermittedHost((struct sockaddr*) &addr, (char*) fromHostFQDN, + pThis->pUsr, pThis->pSessions[iSess]->pUsr)) { dbgprintf("%s is not an allowed sender\n", (char *) fromHostFQDN); if(option_DisallowWarning) { @@ -489,16 +486,19 @@ SessAccept(tcpsrv_t *pThis, int fd) /* OK, we have an allowed sender, so let's continue */ /* we first need to construct a new session object */ - CHKiRet(tcps_sess.Construct(&pTCPSessions[iSess])); - CHKiRet(tcps_sess.SetHost(pTCPSessions[iSess], fromHost)); - CHKiRet(tcps_sess.SetSock(pTCPSessions[iSess], newConn)); - CHKiRet(tcps_sess.SetMsgIdx(pTCPSessions[iSess], 0)); - CHKiRet(tcps_sess.ConstructFinalize(pTCPSessions[iSess])); + CHKiRet(tcps_sess.SetTcpsrv(pThis->pSessions[iSess], pThis)); + CHKiRet(tcps_sess.SetHost(pThis->pSessions[iSess], fromHost)); + CHKiRet(tcps_sess.SetSock(pThis->pSessions[iSess], newConn)); + CHKiRet(tcps_sess.SetMsgIdx(pThis->pSessions[iSess], 0)); + CHKiRet(tcps_sess.ConstructFinalize(pThis->pSessions[iSess])); finalize_it: RUNLOG_VAR("%d", iRet); - if(iRet != RS_RET_OK) + if(iRet != RS_RET_OK) { + if(pThis->pSessions[iSess] != NULL) + tcps_sess.Destruct(&pThis->pSessions[iSess]); iSess = -1; // TODO: change this to be fully iRet compliant ;) + } ENDfunc return iSess; @@ -516,6 +516,7 @@ Run(tcpsrv_t *pThis) int i; int iTCPSess; fd_set readfds; + tcps_sess_t *pNewSess; ISOBJ_TYPE_assert(pThis, tcpsrv); @@ -546,7 +547,7 @@ Run(tcpsrv_t *pThis) iTCPSess = TCPSessGetNxtSess(pThis, -1); while(iTCPSess != -1) { int fdSess; - fdSess = pTCPSessions[iTCPSess]->sock; // TODO: NOT CLEAN!, use method + fdSess = pThis->pSessions[iTCPSess]->sock; // TODO: NOT CLEAN!, use method dbgprintf("Adding TCP Session %d\n", fdSess); FD_SET(fdSess, &readfds); if (fdSess>maxfds) maxfds=fdSess; @@ -570,7 +571,7 @@ Run(tcpsrv_t *pThis) for (i = 0; i < *pThis->pSocksLstn; i++) { if (FD_ISSET(pThis->pSocksLstn[i+1], &readfds)) { dbgprintf("New connect on TCP inetd socket: #%d\n", pThis->pSocksLstn[i+1]); - pThis->pOnSessAccept(pThis, pThis->pSocksLstn[i+1]); + pThis->pOnSessAccept(pThis, &pNewSess, pThis->pSocksLstn[i+1]); --nfds; /* indicate we have processed one */ } } @@ -580,31 +581,31 @@ Run(tcpsrv_t *pThis) while(nfds && iTCPSess != -1) { int fdSess; int state; - fdSess = pTCPSessions[iTCPSess]->sock; // TODO: not clean, use method + fdSess = pThis->pSessions[iTCPSess]->sock; // TODO: not clean, use method if(FD_ISSET(fdSess, &readfds)) { char buf[MAXLINE]; dbgprintf("tcp session socket with new data: #%d\n", fdSess); /* Receive message */ - state = pThis->pRcvData(pTCPSessions[iTCPSess], buf, sizeof(buf)); + state = pThis->pRcvData(pThis->pSessions[iTCPSess], buf, sizeof(buf)); if(state == 0) { - pThis->pOnRegularClose(pTCPSessions[iTCPSess]); - tcps_sess.Destruct(&pTCPSessions[iTCPSess]); + pThis->pOnRegularClose(pThis->pSessions[iTCPSess]); + tcps_sess.Destruct(&pThis->pSessions[iTCPSess]); } else if(state == -1) { logerrorInt("TCP session %d will be closed, error ignored\n", fdSess); - pThis->pOnErrClose(pTCPSessions[iTCPSess]); - tcps_sess.Destruct(&pTCPSessions[iTCPSess]); + pThis->pOnErrClose(pThis->pSessions[iTCPSess]); + tcps_sess.Destruct(&pThis->pSessions[iTCPSess]); } else { /* valid data received, process it! */ - if(tcps_sess.DataRcvd(pTCPSessions[iTCPSess], buf, state) == 0) { + if(tcps_sess.DataRcvd(pThis->pSessions[iTCPSess], buf, state) == 0) { /* in this case, something went awfully wrong. * We are instructed to terminate the session. */ logerrorInt("Tearing down TCP Session %d - see " "previous messages for reason(s)\n", iTCPSess); - pThis->pOnErrClose(pTCPSessions[iTCPSess]); - tcps_sess.Destruct(&pTCPSessions[iTCPSess]); + pThis->pOnErrClose(pThis->pSessions[iTCPSess]); + tcps_sess.Destruct(&pThis->pSessions[iTCPSess]); } } --nfds; /* indicate we have processed one */ @@ -634,7 +635,7 @@ tcpsrvConstructFinalize(tcpsrv_t __attribute__((unused)) *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); - pThis->pSocksLstn = create_tcp_socket(pThis); + pThis->pSocksLstn = pThis->OpenLstnSocks(pThis); RETiRet; } @@ -643,6 +644,9 @@ tcpsrvConstructFinalize(tcpsrv_t __attribute__((unused)) *pThis) /* destructor for the tcpsrv object */ BEGINobjDestruct(tcpsrv) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(tcpsrv) + if(pThis->OnDestruct != NULL) + pThis->OnDestruct(pThis->pUsr); + deinit_tcp_listener(pThis); ENDobjDestruct(tcpsrv) @@ -654,7 +658,7 @@ ENDobjDebugPrint(tcpsrv) /* set functions */ static rsRetVal -SetCBIsPermittedHost(tcpsrv_t *pThis, int (*pCB)(struct sockaddr *addr, char *fromHostFQDN)) +SetCBIsPermittedHost(tcpsrv_t *pThis, int (*pCB)(struct sockaddr *addr, char *fromHostFQDN, void*, void*)) { DEFiRet; pThis->pIsPermittedHost = pCB; @@ -678,7 +682,7 @@ SetCBOnListenDeinit(tcpsrv_t *pThis, int (*pCB)(void*)) } static rsRetVal -SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*,int)) +SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*, tcps_sess_t**, int)) { DEFiRet; pThis->pOnSessAccept = pCB; @@ -686,6 +690,30 @@ SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*,int)) } static rsRetVal +SetCBOnDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) +{ + DEFiRet; + pThis->OnDestruct = pCB; + RETiRet; +} + +static rsRetVal +SetCBOnSessConstructFinalize(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) +{ + DEFiRet; + pThis->OnSessConstructFinalize = pCB; + RETiRet; +} + +static rsRetVal +SetCBOnSessDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) +{ + DEFiRet; + pThis->pOnSessDestruct = pCB; + RETiRet; +} + +static rsRetVal SetCBOnRegularClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*)) { DEFiRet; @@ -701,6 +729,22 @@ SetCBOnErrClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*)) RETiRet; } +static rsRetVal +SetCBOpenLstnSocks(tcpsrv_t *pThis, int* (*pCB)(tcpsrv_t*)) +{ + DEFiRet; + pThis->OpenLstnSocks = pCB; + RETiRet; +} + +static rsRetVal +SetUsrP(tcpsrv_t *pThis, void *pUsr) +{ + DEFiRet; + pThis->pUsr = pUsr; + RETiRet; +} + /* queryInterface function @@ -717,10 +761,6 @@ CODESTARTobjQueryInterface(tcpsrv) * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ - //pIf->freeAllSockets = freeAllSockets; - //pIf->configureTCPListen = configureTCPListen; - //pIf->configureTCPListenSessMax = configureTCPListenSessMax; - //pIf->TCPSessAccept = TCPSessAccept; pIf->DebugPrint = tcpsrvDebugPrint; pIf->Construct = tcpsrvConstruct; pIf->ConstructFinalize = tcpsrvConstructFinalize; @@ -728,12 +768,18 @@ CODESTARTobjQueryInterface(tcpsrv) pIf->SessAccept = SessAccept; pIf->configureTCPListen = configureTCPListen; + pIf->create_tcp_socket = create_tcp_socket; pIf->Run = Run; + pIf->SetUsrP = SetUsrP; pIf->SetCBIsPermittedHost = SetCBIsPermittedHost; + pIf->SetCBOpenLstnSocks = SetCBOpenLstnSocks; pIf->SetCBRcvData = SetCBRcvData; pIf->SetCBOnListenDeinit = SetCBOnListenDeinit; pIf->SetCBOnSessAccept = SetCBOnSessAccept; + pIf->SetCBOnSessConstructFinalize = SetCBOnSessConstructFinalize; + pIf->SetCBOnSessDestruct = SetCBOnSessDestruct; + pIf->SetCBOnDestruct = SetCBOnDestruct; pIf->SetCBOnRegularClose = SetCBOnRegularClose; pIf->SetCBOnErrClose = SetCBOnErrClose; @@ -27,16 +27,24 @@ /* the tcpsrv object */ typedef struct tcpsrv_s { - BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ - int *pSocksLstn; /* listen socket array for server [0] holds count */ - int iSessMax; /* max number of sessions supported */ + BEGINobjInstance; /**< Data to implement generic object - MUST be the first data element! */ + int *pSocksLstn; /**< listen socket array for server [0] holds count */ + int iSessMax; /**< max number of sessions supported */ + char *TCPLstnPort; /**< the port the listener shall listen on */ + tcps_sess_t **pSessions;/**< array of all of our sessions */ + void *pUsr; /**< a user-settable pointer (provides extensibility for "derived classes")*/ /* callbacks */ - int (*pIsPermittedHost)(struct sockaddr *addr, char *fromHostFQDN); - int (*pRcvData)(tcps_sess_t*, char*, size_t); + int (*pIsPermittedHost)(struct sockaddr *addr, char *fromHostFQDN, void*pUsrSrv, void*pUsrSess); + int (*pRcvData)(tcps_sess_t*, char*, size_t); + int* (*OpenLstnSocks)(struct tcpsrv_s*); rsRetVal (*pOnListenDeinit)(void*); - rsRetVal (*pOnSessAccept)(struct tcpsrv_s *, int fd); + rsRetVal (*OnDestruct)(void*); rsRetVal (*pOnRegularClose)(tcps_sess_t *pSess); rsRetVal (*pOnErrClose)(tcps_sess_t *pSess); + /* session specific callbacks */ + rsRetVal (*pOnSessAccept)(struct tcpsrv_s *, tcps_sess_t**, int fd); + rsRetVal (*OnSessConstructFinalize)(void*); + rsRetVal (*pOnSessDestruct)(void*); } tcpsrv_t; @@ -47,16 +55,22 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ rsRetVal (*ConstructFinalize)(tcpsrv_t __attribute__((unused)) *pThis); rsRetVal (*Destruct)(tcpsrv_t **ppThis); void (*configureTCPListen)(tcpsrv_t*, char *cOptarg); - //no longer needed? void (*configureTCPListenSessMax)(char *cOptarg); - int (*SessAccept)(tcpsrv_t *pThis, int fd); + int (*SessAccept)(tcpsrv_t *pThis, tcps_sess_t**ppSess, int fd); + int* (*create_tcp_socket)(tcpsrv_t *pThis); rsRetVal (*Run)(tcpsrv_t *pThis); /* set methods */ - rsRetVal (*SetCBIsPermittedHost)(tcpsrv_t*, int (*) (struct sockaddr *addr, char*)); + rsRetVal (*SetUsrP)(tcpsrv_t*, void*); + rsRetVal (*SetCBIsPermittedHost)(tcpsrv_t*, int (*) (struct sockaddr *addr, char*, void*, void*)); + rsRetVal (*SetCBOpenLstnSocks)(tcpsrv_t *, int* (*)(tcpsrv_t*)); rsRetVal (*SetCBRcvData)(tcpsrv_t *, int (*)(tcps_sess_t*, char*, size_t)); rsRetVal (*SetCBOnListenDeinit)(tcpsrv_t*, rsRetVal (*)(void*)); - rsRetVal (*SetCBOnSessAccept)(tcpsrv_t*, rsRetVal (*) (tcpsrv_t*,int)); + rsRetVal (*SetCBOnDestruct)(tcpsrv_t*, rsRetVal (*) (void*)); rsRetVal (*SetCBOnRegularClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*)); rsRetVal (*SetCBOnErrClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*)); + /* session specifics */ + rsRetVal (*SetCBOnSessAccept)(tcpsrv_t*, rsRetVal (*) (tcpsrv_t*, tcps_sess_t**, int)); + rsRetVal (*SetCBOnSessDestruct)(tcpsrv_t*, rsRetVal (*) (void*)); + rsRetVal (*SetCBOnSessConstructFinalize)(tcpsrv_t*, rsRetVal (*) (void*)); ENDinterface(tcpsrv) #define tcpsrvCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ |