diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | doc/rsconf1_dircreatemode.html | 10 | ||||
-rw-r--r-- | plugins/imudp/imudp.c | 3 | ||||
-rw-r--r-- | plugins/omstdout/omstdout.c | 2 | ||||
-rw-r--r-- | runtime/datetime.c | 119 | ||||
-rw-r--r-- | runtime/datetime.h | 4 | ||||
-rw-r--r-- | runtime/parser.c | 13 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | tools/syslogd.c | 100 |
9 files changed, 185 insertions, 77 deletions
@@ -128,6 +128,15 @@ Version 4.5.0 [DEVEL] (rgerhards), 2009-07-02 an abort --------------------------------------------------------------------------- Version 4.4.2 [v4-stable] (rgerhards), 2009-09-?? +- bugfix: invalid handling of zero-sized messages, could lead to mis- + addressing and potential memory corruption/segfault +- bugfix: zero-sized UDP messages are no longer processed + until now, they were forwarded to processing, but this makes no sense + Also, it looks like the system seems to provide a zero return code + on a UDP recvfrom() from time to time for some internal reasons. These + "receives" are now silently ignored. +- bugfix: random data could be appended to message, possibly causing + segfaults - bugfix: reverse lookup reduction logic in imudp do DNS queries too often A comparison was done between the current and the former source address. However, this was done on the full sockaddr_storage structure and not @@ -1520,6 +1529,7 @@ Version 2.0.8 V2-STABLE (rgerhards), 2008-??-?? connection broke, but not if there was a problem with statement execution. The most probable case for such a case would be invalid sql inside the template, and this is now much easier to diagnose. +- doc bugfix: default for $DirCreateMode incorrectly stated --------------------------------------------------------------------------- Version 2.0.7 V2-STABLE (rgerhards), 2008-04-14 - bugfix: the default for $DirCreateMode was 0644, and as such wrong. diff --git a/doc/rsconf1_dircreatemode.html b/doc/rsconf1_dircreatemode.html index 9a9c61eb..b22b6c59 100644 --- a/doc/rsconf1_dircreatemode.html +++ b/doc/rsconf1_dircreatemode.html @@ -7,9 +7,13 @@ <h2>$DirCreateMode</h2> <p><b>Type:</b> global configuration directive</p> -<p><b>Default:</b> 0644</p> +<p><b>Default:</b> 0700</p> <p><b>Description:</b></p> <p>This is the same as $FileCreateMode, but for directories automatically generated.</p> +<p>Please visit the +<a target="_blank" href="http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html">rsyslog mailing list +archive</a> +to understand why the default is so restrictive.</p> <p><b>Sample:</b></p> <p><code><b></b></code></p> @@ -17,8 +21,8 @@ index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> <p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> project.<br> -Copyright © 2007 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and +Copyright © 2007-2009 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and <a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL -version 2 or higher.</font></p> +version 3 or higher.</font></p> </body> </html> diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index cd250657..0970259d 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -208,6 +208,9 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, ABORT_FINALIZE(RS_RET_ERR); } + if(lenRcvBuf == 0) + continue; /* this looks a bit strange, but practice shows it happens... */ + /* if we reach this point, we had a good receive and can process the packet received */ /* check if we have a different sender than before, if so, we need to query some new values */ if(net.CmpHost(&frominet, frominetPrev, socklen) != 0) { diff --git a/plugins/omstdout/omstdout.c b/plugins/omstdout/omstdout.c index 584ae458..b3ec6287 100644 --- a/plugins/omstdout/omstdout.c +++ b/plugins/omstdout/omstdout.c @@ -124,7 +124,7 @@ CODESTARTdoAction toWrite = (char*) ppString[0]; } len = strlen(toWrite); - write(1, toWrite, strlen(toWrite)); /* 1 is stdout! */ + write(1, toWrite, len); /* 1 is stdout! */ if(pData->bEnsureLFEnding && toWrite[len-1] != '\n') { write(1, "\n", 1); /* write missing LF */ } diff --git a/runtime/datetime.c b/runtime/datetime.c index dfa56b4f..6160bd7c 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -143,6 +143,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. * @@ -150,17 +151,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; @@ -172,9 +177,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 */ @@ -189,6 +198,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; @@ -196,48 +206,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; @@ -245,23 +262,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 { @@ -270,10 +291,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; @@ -289,6 +312,7 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) pTime->OffsetMode = OffsetMode; pTime->OffsetHour = OffsetHour; pTime->OffsetMinute = OffsetMinute; + *pLenStr = lenStr; finalize_it: RETiRet; @@ -307,9 +331,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; @@ -319,6 +347,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; @@ -326,6 +355,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: @@ -348,6 +379,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': @@ -470,26 +504,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. @@ -499,23 +538,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); @@ -523,8 +565,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 @@ -541,6 +585,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 58f368e7..8140eb71 100644 --- a/runtime/datetime.h +++ b/runtime/datetime.h @@ -34,8 +34,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); int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst); int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf); diff --git a/runtime/parser.c b/runtime/parser.c index db11ac5b..466066e7 100644 --- a/runtime/parser.c +++ b/runtime/parser.c @@ -167,6 +167,7 @@ sanitizeMessage(msg_t *pMsg) uchar szSanBuf[32*1024]; /* buffer used for sanitizing a string */ assert(pMsg != NULL); + assert(pMsg->iLenRawMsg > 0); # ifdef USE_NETZIP CHKiRet(uncompressMessage(pMsg)); @@ -254,6 +255,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. @@ -264,6 +266,11 @@ 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)); @@ -271,15 +278,17 @@ rsRetVal parseMsg(msg_t *pMsg) DBGPRINTF("msg parser: flags %x, from '%s', msg '%s'\n", pMsg->msgFlags, getRcvFrom(pMsg), 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 * inside the msg object. This may not be ideal from an OOP point of view, * but it offers us performance... */ pri = 0; - while(isdigit((int) *++msg)) { + while(--lenMsg > 0 && isdigit((int) *++msg)) { pri = 10 * pri + (*msg - '0'); } if(*msg == '>') diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 8a043dde..e218110d 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -367,6 +367,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */ RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */ + 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) */ diff --git a/tools/syslogd.c b/tools/syslogd.c index 88588621..2e6de66c 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -947,10 +947,12 @@ msgConsumer(void __attribute__((unused)) *notNeeded, void *pUsr) * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not - * SP-terminated or any other error occurs. - * rger, 2005-11-24 + * SP-terminated or any other error occurs. -- rger, 2005-11-24 + * The function now receives the size of the string and makes sure + * that it does not process more than that. The *pLenStr counter is + * updated on exit. -- rgerhards, 2009-09-23 */ -static int parseRFCField(uchar **pp2parse, uchar *pResult) +static int parseRFCField(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int iRet = 0; @@ -962,14 +964,17 @@ static int parseRFCField(uchar **pp2parse, uchar *pResult) p2parse = *pp2parse; /* this is the actual parsing loop */ - while(*p2parse && *p2parse != ' ') { + while(*pLenStr > 0 && *p2parse != ' ') { *pResult++ = *p2parse++; + --(*pLenStr); } - if(*p2parse == ' ') + if(*pLenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ - else + --(*pLenStr); + } else { iRet = 1; /* there MUST be an SP! */ + } *pResult = '\0'; /* set the new parse pointer */ @@ -985,20 +990,24 @@ static int parseRFCField(uchar **pp2parse, uchar *pResult) * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not - * SP-terminated or any other error occurs. - * rger, 2005-11-24 + * SP-terminated or any other error occurs. -- rger, 2005-11-24 + * The function now receives the size of the string and makes sure + * that it does not process more than that. The *pLenStr counter is + * updated on exit. -- rgerhards, 2009-09-23 */ -static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult) +static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int bCont = 1; int iRet = 0; + int lenStr; assert(pp2parse != NULL); assert(*pp2parse != NULL); assert(pResult != NULL); p2parse = *pp2parse; + lenStr = *pLenStr; /* this is the actual parsing loop * Remeber: structured data starts with [ and includes any characters @@ -1006,40 +1015,55 @@ static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult) * structured data. There may also be \] inside the structured data, which * do NOT terminate an element. */ - if(*p2parse != '[') + if(lenStr == 0 || *p2parse != '[') return 1; /* this is NOT structured data! */ if(*p2parse == '-') { /* empty structured data? */ *pResult++ = '-'; ++p2parse; + --lenStr; } else { while(bCont) { - if(*p2parse == '\0') { - iRet = 1; /* this is not valid! */ - bCont = 0; + if(lenStr < 2) { + /* we now need to check if we have only structured data */ + if(lenStr > 0 && *p2parse == ']') { + *pResult++ = *p2parse; + p2parse++; + lenStr--; + bCont = 0; + } else { + iRet = 1; /* this is not valid! */ + bCont = 0; + } } else if(*p2parse == '\\' && *(p2parse+1) == ']') { /* this is escaped, need to copy both */ *pResult++ = *p2parse++; *pResult++ = *p2parse++; + lenStr -= 2; } else if(*p2parse == ']' && *(p2parse+1) == ' ') { /* found end, just need to copy the ] and eat the SP */ *pResult++ = *p2parse; p2parse += 2; + lenStr -= 2; bCont = 0; } else { *pResult++ = *p2parse++; + --lenStr; } } } - if(*p2parse == ' ') + if(lenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ - else + --lenStr; + } else { iRet = 1; /* there MUST be an SP! */ + } *pResult = '\0'; /* set the new parse pointer */ *pp2parse = p2parse; + *pLenStr = lenStr; return 0; } @@ -1064,23 +1088,26 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) { uchar *p2parse; uchar *pBuf; + int lenMsg; int bContParse = 1; BEGINfunc assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ + lenMsg = pMsg->iLenRawMsg - (pMsg->offAfterPRI); - /* do a sanity check on the version and eat it */ + /* do a sanity check on the version and eat it (the caller checked this already) */ assert(p2parse[0] == '1' && p2parse[1] == ' '); p2parse += 2; + lenMsg -= 2; /* Now get us some memory we can use as a work buffer while parsing. * We simply allocated a buffer sufficiently large to hold all of the * message, so we can not run into any troubles. I think this is * more wise then to use individual buffers. */ - if((pBuf = malloc(sizeof(uchar) * ustrlen(p2parse) + 1)) == NULL) + if((pBuf = malloc(sizeof(uchar) * (lenMsg + 1))) == NULL) return 1; /* IMPORTANT NOTE: @@ -1091,7 +1118,7 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) */ /* TIMESTAMP */ - if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { if(flags & IGNDATE) { /* we need to ignore the msg data, so simply copy over reception date */ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime)); @@ -1103,31 +1130,31 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) /* HOSTNAME */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetHOSTNAME(pMsg, pBuf, ustrlen(pBuf)); } /* APP-NAME */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetAPPNAME(pMsg, (char*)pBuf); } /* PROCID */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetPROCID(pMsg, (char*)pBuf); } /* MSGID */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetMSGID(pMsg, (char*)pBuf); } /* STRUCTURED-DATA */ if(bContParse) { - parseRFCStructuredData(&p2parse, pBuf); + parseRFCStructuredData(&p2parse, pBuf, &lenMsg); MsgSetStructuredData(pMsg, (char*)pBuf); } @@ -1156,6 +1183,7 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) int parseLegacySyslogMsg(msg_t *pMsg, int flags) { uchar *p2parse; + int lenMsg; int bTAGCharDetected; int i; /* general index for parsing */ uchar bufParseTAG[CONF_TAG_MAXSIZE]; @@ -1164,27 +1192,32 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); + lenMsg = pMsg->iLenRawMsg - (pMsg->offAfterPRI + 1); +RUNLOG_VAR("%d", pMsg->offAfterPRI); +RUNLOG_VAR("%d", lenMsg); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ /* Check to see if msg contains a timestamp. We start by assuming - * that the message timestamp is the time of reciption (which we + * that the message timestamp is the time of reception (which we * generated ourselfs and then try to actually find one inside the * message. There we go from high-to low precison and are done * when we find a matching one. -- rgerhards, 2008-09-16 */ - if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */; - } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; - } else if(*p2parse == ' ') { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */ + } else if(*p2parse == ' ' && lenMsg > 1) { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */ ++p2parse; /* move over space */ - if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + --lenMsg; + if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* indeed, we got it! */ /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; } else {/* parse pointer needs to be restored, as we moved it off-by-one * for this try. */ --p2parse; + ++lenMsg; } } @@ -1215,12 +1248,13 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) * that is not a valid hostname. */ bTAGCharDetected = 0; - if(flags & PARSE_HOSTNAME) { + if(lenMsg > 0 && flags & PARSE_HOSTNAME) { i = 0; - while((isalnum(p2parse[i]) || p2parse[i] == '.' || p2parse[i] == '.' + while(lenMsg > 0 && (isalnum(p2parse[i]) || p2parse[i] == '.' || p2parse[i] == '.' || p2parse[i] == '_' || p2parse[i] == '-') && i < CONF_TAG_MAXSIZE) { bufParseHOSTNAME[i] = p2parse[i]; ++i; + --lenMsg; } if(i > 0 && p2parse[i] == ' ' && isalnum(p2parse[i-1])) { @@ -1245,11 +1279,13 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) * outputs so that only 32 characters max are used by default. */ i = 0; - while(*p2parse && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE) { + while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE) { bufParseTAG[i++] = *p2parse++; + --lenMsg; } - if(*p2parse == ':') { + if(lenMsg > 0 && *p2parse == ':') { ++p2parse; + --lenMsg; bufParseTAG[i++] = ':'; } |