diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | doc/omudpspoof.html | 4 | ||||
-rw-r--r-- | plugins/omudpspoof/omudpspoof.c | 60 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 |
4 files changed, 52 insertions, 18 deletions
@@ -5,6 +5,11 @@ Version 7.2.5 [v7-stable] 2013-01-?? On Ethernet, they need to be transmitted in multiple fragments. While it is known that fragmentation can cause issues, it is the best choice to be made in that case. Also improved debug output. +- bugfix: omudpspoof failed depending on the execution environment + The v7 engine closes fds, and closed some of libnet's fds as well, what + lead to problems (unfortunately, at least some libnet versions do not + report a proper error state but still "success"...). The order of libnet + calls has been adjusted to by in sync with what the core engine does. - build system cleanup (thanks to Michael Biebl for this!) - bugfix: omelasticsearch did not properly compile on some platforms due to missing libmath. Thanks to Michael Biebl for the fix diff --git a/doc/omudpspoof.html b/doc/omudpspoof.html index ffbd04e1..930412c8 100644 --- a/doc/omudpspoof.html +++ b/doc/omudpspoof.html @@ -15,6 +15,10 @@ and David Lang <david@lang.hm> <p>This module is similar to the regular UDP forwarder, but permits to spoof the sender address. Also, it enables to circle through a number of source ports. +<p><b>Important:</b> This module requires root priveleges for its low-level +socket access. As such, the <b>module will not work if rsyslog is configured to +drop privileges</b>. + <p><b>load() Parameters</b>:</p> <ul> <li><strong>Template </strong>[templateName]<br> diff --git a/plugins/omudpspoof/omudpspoof.c b/plugins/omudpspoof/omudpspoof.c index a9c48351..c0ed7e7e 100644 --- a/plugins/omudpspoof/omudpspoof.c +++ b/plugins/omudpspoof/omudpspoof.c @@ -104,6 +104,7 @@ typedef struct _instanceData { u_short sourcePort; u_short sourcePortStart; /* for sorce port iteration */ u_short sourcePortEnd; + int bReportLibnetInitErr; /* help prevent multiple error messages on init err */ libnet_t *libnet_handle; char errbuf[LIBNET_ERRBUF_SIZE]; } instanceData; @@ -310,7 +311,9 @@ ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance + pData->libnet_handle = NULL; pData->mtu = 1500; + pData->bReportLibnetInitErr = 1; ENDcreateInstance @@ -329,6 +332,8 @@ CODESTARTfreeInstance free(pData->port); free(pData->host); free(pData->sourceTpl); + if(pData->libnet_handle != NULL) + libnet_destroy(pData->libnet_handle); ENDfreeInstance @@ -379,18 +384,6 @@ UDPSend(instanceData *pData, uchar *pszSourcename, char *msg, size_t len) bSendSuccess = RSFALSE; d_pthread_mutex_lock(&mutLibnet); bNeedUnlock = 1; -/* Initialize the libnet library. Root priviledges are required. -* this initializes a IPv4 socket to use for forging UDP packets. -*/ -pData->libnet_handle = libnet_init( - LIBNET_RAW4, /* injection type */ - NULL, /* network interface */ - pData->errbuf); /* errbuf */ - -if(pData->libnet_handle == NULL) { - errmsg.LogError(0, NO_ERRCODE, "Error initializing libnet, can not continue "); - ABORT_FINALIZE(RS_RET_ERR_LIBNET_INIT); -} for (r = pData->f_addr; r && bSendSuccess == RSFALSE ; r = r->ai_next) { tempaddr = (struct sockaddr_in *)r->ai_addr; /* Getting max payload size (must be multiple of 8) */ @@ -442,12 +435,17 @@ if(pData->libnet_handle == NULL) { } /* Write it to the wire. */ -dbgprintf("DDDD: omudpspoof fd %d\n", pData->libnet_handle->fd); lsent = libnet_write(pData->libnet_handle); - dbgprintf("DDDD: omudpspoof stage 1 return state %d (expected %d)\n", lsent, (int) (LIBNET_IPV4_H+LIBNET_UDP_H+pktLen)); + dbgprintf("DDDD: omudpspoof stage 1 return state %d (expected %d), fd %d\n", lsent, + (int) (LIBNET_IPV4_H+LIBNET_UDP_H+pktLen), pData->libnet_handle->fd); if(lsent != (int) (LIBNET_IPV4_H+LIBNET_UDP_H+pktLen)) { - DBGPRINTF("omudpspoof: write error (total len %d): pktLen %d, sent %d: %s\n", - len, LIBNET_IPV4_H+LIBNET_UDP_H+pktLen, lsent, libnet_geterror(pData->libnet_handle)); + /* note: access to fd is a libnet internal. If a newer version of libnet does + * not expose that member, we should simply remove it. However, while it is there + * it is useful for consolidating with strace output. + */ + DBGPRINTF("omudpspoof: write error (total len %d): pktLen %d, sent %d, fd %d: %s\n", + len, LIBNET_IPV4_H+LIBNET_UDP_H+pktLen, lsent, pData->libnet_handle->fd, + libnet_geterror(pData->libnet_handle)); if(lsent != -1) { bSendSuccess = RSTRUE; } @@ -485,7 +483,7 @@ dbgprintf("DDDD: omudpspoof fd %d\n", pData->libnet_handle->fd); source_ip.sin_addr.s_addr, tempaddr->sin_addr.s_addr, (u_int8_t*)(msg+msgOffs), /* payload */ - pktLen, /* payload size */ + pktLen, /* payload size */ pData->libnet_handle, /* libnet handle */ ip); /* libnet id */ if (ip == -1) { @@ -505,8 +503,13 @@ dbgprintf("DDDD: omudpspoof fd %d\n", pData->libnet_handle->fd); } finalize_it: + if(iRet != RS_RET_OK) { + if(pData->libnet_handle != NULL) { + libnet_destroy(pData->libnet_handle); + pData->libnet_handle = NULL; + } + } if(bNeedUnlock) { -libnet_destroy(pData->libnet_handle); d_pthread_mutex_unlock(&mutLibnet); } RETiRet; @@ -529,6 +532,27 @@ static rsRetVal doTryResume(instanceData *pData) if(pData->host == NULL) ABORT_FINALIZE(RS_RET_DISABLE_ACTION); + if(pData->libnet_handle == NULL) { + /* Initialize the libnet library. Root priviledges are required. + * this initializes a IPv4 socket to use for forging UDP packets. + */ + pData->libnet_handle = libnet_init( + LIBNET_RAW4, /* injection type */ + NULL, /* network interface */ + pData->errbuf); /* errbuf */ + + if(pData->libnet_handle == NULL) { + if(pData->bReportLibnetInitErr) { + errmsg.LogError(0, RS_RET_LIBNET_INIT_FAILED, "omudpsoof: error " + "initializing libnet - are you running as root?"); + pData->bReportLibnetInitErr = 0; + } + ABORT_FINALIZE(RS_RET_ERR_LIBNET_INIT); + } + } + DBGPRINTF("omudpspoof: libnit_init() ok\n"); + pData->bReportLibnetInitErr = 1; + /* The remote address is not yet known and needs to be obtained */ DBGPRINTF("omudpspoof trying resume for '%s'\n", pData->host); memset(&hints, 0, sizeof(hints)); diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 07d58d68..d85109c3 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -393,6 +393,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_INVLD_SETOP = -2305, /**< invalid variable set operation, incompatible type */ RS_RET_RULESET_EXISTS = -2306,/**< ruleset already exists */ RS_RET_DEPRECATED = -2307,/**< deprecated functionality is used */ + RS_RET_LIBNET_INIT_FAILED = -2308,/**< libnet_init() failed, probably because of not running as root */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ |