diff -urN src.orig/malware.c src/malware.c --- src.orig/malware.c Tue Sep 7 18:00:46 2004 +++ src/malware.c Tue Sep 21 09:36:18 2004 @@ -841,6 +841,14 @@ uschar hostname[256]; struct hostent *he; struct in_addr in; + uschar *clamd_options2; + uschar clamd_options2_buffer[1024]; + uschar clamd_options2_default[] = ""; + uschar av_buffer2[1024]; + uschar *clamav_fbuf; + uschar scanrequest[1024]; + int sockData, clam_fd, result; + unsigned int fsize; if ((clamd_options = string_nextinlist(&av_scanner_work, &sep, clamd_options_buffer, @@ -849,6 +857,12 @@ clamd_options = clamd_options_default; } + if ((clamd_options2 = string_nextinlist(&av_scanner_work, &sep, + clamd_options2_buffer, + sizeof(clamd_options2_buffer))) == NULL) { + clamd_options2 = clamd_options2_default; + } + /* socket does not start with '/' -> network socket */ if (*clamd_options != '/') { @@ -883,6 +897,126 @@ inet_ntoa(in), port, strerror(errno)); return DEFER; } + + if (strcmpic(clamd_options2,US"local") == 0) { + + /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */ + + snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id); + + if (send(sock, file_name, Ustrlen(file_name), 0) < 0) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)", + strerror(errno)); + return DEFER; + } + } else { + + /* Pass the string to ClamAV (7 = "STREAM\n") */ + + if (send(sock, "STREAM\n", 7, 0) < 0) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)", + strerror(errno)); + return DEFER; + } + memset(av_buffer2, 0, sizeof(av_buffer2)); + bread = read(sock, av_buffer2, sizeof(av_buffer2)); + + if (bread < 0) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to read PORT from socket (%s)", + strerror(errno)); + return DEFER; + } + + if (bread == sizeof(av_buffer)) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: buffer too small"); + return DEFER; + } + + if (!(*av_buffer2)) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: ClamAV returned null"); + return DEFER; + } + + av_buffer2[bread] = '\0'; + if( sscanf(CS av_buffer2, "PORT %hu\n", &port) != 1 ) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: Expected port information from clamd, got '%s'", av_buffer2); + return DEFER; + }; + + if ( (sockData = ip_socket(SOCK_STREAM, AF_INET)) < 0) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to acquire socket (%s)", + strerror(errno)); + return DEFER; + } + + if (ip_connect(sockData, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) { + close(sockData); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: connection to %s, port %u failed (%s)", + inet_ntoa(in), port, strerror(errno)); + return DEFER; + } + + snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml", + spool_directory, message_id, message_id); + + /* calc file size */ + clam_fd = open(CS scanrequest, O_RDONLY); + if (clam_fd == -1) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't open spool file %s: %s", + scanrequest, strerror(errno)); + return DEFER; + } + fsize = lseek(clam_fd, 0, SEEK_END); + if (fsize == -1) { + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't seek spool file %s: %s", + scanrequest, strerror(errno)); + return DEFER; + } + lseek(clam_fd, 0, SEEK_SET); + + clamav_fbuf = (uschar *) malloc (fsize); + if (!clamav_fbuf) { + close(sockData); + close(clam_fd); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to allocate memory %u for file (%s)", + fsize, scanrequest); + return DEFER; + } + + result = read (clam_fd, clamav_fbuf, fsize); + if (result == -1) { + close(sockData); + close(clam_fd); + free(clamav_fbuf); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't read spool file %s: %s", + scanrequest, strerror(errno)); + return DEFER; + } + close(clam_fd); + + /* send file body to socket */ + if (send(sockData, clamav_fbuf, fsize, 0) < 0) { + close(sockData); + free(clamav_fbuf); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to send file body to socket (%s:%u)", hostname, port); + return DEFER; + } + free(clamav_fbuf); + close(sockData); + } } else { /* open the local socket */ @@ -903,17 +1037,17 @@ clamd_options, strerror(errno) ); return DEFER; } - } - + /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */ - snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id); + snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id); - if (send(sock, file_name, Ustrlen(file_name), 0) < 0) { - close(sock); - log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)", + if (send(sock, file_name, Ustrlen(file_name), 0) < 0) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)", strerror(errno)); - return DEFER; + return DEFER; + } } /*