From aebd480be7149d51c628fe50531a3bd359550a82 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 18 Sep 2007 13:05:05 +0000 Subject: split the function cvthname() for clarity. Also changed to using the rsRetVal status return system --- net.c | 67 +++++++++++++++++++++++++++++++++++++++++++++------------------ net.h | 2 +- rsyslog.h | 3 +++ syslogd.c | 4 ++-- 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/net.c b/net.c index 20af3330..ee2c0d9d 100644 --- a/net.c +++ b/net.c @@ -92,14 +92,11 @@ int should_use_so_bsdcompat(void) #endif -/* Return a printable representation of a host address. - * Now (2007-07-16) also returns the full host name (if it could be obtained) - * in the second param [thanks to mildew@gmail.com for the patch]. - * The caller must provide buffer space for pszHost and pszHostFQDN. These - * buffers must be of size NI_MAXHOST. This is not checked here, because - * there is no way to check it. We use this way of doing things because it - * frees us from using dynamic memory allocation where it really does not - * pay. +/* get the hostname of the message source. This was originally in cvthname() + * but has been moved out of it because of clarity and fuctional separation. + * It must be provided by the socket we received the message on as well as + * a NI_MAXHOST size large character buffer for the FQDN. + * * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats) * for some explanation of the code found below. We do by default not * discard message where we detected malicouos DNS PTR records. However, @@ -107,16 +104,16 @@ int should_use_so_bsdcompat(void) * we should abort. For this, the return value tells the caller if the * message should be processed (1) or discarded (0). */ -int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) +/* TODO: after the bughunt, make this function static - rgerhards, 2007-09-18 */ +rsRetVal gethname(struct sockaddr_storage *f, uchar *pszHostFQDN) { - register uchar *p; - int count, error; + DEFiRet; + int error; sigset_t omask, nmask; char ip[NI_MAXHOST]; struct addrinfo hints, *res; assert(f != NULL); - assert(pszHost != NULL); assert(pszHostFQDN != NULL); error = getnameinfo((struct sockaddr *)f, SALEN((struct sockaddr *)f), @@ -124,9 +121,8 @@ int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) if (error) { dbgprintf("Malformed from address %s\n", gai_strerror(error)); - strcpy((char*) pszHost, "???"); strcpy((char*) pszHostFQDN, "???"); - return 1; + ABORT_FINALIZE(RS_RET_INVALID_SOURCE); } if (!DisableDNS) { @@ -134,7 +130,6 @@ int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) sigaddset(&nmask, SIGHUP); pthread_sigmask(SIG_BLOCK, &nmask, &omask); - //error = getnameinfo((struct sockaddr *)f, sizeof(*f), error = getnameinfo((struct sockaddr *)f, SALEN((struct sockaddr *) f), (char*)pszHostFQDN, NI_MAXHOST, NULL, 0, NI_NAMEREQD); @@ -166,7 +161,7 @@ int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) ip, pszHostFQDN); logerror((char*)szErrMsg); pthread_sigmask(SIG_SETMASK, &omask, NULL); - return 0; + ABORT_FINALIZE(RS_RET_MALICIOUS_ENTITY); } /* Please note: we deal with a malicous entry. Thus, we have crafted @@ -190,10 +185,42 @@ int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) if (error || DisableDNS) { dbgprintf("Host name for your address (%s) unknown\n", ip); strcpy((char*) pszHostFQDN, ip); - strcpy((char*) pszHost, ip); - return 1; + ABORT_FINALIZE(RS_RET_ADDRESS_UNKNOWN); } +finalize_it: + return iRet; +} +/* Return a printable representation of a host address. + * Now (2007-07-16) also returns the full host name (if it could be obtained) + * in the second param [thanks to mildew@gmail.com for the patch]. + * The caller must provide buffer space for pszHost and pszHostFQDN. These + * buffers must be of size NI_MAXHOST. This is not checked here, because + * there is no way to check it. We use this way of doing things because it + * frees us from using dynamic memory allocation where it really does not + * pay. + */ +rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) +{ + DEFiRet; + register uchar *p; + int count; + + assert(f != NULL); + assert(pszHost != NULL); + assert(pszHostFQDN != NULL); + + iRet = gethname(f, pszHostFQDN); + + if(iRet == RS_RET_INVALID_SOURCE || iRet == RS_RET_ADDRESS_UNKNOWN) { + strcpy((char*) pszHost, (char*) pszHostFQDN); /* we use whatever was provided as replacement */ + ABORT_FINALIZE(RS_RET_OK); /* this is handled, we are happy with it */ + } else if(iRet != RS_RET_OK) { + FINALIZE; /* we return whatever error state we have - can not handle it */ + } + + /* if we reach this point, we obtained a non-numeric hostname and can now process it */ + /* Convert to lower case, just like LocalDomain above */ for (p = pszHostFQDN ; *p ; p++) @@ -249,7 +276,9 @@ int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN) } } } - return 1; + +finalize_it: + return iRet; } #endif /* #ifdef SYSLOG_INET */ diff --git a/net.h b/net.h index 5f6705d7..1164e33f 100644 --- a/net.h +++ b/net.h @@ -69,7 +69,7 @@ static inline size_t SALEN(struct sockaddr *sa) { } #endif -int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN); +rsRetVal cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN); #endif /* #ifdef SYSLOG_INET */ #endif /* #ifndef INCLUDED_NET_H */ diff --git a/rsyslog.h b/rsyslog.h index 6ecb7440..00f8fad4 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -70,6 +70,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_INVALID_PARAMS = -2016,/**< supplied parameters are invalid */ RS_RET_EMPTY_LIST = -2017, /**< linked list is empty */ RS_RET_FINISHED = -2018, /**< some opertion is finished, not an error state */ + RS_RET_INVALID_SOURCE = -2019, /**< source (address) invalid for some reason */ + RS_RET_ADDRESS_UNKNOWN = -2020, /**< an address is unknown - not necessarily an error */ + RS_RET_MALICIOUS_ENTITY = -2021, /**< there is an malicious entity involved */ RS_RET_OK = 0 /**< operation successful */ }; typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */ diff --git a/syslogd.c b/syslogd.c index d45e561f..79562944 100644 --- a/syslogd.c +++ b/syslogd.c @@ -5627,12 +5627,12 @@ static rsRetVal processSelectAfter(int maxfds, int nfds, fd_set *pReadfds, fd_se for (i = 0; i < *finet; i++) { if (FD_ISSET(finet[i+1], pReadfds)) { socklen = sizeof(frominet); - memset(line, '\0', sizeof(line)); + memset(line, '\0', sizeof(line)); // TODO: I think we need this for debug only - remove after bug hunt l = recvfrom(finet[i+1], line, MAXLINE - 1, 0, (struct sockaddr *)&frominet, &socklen); if (l > 0) { line[l] = '\0'; - if(cvthname(&frominet, fromHost, fromHostFQDN) == 1) { + if(cvthname(&frominet, fromHost, fromHostFQDN) == RS_RET_OK) { dbgprintf("Message from inetd socket: #%d, host: %s\n", finet[i+1], fromHost); /* Here we check if a host is permitted to send us -- cgit