From f01e810ec85d4b9927890c7541463bb6612a4cf8 Mon Sep 17 00:00:00 2001 From: don Date: Thu, 21 Jun 2012 21:05:23 +0000 Subject: [PATCH] =?utf8?q?*=20No=20longer=20create=20home=20directory=20fo?= =?utf8?q?r=20spamass-milter;=20remove=20on=20purge=20if=20=20=20it=20exis?= =?utf8?q?ts=20(closes:=20#668717)=20*=20Use=20autotools-dev=20to=20update?= =?utf8?q?=20config.sub/config.guess=20(closes:=20#539791)=20*=20Include?= =?utf8?q?=20support=20for=20ipv6=20(Thanks=20to=20Wilmer=20van=20der=20Ga?= =?utf8?q?ast)=20(closes:=20#569483)=20*=20Add=20SMTP=20auth=20information?= =?utf8?q?=20to=20received=20header=20(Thanks=20to=20Knut=20Arne=20=20=20B?= =?utf8?q?j=C3=B8rndal)=20(closes:=20#627989)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- debian/changelog | 9 +- debian/patches/add_ipv6_support | 275 ++++++++++++++++++ debian/patches/auth_in_received | 65 +++++ debian/patches/fix_header_char_cast | 32 ++ debian/patches/fix_spacing_in_received_header | 13 + debian/patches/ignore_by_smtp_auth | 93 ++++++ debian/patches/series | 5 + 7 files changed, 490 insertions(+), 2 deletions(-) create mode 100644 debian/patches/add_ipv6_support create mode 100644 debian/patches/auth_in_received create mode 100644 debian/patches/fix_header_char_cast create mode 100644 debian/patches/fix_spacing_in_received_header create mode 100644 debian/patches/ignore_by_smtp_auth create mode 100644 debian/patches/series diff --git a/debian/changelog b/debian/changelog index 2b446f8..f3dc9a8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,13 @@ spamass-milter (0.3.2-1) UNRELEASED; urgency=low * New upstream release - * No longer create home directory for spamass-milter; remove on purge if it exists (closes: #668717) - + * No longer create home directory for spamass-milter; remove on purge if + it exists (closes: #668717) + * Use autotools-dev to update config.sub/config.guess (closes: #539791) + * Include support for ipv6 (Thanks to Wilmer van der Gaast) (closes: #569483) + * Add SMTP auth information to received header (Thanks to Knut Arne + Bjørndal) (closes: #627989) + -- Don Armstrong Mon, 13 Jun 2011 17:00:00 -0700 spamass-milter (0.3.1-10) unstable; urgency=low diff --git a/debian/patches/add_ipv6_support b/debian/patches/add_ipv6_support new file mode 100644 index 0000000..dc6f3bc --- /dev/null +++ b/debian/patches/add_ipv6_support @@ -0,0 +1,275 @@ +Index: spamass-milter/spamass-milter.cpp +=================================================================== +--- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:03:25.000000000 -0700 ++++ spamass-milter/spamass-milter.cpp 2012-06-21 13:03:42.000000000 -0700 +@@ -88,6 +88,7 @@ + #include "subst_poll.h" + #endif + #include ++#include + + // C++ includes + #include +@@ -678,6 +679,8 @@ + { + struct context *sctx; + int rv; ++ struct sockaddr_in localhost; ++ + + debug(D_FUNC, "mlfi_connect: enter"); + +@@ -687,10 +690,15 @@ + { + /* not a socket; probably a local user calling sendmail directly */ + /* set to 127.0.0.1 */ +- sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK); ++ strcpy(sctx->connect_ip, "127.0.0.1"); ++ localhost.sin_family = AF_INET; ++ localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ++ hostaddr = (struct sockaddr*) &localhost; + } else + { +- sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr; ++ getnameinfo(hostaddr, sizeof(struct sockaddr_in6), ++ sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST); ++ debug(D_FUNC, "Remote address: %s", sctx->connect_ip); + } + sctx->assassin = NULL; + sctx->helo = NULL; +@@ -704,10 +712,10 @@ + } + /* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */ + +- if (ip_in_networklist(sctx->connect_ip, &ignorenets)) ++ if (ip_in_networklist(hostaddr, &ignorenets)) + { + debug(D_NET, "%s is in our ignore list - accepting message", +- inet_ntoa(sctx->connect_ip)); ++ sctx->connect_ip); + debug(D_FUNC, "mlfi_connect: exit ignore"); + return SMFIS_ACCEPT; + } +@@ -779,7 +787,7 @@ + return SMFIS_TEMPFAIL; + }; + +- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip))); ++ assassin->set_connectip(string(sctx->connect_ip)); + + // Store a pointer to the assassin object in our context struct + sctx->assassin = assassin; +@@ -2033,69 +2041,119 @@ + { + char *tnet = strsep(&token, "/"); + char *tmask = token; +- struct in_addr net, mask; ++ struct in_addr net; ++ struct in6_addr net6; + + if (list->num_nets % 10 == 0) +- list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); ++ list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10)); + +- if (!inet_aton(tnet, &net)) ++ if (inet_pton(AF_INET, tnet, &net)) + { +- fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); +- exit(1); +- } ++ struct in_addr mask; ++ ++ if (tmask) ++ { ++ if (strchr(tmask, '.') == NULL) ++ { ++ /* CIDR */ ++ unsigned int bits; ++ int ret; ++ ret = sscanf(tmask, "%u", &bits); ++ if (ret != 1 || bits > 32) ++ { ++ fprintf(stderr,"%s: bad CIDR value", tmask); ++ exit(1); ++ } ++ mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); ++ } else if (!inet_pton(AF_INET6, tmask, &mask)) ++ { ++ fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); ++ exit(1); ++ } ++ } else ++ mask.s_addr = 0xffffffff; + +- if (tmask) ++ { ++ char *snet = strdup(inet_ntoa(net)); ++ debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); ++ free(snet); ++ } ++ ++ net.s_addr = net.s_addr & mask.s_addr; ++ list->nets[list->num_nets].net4.af = AF_INET; ++ list->nets[list->num_nets].net4.network = net; ++ list->nets[list->num_nets].net4.netmask = mask; ++ list->num_nets++; ++ } else if (inet_pton(AF_INET6, tnet, &net6)) + { +- if (strchr(tmask, '.') == NULL) ++ int mask; ++ ++ if (tmask) + { +- /* CIDR */ +- unsigned int bits; +- int ret; +- ret = sscanf(tmask, "%u", &bits); +- if (ret != 1 || bits > 32) ++ if (sscanf(tmask, "%d", &mask) != 1 || mask > 128) + { + fprintf(stderr,"%s: bad CIDR value", tmask); + exit(1); + } +- mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff); +- } else if (!inet_aton(tmask, &mask)) +- { +- fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask); +- exit(1); +- } ++ } else ++ mask = 128; ++ ++ list->nets[list->num_nets].net6.af = AF_INET6; ++ list->nets[list->num_nets].net6.network = net6; ++ list->nets[list->num_nets].net6.netmask = mask; ++ list->num_nets++; + } else +- mask.s_addr = 0xffffffff; +- + { +- char *snet = strdup(inet_ntoa(net)); +- debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask)); +- free(snet); ++ fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet); ++ exit(1); + } + +- net.s_addr = net.s_addr & mask.s_addr; +- list->nets[list->num_nets].network = net; +- list->nets[list->num_nets].netmask = mask; +- list->num_nets++; + } + free(string); + } + +-int ip_in_networklist(struct in_addr ip, struct networklist *list) ++int ip_in_networklist(struct sockaddr *addr, struct networklist *list) + { + int i; + + if (list->num_nets == 0) + return 0; +- +- debug(D_NET, "Checking %s against:", inet_ntoa(ip)); ++ ++ //debug(D_NET, "Checking %s against:", inet_ntoa(ip)); + for (i = 0; i < list->num_nets; i++) + { +- debug(D_NET, "%s", inet_ntoa(list->nets[i].network)); +- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask)); +- if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr) +- { +- debug(D_NET, "Hit!"); +- return 1; ++ if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET) ++ { ++ struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr; ++ ++ debug(D_NET, "%s", inet_ntoa(list->nets[i].net4.network)); ++ debug(D_NET, "/%s", inet_ntoa(list->nets[i].net4.netmask)); ++ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr) ++ { ++ debug(D_NET, "Hit!"); ++ return 1; ++ } ++ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6) ++ { ++ u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr; ++ int mask, j; ++ ++ mask = list->nets[i].net6.netmask; ++ for (j = 0; j < 16 && mask > 0; j++, mask -= 8) ++ { ++ unsigned char bytemask; ++ ++ bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff; ++ ++ if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask)) ++ break; ++ } ++ ++ if (mask <= 0) ++ { ++ debug(D_NET, "Hit!"); ++ return 1; ++ } + } + } + +Index: spamass-milter/spamass-milter.h +=================================================================== +--- spamass-milter.orig/spamass-milter.h 2012-06-21 13:03:25.000000000 -0700 ++++ spamass-milter/spamass-milter.h 2012-06-21 13:03:42.000000000 -0700 +@@ -56,16 +56,30 @@ + extern struct smfiDesc smfilter; + + /* struct describing a single network */ +-struct net ++union net + { +- struct in_addr network; +- struct in_addr netmask; ++ struct ++ { ++ uint8_t af; ++ } net; ++ struct ++ { ++ uint8_t af; ++ struct in_addr network; ++ struct in_addr netmask; ++ } net4; ++ struct ++ { ++ uint8_t af; ++ struct in6_addr network; ++ int netmask; /* Just the number of bits for IPv6 */ ++ } net6; + }; + + /* an array of networks */ + struct networklist + { +- struct net *nets; ++ union net *nets; + int num_nets; + }; + +@@ -165,7 +179,7 @@ + /* Private data structure to carry per-client data between calls */ + struct context + { +- struct in_addr connect_ip; // remote IP address ++ char connect_ip[64]; // remote IP address + char *helo; + SpamAssassin *assassin; // pointer to the SA object if we're processing a message + }; +@@ -182,7 +196,7 @@ + int cmp_nocase_partial(const string&, const string&); + void closeall(int fd); + void parse_networklist(char *string, struct networklist *list); +-int ip_in_networklist(struct in_addr ip, struct networklist *list); ++int ip_in_networklist(struct sockaddr *addr, struct networklist *list); + void parse_debuglevel(char* string); + char *strlwr(char *str); + void warnmacro(char *macro, char *scope); diff --git a/debian/patches/auth_in_received b/debian/patches/auth_in_received new file mode 100644 index 0000000..8ac1b09 --- /dev/null +++ b/debian/patches/auth_in_received @@ -0,0 +1,65 @@ +Index: spamass-milter/spamass-milter.cpp +=================================================================== +--- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:03:42.000000000 -0700 ++++ spamass-milter/spamass-milter.cpp 2012-06-21 14:02:32.000000000 -0700 +@@ -898,7 +898,8 @@ + + */ + 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_type, *macro_auth_ssf; + char date[32]; + + /* RFC 822 date. */ +@@ -935,7 +936,22 @@ + macro_r = "SMTP"; + warnmacro("r", "ENVRCPT"); + } +- ++ ++ /* Authenticated bits Information */ ++ macro_auth_type = smfi_getsymval(ctx, "{auth_type}"); ++ if (!macro_auth_type) ++ { ++ macro_auth_type = ""; ++ warnmacro("auth_type", "ENVRCPT"); ++ } ++ ++ macro_auth_ssf = smfi_getsymval(ctx, "{auth_ssf}"); ++ if (!macro_auth_ssf) ++ { ++ macro_auth_ssf = ""; ++ warnmacro("auth_ssf", "ENVRCPT"); ++ } ++ + /* 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 +@@ -974,11 +990,22 @@ + assassin->output((string)"X-Envelope-From: "+assassin->from()+"\r\n"); + assassin->output((string)"X-Envelope-To: "+envrcpt[0]+"\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"+ ++ string rec_header; ++ rec_header=(string)"Received: from "+macro_s+" ("+macro__+")\r\n\t"; ++ if (strlen(macro_auth_type)!=0) { ++ rec_header+=(string)"(authenticated"; ++ if (strlen(macro_auth_ssf)!=0) { ++ rec_header+=(string)" bits="+macro_auth_ssf; ++ } ++ rec_header+=(string)")\r\n\t"; ++ } ++ 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"); ++ "(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"); diff --git a/debian/patches/fix_header_char_cast b/debian/patches/fix_header_char_cast new file mode 100644 index 0000000..2ec413e --- /dev/null +++ b/debian/patches/fix_header_char_cast @@ -0,0 +1,32 @@ +Index: spamass-milter/spamass-milter.cpp +=================================================================== +--- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:02:08.000000000 -0700 ++++ spamass-milter/spamass-milter.cpp 2012-06-21 13:02:15.000000000 -0700 +@@ -363,7 +363,7 @@ + // }}} + + /* Update a header if SA changes it, or add it if it is new. */ +-void update_or_insert(SpamAssassin* assassin, SMFICTX* ctx, string oldstring, t_setter setter, char *header ) ++void update_or_insert(SpamAssassin* assassin, SMFICTX* ctx, string oldstring, t_setter setter, const char *header ) + { + string::size_type eoh1 = assassin->d().find("\n\n"); + string::size_type eoh2 = assassin->d().find("\n\r\n"); +@@ -386,15 +386,16 @@ + { + /* change if old one was present, append if non-null */ + char* cstr = const_cast(newstring.c_str()); ++ char* hstr = const_cast(header); + if (oldsize > 0) + { + debug(D_UORI, "u_or_i: changing"); +- smfi_chgheader(ctx, header, 1, newstring.size() > 0 ? ++ smfi_chgheader(ctx, hstr, 1, newstring.size() > 0 ? + cstr : NULL ); + } else if (newstring.size() > 0) + { + debug(D_UORI, "u_or_i: inserting"); +- smfi_addheader(ctx, header, cstr); ++ smfi_addheader(ctx, hstr, cstr); + } + } else + { diff --git a/debian/patches/fix_spacing_in_received_header b/debian/patches/fix_spacing_in_received_header new file mode 100644 index 0000000..910b43f --- /dev/null +++ b/debian/patches/fix_spacing_in_received_header @@ -0,0 +1,13 @@ +Index: spamass-milter/spamass-milter.cpp +=================================================================== +--- spamass-milter.orig/spamass-milter.cpp 2012-06-21 13:02:06.000000000 -0700 ++++ spamass-milter/spamass-milter.cpp 2012-06-21 13:02:08.000000000 -0700 +@@ -967,7 +967,7 @@ + + 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"+ ++ "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"); + diff --git a/debian/patches/ignore_by_smtp_auth b/debian/patches/ignore_by_smtp_auth new file mode 100644 index 0000000..f25b117 --- /dev/null +++ b/debian/patches/ignore_by_smtp_auth @@ -0,0 +1,93 @@ +Index: spamass-milter/spamass-milter.1.in +=================================================================== +--- spamass-milter.orig/spamass-milter.1.in 2012-06-21 12:53:44.000000000 -0700 ++++ spamass-milter/spamass-milter.1.in 2012-06-21 12:56:56.000000000 -0700 +@@ -14,6 +14,7 @@ + .Op Fl e Ar defaultdomain + .Op Fl f + .Op Fl i Ar networks ++.Op Fl I + .Op Fl m + .Op Fl M + .Op Fl P Ar pidfile +@@ -119,6 +120,8 @@ + flags will append to the list. + For example, if you list all your internal networks, no outgoing emails + will be filtered. ++.It Fl I ++Ignores messages if the sender has authenticated via SMTP AUTH. + .It Fl m + Disables modification of the + .Ql Subject: +Index: spamass-milter/spamass-milter.cpp +=================================================================== +--- spamass-milter.orig/spamass-milter.cpp 2012-06-21 12:53:49.000000000 -0700 ++++ spamass-milter/spamass-milter.cpp 2012-06-21 12:56:56.000000000 -0700 +@@ -169,6 +169,7 @@ + char *spambucket; + bool flag_full_email = false; /* pass full email address to spamc */ + bool flag_expand = false; /* alias/virtusertable expansion */ ++bool ignore_authenticated_senders = false; + bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ + + // {{{ main() +@@ -177,7 +178,7 @@ + main(int argc, char* argv[]) + { + int c, err = 0; +- const char *args = "fd:mMp:P:r:u:D:i:b:B:e:x"; ++ const char *args = "fd:mMp:P:r:u:D:i:Ib:B:e:x"; + char *sock = NULL; + bool dofork = false; + char *pidfilename = NULL; +@@ -209,6 +210,10 @@ + debug(D_MISC, "Parsing ignore list"); + parse_networklist(optarg, &ignorenets); + break; ++ case 'I': ++ debug(D_MISC, "Ignore authenticated senders"); ++ ignore_authenticated_senders = true; ++ break; + case 'm': + dontmodifyspam = true; + smfilter.xxfi_flags &= ~SMFIF_CHGBODY; +@@ -276,7 +281,7 @@ + cout << PACKAGE_NAME << " - Version " << PACKAGE_VERSION << endl; + cout << "SpamAssassin Sendmail Milter Plugin" << endl; + cout << "Usage: spamass-milter -p socket [-b|-B bucket] [-d xx[,yy...]] [-D host]" << endl; +- cout << " [-e defaultdomain] [-f] [-i networks] [-m] [-M]" << endl; ++ cout << " [-e defaultdomain] [-f] [-i networks] [-I] [-m] [-M]" << endl; + cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x]" << endl; + cout << " [-- spamc args ]" << endl; + cout << " -p socket: path to create socket" << endl; +@@ -290,6 +295,7 @@ + cout << " -f: fork into background" << endl; + cout << " -i: skip (ignore) checks from these IPs or netblocks" << endl; + cout << " example: -i 192.168.12.5,10.0.0.0/8,172.16.0.0/255.255.0.0" << endl; ++ cout << " -I: skip (ignore) checks if sender is authenticated" << endl; + cout << " -m: don't modify body, Content-type: or Subject:" << endl; + cout << " -M: don't modify the message at all" << endl; + cout << " -P pidfile: Put processid in pidfile" << endl; +@@ -746,6 +753,22 @@ + } + /* debug(D_ALWAYS, "ZZZ got private context %p", sctx); */ + ++ if (ignore_authenticated_senders) ++ { ++ char *auth_authen; ++ ++ auth_authen = smfi_getsymval(ctx, "{auth_authen}"); ++ debug(D_MISC, "auth_authen=%s", auth_authen ?: ""); ++ ++ if (auth_authen) ++ { ++ debug(D_MISC, "sender authenticated (%s) - accepting message", ++ auth_authen); ++ debug(D_FUNC, "mlfi_envfrom: exit ignore"); ++ return SMFIS_ACCEPT; ++ } ++ } ++ + debug(D_FUNC, "mlfi_envfrom: enter"); + try { + // launch new SpamAssassin diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..27d32aa --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,5 @@ +ignore_by_smtp_auth +fix_spacing_in_received_header +fix_header_char_cast +add_ipv6_support +auth_in_received -- 2.39.2