diff options
Diffstat (limited to 'plugins/omgssapi')
-rw-r--r-- | plugins/omgssapi/.cvsignore | 6 | ||||
-rw-r--r-- | plugins/omgssapi/Makefile.am | 4 | ||||
-rw-r--r-- | plugins/omgssapi/omgssapi.c | 263 |
3 files changed, 94 insertions, 179 deletions
diff --git a/plugins/omgssapi/.cvsignore b/plugins/omgssapi/.cvsignore deleted file mode 100644 index 9730646f..00000000 --- a/plugins/omgssapi/.cvsignore +++ /dev/null @@ -1,6 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -*.la -*.lo diff --git a/plugins/omgssapi/Makefile.am b/plugins/omgssapi/Makefile.am index 9fa6a241..c2cbe387 100644 --- a/plugins/omgssapi/Makefile.am +++ b/plugins/omgssapi/Makefile.am @@ -1,6 +1,6 @@ pkglib_LTLIBRARIES = omgssapi.la -omgssapi_la_SOURCES = omgssapi.c ../../module-template.h -omgssapi_la_CPPFLAGS = $(pgsql_cflags) -I$(srcdir)/../.. +omgssapi_la_SOURCES = omgssapi.c +omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags) omgssapi_la_LDFLAGS = -module -avoid-version omgssapi_la_LIBADD = $(gss_libs) diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c index 97b8bd55..82fca2db 100644 --- a/plugins/omgssapi/omgssapi.c +++ b/plugins/omgssapi/omgssapi.c @@ -4,7 +4,7 @@ * NOTE: read comments in module-template.h to understand how this file * works! * - * Copyright 2007 Rainer Gerhards and Adiscon GmbH. + * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -43,65 +43,48 @@ #endif #include <pthread.h> #include <gssapi/gssapi.h> -#include "syslogd.h" +#include "dirty.h" #include "syslogd-types.h" #include "srUtils.h" #include "net.h" -#include "omfwd.h" #include "template.h" #include "msg.h" -#include "tcpsyslog.h" #include "cfsysline.h" #include "module-template.h" #include "gss-misc.h" +#include "tcpclt.h" +#include "glbl.h" +#include "errmsg.h" + +MODULE_TYPE_OUTPUT -#define INET_SUSPEND_TIME 60 /* equal to 1 minute */ - /* rgerhards, 2005-07-26: This was 3 minutes. As the - * same timer is used for tcp based syslog, we have - * reduced it. However, it might actually be worth - * thinking about a buffered tcp sender, which would be - * a much better alternative. When that happens, this - * time here can be re-adjusted to 3 minutes (or, - * even better, made configurable). - */ -#define INET_RETRY_MAX 30 /* maximum of retries for gethostbyname() */ - /* was 10, changed to 30 because we reduced INET_SUSPEND_TIME by one third. So - * this "fixes" some of implications of it (see comment on INET_SUSPEND_TIME). - * rgerhards, 2005-07-26 - */ /* internal structures */ DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(gssutil) +DEFobjCurrIf(tcpclt) typedef struct _instanceData { - char f_hname[MAXHOSTNAMELEN+1]; + char *f_hname; short sock; /* file descriptor */ enum { /* TODO: we shoud revisit these definitions */ eDestFORW, eDestFORW_SUSP, eDestFORW_UNKN } eDestState; - int iRtryCnt; struct addrinfo *f_addr; int compressionLevel; /* 0 - no compression, else level for zlib */ char *port; - char *savedMsg; - int savedMsgLen; /* length of savedMsg in octets */ - TCPFRAMINGMODE tcp_framing; - enum TCPSendStatus { - TCP_SEND_NOTCONNECTED = 0, - TCP_SEND_CONNECTING = 1, - TCP_SEND_READY = 2 - } status; - time_t ttSuspend; /* time selector was suspended */ + tcpclt_t *pTCPClt; /* our tcpclt object */ gss_ctx_id_t gss_context; OM_uint32 gss_flags; -# ifdef USE_PTHREADS - pthread_mutex_t mtxTCPSend; -# endif } instanceData; +/* config data */ +static uchar *pszTplName = NULL; /* name of the default template to use */ static char *gss_base_service_name = NULL; static enum gss_mode_t { GSSMODE_MIC, @@ -114,7 +97,7 @@ static enum gss_mode_t { * We may change the implementation to try to lookup the port * if it is unspecified. So far, we use the IANA default auf 514. */ -char *getFwdSyslogPt(instanceData *pData) +static char *getFwdSyslogPt(instanceData *pData) { assert(pData != NULL); if(pData->port == NULL) @@ -123,48 +106,6 @@ char *getFwdSyslogPt(instanceData *pData) return(pData->port); } -/* get send status - * rgerhards, 2005-10-24 - */ -static void TCPSendSetStatus(instanceData *pData, enum TCPSendStatus iNewState) -{ - assert(pData != NULL); - assert( (iNewState == TCP_SEND_NOTCONNECTED) - || (iNewState == TCP_SEND_CONNECTING) - || (iNewState == TCP_SEND_READY)); - - /* there can potentially be a race condition, so guard by mutex */ -# ifdef USE_PTHREADS - pthread_mutex_lock(&pData->mtxTCPSend); -# endif - pData->status = iNewState; -# ifdef USE_PTHREADS - pthread_mutex_unlock(&pData->mtxTCPSend); -# endif -} - - -/* get send status - * rgerhards, 2005-10-24 - */ -static enum TCPSendStatus TCPSendGetStatus(instanceData *pData) -{ - enum TCPSendStatus eState; - assert(pData != NULL); - - /* there can potentially be a race condition, so guard by mutex */ -# ifdef USE_PTHREADS - pthread_mutex_lock(&pData->mtxTCPSend); -# endif - eState = pData->status; -# ifdef USE_PTHREADS - pthread_mutex_unlock(&pData->mtxTCPSend); -# endif - - return eState; -} - - BEGINcreateInstance CODESTARTcreateInstance ENDcreateInstance @@ -194,7 +135,7 @@ CODESTARTfreeInstance if (pData->gss_context != GSS_C_NO_CONTEXT) { maj_stat = gss_delete_sec_context(&min_stat, &pData->gss_context, GSS_C_NO_BUFFER); if (maj_stat != GSS_S_COMPLETE) - display_status("deleting context", maj_stat, min_stat); + gssutil.display_status("deleting context", maj_stat, min_stat); } /* this is meant to be done when module is unloaded, but since this module is static... @@ -204,13 +145,13 @@ CODESTARTfreeInstance gss_base_service_name = NULL; } -# ifdef USE_PTHREADS - /* delete any mutex objects, if present */ - pthread_mutex_destroy(&pData->mtxTCPSend); -# endif /* final cleanup */ + tcpclt.Destruct(&pData->pTCPClt); if(pData->sock >= 0) close(pData->sock); + + if(pData->f_hname != NULL) + free(pData->f_hname); ENDfreeInstance @@ -220,8 +161,6 @@ CODESTARTdbgPrintInstInfo ENDdbgPrintInstInfo -/* CODE FOR SENDING TCP MESSAGES */ - /* This function is called immediately before a send retry is attempted. * It shall clean up whatever makes sense. * rgerhards, 2007-12-28 @@ -253,9 +192,7 @@ static rsRetVal TCPSendGSSInit(void *pvData) base = (gss_base_service_name == NULL) ? "host" : gss_base_service_name; out_tok.length = strlen(pData->f_hname) + strlen(base) + 2; - if ((out_tok.value = malloc(out_tok.length)) == NULL) { - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } + CHKmalloc(out_tok.value = malloc(out_tok.length)); strcpy(out_tok.value, base); strcat(out_tok.value, "@"); strcat(out_tok.value, pData->f_hname); @@ -271,7 +208,7 @@ static rsRetVal TCPSendGSSInit(void *pvData) out_tok.length = 0; if (maj_stat != GSS_S_COMPLETE) { - display_status("parsing name", maj_stat, min_stat); + gssutil.display_status("parsing name", maj_stat, min_stat); goto fail; } @@ -284,7 +221,7 @@ static rsRetVal TCPSendGSSInit(void *pvData) *sess_flags |= GSS_C_CONF_FLAG; } dbgprintf("GSS-API requested context flags:\n"); - display_ctx_flags(*sess_flags); + gssutil.display_ctx_flags(*sess_flags); do { maj_stat = gss_init_sec_context(&init_sec_min_stat, GSS_C_NO_CREDENTIAL, context, @@ -295,17 +232,17 @@ static rsRetVal TCPSendGSSInit(void *pvData) if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { - display_status("initializing context", maj_stat, init_sec_min_stat); + gssutil.display_status("initializing context", maj_stat, init_sec_min_stat); goto fail; } if (s == -1) - if ((s = pData->sock = TCPSendCreateSocket(pData->f_addr)) == -1) + if ((s = pData->sock = tcpclt.CreateSocket(pData->f_addr)) == -1) goto fail; if (out_tok.length != 0) { dbgprintf("GSS-API Sending init_sec_context token (length: %ld)\n", (long) out_tok.length); - if (send_token(s, &out_tok) < 0) { + if (gssutil.send_token(s, &out_tok) < 0) { goto fail; } } @@ -313,7 +250,7 @@ static rsRetVal TCPSendGSSInit(void *pvData) if (maj_stat == GSS_S_CONTINUE_NEEDED) { dbgprintf("GSS-API Continue needed...\n"); - if (recv_token(s, &in_tok) <= 0) { + if (gssutil.recv_token(s, &in_tok) <= 0) { goto fail; } tok_ptr = &in_tok; @@ -322,16 +259,16 @@ static rsRetVal TCPSendGSSInit(void *pvData) dbgprintf("GSS-API Provided context flags:\n"); *sess_flags = ret_flags; - display_ctx_flags(*sess_flags); + gssutil.display_ctx_flags(*sess_flags); dbgprintf("GSS-API Context initialized\n"); gss_release_name(&min_stat, &target_name); finalize_it: - return iRet; + RETiRet; fail: - logerror("GSS-API Context initialization failed\n"); + errmsg.LogError(0, RS_RET_GSS_SENDINIT_ERROR, "GSS-API Context initialization failed\n"); gss_release_name(&min_stat, &target_name); gss_release_buffer(&min_stat, &out_tok); if (*context != GSS_C_NO_CONTEXT) { @@ -341,7 +278,7 @@ finalize_it: if (s != -1) close(s); pData->sock = -1; - return RS_RET_GSS_SENDINIT_ERROR; + ABORT_FINALIZE(RS_RET_GSS_SENDINIT_ERROR); } @@ -364,11 +301,11 @@ static rsRetVal TCPSendGSSSend(void *pvData, char *msg, size_t len) maj_stat = gss_wrap(&min_stat, *context, (gss_mode == GSSMODE_ENC) ? 1 : 0, GSS_C_QOP_DEFAULT, &in_buf, NULL, &out_buf); if (maj_stat != GSS_S_COMPLETE) { - display_status("wrapping message", maj_stat, min_stat); + gssutil.display_status("wrapping message", maj_stat, min_stat); goto fail; } - if (send_token(s, &out_buf) < 0) { + if (gssutil.send_token(s, &out_buf) < 0) { goto fail; } gss_release_buffer(&min_stat, &out_buf); @@ -411,13 +348,12 @@ static rsRetVal doTryResume(instanceData *pData) * a common function. */ hints.ai_flags = AI_NUMERICSERV; - hints.ai_family = family; + hints.ai_family = glbl.GetDefPFFamily(); hints.ai_socktype = SOCK_STREAM; if((e = getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res)) == 0) { dbgprintf("%s found, resuming.\n", pData->f_hname); pData->f_addr = res; - pData->iRtryCnt = 0; pData->eDestState = eDestFORW; } else { iRet = RS_RET_SUSPENDED; @@ -430,7 +366,7 @@ static rsRetVal doTryResume(instanceData *pData) break; } - return iRet; + RETiRet; } @@ -456,7 +392,6 @@ CODESTARTdoAction case eDestFORW: dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData), "tcp-gssapi"); - pData->ttSuspend = time(NULL); psz = (char*) ppString[0]; l = strlen((char*) psz); if (l > MAXLINE) @@ -499,7 +434,7 @@ CODESTARTdoAction } # endif - CHKiRet_Hdlr(TCPSend(pData, psz, l, pData->tcp_framing, TCPSendGSSInit, TCPSendGSSSend, TCPSendGSSPrepRetry)) { + CHKiRet_Hdlr(tcpclt.Send(pData->pTCPClt, pData, psz, l)) { /* error! */ dbgprintf("error forwarding via tcp, suspending\n"); pData->eDestState = eDestFORW_SUSP; @@ -516,6 +451,7 @@ BEGINparseSelectorAct int error; int bErr; struct addrinfo hints, *res; + TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING; CODESTARTparseSelectorAct CODE_STD_STRING_REQUESTparseSelectorAct(1) /* first check if this config line is actually for us @@ -537,10 +473,6 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) if((iRet = createInstance(&pData)) != RS_RET_OK) goto finalize_it; -# ifdef USE_PTHREADS - pthread_mutex_init(&pData->mtxTCPSend, 0); -# endif - /* we are now after the protocol indicator. Now check if we should * use compression. We begin to use a new option format for this: * @(option,option)host:port @@ -569,20 +501,20 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) ++p; /* eat */ pData->compressionLevel = iLevel; } else { - logerrorInt("Invalid compression level '%c' specified in " + errmsg.LogError(0, NO_ERRCODE, "Invalid compression level '%c' specified in " "forwardig action - NOT turning on compression.", *p); } # else - logerror("Compression requested, but rsyslogd is not compiled " + errmsg.LogError(0, NO_ERRCODE, "Compression requested, but rsyslogd is not compiled " "with compression support - request ignored."); # endif /* #ifdef USE_NETZIP */ } else if(*p == 'o') { /* octet-couting based TCP framing? */ ++p; /* eat */ /* no further options settable */ - pData->tcp_framing = TCP_FRAMING_OCTET_COUNTING; + tcp_framing = TCP_FRAMING_OCTET_COUNTING; } else { /* invalid option! Just skip it... */ - logerrorInt("Invalid option %c in forwarding action - ignoring.", *p); + errmsg.LogError(0, NO_ERRCODE, "Invalid option %c in forwarding action - ignoring.", *p); ++p; /* eat invalid option */ } /* the option processing is done. We now do a generic skip @@ -598,12 +530,12 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* we probably have end of string - leave it for the rest * of the code to handle it (but warn the user) */ - logerror("Option block not terminated in gssapi forward action."); + errmsg.LogError(0, NO_ERRCODE, "Option block not terminated in gssapi forward action."); } /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0') * now skip to port and then template name. rgerhards 2005-07-06 */ - for(q = p ; *p && *p != ';' && *p != ':' ; ++p) + for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p) /* JUST SKIP */; pData->port = NULL; @@ -616,7 +548,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) /* SKIP AND COUNT */; pData->port = malloc(i + 1); if(pData->port == NULL) { - logerror("Could not get memory to store syslog forwarding port, " + errmsg.LogError(0, NO_ERRCODE, "Could not get memory to store syslog forwarding port, " "using default port, results may not be what you intend\n"); /* we leave f_forw.port set to NULL, this is then handled by * getFwdSyslogPt(). @@ -627,6 +559,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) } } + /* now skip to template */ bErr = 0; while(*p && *p != ';') { @@ -634,7 +567,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) if(bErr == 0) { /* only 1 error msg! */ bErr = 1; errno = 0; - logerror("invalid selector line (port), probably not doing " + errmsg.LogError(0, NO_ERRCODE, "invalid selector line (port), probably not doing " "what was intended"); } } @@ -642,33 +575,40 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1) } /* TODO: make this if go away! */ - if(*p == ';') { + if(*p == ';' || *p == '#' || isspace(*p)) { + uchar cTmp = *p; *p = '\0'; /* trick to obtain hostname (later)! */ - strcpy(pData->f_hname, (char*) q); - *p = ';'; - } else - strcpy(pData->f_hname, (char*) q); + CHKmalloc(pData->f_hname = strdup((char*) q)); + *p = cTmp; + } else { + CHKmalloc(pData->f_hname = strdup((char*) q)); + } /* process template */ - if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) " StdFwdFmt")) - != RS_RET_OK) - goto finalize_it; + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, + (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName)); /* first set the pData->eDestState */ memset(&hints, 0, sizeof(hints)); /* port must be numeric, because config file syntax requests this */ hints.ai_flags = AI_NUMERICSERV; - hints.ai_family = family; + hints.ai_family = glbl.GetDefPFFamily(); hints.ai_socktype = SOCK_STREAM; if( (error = getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res)) != 0) { pData->eDestState = eDestFORW_UNKN; - pData->iRtryCnt = INET_RETRY_MAX; - pData->ttSuspend = time(NULL); } else { pData->eDestState = eDestFORW; pData->f_addr = res; } + /* now create our tcpclt */ + CHKiRet(tcpclt.Construct(&pData->pTCPClt)); + /* and set callbacks */ + CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendGSSInit)); + CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendGSSSend)); + CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendGSSPrepRetry)); + CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing)); + /* TODO: do we need to call freeInstance if we failed - this is a general question for * all output modules. I'll address it lates as the interface evolves. rgerhards, 2007-07-25 */ @@ -676,45 +616,17 @@ CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct -BEGINneedUDPSocket -CODESTARTneedUDPSocket - iRet = RS_RET_FALSE; -ENDneedUDPSocket - - -BEGINonSelectReadyWrite -CODESTARTonSelectReadyWrite - dbgprintf("tcp send socket %d ready for writing.\n", pData->sock); - TCPSendSetStatus(pData, TCP_SEND_READY); - /* Send stored message (if any) */ - if(pData->savedMsg != NULL) { - if(TCPSend(pData, pData->savedMsg, pData->savedMsgLen, pData->tcp_framing, - TCPSendGSSInit, TCPSendGSSSend, TCPSendGSSPrepRetry) != RS_RET_OK) { - /* error! */ - pData->eDestState = eDestFORW_SUSP; - errno = 0; - logerror("error forwarding via tcp, suspending..."); - } - free(pData->savedMsg); - pData->savedMsg = NULL; - } -ENDonSelectReadyWrite - - -BEGINgetWriteFDForSelect -CODESTARTgetWriteFDForSelect - if( (pData->eDestState == eDestFORW) - && TCPSendGetStatus(pData) == TCP_SEND_CONNECTING) { - *fd = pData->sock; - iRet = RS_RET_OK; - } -ENDgetWriteFDForSelect - - - - BEGINmodExit CODESTARTmodExit + objRelease(glbl, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); + objRelease(gssutil, LM_GSSUTIL_FILENAME); + objRelease(tcpclt, LM_TCPCLT_FILENAME); + + if(pszTplName != NULL) { + free(pszTplName); + pszTplName = NULL; + } ENDmodExit @@ -727,21 +639,21 @@ ENDqueryEtryPt /* set a new GSSMODE based on config directive */ static rsRetVal setGSSMode(void __attribute__((unused)) *pVal, uchar *mode) { + DEFiRet; + if (!strcmp((char *) mode, "integrity")) { gss_mode = GSSMODE_MIC; - free(mode); dbgprintf("GSS-API gssmode set to GSSMODE_MIC\n"); } else if (!strcmp((char *) mode, "encryption")) { gss_mode = GSSMODE_ENC; - free(mode); dbgprintf("GSS-API gssmode set to GSSMODE_ENC\n"); } else { - logerrorSz("unknown gssmode parameter: %s", (char *) mode); - free(mode); - return RS_RET_ERR; + errmsg.LogError(0, RS_RET_INVALID_PARAMS, "unknown gssmode parameter: %s", (char *) mode); + iRet = RS_RET_INVALID_PARAMS; } + free(mode); - return RS_RET_OK; + RETiRet; } @@ -752,20 +664,29 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a free(gss_base_service_name); gss_base_service_name = NULL; } + if(pszTplName != NULL) { + free(pszTplName); + pszTplName = NULL; + } return RS_RET_OK; } BEGINmodInit() CODESTARTmodInit - *ipIFVersProvided = 1; /* so far, we only support the initial definition */ + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME)); + CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"gssforwardservicename", 0, eCmdHdlrGetWord, NULL, &gss_base_service_name, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"gssmode", 0, eCmdHdlrGetWord, setGSSMode, &gss_mode, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"actiongssforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit #endif /* #ifdef USE_GSSAPI */ -/* - * vi:set ai: +/* vi:set ai: */ |