Mercurial > dnsbl
comparison src/context.cpp @ 421:22027ad2a28f stable-6-0-58
spf code now handles %{d} and %{h} macros; use envelope from value for spf if it is a subdomain of the header from domain
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 19 May 2017 13:44:13 -0700 |
parents | 91f2a127ec69 |
children | c9b7b6dd1206 |
comparison
equal
deleted
inserted
replaced
420:4901cdbc1fca | 421:22027ad2a28f |
---|---|
1128 p = c + 1; | 1128 p = c + 1; |
1129 } while (true); | 1129 } while (true); |
1130 } | 1130 } |
1131 | 1131 |
1132 | 1132 |
1133 void CONTEXT::replace(char *buf, char *p, const char *what) | |
1134 { | |
1135 // replace 4 chars in buf starting at p with what | |
1136 char repl[maxlen]; | |
1137 size_t bn = strlen(buf); | |
1138 size_t wn = strlen(what); | |
1139 if ((bn - 4 + wn) < (size_t)maxlen) { | |
1140 size_t n = p - buf; // leading part length | |
1141 strncpy(repl, buf, n); // leading part | |
1142 strcpy(repl+n, what); // replacement | |
1143 strcpy(repl+n+wn, buf+n+4); // trailing part | |
1144 strcpy(buf, repl); | |
1145 } | |
1146 } | |
1147 | |
1133 bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level) | 1148 bool CONTEXT::resolve_spf(const char *from, uint32_t ip, mlfiPriv *priv, int level) |
1134 { | 1149 { |
1135 // ip is in host order | 1150 // ip is in host order |
1151 if ((level == 0) && (priv->mailaddr)) { | |
1152 const char *f = strchr(priv->mailaddr, '@'); | |
1153 if (f) { | |
1154 f++; | |
1155 size_t efl = strlen(f); // envelope from domain | |
1156 size_t hfl = strlen(from); // header from domain | |
1157 if (efl > hfl) { | |
1158 size_t off = efl - hfl; | |
1159 if ((f[off-1] == '.') && (strcmp(f+off,from) == 0)) { | |
1160 // envelope from is a strict child of header from | |
1161 from = f; // use envelope from rather than header from | |
1162 } | |
1163 } | |
1164 } | |
1165 } | |
1136 char buf[maxlen]; | 1166 char buf[maxlen]; |
1137 log(priv->queueid, "looking for %s txt record", from); | 1167 log(priv->queueid, "looking for %s txt record", from); |
1138 dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen); | 1168 dns_interface(*priv, from, ns_t_txt, false, NULL, buf, maxlen); |
1139 if (*buf) { | 1169 if (*buf) { |
1140 log(priv->queueid, "found txt record %s", buf); | 1170 log(priv->queueid, "found txt record %s", buf); |
1141 // expand some macros here - a very restricted subset of all possible spf macros | 1171 // expand some macros here - a very restricted subset of all possible spf macros |
1142 // only expand the first one. | 1172 // only expand the first instance of each. |
1143 char *p = strstr(buf, "%{i}"); | 1173 char *p = strstr(buf, "%{i}"); |
1144 if (p) { | 1174 if (p) { |
1145 char repl[maxlen]; | |
1146 char adr[sizeof "255.255.255.255 "]; | 1175 char adr[sizeof "255.255.255.255 "]; |
1147 adr[0] = '\0'; | 1176 adr[0] = '\0'; |
1148 inet_ntop(AF_INET, (const u_char *)&priv->ip, adr, sizeof(adr)); | 1177 inet_ntop(AF_INET, (const u_char *)&priv->ip, adr, sizeof(adr)); |
1149 size_t bn = strlen(buf); | 1178 replace(buf, p, adr); |
1150 size_t an = strlen(adr); | 1179 log(priv->queueid, "have txt record %s", buf); |
1151 if ((bn - 4 + an) < (size_t)maxlen) { | 1180 } |
1152 size_t n = p - buf; // leading part length | 1181 p = strstr(buf, "%{h}"); |
1153 strncpy(repl, buf, n); // leading part | 1182 if (p) { |
1154 strcpy(repl+n, adr); // replacement | 1183 replace(buf, p, priv->helo); |
1155 strcpy(repl+n+an, buf+n+4); // trailing part | 1184 log(priv->queueid, "have txt record %s", buf); |
1156 strcpy(buf, repl); | 1185 } |
1157 } | 1186 p = strstr(buf, "%{d}"); |
1187 if (p) { | |
1188 replace(buf, p, from); | |
1158 log(priv->queueid, "have txt record %s", buf); | 1189 log(priv->queueid, "have txt record %s", buf); |
1159 } | 1190 } |
1160 // | 1191 // |
1161 p = strchr(buf, ' '); // must start with 'v=spf1 ' | 1192 p = strchr(buf, ' '); // must start with 'v=spf1 ' |
1162 if (!p) return false; // broken spf | 1193 if (!p) return false; // broken spf |