summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2009-10-10 12:29:11 +0200
committerMichael Biebl <biebl@debian.org>2009-10-10 12:29:11 +0200
commitb743785de633f7ff5c39f980496d359e4758ec83 (patch)
treecbb40602f0c84f5fdb911b0bbd3a4b74e49b5211 /runtime
parenta3320fb454a00c23e50fa18b5507b657212b01d2 (diff)
downloadrsyslog-b743785de633f7ff5c39f980496d359e4758ec83.tar.gz
Imported Upstream version 4.4.2upstream/4.4.2
Diffstat (limited to 'runtime')
-rw-r--r--runtime/datetime.c119
-rw-r--r--runtime/datetime.h4
-rw-r--r--runtime/net.c44
-rw-r--r--runtime/net.h4
-rw-r--r--runtime/parser.c13
-rw-r--r--runtime/rsyslog.h1
6 files changed, 142 insertions, 43 deletions
diff --git a/runtime/datetime.c b/runtime/datetime.c
index 40ab4e9..99caaf9 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -140,6 +140,7 @@ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds)
* DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!!
*/
+
/**
* Parse a 32 bit integer number from a string.
*
@@ -147,17 +148,21 @@ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds)
* must be positioned at the first digit. Will be updated
* so that on return it points to the first character AFTER
* the integer parsed.
+ * \param pLenStr pointer to string length, decremented on exit by
+ * characters processed
+ * Note that if an empty string (len < 1) is passed in,
+ * the method always returns zero.
* \retval The number parsed.
*/
-
-static int srSLMGParseInt32(uchar** ppsz)
+static int srSLMGParseInt32(uchar** ppsz, int *pLenStr)
{
register int i;
i = 0;
- while(isdigit((int) **ppsz)) {
+ while(*pLenStr > 0 && isdigit((int) **ppsz)) {
i = i * 10 + **ppsz - '0';
++(*ppsz);
+ --(*pLenStr);
}
return i;
@@ -169,9 +174,13 @@ static int srSLMGParseInt32(uchar** ppsz)
* updates the parse pointer position. The pTime parameter
* is guranteed to be updated only if a new valid timestamp
* could be obtained (restriction added 2008-09-16 by rgerhards).
+ * This method now also checks the maximum string length it is passed.
+ * If a *valid* timestamp is found, the string length is decremented
+ * by the number of characters processed. If it is not a valid timestamp,
+ * the length is kept unmodified. -- rgerhards, 2009-09-23
*/
static rsRetVal
-ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
+ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
{
uchar *pszTS = *ppszTS;
/* variables to temporarily hold time information while we parse */
@@ -186,6 +195,7 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
char OffsetMode; /* UTC offset + or - */
char OffsetHour; /* UTC offset in hours */
int OffsetMinute; /* UTC offset in minutes */
+ int lenStr;
/* end variables to temporarily hold time information while we parse */
DEFiRet;
@@ -193,48 +203,55 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
assert(ppszTS != NULL);
assert(pszTS != NULL);
- year = srSLMGParseInt32(&pszTS);
+ lenStr = *pLenStr;
+ year = srSLMGParseInt32(&pszTS, &lenStr);
/* We take the liberty to accept slightly malformed timestamps e.g. in
* the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course,
* with the current state of affairs, we would never run into this code
* here because at postion 11, there is no "T" in such cases ;)
*/
- if(*pszTS++ != '-')
+ if(lenStr == 0 || *pszTS++ != '-')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- month = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ month = srSLMGParseInt32(&pszTS, &lenStr);
if(month < 1 || month > 12)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != '-')
+ if(lenStr == 0 || *pszTS++ != '-')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- day = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ day = srSLMGParseInt32(&pszTS, &lenStr);
if(day < 1 || day > 31)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != 'T')
+ if(lenStr == 0 || *pszTS++ != 'T')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
- hour = srSLMGParseInt32(&pszTS);
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
if(hour < 0 || hour > 23)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ':')
+ if(lenStr == 0 || *pszTS++ != ':')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- minute = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ minute = srSLMGParseInt32(&pszTS, &lenStr);
if(minute < 0 || minute > 59)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ':')
+ if(lenStr == 0 || *pszTS++ != ':')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- second = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ second = srSLMGParseInt32(&pszTS, &lenStr);
if(second < 0 || second > 60)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
/* Now let's see if we have secfrac */
- if(*pszTS == '.') {
+ if(lenStr > 0 && *pszTS == '.') {
+ --lenStr;
uchar *pszStart = ++pszTS;
- secfrac = srSLMGParseInt32(&pszTS);
+ secfrac = srSLMGParseInt32(&pszTS, &lenStr);
secfracPrecision = (int) (pszTS - pszStart);
} else {
secfracPrecision = 0;
@@ -242,23 +259,27 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
}
/* check the timezone */
- if(*pszTS == 'Z')
- {
+ if(lenStr == 0)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(*pszTS == 'Z') {
+ --lenStr;
pszTS++; /* eat Z */
OffsetMode = 'Z';
OffsetHour = 0;
OffsetMinute = 0;
} else if((*pszTS == '+') || (*pszTS == '-')) {
OffsetMode = *pszTS;
+ --lenStr;
pszTS++;
- OffsetHour = srSLMGParseInt32(&pszTS);
+ OffsetHour = srSLMGParseInt32(&pszTS, &lenStr);
if(OffsetHour < 0 || OffsetHour > 23)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ':')
+ if(lenStr == 0 || *pszTS++ != ':')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- OffsetMinute = srSLMGParseInt32(&pszTS);
+ OffsetMinute = srSLMGParseInt32(&pszTS, &lenStr);
if(OffsetMinute < 0 || OffsetMinute > 59)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
} else {
@@ -267,10 +288,12 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
}
/* OK, we actually have a 3339 timestamp, so let's indicated this */
- if(*pszTS == ' ')
+ if(lenStr > 0 && *pszTS == ' ') {
+ --lenStr;
++pszTS;
- else
+ } else {
ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ }
/* we had success, so update parse pointer and caller-provided timestamp */
*ppszTS = pszTS;
@@ -286,6 +309,7 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS)
pTime->OffsetMode = OffsetMode;
pTime->OffsetHour = OffsetHour;
pTime->OffsetMinute = OffsetMinute;
+ *pLenStr = lenStr;
finalize_it:
RETiRet;
@@ -304,9 +328,13 @@ finalize_it:
* permits us to use a pre-aquired timestamp and thus avoids to do
* a (costly) time() call. Thanks to David Lang for insisting on
* time() call reduction ;).
+ * This method now also checks the maximum string length it is passed.
+ * If a *valid* timestamp is found, the string length is decremented
+ * by the number of characters processed. If it is not a valid timestamp,
+ * the length is kept unmodified. -- rgerhards, 2009-09-23
*/
static rsRetVal
-ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
+ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
{
/* variables to temporarily hold time information while we parse */
int month;
@@ -316,6 +344,7 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
int minute;
int second;
/* end variables to temporarily hold time information while we parse */
+ int lenStr;
uchar *pszTS;
DEFiRet;
@@ -323,6 +352,8 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
pszTS = *ppszTS;
assert(pszTS != NULL);
assert(pTime != NULL);
+ assert(pLenStr != NULL);
+ lenStr = *pLenStr;
/* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec),
* we may see the following character sequences occur:
@@ -341,6 +372,9 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
* june, when it first manifested. This also lead to invalid parsing of the rest
* of the message, as the time stamp was not detected to be correct. - rgerhards
*/
+ if(lenStr < 3)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
switch(*pszTS++)
{
case 'J':
@@ -455,26 +489,31 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
}
+ lenStr -= 3;
+
/* done month */
- if(*pszTS++ != ' ')
+ if(lenStr == 0 || *pszTS++ != ' ')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
/* we accept a slightly malformed timestamp when receiving. This is
* we accept one-digit days
*/
- if(*pszTS == ' ')
+ if(*pszTS == ' ') {
+ --lenStr;
++pszTS;
+ }
- day = srSLMGParseInt32(&pszTS);
+ day = srSLMGParseInt32(&pszTS, &lenStr);
if(day < 1 || day > 31)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ' ')
+ if(lenStr == 0 || *pszTS++ != ' ')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
/* time part */
- hour = srSLMGParseInt32(&pszTS);
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
if(hour > 1970 && hour < 2100) {
/* if so, we assume this actually is a year. This is a format found
* e.g. in Cisco devices.
@@ -484,23 +523,26 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
year = hour;
/* re-query the hour, this time it must be valid */
- if(*pszTS++ != ' ')
+ if(lenStr == 0 || *pszTS++ != ' ')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- hour = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
}
if(hour < 0 || hour > 23)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ':')
+ if(lenStr == 0 || *pszTS++ != ':')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- minute = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ minute = srSLMGParseInt32(&pszTS, &lenStr);
if(minute < 0 || minute > 59)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- if(*pszTS++ != ':')
+ if(lenStr == 0 || *pszTS++ != ':')
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- second = srSLMGParseInt32(&pszTS);
+ --lenStr;
+ second = srSLMGParseInt32(&pszTS, &lenStr);
if(second < 0 || second > 60)
ABORT_FINALIZE(RS_RET_INVLD_TIME);
@@ -508,8 +550,10 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
* invalid format, it occurs frequently enough (e.g. with Cisco devices)
* to permit it as a valid case. -- rgerhards, 2008-09-12
*/
- if(*pszTS++ == ':')
+ if(lenStr == 0 || *pszTS++ == ':') {
++pszTS; /* just skip past it */
+ --lenStr;
+ }
/* we had success, so update parse pointer and caller-provided timestamp
* fields we do not have are not updated in the caller's timestamp. This
@@ -526,6 +570,7 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
pTime->second = second;
pTime->secfracPrecision = 0;
pTime->secfrac = 0;
+ *pLenStr = lenStr;
finalize_it:
RETiRet;
diff --git a/runtime/datetime.h b/runtime/datetime.h
index efb0a0a..6377a4a 100644
--- a/runtime/datetime.h
+++ b/runtime/datetime.h
@@ -36,8 +36,8 @@ typedef struct datetime_s {
/* interfaces */
BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds);
- rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS);
- rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS);
+ rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS, int *);
+ rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int *);
int (*formatTimestampToMySQL)(struct syslogTime *ts, char* pDst, size_t iLenDst);
int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst, size_t iLenDst);
int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
diff --git a/runtime/net.c b/runtime/net.c
index db2d7e3..5cafe52 100644
--- a/runtime/net.c
+++ b/runtime/net.c
@@ -1496,6 +1496,49 @@ int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer)
}
+/* check if two provided socket addresses point to the same host. Note that the
+ * length of the sockets must be provided as third parameter. This is necessary to
+ * compare non IPv4/v6 hosts, in which case we do a simple memory compare of the
+ * address structure (in that case, the same host may not reliably be detected).
+ * Note that we need to do the comparison not on the full structure, because it contains things
+ * like the port, which we do not need to look at when thinking about hostnames. So we look
+ * at the relevant fields, what means a somewhat more complicated processing.
+ * Also note that we use a non-standard calling interface, as this is much more natural and
+ * it looks extremely unlikely that we get an exception of any kind here. What we
+ * return is mimiced after memcmp(), and as such useful for building binary trees
+ * (the order relation may be a bit arbritrary, but at least it is consistent).
+ * rgerhards, 2009-09-03
+ */
+static int CmpHost(struct sockaddr_storage *s1, struct sockaddr_storage* s2, size_t socklen)
+{
+ int ret;
+
+ if(((struct sockaddr*) s1)->sa_family != ((struct sockaddr*) s2)->sa_family) {
+ ret = memcmp(s1, s2, socklen);
+ goto finalize_it;
+ }
+
+ if(((struct sockaddr*) s1)->sa_family == AF_INET) {
+ if(((struct sockaddr_in *) s1)->sin_addr.s_addr == ((struct sockaddr_in*)s2)->sin_addr.s_addr) {
+ ret = 0;
+ } else if(((struct sockaddr_in *) s1)->sin_addr.s_addr < ((struct sockaddr_in*)s2)->sin_addr.s_addr) {
+ ret = -1;
+ } else {
+ ret = 1;
+ }
+ } else if(((struct sockaddr*) s1)->sa_family == AF_INET6) {
+ /* IPv6 addresses are always 16 octets long */
+ ret = memcmp(((struct sockaddr_in6 *)s1)->sin6_addr.s6_addr, ((struct sockaddr_in6*)s2)->sin6_addr.s6_addr, 16);
+ } else {
+ ret = memcmp(s1, s2, socklen);
+ }
+
+dbgprintf("CmpHost returns %d\n", ret);
+finalize_it:
+ return ret;
+}
+
+
/* queryInterface function
* rgerhards, 2008-03-05
*/
@@ -1524,6 +1567,7 @@ CODESTARTobjQueryInterface(net)
pIf->AddPermittedPeer = AddPermittedPeer;
pIf->DestructPermittedPeers = DestructPermittedPeers;
pIf->PermittedPeerWildcardMatch = PermittedPeerWildcardMatch;
+ pIf->CmpHost = CmpHost;
finalize_it:
ENDobjQueryInterface(net)
diff --git a/runtime/net.h b/runtime/net.h
index 092c311..ec364b1 100644
--- a/runtime/net.h
+++ b/runtime/net.h
@@ -146,11 +146,13 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
rsRetVal (*AddPermittedPeer)(permittedPeers_t **ppRootPeer, uchar *pszID);
rsRetVal (*DestructPermittedPeers)(permittedPeers_t **ppRootPeer);
rsRetVal (*PermittedPeerWildcardMatch)(permittedPeers_t *pPeer, uchar *pszNameToMatch, int *pbIsMatching);
+ /* v5 interface additions */
+ int (*CmpHost)(struct sockaddr_storage *, struct sockaddr_storage*, size_t);
/* data members - these should go away over time... TODO */
int *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */
int *pACLDontResolve; /* add hostname to acl instead of resolving it to IP(s) */
ENDinterface(net)
-#define netCURR_IF_VERSION 4 /* increment whenever you change the interface structure! */
+#define netCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */
/* prototypes */
PROTOTYPEObj(net);
diff --git a/runtime/parser.c b/runtime/parser.c
index 0b45bfd..7eff080 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -167,6 +167,7 @@ sanitizeMessage(msg_t *pMsg)
size_t iMaxLine;
assert(pMsg != NULL);
+ assert(pMsg->iLenRawMsg > 0);
# ifdef USE_NETZIP
CHKiRet(uncompressMessage(pMsg));
@@ -274,6 +275,7 @@ finalize_it:
RETiRet;
}
+
/* Parse a received message. The object's rawmsg property is taken and
* parsed according to the relevant standards. This can later be
* extended to support configured parsers.
@@ -284,16 +286,21 @@ rsRetVal parseMsg(msg_t *pMsg)
DEFiRet;
uchar *msg;
int pri;
+ int lenMsg;
int iPriText;
+ if(pMsg->iLenRawMsg == 0)
+ ABORT_FINALIZE(RS_RET_EMPTY_MSG);
+
CHKiRet(sanitizeMessage(pMsg));
/* we needed to sanitize first, because we otherwise do not have a C-string we can print... */
DBGPRINTF("msg parser: flags %x, from '%s', msg '%s'\n", pMsg->msgFlags, pMsg->pszRcvFrom, pMsg->pszRawMsg);
/* pull PRI */
- pri = DEFUPRI;
+ lenMsg = pMsg->iLenRawMsg;
msg = pMsg->pszRawMsg;
+ pri = DEFUPRI;
iPriText = 0;
if(*msg == '<') {
/* while we process the PRI, we also fill the PRI textual representation
@@ -301,7 +308,7 @@ rsRetVal parseMsg(msg_t *pMsg)
* but it offers us performance...
*/
pri = 0;
- while(isdigit((int) *++msg)) {
+ while(--lenMsg > 0 && isdigit((int) *++msg)) {
pMsg->bufPRI[iPriText++ % 4] = *msg; /* mod 4 to guard against malformed messages! */
pri = 10 * pri + (*msg - '0');
}
@@ -342,7 +349,7 @@ rsRetVal parseMsg(msg_t *pMsg)
/* finalize message object */
pMsg->msgFlags &= ~NEEDS_PARSING; /* this message is now parsed */
- MsgPrepareEnqueue(pMsg); /* "historical" name - preparese for multi-threading */
+ MsgPrepareEnqueue(pMsg); /* "historical" name - prepare for multi-threading */
finalize_it:
RETiRet;
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 32177a9..835fff2 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -280,6 +280,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended (consider this permanent for the time being) */
RS_RET_NONFATAL_CONFIG_ERR = -2124, /**< non-fatal error during config processing */
RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */
+ RS_RET_EMPTY_MSG = -2143, /**< provided (raw) MSG is empty */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */