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