Browse code

AddHeader

git-svn: trunk@4527

aCaB authored on 2008/12/05 01:26:52
Showing 5 changed files
... ...
@@ -47,7 +47,7 @@
47 47
 struct smfiDesc descr = {
48 48
     "ClamAV", 		/* filter name */
49 49
     SMFI_VERSION,	/* milter version */
50
-    SMFIF_ADDHDRS|SMFIF_QUARANTINE, /* flags */
50
+    SMFIF_CHGHDRS|SMFIF_QUARANTINE, /* flags */
51 51
     clamfi_connect,	/* connection info filter */
52 52
     NULL,		/* SMTP HELO command filter */
53 53
     NULL,		/* envelope sender filter */
... ...
@@ -203,11 +203,27 @@ int main(int argc, char **argv) {
203 203
 	return 1;
204 204
     }
205 205
 
206
+
206 207
     /* FIXME: find a place for these:
207 208
      * maxthreads = cfgopt(copt, "MaxThreads")->numarg;
208 209
      * logclean = cfgopt(copt, "LogClean")->numarg;
209 210
      */
210 211
 
212
+    if(cfgopt(copt, "AddHeader")->enabled) {
213
+	char myname[255];
214
+
215
+	if(!gethostname(myname, sizeof(myname))) {
216
+	    char mydomain[255];
217
+
218
+	    myname[sizeof(myname)-1] = '\0';
219
+	    snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", get_version(), myname);
220
+	    xvirushdr[sizeof(xvirushdr)-1] = '\0';
221
+	} else {
222
+	    snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", get_version());
223
+	    xvirushdr[sizeof(xvirushdr)-1] = '\0';
224
+	}
225
+	addxvirus = 1;
226
+    }
211 227
     
212 228
     umask(0007);
213 229
     if(!(my_socket = cfgopt(copt, "MilterSocket")->strarg)) {
... ...
@@ -22,6 +22,7 @@
22 22
 #include "clamav-config.h"
23 23
 #endif
24 24
 
25
+#include <stdio.h>
25 26
 #include <stdlib.h>
26 27
 #include <string.h>
27 28
 #include <sys/types.h>
... ...
@@ -35,12 +36,21 @@
35 35
 #include "connpool.h"
36 36
 #include "netcode.h"
37 37
 
38
+#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
39
+#define _UNUSED_ __attribute__ ((__unused__))
40
+#else
41
+#define _UNUSED_
42
+#endif
43
+
38 44
 uint64_t maxfilesize;
39 45
 
40 46
 static sfsistat FailAction;
41 47
 static sfsistat (*CleanAction)(SMFICTX *ctx);
42 48
 static sfsistat (*InfectedAction)(SMFICTX *ctx);
43 49
 
50
+int addxvirus = 0;
51
+char xvirushdr[255];
52
+
44 53
 #define CLAMFIBUFSZ 1424
45 54
 
46 55
 struct CLAMFI {
... ...
@@ -53,9 +63,15 @@ struct CLAMFI {
53 53
 };
54 54
 
55 55
 
56
+void add_x_header(SMFICTX *ctx, char *st) {
57
+    smfi_chgheader(ctx, "X-Virus-Scanned", 1, xvirushdr);
58
+    smfi_chgheader(ctx, "X-Virus-Status", 1, st);
59
+}
60
+
61
+
56 62
 static sfsistat sendchunk(struct CLAMFI *cf, unsigned char *bodyp, size_t len, SMFICTX *ctx) {
57 63
     if(cf->totsz >= maxfilesize)
58
-	return SMFIS_CONTINUE; /* FIXME: SMFIS_SKIP needs negotiation (only for _body() */
64
+	return SMFIS_CONTINUE;
59 65
 
60 66
     if(cf->totsz + len > maxfilesize)
61 67
 	len = maxfilesize - cf->totsz;
... ...
@@ -126,7 +142,9 @@ sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) {
126 126
 	}
127 127
 	if((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE)
128 128
 	    return ret;
129
+
129 130
     }
131
+
130 132
     if((ret = sendchunk(cf, (unsigned char *)headerf, strlen(headerf), ctx)) != SMFIS_CONTINUE)
131 133
 	return ret;
132 134
     if((ret = sendchunk(cf, (unsigned char *)": ", 2, ctx)) != SMFIS_CONTINUE)
... ...
@@ -199,11 +217,29 @@ sfsistat clamfi_eom(SMFICTX *ctx) {
199 199
     free(cf);
200 200
 
201 201
     len = strlen(reply);
202
-    if(len>5 && !strcmp(reply + len - 5, ": OK\n"))
202
+    if(len>5 && !strcmp(reply + len - 5, ": OK\n")) {
203
+	if(addxvirus) add_x_header(ctx, "Clean");
203 204
 	ret = CleanAction(ctx);
204
-    else if (len>7 && !strcmp(reply + len - 7, " FOUND\n"))
205
+    } else if (len>7 && !strcmp(reply + len - 7, " FOUND\n")) {
206
+	logg("^%s\n", reply);
207
+	if(addxvirus) {
208
+	    char *vir;
209
+
210
+	    reply[len-7] = '\0';
211
+	    vir = strrchr(reply, ' ');
212
+	    logg("^%s\n", reply);
213
+	    if(vir) {
214
+		char msg[255];
215
+
216
+		vir++;
217
+		logg("^v: >%s<\n", vir);
218
+		snprintf(msg, sizeof(msg), "Infected (%s)", vir);
219
+		msg[sizeof(msg)-1] = '\0';
220
+		add_x_header(ctx, msg);
221
+	    }
222
+	}
205 223
 	ret = InfectedAction(ctx);
206
-    else {
224
+    } else {
207 225
 	logg("!Unknown reply from clamd\n");
208 226
 	ret = FailAction;
209 227
     }
... ...
@@ -213,9 +249,7 @@ sfsistat clamfi_eom(SMFICTX *ctx) {
213 213
 }
214 214
 
215 215
 
216
-sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) {
217
-    struct CLAMFI *cf;
218
-
216
+sfsistat clamfi_connect(_UNUSED_ SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) {
219 217
     while(1) {
220 218
 	/* Postfix doesn't seem to honor passing a NULL hostaddr and hostname
221 219
 	   set to "localhost" for non-smtp messages (they still appear as SMTP
... ...
@@ -255,16 +289,16 @@ static int parse_action(char *action) {
255 255
 }
256 256
 
257 257
 
258
-static sfsistat action_accept(SMFICTX *ctx) {
258
+static sfsistat action_accept(_UNUSED_ SMFICTX *ctx) {
259 259
     return SMFIS_ACCEPT;
260 260
 }
261
-static sfsistat action_defer(SMFICTX *ctx) {
261
+static sfsistat action_defer(_UNUSED_ SMFICTX *ctx) {
262 262
     return SMFIS_TEMPFAIL;
263 263
 }
264
-static sfsistat action_reject(SMFICTX *ctx) {
264
+static sfsistat action_reject(_UNUSED_ SMFICTX *ctx) {
265 265
     return SMFIS_REJECT;
266 266
 }
267
-static sfsistat action_blackhole(SMFICTX *ctx)  {
267
+static sfsistat action_blackhole(_UNUSED_ SMFICTX *ctx)  {
268 268
     return SMFIS_DISCARD;
269 269
 }
270 270
 static sfsistat action_quarantine(SMFICTX *ctx) {
... ...
@@ -4,7 +4,10 @@
4 4
 #include "shared/cfgparser.h"
5 5
 #include <libmilter/mfapi.h>
6 6
 
7
-uint64_t maxfilesize;
7
+extern uint64_t maxfilesize;
8
+extern int addxvirus;
9
+extern char xvirushdr[255];
10
+
8 11
 
9 12
 sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len);
10 13
 sfsistat clamfi_eom(SMFICTX *ctx);
... ...
@@ -107,6 +107,8 @@ Example
107 107
 #   Like accept but the message is sent to oblivion
108 108
 # - Quarantine (not available for OnFail)
109 109
 #   Like accept but message is quarantined instead of being deilievered
110
+#   In sendmail the quarantine queue can be examined via mailq -qQ
111
+#   For Postfix this causes the message to be accepted but placed on hold
110 112
 # 
111 113
 # Action to be performed on clean messages (mostly useful for testing)
112 114
 # Default Accept
... ...
@@ -122,6 +124,13 @@ Example
122 122
 # Default Defer
123 123
 #OnFail Defer
124 124
 
125
+# If this option is set to Yes, an "X-Virus-Scanned" and an "X-Virus-Status"
126
+# headers will be attached to each processed message, possibly replacing
127
+# existing headers. 
128
+# Default: No
129
+#AddHeader Yes
130
+
131
+
125 132
 ##
126 133
 ## Logging options
127 134
 ##
... ...
@@ -250,9 +259,9 @@ Example
250 250
 #--server
251 251
 
252 252
 #Reworked
253
-#-A --advisory
254
-#-d --dont-scan-on-error
255
-#-n --noxheader
256
-#-N --noreject
257
-#-Q --quarantine
258
-#-U, --quarantine-dir
253
+##-A --advisory
254
+##-d --dont-scan-on-error
255
+##-n --noxheader
256
+##-N --noreject
257
+##-Q --quarantine
258
+##-U, --quarantine-dir
... ...
@@ -142,14 +142,14 @@ struct cfgoption cfg_options[] = {
142 142
     {"ArchiveBlockMax", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
143 143
     {"ArchiveLimitMemoryUsage", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED },
144 144
 
145
-
146 145
     /* Milter specific options */
147 146
     {"ClamdSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER},
148 147
     {"MilterSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER},
149 148
     {"LocalNet", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER},
150
-    {"ActionClean", OPT_QUOTESTR, -1, "Accept", 1, OPT_MILTER},
151
-    {"ActionInfected", OPT_QUOTESTR, -1, "Quarantine", 1, OPT_MILTER},
152
-    {"ActionFail", OPT_QUOTESTR, -1, "Defer", 1, OPT_MILTER},
149
+    {"OnClean", OPT_QUOTESTR, -1, "Accept", 0, OPT_MILTER},
150
+    {"OnInfected", OPT_QUOTESTR, -1, "Quarantine", 0, OPT_MILTER},
151
+    {"OnFail", OPT_QUOTESTR, -1, "Defer", 0, OPT_MILTER},
152
+    {"AddHeader", OPT_BOOL, 0, NULL, 0, OPT_MILTER},
153 153
 
154 154
     /* Deprecated milter options */
155 155
     {"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},