git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@447 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/03/28 06:46:03... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Sat Mar 27 21:55:33 GMT 2004 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * clamav-milter: Delay connection to clamd to handle clamd's timeout |
|
4 |
+ when the remote end (the end talking to sendmail) is slow |
|
5 |
+ |
|
1 | 6 |
Sat Mar 27 19:55:52 CET 2004 (tk) |
2 | 7 |
--------------------------------- |
3 | 8 |
* freshclam: remove timeout code; clean up return codes |
... | ... |
@@ -293,6 +293,13 @@ Changes |
293 | 293 |
0.70b 26/3/04 Display errno information on write failure to clamd |
294 | 294 |
Ensure errno is passed to strerror |
295 | 295 |
Print fd in clamfi_send debug |
296 |
+0.70c 27/3/04 Timestamp clamfi_send messages |
|
297 |
+ Call cli_warnmsg if ERROR received |
|
298 |
+ Minor code tidy |
|
299 |
+ Delay connection to clamd to handle clamd's appetite for timing |
|
300 |
+ out when the remote end (the end talking to |
|
301 |
+ sendmail) is slow |
|
302 |
+ Prefer cli_dbgmsg/cli_warnmsg over printf |
|
296 | 303 |
|
297 | 304 |
BUG REPORTS |
298 | 305 |
|
... | ... |
@@ -292,9 +292,19 @@ |
292 | 292 |
* 0.70b 26/3/04 Display errno information on write failure to clamd |
293 | 293 |
* Ensure errno is passed to strerror |
294 | 294 |
* Print fd in clamfi_send debug |
295 |
+ * 0.70c 27/3/04 Timestamp clamfi_send messages |
|
296 |
+ * Call cli_warnmsg if ERROR received |
|
297 |
+ * Minor code tidy |
|
298 |
+ * Delay connection to clamd to handle clamd's appetite |
|
299 |
+ * for timing out when the remote end (the end talking to |
|
300 |
+ * sendmail) is slow |
|
301 |
+ * Prefer cli_dbgmsg/cli_warnmsg over printf |
|
295 | 302 |
* |
296 | 303 |
* Change History: |
297 | 304 |
* $Log: clamav-milter.c,v $ |
305 |
+ * Revision 1.65 2004/03/27 21:44:21 nigelhorne |
|
306 |
+ * Attempt to handle clamd quick timeout for slow remote sites |
|
307 |
+ * |
|
298 | 308 |
* Revision 1.64 2004/03/26 11:10:27 nigelhorne |
299 | 309 |
* Added debug information |
300 | 310 |
* |
... | ... |
@@ -472,9 +482,9 @@ |
472 | 472 |
* Revision 1.6 2003/09/28 16:37:23 nigelhorne |
473 | 473 |
* Added -f flag use MaxThreads if --max-children not set |
474 | 474 |
*/ |
475 |
-static char const rcsid[] = "$Id: clamav-milter.c,v 1.64 2004/03/26 11:10:27 nigelhorne Exp $"; |
|
475 |
+static char const rcsid[] = "$Id: clamav-milter.c,v 1.65 2004/03/27 21:44:21 nigelhorne Exp $"; |
|
476 | 476 |
|
477 |
-#define CM_VERSION "0.70b" |
|
477 |
+#define CM_VERSION "0.70c" |
|
478 | 478 |
|
479 | 479 |
/*#define CONFDIR "/usr/local/etc"*/ |
480 | 480 |
|
... | ... |
@@ -608,6 +618,7 @@ static header_list_t header_list_new(void); |
608 | 608 |
static void header_list_free(header_list_t list); |
609 | 609 |
static void header_list_add(header_list_t list, const char *headerf, const char *headerv); |
610 | 610 |
static void header_list_print(header_list_t list, FILE *fp); |
611 |
+static int connect2clamd(struct privdata *privdata); |
|
611 | 612 |
static void checkClamd(void); |
612 | 613 |
|
613 | 614 |
static char clamav_version[128]; |
... | ... |
@@ -1254,6 +1265,7 @@ pingServer(int serverNumber) |
1254 | 1254 |
checkClamd(); |
1255 | 1255 |
if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) { |
1256 | 1256 |
perror(localSocket); |
1257 |
+ close(sock); |
|
1257 | 1258 |
return 0; |
1258 | 1259 |
} |
1259 | 1260 |
} else { |
... | ... |
@@ -1380,6 +1392,7 @@ findServer(void) |
1380 | 1380 |
if(use_syslog) |
1381 | 1381 |
syslog(LOG_WARNING, "findServer: Check server %d - it may be down", i); |
1382 | 1382 |
socks[i] = -1; |
1383 |
+ close(sock); |
|
1383 | 1384 |
continue; |
1384 | 1385 |
} |
1385 | 1386 |
|
... | ... |
@@ -1430,9 +1443,12 @@ findServer(void) |
1430 | 1430 |
return 0; |
1431 | 1431 |
} |
1432 | 1432 |
|
1433 |
+/* |
|
1434 |
+ * Sendmail wants to establish a connection to us |
|
1435 |
+ */ |
|
1433 | 1436 |
static sfsistat |
1434 | 1437 |
clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) |
1435 |
- |
|
1438 |
+{ |
|
1436 | 1439 |
char ip[INET_ADDRSTRLEN]; /* IPv4 only */ |
1437 | 1440 |
char *remoteIP; |
1438 | 1441 |
|
... | ... |
@@ -1563,20 +1579,14 @@ static sfsistat |
1563 | 1563 |
clamfi_envfrom(SMFICTX *ctx, char **argv) |
1564 | 1564 |
{ |
1565 | 1565 |
struct privdata *privdata; |
1566 |
- struct sockaddr_in reply; |
|
1567 |
- unsigned short port; |
|
1568 |
- int nbytes, rc, freeServer; |
|
1569 |
- char buf[64]; |
|
1570 | 1566 |
|
1571 | 1567 |
if(logVerbose) |
1572 | 1568 |
syslog(LOG_DEBUG, "clamfi_envfrom: %s", argv[0]); |
1573 | 1569 |
|
1574 |
-#ifdef CL_DEBUG |
|
1575 |
- printf("clamfi_envfrom: %s\n", argv[0]); |
|
1576 |
-#endif |
|
1570 |
+ cli_dbgmsg("clamfi_envfrom: %s\n", argv[0]); |
|
1577 | 1571 |
|
1578 | 1572 |
if(max_children > 0) { |
1579 |
- rc = 0; |
|
1573 |
+ int rc = 0; |
|
1580 | 1574 |
|
1581 | 1575 |
pthread_mutex_lock(&n_children_mutex); |
1582 | 1576 |
|
... | ... |
@@ -1614,9 +1624,7 @@ clamfi_envfrom(SMFICTX *ctx, char **argv) |
1614 | 1614 |
} |
1615 | 1615 |
n_children++; |
1616 | 1616 |
|
1617 |
-#ifdef CL_DEBUG |
|
1618 |
- printf(">n_children = %d\n", n_children); |
|
1619 |
-#endif |
|
1617 |
+ cli_dbgmsg(">n_children = %d\n", n_children); |
|
1620 | 1618 |
pthread_mutex_unlock(&n_children_mutex); |
1621 | 1619 |
|
1622 | 1620 |
if(rc == ETIMEDOUT) { |
... | ... |
@@ -1632,172 +1640,6 @@ clamfi_envfrom(SMFICTX *ctx, char **argv) |
1632 | 1632 |
privdata->dataSocket = -1; /* 0.4 */ |
1633 | 1633 |
privdata->cmdSocket = -1; /* 0.4 */ |
1634 | 1634 |
|
1635 |
- if(quarantine_dir) { |
|
1636 |
- /* |
|
1637 |
- * quarantine_dir is specified |
|
1638 |
- * store message in a temporary file |
|
1639 |
- */ |
|
1640 |
- int ntries = 5; |
|
1641 |
- |
|
1642 |
- privdata->filename = (char *)cli_malloc(strlen(quarantine_dir) + 12); |
|
1643 |
- |
|
1644 |
- do { |
|
1645 |
- sprintf(privdata->filename, "%s/msg.XXXXXX", quarantine_dir); |
|
1646 |
-#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) |
|
1647 |
- privdata->dataSocket = mkstemp(privdata->filename); |
|
1648 |
-#else |
|
1649 |
- if(mktemp(privdata->filename) == NULL) { |
|
1650 |
- if(use_syslog) |
|
1651 |
- syslog(LOG_ERR, "mktemp %s failed", privdata->filename); |
|
1652 |
- clamfi_free(privdata); |
|
1653 |
- return cl_error; |
|
1654 |
- } |
|
1655 |
- privdata->dataSocket = open(privdata->filename, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0600); |
|
1656 |
-#endif |
|
1657 |
- } while((--ntries > 0) && (privdata->dataSocket < 0)); |
|
1658 |
- |
|
1659 |
- if(privdata->dataSocket < 0) { |
|
1660 |
- if(use_syslog) |
|
1661 |
- syslog(LOG_ERR, "tempfile %s creation failed", privdata->filename); |
|
1662 |
- clamfi_free(privdata); |
|
1663 |
- return cl_error; |
|
1664 |
- } |
|
1665 |
- } else { |
|
1666 |
- /* |
|
1667 |
- * Create socket to talk to clamd. It will tell us the port to use |
|
1668 |
- * to send the data. That will require another socket. |
|
1669 |
- */ |
|
1670 |
- if(localSocket) { |
|
1671 |
- struct sockaddr_un server; |
|
1672 |
- |
|
1673 |
- memset((char *)&server, 0, sizeof(struct sockaddr_un)); |
|
1674 |
- server.sun_family = AF_UNIX; |
|
1675 |
- strncpy(server.sun_path, localSocket, sizeof(server.sun_path)); |
|
1676 |
- |
|
1677 |
- if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { |
|
1678 |
- perror("socket"); |
|
1679 |
- clamfi_free(privdata); |
|
1680 |
- return cl_error; |
|
1681 |
- } |
|
1682 |
- if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) { |
|
1683 |
- perror(localSocket); |
|
1684 |
- clamfi_free(privdata); |
|
1685 |
- return cl_error; |
|
1686 |
- } |
|
1687 |
- freeServer = 0; |
|
1688 |
- } else { |
|
1689 |
- struct sockaddr_in server; |
|
1690 |
- |
|
1691 |
- memset((char *)&server, 0, sizeof(struct sockaddr_in)); |
|
1692 |
- server.sin_family = AF_INET; |
|
1693 |
- server.sin_port = (in_port_t)htons(tcpSocket); |
|
1694 |
- |
|
1695 |
- assert(serverIPs != NULL); |
|
1696 |
- |
|
1697 |
- freeServer = findServer(); |
|
1698 |
- if(freeServer < 0) { |
|
1699 |
- clamfi_free(privdata); |
|
1700 |
- return cl_error; |
|
1701 |
- } |
|
1702 |
- |
|
1703 |
- server.sin_addr.s_addr = serverIPs[freeServer]; |
|
1704 |
- |
|
1705 |
- if((privdata->cmdSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
1706 |
- perror("socket"); |
|
1707 |
- clamfi_free(privdata); |
|
1708 |
- return cl_error; |
|
1709 |
- } |
|
1710 |
- if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) { |
|
1711 |
- perror("connect"); |
|
1712 |
- clamfi_free(privdata); |
|
1713 |
- return cl_error; |
|
1714 |
- } |
|
1715 |
- } |
|
1716 |
- |
|
1717 |
- /* |
|
1718 |
- * Create socket that we'll use to send the data to clamd |
|
1719 |
- */ |
|
1720 |
- if((privdata->dataSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
1721 |
- perror("socket"); |
|
1722 |
- clamfi_free(privdata); |
|
1723 |
- if(use_syslog) |
|
1724 |
- syslog(LOG_ERR, "failed to create socket"); |
|
1725 |
- return cl_error; |
|
1726 |
- } |
|
1727 |
- |
|
1728 |
- shutdown(privdata->dataSocket, SHUT_RD); |
|
1729 |
- |
|
1730 |
- if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) { |
|
1731 |
- perror("send"); |
|
1732 |
- clamfi_free(privdata); |
|
1733 |
- if(use_syslog) |
|
1734 |
- syslog(LOG_ERR, "send failed to clamd"); |
|
1735 |
- return cl_error; |
|
1736 |
- } |
|
1737 |
- |
|
1738 |
- shutdown(privdata->cmdSocket, SHUT_WR); |
|
1739 |
- |
|
1740 |
- nbytes = clamd_recv(privdata->cmdSocket, buf, sizeof(buf)); |
|
1741 |
- if(nbytes < 0) { |
|
1742 |
- perror("recv"); |
|
1743 |
- clamfi_free(privdata); |
|
1744 |
- if(use_syslog) |
|
1745 |
- syslog(LOG_ERR, "recv failed from clamd getting PORT"); |
|
1746 |
- return cl_error; |
|
1747 |
- } |
|
1748 |
- buf[nbytes] = '\0'; |
|
1749 |
-#ifdef CL_DEBUG |
|
1750 |
- if(debug_level >= 4) |
|
1751 |
- printf("Received: %s", buf); |
|
1752 |
-#endif |
|
1753 |
- if(sscanf(buf, "PORT %hu\n", &port) != 1) { |
|
1754 |
- clamfi_free(privdata); |
|
1755 |
- if(use_syslog) |
|
1756 |
- syslog(LOG_ERR, "Expected port information from clamd, got '%s'", |
|
1757 |
- buf); |
|
1758 |
- else |
|
1759 |
- fprintf(stderr, "Expected port information from clamd, got '%s'\n", |
|
1760 |
- buf); |
|
1761 |
- return cl_error; |
|
1762 |
- } |
|
1763 |
- |
|
1764 |
- memset((char *)&reply, 0, sizeof(struct sockaddr_in)); |
|
1765 |
- reply.sin_family = AF_INET; |
|
1766 |
- reply.sin_port = (in_port_t)htons(port); |
|
1767 |
- |
|
1768 |
- assert(serverIPs != NULL); |
|
1769 |
- |
|
1770 |
- reply.sin_addr.s_addr = serverIPs[freeServer]; |
|
1771 |
- |
|
1772 |
-#ifdef CL_DEBUG |
|
1773 |
- if(debug_level >= 4) |
|
1774 |
- printf("Connecting to local port %d\n", port); |
|
1775 |
-#endif |
|
1776 |
- |
|
1777 |
- rc = connect(privdata->dataSocket, (struct sockaddr *)&reply, sizeof(struct sockaddr_in)); |
|
1778 |
- |
|
1779 |
- if(rc < 0) { |
|
1780 |
- perror("connect"); |
|
1781 |
- |
|
1782 |
- /* 0.4 - use better error message */ |
|
1783 |
- if(use_syslog) { |
|
1784 |
-#ifdef HAVE_STRERROR_R |
|
1785 |
- strerror_r(errno, buf, sizeof(buf)); |
|
1786 |
- syslog(LOG_ERR, |
|
1787 |
- "Failed to connect to port %d given by clamd: %s", |
|
1788 |
- port, buf); |
|
1789 |
-#else |
|
1790 |
- syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, strerror(errno)); |
|
1791 |
-#endif |
|
1792 |
- } |
|
1793 |
- clamfi_free(privdata); |
|
1794 |
- |
|
1795 |
- return cl_error; |
|
1796 |
- } |
|
1797 |
- } |
|
1798 |
- |
|
1799 |
- clamfi_send(privdata, 0, "Received: by clamav-milter\nFrom: %s\n", argv[0]); |
|
1800 |
- |
|
1801 | 1635 |
privdata->from = strdup(argv[0]); |
1802 | 1636 |
privdata->to = NULL; |
1803 | 1637 |
|
... | ... |
@@ -1819,11 +1661,7 @@ clamfi_envrcpt(SMFICTX *ctx, char **argv) |
1819 | 1819 |
if(logVerbose) |
1820 | 1820 |
syslog(LOG_DEBUG, "clamfi_envrcpt: %s", argv[0]); |
1821 | 1821 |
|
1822 |
-#ifdef CL_DEBUG |
|
1823 |
- printf("clamfi_envrcpt: %s\n", argv[0]); |
|
1824 |
-#endif |
|
1825 |
- |
|
1826 |
- clamfi_send(privdata, 0, "To: %s\n", argv[0]); |
|
1822 |
+ cli_dbgmsg("clamfi_envrcpt: %s\n", argv[0]); |
|
1827 | 1823 |
|
1828 | 1824 |
if(privdata->to == NULL) { |
1829 | 1825 |
privdata->to = cli_malloc(sizeof(char *) * 2); |
... | ... |
@@ -1847,11 +1685,20 @@ clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) |
1847 | 1847 |
syslog(LOG_DEBUG, "clamfi_header: %s: %s", headerf, headerv); |
1848 | 1848 |
#ifdef CL_DEBUG |
1849 | 1849 |
if(debug_level >= 9) |
1850 |
- printf("clamfi_header: %s: %s\n", headerf, headerv); |
|
1850 |
+ cli_dbgmsg("clamfi_header: %s: %s\n", headerf, headerv); |
|
1851 | 1851 |
else |
1852 | 1852 |
cli_dbgmsg("clamfi_header\n"); |
1853 | 1853 |
#endif |
1854 | 1854 |
|
1855 |
+ if(privdata->dataSocket == -1) |
|
1856 |
+ /* |
|
1857 |
+ * First header - make connection with clamd |
|
1858 |
+ */ |
|
1859 |
+ if(!connect2clamd(privdata)) { |
|
1860 |
+ clamfi_cleanup(ctx); |
|
1861 |
+ return cl_error; |
|
1862 |
+ } |
|
1863 |
+ |
|
1855 | 1864 |
if(clamfi_send(privdata, 0, "%s: %s\n", headerf, headerv) < 0) { |
1856 | 1865 |
clamfi_cleanup(ctx); |
1857 | 1866 |
return cl_error; |
... | ... |
@@ -1872,9 +1719,19 @@ clamfi_eoh(SMFICTX *ctx) |
1872 | 1872 |
if(logVerbose) |
1873 | 1873 |
syslog(LOG_DEBUG, "clamfi_eoh"); |
1874 | 1874 |
#ifdef CL_DEBUG |
1875 |
- cli_dbgmsg("clamfi_eoh\n"); |
|
1875 |
+ if(debug_level >= 4) |
|
1876 |
+ cli_dbgmsg("clamfi_eoh\n"); |
|
1876 | 1877 |
#endif |
1877 | 1878 |
|
1879 |
+ if(privdata->dataSocket == -1) |
|
1880 |
+ /* |
|
1881 |
+ * No headers - make connection with clamd |
|
1882 |
+ */ |
|
1883 |
+ if(!connect2clamd(privdata)) { |
|
1884 |
+ clamfi_cleanup(ctx); |
|
1885 |
+ return cl_error; |
|
1886 |
+ } |
|
1887 |
+ |
|
1878 | 1888 |
if(clamfi_send(privdata, 1, "\n") < 0) { |
1879 | 1889 |
clamfi_cleanup(ctx); |
1880 | 1890 |
return cl_error; |
... | ... |
@@ -1932,7 +1789,7 @@ clamfi_body(SMFICTX *ctx, u_char *bodyp, size_t len) |
1932 | 1932 |
if(logVerbose) |
1933 | 1933 |
syslog(LOG_DEBUG, "clamfi_envbody: %u bytes", len); |
1934 | 1934 |
#ifdef CL_DEBUG |
1935 |
- printf("clamfi_envbody: %u bytes\n", len); |
|
1935 |
+ cli_dbgmsg("clamfi_envbody: %u bytes\n", len); |
|
1936 | 1936 |
#endif |
1937 | 1937 |
|
1938 | 1938 |
if(clamfi_send(privdata, len, (char *)bodyp) < 0) { |
... | ... |
@@ -2022,9 +1879,7 @@ clamfi_eom(SMFICTX *ctx) |
2022 | 2022 |
|
2023 | 2023 |
if(logVerbose) |
2024 | 2024 |
syslog(LOG_DEBUG, "clamfi_eom: read %s", mess); |
2025 |
-#ifdef CL_DEBUG |
|
2026 |
- printf("clamfi_eom: read %s\n", mess); |
|
2027 |
-#endif |
|
2025 |
+ cli_dbgmsg("clamfi_eom: read %s\n", mess); |
|
2028 | 2026 |
} else { |
2029 | 2027 |
clamfi_cleanup(ctx); |
2030 | 2028 |
syslog(LOG_NOTICE, "clamfi_eom: read nothing from clamd"); |
... | ... |
@@ -2038,8 +1893,12 @@ clamfi_eom(SMFICTX *ctx) |
2038 | 2038 |
privdata->cmdSocket = -1; |
2039 | 2039 |
|
2040 | 2040 |
if(strstr(mess, "ERROR") != NULL) { |
2041 |
+ |
|
2042 |
+ ptr = smfi_getsymval(ctx, "i"); |
|
2043 |
+ |
|
2044 |
+ cli_warnmsg("%s: %s\n", ptr, mess); |
|
2041 | 2045 |
if(use_syslog) |
2042 |
- syslog(LOG_ERR, "%s: %s\n", smfi_getsymval(ctx, "i"), mess); |
|
2046 |
+ syslog(LOG_ERR, "%s: %s\n", ptr, mess); |
|
2043 | 2047 |
clamfi_cleanup(ctx); |
2044 | 2048 |
return cl_error; |
2045 | 2049 |
} |
... | ... |
@@ -2217,7 +2076,7 @@ clamfi_eom(SMFICTX *ctx) |
2217 | 2217 |
if(use_syslog) |
2218 | 2218 |
syslog(LOG_DEBUG, "Can't set quarantine user %s", quarantine); |
2219 | 2219 |
else |
2220 |
- fprintf(stderr, "Can't set quarantine user %s\n", quarantine); |
|
2220 |
+ cli_warnmsg("Can't set quarantine user %s\n", quarantine); |
|
2221 | 2221 |
} else |
2222 | 2222 |
/* |
2223 | 2223 |
* FIXME: doesn't work if there's no subject |
... | ... |
@@ -2268,7 +2127,7 @@ clamfi_close(SMFICTX *ctx) |
2268 | 2268 |
if(use_syslog) |
2269 | 2269 |
syslog(LOG_DEBUG, "clamfi_close, privdata != NULL"); |
2270 | 2270 |
else |
2271 |
- puts("clamfi_close, privdata != NULL"); |
|
2271 |
+ cli_warnmsg("clamfi_close, privdata != NULL"); |
|
2272 | 2272 |
} |
2273 | 2273 |
#endif |
2274 | 2274 |
|
... | ... |
@@ -2374,6 +2233,9 @@ clamfi_free(struct privdata *privdata) |
2374 | 2374 |
} |
2375 | 2375 |
} |
2376 | 2376 |
|
2377 |
+/* |
|
2378 |
+ * Returns < 0 for failure |
|
2379 |
+ */ |
|
2377 | 2380 |
static int |
2378 | 2381 |
clamfi_send(const struct privdata *privdata, size_t len, const char *format, ...) |
2379 | 2382 |
{ |
... | ... |
@@ -2399,9 +2261,17 @@ clamfi_send(const struct privdata *privdata, size_t len, const char *format, ... |
2399 | 2399 |
ptr = output; |
2400 | 2400 |
} |
2401 | 2401 |
#ifdef CL_DEBUG |
2402 |
- if(debug_level >= 9) |
|
2403 |
- printf("clamfi_send: len=%u bufsiz=%u, fd=%d\n", |
|
2404 |
- len, sizeof(output), privdata->dataSocket); |
|
2402 |
+ if(debug_level >= 9) { |
|
2403 |
+ time_t t; |
|
2404 |
+ const struct tm *tm; |
|
2405 |
+ |
|
2406 |
+ time(&t); |
|
2407 |
+ tm = localtime(&t); |
|
2408 |
+ |
|
2409 |
+ cli_dbgmsg("%d:%d:%d clamfi_send: len=%u bufsiz=%u, fd=%d\n", |
|
2410 |
+ tm->tm_hour, tm->tm_min, tm->tm_sec, len, |
|
2411 |
+ sizeof(output), privdata->dataSocket); |
|
2412 |
+ } |
|
2405 | 2413 |
#endif |
2406 | 2414 |
|
2407 | 2415 |
while(len > 0) { |
... | ... |
@@ -2579,6 +2449,199 @@ header_list_print(header_list_t list, FILE *fp) |
2579 | 2579 |
for(iter = list->first; iter; iter = iter->next) |
2580 | 2580 |
fprintf(fp, "%s\n", iter->header); |
2581 | 2581 |
} |
2582 |
+ |
|
2583 |
+/* |
|
2584 |
+ * Establish a connection to clamd |
|
2585 |
+ * Returns success (1) or failure (0) |
|
2586 |
+ */ |
|
2587 |
+static int |
|
2588 |
+connect2clamd(struct privdata *privdata) |
|
2589 |
+{ |
|
2590 |
+ char **to; |
|
2591 |
+ |
|
2592 |
+ assert(privdata->dataSocket == -1); |
|
2593 |
+ assert(privdata->from != NULL); |
|
2594 |
+ assert(privdata->to != NULL); |
|
2595 |
+ |
|
2596 |
+#ifdef CL_DEBUG |
|
2597 |
+ if((debug_level > 0) && use_syslog) |
|
2598 |
+ syslog(LOG_DEBUG, "connect2clamd"); |
|
2599 |
+ if(debug_level >= 4) |
|
2600 |
+ cli_dbgmsg("connect2clamd\n"); |
|
2601 |
+#endif |
|
2602 |
+ |
|
2603 |
+ if(quarantine_dir) { |
|
2604 |
+ /* |
|
2605 |
+ * quarantine_dir is specified |
|
2606 |
+ * store message in a temporary file |
|
2607 |
+ */ |
|
2608 |
+ int ntries = 5; |
|
2609 |
+ |
|
2610 |
+ privdata->filename = (char *)cli_malloc(strlen(quarantine_dir) + 12); |
|
2611 |
+ |
|
2612 |
+ do { |
|
2613 |
+ sprintf(privdata->filename, "%s/msg.XXXXXX", quarantine_dir); |
|
2614 |
+#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) |
|
2615 |
+ privdata->dataSocket = mkstemp(privdata->filename); |
|
2616 |
+#else |
|
2617 |
+ if(mktemp(privdata->filename) == NULL) { |
|
2618 |
+ if(use_syslog) |
|
2619 |
+ syslog(LOG_ERR, "mktemp %s failed", privdata->filename); |
|
2620 |
+ return 0; |
|
2621 |
+ } |
|
2622 |
+ privdata->dataSocket = open(privdata->filename, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0600); |
|
2623 |
+#endif |
|
2624 |
+ } while((--ntries > 0) && (privdata->dataSocket < 0)); |
|
2625 |
+ |
|
2626 |
+ if(privdata->dataSocket < 0) { |
|
2627 |
+ if(use_syslog) |
|
2628 |
+ syslog(LOG_ERR, "tempfile %s creation failed", privdata->filename); |
|
2629 |
+ return 0; |
|
2630 |
+ } |
|
2631 |
+ } else { |
|
2632 |
+ int freeServer, nbytes; |
|
2633 |
+ struct sockaddr_in reply; |
|
2634 |
+ unsigned short port; |
|
2635 |
+ char buf[64]; |
|
2636 |
+ |
|
2637 |
+ assert(privdata->cmdSocket == -1); |
|
2638 |
+ |
|
2639 |
+ /* |
|
2640 |
+ * Create socket to talk to clamd. It will tell us the port to |
|
2641 |
+ * use to send the data. That will require another socket. |
|
2642 |
+ */ |
|
2643 |
+ if(localSocket) { |
|
2644 |
+ struct sockaddr_un server; |
|
2645 |
+ |
|
2646 |
+ memset((char *)&server, 0, sizeof(struct sockaddr_un)); |
|
2647 |
+ server.sun_family = AF_UNIX; |
|
2648 |
+ strncpy(server.sun_path, localSocket, sizeof(server.sun_path)); |
|
2649 |
+ |
|
2650 |
+ if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { |
|
2651 |
+ perror("socket"); |
|
2652 |
+ return 0; |
|
2653 |
+ } |
|
2654 |
+ if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) { |
|
2655 |
+ perror(localSocket); |
|
2656 |
+ return 0; |
|
2657 |
+ } |
|
2658 |
+ freeServer = 0; |
|
2659 |
+ } else { |
|
2660 |
+ struct sockaddr_in server; |
|
2661 |
+ |
|
2662 |
+ memset((char *)&server, 0, sizeof(struct sockaddr_in)); |
|
2663 |
+ server.sin_family = AF_INET; |
|
2664 |
+ server.sin_port = (in_port_t)htons(tcpSocket); |
|
2665 |
+ |
|
2666 |
+ assert(serverIPs != NULL); |
|
2667 |
+ |
|
2668 |
+ freeServer = findServer(); |
|
2669 |
+ if(freeServer < 0) |
|
2670 |
+ return 0; |
|
2671 |
+ |
|
2672 |
+ server.sin_addr.s_addr = serverIPs[freeServer]; |
|
2673 |
+ |
|
2674 |
+ if((privdata->cmdSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
2675 |
+ perror("socket"); |
|
2676 |
+ return 0; |
|
2677 |
+ } |
|
2678 |
+ if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) { |
|
2679 |
+ perror("connect"); |
|
2680 |
+ return 0; |
|
2681 |
+ } |
|
2682 |
+ } |
|
2683 |
+ |
|
2684 |
+ /* |
|
2685 |
+ * Create socket that we'll use to send the data to clamd |
|
2686 |
+ */ |
|
2687 |
+ if((privdata->dataSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
|
2688 |
+ perror("socket"); |
|
2689 |
+ if(use_syslog) |
|
2690 |
+ syslog(LOG_ERR, "failed to create socket"); |
|
2691 |
+ return 0; |
|
2692 |
+ } |
|
2693 |
+ |
|
2694 |
+ shutdown(privdata->dataSocket, SHUT_RD); |
|
2695 |
+ |
|
2696 |
+ if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) { |
|
2697 |
+ perror("send"); |
|
2698 |
+ if(use_syslog) |
|
2699 |
+ syslog(LOG_ERR, "send failed to clamd"); |
|
2700 |
+ return 0; |
|
2701 |
+ } |
|
2702 |
+ |
|
2703 |
+ shutdown(privdata->cmdSocket, SHUT_WR); |
|
2704 |
+ |
|
2705 |
+ nbytes = clamd_recv(privdata->cmdSocket, buf, sizeof(buf)); |
|
2706 |
+ if(nbytes < 0) { |
|
2707 |
+ perror("recv"); |
|
2708 |
+ if(use_syslog) |
|
2709 |
+ syslog(LOG_ERR, "recv failed from clamd getting PORT"); |
|
2710 |
+ return 0; |
|
2711 |
+ } |
|
2712 |
+ buf[nbytes] = '\0'; |
|
2713 |
+#ifdef CL_DEBUG |
|
2714 |
+ if(debug_level >= 4) |
|
2715 |
+ cli_dbgmsg("Received: %s", buf); |
|
2716 |
+#endif |
|
2717 |
+ if(sscanf(buf, "PORT %hu\n", &port) != 1) { |
|
2718 |
+ if(use_syslog) |
|
2719 |
+ syslog(LOG_ERR, "Expected port information from clamd, got '%s'", |
|
2720 |
+ buf); |
|
2721 |
+ else |
|
2722 |
+ cli_warnmsg("Expected port information from clamd, got '%s'\n", |
|
2723 |
+ buf); |
|
2724 |
+ return 0; |
|
2725 |
+ } |
|
2726 |
+ |
|
2727 |
+ memset((char *)&reply, 0, sizeof(struct sockaddr_in)); |
|
2728 |
+ reply.sin_family = AF_INET; |
|
2729 |
+ reply.sin_port = (in_port_t)htons(port); |
|
2730 |
+ |
|
2731 |
+ assert(serverIPs != NULL); |
|
2732 |
+ |
|
2733 |
+ reply.sin_addr.s_addr = serverIPs[freeServer]; |
|
2734 |
+ |
|
2735 |
+#ifdef CL_DEBUG |
|
2736 |
+ if(debug_level >= 4) |
|
2737 |
+ cli_dbgmsg("Connecting to local port %d\n", port); |
|
2738 |
+#endif |
|
2739 |
+ |
|
2740 |
+ if(connect(privdata->dataSocket, (struct sockaddr *)&reply, sizeof(struct sockaddr_in)) < 0) { |
|
2741 |
+ perror("connect"); |
|
2742 |
+ |
|
2743 |
+ /* 0.4 - use better error message */ |
|
2744 |
+ if(use_syslog) { |
|
2745 |
+#ifdef HAVE_STRERROR_R |
|
2746 |
+ strerror_r(errno, buf, sizeof(buf)); |
|
2747 |
+ syslog(LOG_ERR, |
|
2748 |
+ "Failed to connect to port %d given by clamd: %s", |
|
2749 |
+ port, buf); |
|
2750 |
+#else |
|
2751 |
+ syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, strerror(errno)); |
|
2752 |
+#endif |
|
2753 |
+ } |
|
2754 |
+ return 0; |
|
2755 |
+ } |
|
2756 |
+ } |
|
2757 |
+ |
|
2758 |
+ /* |
|
2759 |
+ * TODO: |
|
2760 |
+ * Put from and to data into a buffer and call clamfi_send once |
|
2761 |
+ * to save bandwidth when using TCP/IP to connect with a remote clamd |
|
2762 |
+ */ |
|
2763 |
+ clamfi_send(privdata, 0, |
|
2764 |
+ "Received: by clamav-milter\nFrom: %s\n", |
|
2765 |
+ privdata->from); |
|
2766 |
+ |
|
2767 |
+ for(to = privdata->to; *to; to++) |
|
2768 |
+ if(clamfi_send(privdata, 0, "To: %s\n", *to) < 0) |
|
2769 |
+ return 0; |
|
2770 |
+ |
|
2771 |
+ cli_dbgmsg("connect2clamd OK\n"); |
|
2772 |
+ |
|
2773 |
+ return 1; |
|
2774 |
+} |
|
2582 | 2775 |
|
2583 | 2776 |
/* |
2584 | 2777 |
* If possible, check if clamd has died, and report if it has |