From 430cf18155806020967f5a6d7d0e8b73fc3e0760 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 2 Feb 2014 20:09:10 +0000 Subject: [PATCH] Refactor tcp socket opens --- src/src/malware.c | 192 +++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 103 deletions(-) diff --git a/src/src/malware.c b/src/src/malware.c index 9d4d16aba..88e96911f 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -222,6 +222,79 @@ clmd_errlog(const uschar * str) /*************************************************/ +static int +m_streamsocket(const uschar * hostname, struct in_addr * inp, uschar ** errstr) +{ + struct hostent * he; + int sock; + + /* Lookup the host */ + if(!(he = gethostbyname(CS hostname))) { + *errstr = string_sprintf("failed to lookup host '%s'", hostname); + return -1; + } + *inp = *(struct in_addr *) he->h_addr_list[0]; + + /* Create the TCP socket */ + if ((sock = ip_socket(SOCK_STREAM, AF_INET)) >= 0) + return sock; + + *errstr = string_sprintf("unable to acquire socket (%s)", strerror(errno)); + return -1; +} + +static int +m_tcpsocket(const uschar * hostname, unsigned int port, + struct in_addr * inp, uschar ** errstr) +{ + int sock; + + if ((sock = m_streamsocket(hostname, inp, errstr)) < 0) + return -1; + + if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(*inp), port, 5) >= 0) + return sock; + + *errstr = string_sprintf("connection to %s, port %u failed (%s)", + inet_ntoa(*inp), port, strerror(errno)); + (void)close(sock); + return -1; +} + +static int +m_tcpsocket_fromdef(const uschar * hostport, uschar ** errstr) +{ + int scan; + uschar hostname[256]; + unsigned int port, portlow, porthigh; + struct hostent * he; + struct in_addr in; + int sock; + + /* extract host and port part */ + scan = sscanf(CS hostport, "%255s %u-%u", hostname, &portlow, &porthigh); + if ( scan != 3 ) { + if ( scan != 2 ) { + *errstr = string_sprintf("invalid socket '%s'", hostport); + return -1; + } + porthigh = portlow; + } + + if ((sock = m_streamsocket(hostname, &in, errstr)) < 0) + return -1; + + /* Try to connect to all ports low-high until connection is established */ + for (port = portlow; port <= porthigh; port++) + if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) >= 0) + return sock; + + *errstr = string_sprintf("connection to %s, port %u-%u failed (%s)", + inet_ntoa(in), portlow, porthigh, strerror(errno)); + (void)close(sock); + return -1; +} + static int m_unixsocket(const uschar * path, uschar ** errstr) { @@ -387,48 +460,13 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) case M_FPROTD: /* "f-protd" scanner type -------------------------------- */ { uschar *fp_scan_option; - uschar hostname[256]; - unsigned int port, portlow, porthigh, connect_ok=0, detected=0, par_count=0; - struct hostent *he; - struct in_addr in; + unsigned int detected=0, par_count=0; int sock; uschar * scanrequest; uschar buf[32768], *strhelper, *strhelper2; - /* extract host and port part */ - if ( sscanf(CS scanner_options, "%255s %u-%u", hostname, &portlow, &porthigh) != 3 ) { - if ( sscanf(CS scanner_options, "%s %u", hostname, &portlow) != 2 ) - return fprotd_errlog_defer( - string_sprintf("invalid socket '%s'", scanner_options)); - porthigh = portlow; - } - - /* Lookup the host */ - if((he = gethostbyname(CS hostname)) == 0) - return fprotd_errlog_defer( - string_sprintf("failed to lookup host '%s'", hostname)); - - in = *(struct in_addr *) he->h_addr_list[0]; - port = portlow; - - - /* Open the f-protd TCP socket */ - if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) - return fprotd_errlog_defer( - string_sprintf("unable to acquire socket (%s)", strerror(errno))); - - /* Try to connect to all portslow-high until connection is established */ - for (port = portlow; !connect_ok && port < porthigh; port++) - if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) >= 0) - connect_ok = 1; - - if ( !connect_ok ) { - int err = errno; - (void)close(sock); - return fprotd_errlog_defer( - string_sprintf("connection to %s, port %u-%u failed (%s)", - inet_ntoa(in), portlow, porthigh, strerror(err))); - } + if ((sock = m_tcpsocket_fromdef(scanner_options, &errstr)) < 0) + return fprotd_errlog_defer(errstr); DEBUG(D_acl) debug_printf("Malware scan: issuing %s GET\n", scanner_name); scanrequest = string_sprintf("GET %s", eml_filename); @@ -470,42 +508,16 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) { struct sockaddr_un server; int sock, result, ovector[10*3]; - unsigned int port, fsize; + unsigned int fsize; uschar * tmpbuf, *drweb_fbuf; int drweb_rc, drweb_cmd, drweb_flags = 0x0000, drweb_fd, drweb_vnum, drweb_slen, drweb_fin = 0x0000; unsigned long bread; - uschar hostname[256]; - struct hostent *he; - struct in_addr in; pcre *drweb_re; if (*scanner_options != '/') { - - /* extract host and port part */ - if( sscanf(CS scanner_options, "%255s %u", hostname, &port) != 2 ) - return drweb_errlog_defer( - string_sprintf("invalid socket '%s'", scanner_options)); - - /* Lookup the host */ - if((he = gethostbyname(CS hostname)) == 0) - return drweb_errlog_defer( - string_sprintf("failed to lookup host '%s'", hostname)); - - in = *(struct in_addr *) he->h_addr_list[0]; - - /* Open the drwebd TCP socket */ - if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) - return drweb_errlog_defer( - string_sprintf("unable to acquire socket (%s)", strerror(errno))); - - if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) { - int err = errno; - (void)close(sock); - return drweb_errlog_defer( - string_sprintf("connection to %s, port %u failed (%s)", - inet_ntoa(in), port, strerror(err))); - } + if ((sock = m_tcpsocket_fromdef(scanner_options, &errstr)) < 0) + return drweb_errlog_defer(errstr); /* prepare variables */ drweb_cmd = htonl(DRWEBD_SCAN_CMD); @@ -532,8 +544,8 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) drweb_slen = htonl(fsize); lseek(drweb_fd, 0, SEEK_SET); - DEBUG(D_acl) debug_printf("Malware scan: issuing %s remote scan [%s %u]\n", - scanner_name, hostname, port); + DEBUG(D_acl) debug_printf("Malware scan: issuing %s remote scan [%s]\n", + scanner_name, scanner_options); /* send scan request */ if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) || @@ -614,8 +626,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) drweb_vnum = ntohl(drweb_vnum); /* "virus(es) found" if virus number is > 0 */ - if (drweb_vnum) - { + if (drweb_vnum) { int i; /* setup default virus name */ @@ -1177,12 +1188,11 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) uschar *p, *vname, *result_tag, *response_end; struct sockaddr_un server; - int sock,bread=0; + int sock, bread=0; unsigned int port; uschar * file_name; uschar av_buffer[1024]; uschar *hostname = ""; - struct hostent *he; struct in_addr in; uschar *clamav_fbuf; int clam_fd, result; @@ -1271,41 +1281,17 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) /* Lookup the host. This is to ensure that we connect to the same IP * on both connections (as one host could resolve to multiple ips) */ - if((he = gethostbyname(CS clamd_address_vector[current_server]->tcp_addr)) - == 0) { - clmd_errlog(string_sprintf("failed to lookup host '%s'", - clamd_address_vector[current_server]->tcp_addr)); - goto try_next_server; - } - - in = *(struct in_addr *) he->h_addr_list[0]; - - /* Open the ClamAV Socket */ - if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) { - clmd_errlog(string_sprintf("unable to acquire socket (%s)", - strerror(errno))); - goto try_next_server; - } - - if (ip_connect( sock, - AF_INET, - (uschar*)inet_ntoa(in), - clamd_address_vector[current_server]->tcp_port, - 5 ) > -1) { + sock= m_tcpsocket(CS clamd_address_vector[current_server]->tcp_addr, + clamd_address_vector[current_server]->tcp_port, + &in, &errstr); + if (sock >= 0) { /* Connection successfully established with a server */ hostname = clamd_address_vector[current_server]->tcp_addr; break; - } else { - clmd_errlog(string_sprintf( - "malware acl condition: clamd: connection to %s, port %u failed (%s)", - clamd_address_vector[current_server]->tcp_addr, - clamd_address_vector[current_server]->tcp_port, - strerror(errno))); - - (void)close(sock); } - try_next_server: + clmd_errlog(errstr); + /* Remove the server from the list. XXX We should free the memory */ num_servers--; int i; -- 2.30.2