Mercurial > dnsbl
diff src/dnsbl.cpp @ 322:9f8411f3919c
add dkim white/black listing
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 17 Dec 2016 17:04:52 -0800 |
parents | e172dc10fe24 |
children | a6de27b0a1e9 |
line wrap: on
line diff
--- a/src/dnsbl.cpp Sat Dec 17 13:47:28 2016 -0800 +++ b/src/dnsbl.cpp Sat Dec 17 17:04:52 2016 -0800 @@ -98,6 +98,8 @@ const int maxlen = 1000; // used for snprintf buffers regex_t srs_pattern; // used to detect srs coding in mail addresses regex_t prvs_pattern; // used to detect prvs coding in mail addresses +regex_t dkim_pattern; // used to detect dkim signatures in authentication header generated by the upstream opendkim milter +regex_t from_pattern; // used to extract the senders mail domain from the body from: header pthread_mutex_t config_mutex; pthread_mutex_t syslog_mutex; @@ -522,6 +524,8 @@ mailaddr = NULL; fromaddr = NULL; header_count = 0; + dkim_ok = true; + dkim_signer = NULL; queueid = NULL; authenticated = NULL; client_name = NULL; @@ -570,6 +574,7 @@ } if (mailaddr) free((void*)mailaddr); if (fromaddr) free((void*)fromaddr); + if (dkim_signer) free((void*)dkim_signer); if (queueid) free((void*)queueid); if (authenticated) free((void*)authenticated); if (client_name) free((void*)client_name); @@ -587,6 +592,8 @@ mailaddr = NULL; fromaddr = NULL; header_count = 0; + dkim_ok = true; + dkim_signer = NULL; queueid = NULL; authenticated = NULL; client_name = NULL; @@ -1450,8 +1457,8 @@ { mlfiPriv &priv = *MLFIPRIV; priv.header_count++; + char msg[maxlen]; if ((priv.header_count < 4) || (strcasecmp(headerf, "from") == 0)) { - char msg[maxlen]; snprintf(msg, sizeof(msg), "header %s: %s", headerf, headerv); for (int i=0; i<strlen(msg); i++) { if (msg[i] < 0x20) msg[i] = ' '; @@ -1459,6 +1466,38 @@ my_syslog(&priv, msg); } + if (priv.dkim_ok) { + if ((priv.header_count == 1) && (strcasecmp(headerf, "DKIM-Filter") != 0)) priv.dkim_ok = false; + if (priv.header_count == 2) { + if (strcasecmp(headerf, "Authentication-Results") != 0) priv.dkim_ok = false; + if (strncasecmp(headerv, token_myhostname, strlen(token_myhostname)) != 0) priv.dkim_ok = false; + if (priv.dkim_ok) { + const int nmatch = 2; + regmatch_t match[nmatch]; + if (0 == regexec(&dkim_pattern, msg, nmatch, match, 0)) { + int s1 = match[1].rm_so; // domain + int e1 = match[1].rm_eo; + if (s1 != -1) { + msg[e1] = '\0'; + priv.dkim_signer = strdup(msg+s1); + } + } + } + } + if ((priv.header_count > 2) && (strcasecmp(headerf, "from"))) { + const int nmatch = 2; + regmatch_t match[nmatch]; + if (0 == regexec(&from_pattern, msg, nmatch, match, 0)) { + int s1 = match[1].rm_so; // domain + int e1 = match[1].rm_eo; + if (s1 != -1) { + msg[e1] = '\0'; + priv.fromaddr = strdup(msg+s1); + } + } + } + } + // headers that avoid autowhitelisting if (((strcasecmp(headerf, "precedence") == 0) && (strcasecmp(headerv, "bulk") == 0)) || ((strcasecmp(headerf, "content-type") == 0) && (strncasecmp(headerv, "multipart/report", 16) == 0))) { @@ -1546,9 +1585,11 @@ for (context_map::iterator i=priv.env_to.begin(); i!=priv.env_to.end(); i++) { const char *rcpt = (*i).first; CONTEXT &con = *((*i).second); - if (!con.acceptable_content(*priv.memory, score, bulk, msg)) { + if (!con.acceptable_content(*priv.memory, score, bulk, priv.dkim_signer, priv.fromaddr, msg)) { // bad html tags or excessive hosts or // high spam assassin score or dcc bulk threshold exceedeed + // or signed by a dkim signer that we don't like + // or header from requires dkim signer that is missing smfi_delrcpt(ctx, (char*)rcpt); } else { @@ -1804,6 +1845,18 @@ exit(3); } + // setup dkim signature detection + if (regcomp(&dkim_pattern, " dkim=pass .* header.d=([^ ]+) ", REG_ICASE | REG_EXTENDED)) { + printf("cannot compile regex pattern to find dkim signatures\n"); + exit(3); + } + + // setup from domain extraction + if (regcomp(&from_pattern, "@([a-zA-Z0-9.-]+)", REG_ICASE | REG_EXTENDED)) { + printf("cannot compile regex pattern to find dkim signatures\n"); + exit(3); + } + // Process command line options while ((c = getopt(argc, argv, args)) != -1) { switch (c) {