sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len) { struct CLAMFI *cf; if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) return SMFIS_CONTINUE; /* whatever */ if(!cf->gotbody) { sfsistat ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx); if(ret != SMFIS_CONTINUE) return ret; cf->gotbody = 1; } return sendchunk(cf, bodyp, len, ctx); }
sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) { struct CLAMFI *cf; sfsistat ret; if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) return SMFIS_CONTINUE; /* whatever */ if(!cf->totsz && cf->all_whitelisted) { logg("*Skipping scan (all destinations whitelisted)\n"); nullify(ctx, cf, CF_NONE); free(cf); return SMFIS_ACCEPT; } if(!headerf) return SMFIS_CONTINUE; /* just in case */ if((loginfected & (LOGINF_FULL | LOGCLN_FULL)) || viraction) { if(!cf->msg_subj && !strcasecmp(headerf, "Subject")) cf->msg_subj = strdup(headerv ? headerv : ""); if(!cf->msg_date && !strcasecmp(headerf, "Date")) cf->msg_date = strdup(headerv ? headerv : ""); if(!cf->msg_id && !strcasecmp(headerf, "Message-ID")) cf->msg_id = strdup(headerv ? headerv : ""); } if(addxvirus==1) { if(!strcasecmp(headerf, "X-Virus-Scanned")) cf->scanned_count++; if(!strcasecmp(headerf, "X-Virus-Status")) cf->status_count++; } if((ret = sendchunk(cf, (unsigned char *)headerf, strlen(headerf), ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } if((ret = sendchunk(cf, (unsigned char *)": ", 2, ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } if(headerv && (ret = sendchunk(cf, (unsigned char *)headerv, strlen(headerv), ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx); if(ret != SMFIS_CONTINUE) free(cf); return ret; }
static sfsistat sendchunk(struct CLAMFI *cf, unsigned char *bodyp, size_t len, SMFICTX *ctx) { if(cf->totsz >= maxfilesize || len == 0) return SMFIS_CONTINUE; if(!cf->totsz) { sfsistat ret; if(nc_connect_rand(&cf->main, &cf->alt, &cf->local)) { logg("!Failed to initiate streaming/fdpassing\n"); nullify(ctx, cf, CF_NONE); return FailAction; } cf->totsz = 1; /* do not infloop */ if((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE) return ret; cf->totsz -= 1; } if(cf->totsz + len > maxfilesize) len = maxfilesize - cf->totsz; cf->totsz += len; if(cf->local) { while(len) { int n = write(cf->alt, bodyp, len); if (n==-1) { logg("!Failed to write temporary file\n"); nullify(ctx, cf, CF_BOTH); return FailAction; } len -= n; bodyp += n; } } else { int sendfailed = 0; if(len < CLAMFIBUFSZ - cf->bufsz) { memcpy(&cf->buffer[cf->bufsz], bodyp, len); cf->bufsz += len; } else if(len < CLAMFIBUFSZ) { memcpy(&cf->buffer[cf->bufsz], bodyp, CLAMFIBUFSZ - cf->bufsz); sendfailed = nc_send(cf->alt, cf->buffer, CLAMFIBUFSZ); len -= (CLAMFIBUFSZ - cf->bufsz); memcpy(cf->buffer, &bodyp[CLAMFIBUFSZ - cf->bufsz], len); cf->bufsz = len; } else { if(nc_send(cf->alt, cf->buffer, cf->bufsz) || nc_send(cf->alt, bodyp, len)) sendfailed = 1; cf->bufsz = 0; } if(sendfailed) { logg("!Streaming failed\n"); nullify(ctx, cf, CF_MAIN); return FailAction; } } return SMFIS_CONTINUE; }