You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
8.5 KiB
289 lines
8.5 KiB
Add authenticated bits information into the dummy generated |
|
Received-header for SpamAssassin to facilitate adding a rule |
|
to score mail from authenticated clients. |
|
|
|
Discussion: |
|
http://bugzilla.redhat.com/496769 |
|
http://www.gossamer-threads.com/lists/spamassassin/users/146948 |
|
|
|
This patch also moves some of the macro collection to the |
|
ENVFROM callback, where the required macros are available by default. |
|
|
|
--- README |
|
+++ README |
|
@@ -55,16 +55,28 @@ configuring sendmail through m4 & the se |
|
adding the lines |
|
|
|
INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/sendmail/spamass.sock, F=, T=C:15m;S:4m;R:4m;E:10m')dnl |
|
-define(`confMILTER_MACROS_CONNECT',`t, b, j, _, {daemon_name}, {if_name}, {if_addr}')dnl |
|
-define(`confMILTER_MACROS_HELO',`s, {tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}')dnl |
|
-define(`confMILTER_MACROS_ENVFROM',`{auth_authen}, {auth_type}')dnl |
|
-define(`confMILTER_MACROS_ENVRCPT',`r, v, Z')dnl |
|
+define(`confMILTER_MACROS_ENVRCPT',confMILTER_MACROS_ENVRCPT`, b, r, v, Z')dnl |
|
+ |
|
|
|
should do the trick. Of course you need to modify the path of the |
|
socket if you put another one into the startup script. The timeouts |
|
have been increased somewhat because SpamAssassin may chew on it for a |
|
little while on a slow machine. |
|
|
|
+If you are using multiple milter mail filters on your mail server, you may |
|
+have overridden the default values of some of the confMILTER_MACROS_* |
|
+macros whilst configuring the other filters. You need to ensure that at |
|
+least the following values are present: |
|
+ |
|
+confMILTER_MACROS_CONNECT must include the {j} and {_} macros |
|
+(all included by default) |
|
+ |
|
+confMILTER_MACROS_ENVFROM must include the {i}, {auth_authen}, {auth_ssf} |
|
+and {auth_type} macros (all included by default) |
|
+ |
|
+confMILTER_MACROS_ENVRCPT must include the {b}, {r}, {v}, and {Z} macros |
|
+ |
|
+ |
|
Now recreate sendmail.cf, restart sendmail and experiment around a bit |
|
with the setup to make sure it is working. |
|
|
|
--- spamass-milter.cpp |
|
+++ spamass-milter.cpp |
|
@@ -702,6 +702,7 @@ sfsistat |
|
mlfi_connect(SMFICTX * ctx, char *hostname, _SOCK_ADDR * hostaddr) |
|
{ |
|
struct context *sctx; |
|
+ const char *macro_j, *macro__; |
|
int rv; |
|
|
|
debug(D_FUNC, "mlfi_connect: enter"); |
|
@@ -726,8 +727,31 @@ mlfi_connect(SMFICTX * ctx, char *hostna |
|
} |
|
sctx->assassin = NULL; |
|
sctx->helo = NULL; |
|
- |
|
- /* store a pointer to it with setpriv */ |
|
+ sctx->our_fqdn = NULL; |
|
+ sctx->sender_address = NULL; |
|
+ sctx->queueid = NULL; |
|
+ sctx->auth_authen = NULL; |
|
+ sctx->auth_ssf = NULL; |
|
+ |
|
+ /* store our FQDN */ |
|
+ macro_j = smfi_getsymval(ctx, const_cast<char *>("j")); |
|
+ if (!macro_j) |
|
+ { |
|
+ macro_j = "localhost"; |
|
+ warnmacro("j", "CONNECT"); |
|
+ } |
|
+ sctx->our_fqdn = strdup(macro_j); |
|
+ |
|
+ /* store the validated sending site's address */ |
|
+ macro__ = smfi_getsymval(ctx, const_cast<char *>("_")); |
|
+ if (!macro__) |
|
+ { |
|
+ macro__ = "unknown"; |
|
+ warnmacro("_", "CONNECT"); |
|
+ } |
|
+ sctx->sender_address = strdup(macro__); |
|
+ |
|
+ /* store a pointer to our private data with setpriv */ |
|
rv = smfi_setpriv(ctx, sctx); |
|
if (rv != MI_SUCCESS) |
|
{ |
|
@@ -778,7 +802,7 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro |
|
{ |
|
SpamAssassin* assassin; |
|
struct context *sctx = (struct context *)smfi_getpriv(ctx); |
|
- const char *queueid; |
|
+ const char *queueid, *macro_auth_ssf, *macro_auth_authen; |
|
|
|
if (sctx == NULL) |
|
{ |
|
@@ -814,17 +838,44 @@ mlfi_envfrom(SMFICTX* ctx, char** envfro |
|
|
|
// remember the MAIL FROM address |
|
assassin->set_from(string(envfrom[0])); |
|
- |
|
+ |
|
+ // remember the queueid for this message |
|
queueid=smfi_getsymval(ctx, const_cast<char *>("i")); |
|
if (!queueid) |
|
{ |
|
queueid="unknown"; |
|
warnmacro("i", "ENVFROM"); |
|
} |
|
- assassin->queueid = queueid; |
|
- |
|
+ sctx->queueid = strdup(queueid); |
|
debug(D_MISC, "queueid=%s", queueid); |
|
|
|
+ // remember the SMTP AUTH login name |
|
+ macro_auth_authen = smfi_getsymval(ctx, const_cast<char *>("{auth_authen}")); |
|
+ if (!macro_auth_authen) |
|
+ { |
|
+ macro_auth_authen = ""; |
|
+ // Don't issue a warning for the auth_authen macro as |
|
+ // it is likely to be unset much of the time - it's |
|
+ // only set if the client has authenticated. |
|
+ // |
|
+ // Similarly, we only issue warnings for the other |
|
+ // auth-related macros if {auth_authen) is available. |
|
+ // |
|
+ // warnmacro("auth_authen", "ENVFROM"); |
|
+ } |
|
+ sctx->auth_authen = strdup(macro_auth_authen); |
|
+ |
|
+ // remember the SASL cipher bits |
|
+ macro_auth_ssf = smfi_getsymval(ctx, const_cast<char *>("{auth_ssf}")); |
|
+ if (!macro_auth_ssf) |
|
+ { |
|
+ macro_auth_ssf = ""; |
|
+ if (strlen(macro_auth_authen)) { |
|
+ warnmacro("auth_ssf", "ENVFROM"); |
|
+ } |
|
+ } |
|
+ sctx->auth_ssf = strdup(macro_auth_ssf); |
|
+ |
|
// tell Milter to continue |
|
debug(D_FUNC, "mlfi_envfrom: exit"); |
|
|
|
@@ -918,7 +969,8 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp |
|
|
|
*/ |
|
const char *macro_b, *macro_i, *macro_j, *macro_r, |
|
- *macro_s, *macro_v, *macro_Z, *macro__; |
|
+ *macro_s, *macro_v, *macro_Z, *macro__, |
|
+ *macro_auth_ssf, *macro_auth_authen; |
|
char date[32]; |
|
|
|
/* RFC 822 date. */ |
|
@@ -933,20 +985,13 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp |
|
} |
|
|
|
/* queue ID */ |
|
- macro_i = smfi_getsymval(ctx, const_cast<char *>("i")); |
|
- if (!macro_i) |
|
- { |
|
- macro_i = "unknown"; |
|
- warnmacro("i", "ENVRCPT"); |
|
- } |
|
+ macro_i = sctx->queueid; |
|
|
|
- /* FQDN of this site */ |
|
- macro_j = smfi_getsymval(ctx, const_cast<char *>("j")); |
|
- if (!macro_j) |
|
- { |
|
- macro_j = "localhost"; |
|
- warnmacro("j", "ENVRCPT"); |
|
- } |
|
+ /* FQDN */ |
|
+ macro_j = sctx->our_fqdn; |
|
+ |
|
+ /* Sender address */ |
|
+ macro__ = sctx->sender_address; |
|
|
|
/* Protocol used to receive the message */ |
|
macro_r = smfi_getsymval(ctx, const_cast<char *>("r")); |
|
@@ -955,7 +1000,11 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp |
|
macro_r = "SMTP"; |
|
warnmacro("r", "ENVRCPT"); |
|
} |
|
- |
|
+ |
|
+ /* SMTP AUTH details */ |
|
+ macro_auth_authen = sctx->auth_authen; |
|
+ macro_auth_ssf = sctx->auth_ssf; |
|
+ |
|
/* Sendmail currently cannot pass us the {s} macro, but |
|
I do not know why. Leave this in for the day sendmail is |
|
fixed. Until that day, use the value remembered by |
|
@@ -983,22 +1032,25 @@ mlfi_envrcpt(SMFICTX* ctx, char** envrcp |
|
warnmacro("Z", "ENVRCPT"); |
|
} |
|
|
|
- /* Validated sending site's address */ |
|
- macro__ = smfi_getsymval(ctx, const_cast<char *>("_")); |
|
- if (!macro__) |
|
+ assassin->output((string)"X-Envelope-From: "+assassin->from()+"\r\n"); |
|
+ assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); |
|
+ |
|
+ string rec_header; |
|
+ |
|
+ rec_header = (string) "Received: from " + macro_s + " (" + macro__ + ")\r\n\t"; |
|
+ |
|
+ if (strlen(macro_auth_ssf)) |
|
{ |
|
- macro__ = "unknown"; |
|
- warnmacro("_", "ENVRCPT"); |
|
+ rec_header += (string) "(authenticated bits=" + macro_auth_ssf + ")\r\n\t"; |
|
} |
|
|
|
- assassin->output((string)"X-Envelope-From: "+assassin->from()+"\r\n"); |
|
- assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); |
|
+ rec_header += (string) "by " + macro_j + " (" + macro_v + "/" + macro_Z + ") with " + |
|
+ macro_r + " id " + macro_i + ";\r\n\t" + |
|
+ macro_b + "\r\n\t" + |
|
+ "(envelope-from " + assassin->from() + ")\r\n"; |
|
|
|
- assassin->output((string) |
|
- "Received: from "+macro_s+" ("+macro__+")\r\n\t"+ |
|
- "by "+macro_j+" ("+macro_v+"/"+macro_Z+") with "+macro_r+" id "+macro_i+";\r\n\t"+ |
|
- macro_b+"\r\n\t"+ |
|
- "(envelope-from "+assassin->from()+")\r\n"); |
|
+ debug(D_SPAMC, "Received header for spamc: %s", rec_header.c_str()); |
|
+ assassin->output(rec_header); |
|
|
|
} else |
|
assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\r\n"); |
|
@@ -1244,16 +1296,27 @@ mlfi_close(SMFICTX* ctx) |
|
{ |
|
struct context *sctx; |
|
debug(D_FUNC, "mlfi_close"); |
|
- |
|
+ |
|
sctx = (struct context*)smfi_getpriv(ctx); |
|
if (sctx == NULL) |
|
return SMFIS_ACCEPT; |
|
|
|
if (sctx->helo) |
|
free(sctx->helo); |
|
+ if (sctx->our_fqdn) |
|
+ free(sctx->our_fqdn); |
|
+ if (sctx->sender_address) |
|
+ free(sctx->sender_address); |
|
+ if (sctx->queueid) |
|
+ free(sctx->queueid); |
|
+ if (sctx->auth_authen) |
|
+ free(sctx->auth_authen); |
|
+ if (sctx->auth_ssf) |
|
+ free(sctx->auth_ssf); |
|
+ |
|
free(sctx); |
|
smfi_setpriv(ctx, NULL); |
|
- |
|
+ |
|
return SMFIS_ACCEPT; |
|
} |
|
|
|
--- spamass-milter.h |
|
+++ spamass-milter.h |
|
@@ -168,9 +168,6 @@ public: |
|
// List of recipients after alias/virtusertable expansion |
|
list <string> expandedrcpt; |
|
|
|
- // the sendmail queue id for this message; used for logging |
|
- string queueid; |
|
- |
|
// Process handling variables |
|
pid_t pid; |
|
int pipe_io[2][2]; |
|
@@ -181,6 +178,11 @@ struct context |
|
{ |
|
char connect_ip[64]; // remote IP address |
|
char *helo; |
|
+ char *our_fqdn; |
|
+ char *sender_address; |
|
+ char *queueid; |
|
+ char *auth_authen; |
|
+ char *auth_ssf; |
|
SpamAssassin *assassin; // pointer to the SA object if we're processing a message |
|
}; |
|
|
|
|