- if (!use_scan_command) {
-
-#ifdef WITH_OLD_CLAMAV_STREAM
- /* "STREAM\n" command, get back a "PORT <N>\n" response, send data to
- * that port on a second connection; then in the scan-method-neutral
- * part, read the response back on the original connection. */
-
- DEBUG(D_acl) debug_printf("Malware scan: issuing %s old-style remote scan (PORT)\n",
- scanner_name);
-
- /* Pass the string to ClamAV (7 = "STREAM\n") */
- if (send(sock, "STREAM\n", 7, 0) < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)",
- strerror(errno));
- (void)close(sock);
- return DEFER;
- }
- memset(av_buffer2, 0, sizeof(av_buffer2));
- bread = ip_recv(sock, av_buffer2, sizeof(av_buffer2), MALWARE_TIMEOUT);
-
- if (bread < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to read PORT from socket (%s)",
- strerror(errno));
- (void)close(sock);
- return DEFER;
- }
-
- if (bread == sizeof(av_buffer)) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: buffer too small");
- (void)close(sock);
- return DEFER;
- }
-
- if (!(*av_buffer2)) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: ClamAV returned null");
- (void)close(sock);
- return DEFER;
- }
-
- av_buffer2[bread] = '\0';
- if( sscanf(CS av_buffer2, "PORT %u\n", &port) != 1 ) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: Expected port information from clamd, got '%s'", av_buffer2);
- (void)close(sock);
- 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));
- (void)close(sock);
- return DEFER;
- }
-
- if (ip_connect(sockData, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: connection to %s, port %u failed (%s)",
- inet_ntoa(in), port, strerror(errno));
- (void)close(sockData); (void)close(sock);
- return DEFER;
- }
-
-#define CLOSE_SOCKDATA (void)close(sockData)
-#else /* WITH_OLD_CLAMAV_STREAM not defined */
- /* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
- chunks, <n> a 4-byte number (network order), terminated by a zero-length
- chunk. */
-
- DEBUG(D_acl) debug_printf("Malware scan: issuing %s new-style remote scan (zINSTREAM)\n",
- scanner_name);
-
- /* Pass the string to ClamAV (10 = "zINSTREAM\0") */
- if (send(sock, "zINSTREAM", 10, 0) < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to send zINSTREAM to socket (%s)",
- strerror(errno));
- (void)close(sock);
- return DEFER;
- }
-
-#define CLOSE_SOCKDATA /**/
-#endif
-
- /* calc file size */
- clam_fd = open(CS eml_filename, O_RDONLY);
- if (clam_fd == -1) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: can't open spool file %s: %s",
- eml_filename, strerror(errno));
- CLOSE_SOCKDATA; (void)close(sock);
- 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",
- eml_filename, strerror(errno));
- CLOSE_SOCKDATA; (void)close(sock);
- return DEFER;
- }
- lseek(clam_fd, 0, SEEK_SET);
-
- clamav_fbuf = (uschar *) malloc (fsize);
- if (!clamav_fbuf) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to allocate memory %u for file (%s)",
- fsize, eml_filename);
- CLOSE_SOCKDATA; (void)close(sock); (void)close(clam_fd);
- return DEFER;
- }
-
- result = read (clam_fd, clamav_fbuf, fsize);
- if (result == -1) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: can't read spool file %s: %s",
- eml_filename, strerror(errno));
- CLOSE_SOCKDATA; (void)close(sock); (void)close(clam_fd);
- free(clamav_fbuf);
- return DEFER;
- }
- (void)close(clam_fd);
-
- /* send file body to socket */
-#ifdef WITH_OLD_CLAMAV_STREAM
- if (send(sockData, clamav_fbuf, fsize, 0) < 0) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to send file body to socket (%s:%u)", hostname, port);
- CLOSE_SOCKDATA; (void)close(sock);
- free(clamav_fbuf);
- return DEFER;
- }
-#else
- send_size = htonl(fsize);
- send_final_zeroblock = 0;
- if ((send(sock, &send_size, sizeof(send_size), 0) < 0) ||
- (send(sock, clamav_fbuf, fsize, 0) < 0) ||
- (send(sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
- {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: unable to send file body to socket (%s:%u)", hostname, port);
- (void)close(sock);
- free(clamav_fbuf);
- return DEFER;
- }
-#endif
-
- free(clamav_fbuf);
-
- CLOSE_SOCKDATA;
-#undef CLOSE_SOCKDATA
-
- } else { /* use scan command */
- /* Send a SCAN command pointing to a filename; then in the then in the
- * scan-method-neutral part, read the response back */
+ if (!use_scan_command)
+ {
+ /* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
+ chunks, <n> a 4-byte number (network order), terminated by a zero-length
+ chunk. */
+
+ DEBUG(D_acl) debug_printf_indent(
+ "Malware scan: issuing %s new-style remote scan (zINSTREAM)\n",
+ scanner_name);
+
+ /* Pass the string to ClamAV (10 = "zINSTREAM\0"), if not already sent */
+ if (cmd_str.len)
+ if (send(malware_daemon_ctx.sock, cmd_str.data, cmd_str.len, 0) < 0)
+ return m_panic_defer_3(scanent, CUS hostname,
+ string_sprintf("unable to send zINSTREAM to socket (%s)",
+ strerror(errno)),
+ malware_daemon_ctx.sock);
+
+ /* calc file size */
+ if ((clam_fd = exim_open2(CS eml_filename, O_RDONLY)) < 0)
+ {
+ int err = errno;
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("can't open spool file %s: %s",
+ eml_filename, strerror(err)),
+ malware_daemon_ctx.sock);
+ }
+ if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0)
+ {
+ int err;
+b_seek: err = errno;
+ (void)close(clam_fd);
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("can't seek spool file %s: %s",
+ eml_filename, strerror(err)),
+ malware_daemon_ctx.sock);
+ }
+ fsize_uint = (unsigned int) fsize;
+ if ((off_t)fsize_uint != fsize)
+ {
+ (void)close(clam_fd);
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("seeking spool file %s, size overflow",
+ eml_filename),
+ malware_daemon_ctx.sock);
+ }
+ if (lseek(clam_fd, 0, SEEK_SET) < 0)
+ goto b_seek;
+
+ if (!(clamav_fbuf = store_malloc(fsize_uint)))
+ {
+ (void)close(clam_fd);
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("unable to allocate memory %u for file (%s)",
+ fsize_uint, eml_filename),
+ malware_daemon_ctx.sock);
+ }
+
+ if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
+ {
+ int err = errno;
+ store_free(clamav_fbuf); (void)close(clam_fd);
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("can't read spool file %s: %s",
+ eml_filename, strerror(err)),
+ malware_daemon_ctx.sock);
+ }
+ (void)close(clam_fd);
+
+ /* send file body to socket */
+ send_size = htonl(fsize_uint);
+ send_final_zeroblock = 0;
+ if ((send(malware_daemon_ctx.sock, &send_size, sizeof(send_size), 0) < 0) ||
+ (send(malware_daemon_ctx.sock, clamav_fbuf, fsize_uint, 0) < 0) ||
+ (send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
+ {
+ store_free(clamav_fbuf);
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("unable to send file body to socket (%s)", hostname),
+ malware_daemon_ctx.sock);
+ }
+ store_free(clamav_fbuf);
+ }
+ else
+ { /* use scan command */
+ /* Send a SCAN command pointing to a filename; then in the then in the
+ * scan-method-neutral part, read the response back */