diff -urN exim-4.43/src/malware.c exim-4.43-vc/src/malware.c --- exim-4.43/src/malware.c 2004-11-09 15:52:52.000000000 +0200 +++ exim-4.43-vc/src/malware.c 2004-11-09 16:47:50.000000000 +0200 @@ -942,13 +942,15 @@ /* "clamd" scanner type ------------------------------------------------- */ /* This code was contributed by David Saez */ + /* modified by Victor Cheburkin */ else if (strcmpic(scanner_name,US"clamd") == 0) { uschar *clamd_options; uschar clamd_options_buffer[1024]; uschar clamd_options_default[] = "/tmp/clamd"; - uschar *p,*vname; + uschar *p,*vname,*clamd_fbuf; struct sockaddr_un server; - int sock,port,bread=0; + int sock,port,clamd_fd,bread; + unsigned int fsize; uschar file_name[1024]; uschar av_buffer[1024]; uschar hostname[256]; @@ -996,6 +997,103 @@ inet_ntoa(in), port, strerror(errno)); return DEFER; } + + /* send "STREAM" command */ + sprintf(CS file_name,"STREAM\n"); + 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 "PORT tcp_port_number" */ + memset(av_buffer, 0, sizeof(av_buffer)); + bread = read(sock, av_buffer, sizeof(av_buffer)); + if (!(bread > 0)) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to read from socket (%s)", + strerror(errno)); + return DEFER; + } + if (!(*av_buffer)) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: ClamAV returned null"); + return DEFER; + } + sscanf(av_buffer, "PORT %d", &port); + + snprintf(CS file_name, 1024, "%s/scan/%s/%s.eml", + spool_directory, message_id, message_id); + clamd_fd = open(CS file_name, O_RDONLY); + if (clamd_fd == -1) { + close(sock); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't open spool file %s: %s", + file_name, strerror(errno)); + return DEFER; + } + fsize = lseek(clamd_fd, 0, SEEK_END); + if (fsize == -1) { + close(sock); + close(clamd_fd); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't seek spool file %s: %s", + file_name, strerror(errno)); + return DEFER; + } + lseek(clamd_fd, 0, SEEK_SET); + clamd_fbuf = (uschar *) malloc(fsize); + if (!clamd_fbuf) { + close(sock); + close(clamd_fd); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to allocate memory %u for file (%s)", + fsize, file_name); + return DEFER; + } + bread = read(clamd_fd, clamd_fbuf, fsize); + if (bread == -1) { + close(sock); + close(clamd_fd); + free(clamd_fbuf); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: can't read spool file %s: %s", + file_name, strerror(errno)); + return DEFER; + } + close(clamd_fd); + + if ((clamd_fd = ip_socket(SOCK_STREAM, AF_INET)) < 0) { + close(sock); + free(clamd_fbuf); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to acquire socket (%s)", + strerror(errno)); + return DEFER; + } + if (ip_connect(clamd_fd, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) { + close(sock); + close(clamd_fd); + free(clamd_fbuf); + 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; + } + /* send file to clamd */ + if (send(clamd_fd, clamd_fbuf, fsize, 0) < 0) { + close(sock); + close(clamd_fd); + free(clamd_fbuf); + log_write(0, LOG_MAIN|LOG_PANIC, + "malware acl condition: clamd: unable to send file body to socket (%s)", + strerror(errno)); + return DEFER; + } + close(clamd_fd); + free(clamd_fbuf); } else { /* open the local socket */