Mercurial > dnsbl
diff src/dnsbl.cpp @ 350:f4ca91f49cb6
send the original mail from address to the verify server, not the srs/pvrs unwrapped version; recognize our own dkim signatures
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 26 Dec 2016 09:31:57 -0800 |
parents | 8fe6d5120771 |
children | f5a6740cabee |
line wrap: on
line diff
--- a/src/dnsbl.cpp Fri Dec 23 09:47:40 2016 -0800 +++ b/src/dnsbl.cpp Mon Dec 26 09:31:57 2016 -0800 @@ -98,7 +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 dkim_r_pattern; // used to detect dkim signatures authenticated by the upstream opendkim milter +regex_t dkim_s_pattern; // used to detect dkim signatures 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; @@ -522,6 +523,7 @@ ip = 0; helo = NULL; mailaddr = NULL; + origaddr = NULL; fromaddr = NULL; header_count = 0; dkim_ok = true; @@ -572,6 +574,7 @@ delayer.pop_front(); } if (mailaddr) free((void*)mailaddr); + if (origaddr) free((void*)origaddr); if (fromaddr) free((void*)fromaddr); if (queueid) free((void*)queueid); if (authenticated) free((void*)authenticated); @@ -589,6 +592,7 @@ ctx = NULL; eom = false; mailaddr = NULL; + origaddr = NULL; fromaddr = NULL; header_count = 0; dkim_ok = true; @@ -716,7 +720,7 @@ return rs; } -void mlfiPriv::need_content_filter(const char *rcpt, CONTEXT &con) { +void mlfiPriv::need_content_filter(CONTEXT &con) { if (!memory) { // first recipient that needs content filtering sets // some of the content filtering parameters @@ -1186,6 +1190,7 @@ { mlfiPriv &priv = *MLFIPRIV; CONFIG &dc = *priv.pc; + priv.origaddr = to_lower_string(from[0], false); priv.mailaddr = to_lower_string(from[0]); priv.queueid = strdup(smfi_getsymval(ctx, (char*)"i")); priv.authenticated = smfi_getsymval(ctx, (char*)"{auth_authen}"); @@ -1302,8 +1307,8 @@ } else if ((fromvalue == token_white) && !self) { // whitelisting based on envelope from value, but ignore it if - // we have a dkim requirement for that domain - const char *domain = strchr(priv.mailaddr, '@'); + // we have a dkim requirement for the original domain + const char *domain = strchr(priv.origaddr, '@'); if (domain) { DKIMP dk = con.find_dkim_from(domain+1); if (dk && (dk->action == token_require_signed)) { @@ -1367,9 +1372,9 @@ } if (ver) { - // try to verify this from/to pair of addresses even if it might be explicitly whitelisted + // try to verify the original from/to pair of addresses even if it might be explicitly whitelisted const char *loto = to_lower_string(rcptaddr, false); - bool rc = ver->ok(priv.queueid, priv.mailaddr, loto); + bool rc = ver->ok(priv.queueid, priv.origaddr, loto); free((void*)loto); if (!rc) { smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"no such user"); @@ -1427,7 +1432,7 @@ smfi_setreply(ctx, (char*)"452", (char*)"4.2.1", (char*)"incompatible filtering contexts"); return SMFIS_TEMPFAIL; } - priv.need_content_filter(rcptaddr, con); + priv.need_content_filter(con); char bu[maxlen]; bool uri = false; // content filtering implies also checking helo name on uribl (if enabled) @@ -1482,13 +1487,12 @@ 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) { + if ((strcasecmp(headerf, "Authentication-Results") == 0) && + (strncasecmp(headerv, token_myhostname, strlen(token_myhostname)) == 0)) { const int nmatch = 2; regmatch_t match[nmatch]; while (true) { - if (0 == regexec(&dkim_pattern, value, nmatch, match, 0)) { + if (0 == regexec(&dkim_r_pattern, value, nmatch, match, 0)) { int s1 = match[1].rm_so; // domain int e1 = match[1].rm_eo; if (s1 != -1) { @@ -1503,6 +1507,19 @@ else break; } } + else if (strcasecmp(headerf, "DKIM-Signature") == 0) { + const int nmatch = 2; + regmatch_t match[nmatch]; + if (0 == regexec(&dkim_s_pattern, value, nmatch, match, 0)) { + int s1 = match[1].rm_so; // domain + int e1 = match[1].rm_eo; + if (s1 != -1) { + value[e1] = '\0'; + priv.dkim_signers.insert(strdup(value+s1)); + } + } + } + else priv.dkim_ok = false; } } @@ -1510,8 +1527,7 @@ if ((!priv.fromaddr) && (strcasecmp(headerf, "from") == 0)) { const int nmatch = 2; regmatch_t match[nmatch]; - int err = regexec(&from_pattern, value, nmatch, match, 0); - if (err == 0) { + if (0 == regexec(&from_pattern, value, nmatch, match, 0)) { int s1 = match[1].rm_so; // domain int e1 = match[1].rm_eo; if (s1 != -1) { @@ -1887,8 +1903,14 @@ exit(3); } - // setup dkim signature detection - if (regcomp(&dkim_pattern, " dkim=pass .[0-9]*-bit key. header.d=([^ ]+) ", REG_ICASE | REG_EXTENDED)) { + // setup dkim results signature detection + if (regcomp(&dkim_r_pattern, " dkim=pass .[0-9]*-bit key. header.d=([^ ]+) ", REG_ICASE | REG_EXTENDED)) { + printf("cannot compile regex pattern to find dkim results gnatures\n"); + exit(3); + } + + // setup dkim results signature detection + if (regcomp(&dkim_s_pattern, " d=([^;]+);", REG_ICASE | REG_EXTENDED)) { printf("cannot compile regex pattern to find dkim signatures\n"); exit(3); }