I saw the below patch in cvs. I just want to point out that I dont think will work.

A) len will typically be a "chunk" of size MILTER_CHUNK_SIZE (65535)
B) sendmail libmilter calls the xxfi_body callback once for each chunk of body
C) clamfi_send should only be called if len > 0 and from then on we should just continue, returning SMFIS_CONTINUE
D) however, we do not want to return until after the code which stores the body for the signature addition. The whole body needs to be sent back to sendmail for that to work. So we need to store it all.
E)its logVerbose, not legVerboze
F) we need to check that we only do the syslog statement once per body, not once per body chunk.


Attached is a patch that does the above for me.

I have also attached a patch which demonstrates how clamd can actualy accept up to the StreamMaxLength option and scan it, instead of aborting.

Thanks for your consideration and (hopefully) feedback.

Joe

cvs diff -u -D yesterday clamav-milter/clamav-milter.c
Index: clamav-milter/clamav-milter.c
===================================================================
RCS file: /cvsroot/clamav/clamav-devel/clamav-milter/clamav-milter.c,v
retrieving revision 1.65
diff -u -r1.65 clamav-milter.c
--- clamav-milter/clamav-milter.c       27 Mar 2004 21:44:21 -0000      1.65
+++ clamav-milter/clamav-milter.c       31 Mar 2004 19:59:27 -0000
@@ -1785,12 +1785,24 @@
clamfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
{
       struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
+       size_t maxzise = 0;
+       struct cfgstruct *cpt = NULL;

if(logVerbose)
syslog(LOG_DEBUG, "clamfi_envbody: %u bytes", len);
#ifdef CL_DEBUG
cli_dbgmsg("clamfi_envbody: %u bytes\n", len);
#endif
+ if((cpt = cfgopt(copt, "StreamMaxLength")))
+ {
+ if(cpt->numarg < len)
+ {
+ if(logVerboze)
+ syslog(LOG_INFO, "clamfi_envbody: %u is more than StreamMaxLength option of %u",len, cpt->numarg);
+ len = cpt->numarg;
+ }
+ }
+


       if(clamfi_send(privdata, len, (char *)bodyp) < 0) {
               clamfi_cleanup(ctx);

--- clamav-0.70-rc/clamav-milter/clamav-milter.c        Mon Mar 15 15:03:13 2004
+++ clamav-0.70-rc-jm/clamav-milter/clamav-milter.c     Tue Mar 30 18:29:39 2004
@@ -566,6 +566,7 @@
        char    *filename;      /* Where to store the message in quarantine */
        u_char  *body;          /* body of the message if Sflag is set */
        size_t  bodyLen;        /* number of bytes in body */
+       size_t  nWritten;       /* number of bytes we have written */
        header_list_t headers;  /* Message headers */
 };
 
@@ -1914,17 +1915,14 @@
 clamfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
 {
        struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
+       struct cfgstruct *cpt = NULL;   
+       size_t sendlen = 0;
 
        if(logVerbose)
                syslog(LOG_DEBUG, "clamfi_envbody: %u bytes", len);
 #ifdef CL_DEBUG
        printf("clamfi_envbody: %u bytes\n", len);
 #endif
-
-       if(clamfi_send(privdata, len, (char *)bodyp) < 0) {
-               clamfi_cleanup(ctx);
-               return cl_error;
-       }
        if(Sflag) {
                if(privdata->body) {
                        assert(privdata->bodyLen > 0);
@@ -1938,6 +1936,41 @@
                        privdata->bodyLen = len;
                }
        }
+
+       if((!quarantine_dir) 
+               && (cpt = cfgopt(copt, "StreamMaxLength")) 
+               && cpt->numarg < (len + privdata->nWritten)
+          ){
+               sendlen = (cpt->numarg - privdata->nWritten);
+               if(use_syslog && privdata->nWritten != cpt->numarg){
+                       char buf[1024]; 
+                       strncpy(buf,privdata->from,sizeof(buf));
+                       syslog(LOG_INFO,"Stream from %s size exceeded max of %u , 
already wrote %u, will write %u more instead of len %u",
+                                       buf,
+                                       cpt->numarg,
+                                       privdata->nWritten,
+                                       sendlen,
+                                       len); 
+               }
+       }
+       else {
+               sendlen = len;
+       }
+
+       if(!sendlen)
+               return SMFIS_CONTINUE;
+
+
+       if(sendlen && (clamfi_send(privdata, sendlen, (char *)bodyp) < 0)) {
+               clamfi_cleanup(ctx);
+               return cl_error;
+       }else
+       {
+               if(sendlen)
+                       privdata->nWritten += sendlen;
+       }               
+
+
        return SMFIS_CONTINUE;
 }
 
@@ -2389,6 +2422,7 @@
                printf("clamfi_send: len=%u bufsiz=%u\n", len, sizeof(output));
 #endif
 
+       errno = 0;
        while(len > 0) {
                const int nbytes = (quarantine_dir) ?
                        write(privdata->dataSocket, ptr, len) :
@@ -2400,7 +2434,8 @@
                        perror("send");
                        checkClamd();
                        if(use_syslog)
-                               syslog(LOG_ERR, "write failure to clamd");
+                               syslog(LOG_ERR, "write failure to clamd, nbytes: %d, 
quarantine_dir: %s, error: %s", 
+                                               nbytes, quarantine_dir, 
strerror(errno) );
 
                        return -1;
                }
--- clamav-0.70-rc/clamd/scanner.c      Mon Mar 15 15:03:12 2004
+++ clamav-0.70-rc-jm/clamd/scanner.c   Tue Mar 30 18:28:29 2004
@@ -186,7 +186,7 @@
 
 int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root, 
const struct cl_limits *limits, int options, const struct cfgstruct *copt)
 {
-       int ret, portscan = CL_DEFAULT_MAXPORTSCAN, sockfd, port, acceptd, tmpd, 
bread, retval;
+       int ret, portscan = CL_DEFAULT_MAXPORTSCAN, sockfd, port, acceptd, tmpd, 
bread, btread, retval;
        long int size = 0, maxsize = 0;
        short bound = 0;
        const char *virname;
@@ -260,22 +260,18 @@
        if((cpt = cfgopt(copt, "StreamMaxLength")))
            maxsize = cpt->numarg;
 
+       btread = sizeof(buff);
        while((retval = poll_fd(acceptd, CL_DEFAULT_SCANTIMEOUT)) == 1) {
-           bread = read(acceptd, buff, sizeof(buff));
+           bread = read(acceptd, buff, btread);
            if (bread <= 0) {
                break;
            }
            size += bread;
 
-           if(maxsize && (size + sizeof(buff)) > maxsize) {
-               shutdown(sockfd, 2);
-               close(sockfd);
-               close(acceptd);
-               mdprintf(odesc, "Size exceeded ERROR\n");
-               logg("^ScanStream: Size exceeded (stopped at %d, max: %d)\n", size, 
maxsize);
-               if(tmp)
-                   fclose(tmp);
-               return -1;
+           btread = ( (maxsize && ( size + btread > maxsize)) ? (maxsize - size) : 
btread);
+           if(btread == 0) {
+               logg("^ScanStream: Size limit reached (max: %d)\n",  maxsize);
+               break;
            }
 
            if(write(tmpd, buff, bread) < 0) {

Reply via email to