Mercurial > dnsbl
comparison src/context.cpp @ 382:c378e9d03f37
start parsing spf txt records
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 06 Mar 2017 12:21:05 -0800 |
parents | 879a470c6ac3 |
children | 7b7066a51c33 |
comparison
equal
deleted
inserted
replaced
381:879a470c6ac3 | 382:c378e9d03f37 |
---|---|
7 */ | 7 */ |
8 | 8 |
9 #include "includes.h" | 9 #include "includes.h" |
10 | 10 |
11 #include <arpa/inet.h> | 11 #include <arpa/inet.h> |
12 #include <arpa/nameser.h> | |
12 #include <net/if.h> | 13 #include <net/if.h> |
13 #include <netdb.h> | 14 #include <netdb.h> |
14 #include <netinet/in.h> | 15 #include <netinet/in.h> |
15 #include <netinet/tcp.h> | 16 #include <netinet/tcp.h> |
16 #include <sys/ioctl.h> | 17 #include <sys/ioctl.h> |
1120 p++; | 1121 p++; |
1121 } while (true); | 1122 } while (true); |
1122 } | 1123 } |
1123 | 1124 |
1124 | 1125 |
1125 #ifdef NS_PACKETSZ | 1126 bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level) |
1126 bool CONTEXT::resolve_spf(const char *from, int32_t ip, mlfiPriv *priv) | |
1127 { | 1127 { |
1128 char buf[maxlen]; | 1128 char buf[maxlen]; |
1129 dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen); | 1129 dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen); |
1130 if (*buf) { | 1130 if (*buf) { |
1131 log(priv->queueid, "found txt record %s", buf); | 1131 log(priv->queueid, "found txt record for %s", from); |
1132 log(priv->queueid, "found txt record value %s", buf); | |
1133 char *p = buf; | |
1134 char *e = p + strlen(p); // point to trailing null | |
1135 while (p = strstr(p, " ip4:")) { | |
1136 p += 5; | |
1137 char *b = strchr(p, ' '); | |
1138 if (b) *b = '\0'; | |
1139 char *s = strchr(p, '/'); | |
1140 if (s) *s = '\0'; | |
1141 in_addr ipx; | |
1142 if (inet_aton(p, &ipx)) { | |
1143 if (s) { | |
1144 int mask = atoi(s+1); | |
1145 if ((mask >= 16) && (mask <= 32)) { | |
1146 int low = (1 << (32-mask)) - 1; | |
1147 ipx.s_addr &= low ^ 0xffffffff; | |
1148 if ((ip >= ipx.s_addr) && (ip <= ipx.s_addr + low)) { | |
1149 log(priv->queueid, "match %s", p); | |
1150 if (s) log(priv->queueid, "match /%s", s+1); | |
1151 return true; | |
1152 } | |
1153 } | |
1154 } | |
1155 } | |
1156 if (b) *b = ' '; | |
1157 if (s) *s = '/'; | |
1158 p = (b) ? b+1 : e; | |
1159 } | |
1160 p = buf; | |
1161 while ((level < 5) && (p = strstr(p, " include:"))) { | |
1162 p += 9; | |
1163 char *b = strchr(p, ' '); | |
1164 if (b) *b = '\0'; | |
1165 if (resolve_spf(p, ip, priv, level+1)) return true; | |
1166 if (b) *b = ' '; | |
1167 p = (b) ? b+1 : e; | |
1168 } | |
1132 } | 1169 } |
1133 return false; | 1170 return false; |
1134 } | 1171 } |
1135 #endif | |
1136 | 1172 |
1137 | 1173 |
1138 const char *CONTEXT::acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, mlfiPriv *priv, string& msg) { | 1174 const char *CONTEXT::acceptable_content(recorder &memory, int score, int bulk, const char *queueid, string_set &signers, const char *from, mlfiPriv *priv, string& msg) { |
1139 DKIMP dk = find_dkim_from(from); | 1175 DKIMP dk = find_dkim_from(from); |
1140 | 1176 |
1147 } | 1183 } |
1148 } | 1184 } |
1149 | 1185 |
1150 if (dk) { | 1186 if (dk) { |
1151 const char *st = dk->action; | 1187 const char *st = dk->action; |
1188 if ((st == token_require_signed) && | |
1189 dk->signer && | |
1190 strcmp(dk->signer, " ") && | |
1191 resolve_spf(from, priv->ip, priv)) { | |
1192 log(queueid, "spf pass for %s with required dkim signer", from); | |
1193 } | |
1152 for (string_set::iterator s=signers.begin(); s!=signers.end(); s++) { | 1194 for (string_set::iterator s=signers.begin(); s!=signers.end(); s++) { |
1153 // signed by a white listed signer | 1195 // signed by a white listed signer |
1154 if ((st == token_signed_white) && in_signing_set(*s,dk->signer)) { | 1196 if ((st == token_signed_white) && in_signing_set(*s,dk->signer)) { |
1155 log(queueid, "whitelisted dkim signer %s", *s); | 1197 log(queueid, "whitelisted dkim signer %s", *s); |
1156 return token_white; | 1198 return token_white; |
1167 msg = string(buf); | 1209 msg = string(buf); |
1168 return token_black; | 1210 return token_black; |
1169 } | 1211 } |
1170 } | 1212 } |
1171 if (st == token_require_signed) { | 1213 if (st == token_require_signed) { |
1172 #ifdef NS_PACKETSZ | 1214 // not signed by a required signer, but maybe passes strong spf check |
1173 // not signed by the required signers, but maybe passes strong spf check | 1215 // only check spf if the list of required signers is not a single blank. |
1174 if (resolve_spf(from, priv->ip, priv) { | 1216 if (dk->signer && strcmp(dk->signer, " ") && resolve_spf(from, priv->ip, priv)) { |
1175 log(queueid, "spf pass for %s rather than required dkim signer", from); | 1217 log(queueid, "spf pass for %s rather than required dkim signer", from); |
1176 return token_white; | 1218 return token_white; |
1177 } | 1219 } |
1178 #endif | |
1179 char buf[maxlen]; | 1220 char buf[maxlen]; |
1180 snprintf(buf, sizeof(buf), "Mail rejected - not dkim signed by %s", dk->signer); | 1221 snprintf(buf, sizeof(buf), "Mail rejected - not dkim signed by %s", dk->signer); |
1181 msg = string(buf); | 1222 msg = string(buf); |
1182 return token_black; | 1223 return token_black; |
1183 } | 1224 } |