diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/qmail-remote/dns.c | 59 | ||||
| -rw-r--r-- | src/qmail-remote/qmail-remote.c | 25 | ||||
| -rw-r--r-- | src/qmail-remote/qmail-remote.h | 2 | ||||
| -rw-r--r-- | src/qmail-remote/tls.c | 4 |
4 files changed, 81 insertions, 9 deletions
diff --git a/src/qmail-remote/dns.c b/src/qmail-remote/dns.c index 61fd483..1d3fc97 100644 --- a/src/qmail-remote/dns.c +++ b/src/qmail-remote/dns.c @@ -113,13 +113,18 @@ static unsigned int use_host_as_mx (skadns_t *a, char const *host, genalloc *mxi #define qmailr_dtempsys(...) do { skadns_end(&a) ; qmailr_tempsys(__VA_ARGS__) ; } while (0) #define qmailr_dtempusys(...) do { skadns_end(&a) ; qmailr_tempusys(__VA_ARGS__) ; } while (0) -unsigned int dns_stuff (char const *host, char const *const *eaddr, unsigned int n, size_t *eaddrpos, genalloc *mxipind, stralloc *storage, unsigned int timeoutdns, char const *ipme4, unsigned int n4, char const *ipme6, unsigned int n6, uint32_t flags) +unsigned int dns_stuff (char const *helohost, char *heloip4, char *heloip6, char const *host, char const *const *eaddr, unsigned int n, size_t *eaddrpos, genalloc *mxipind, stralloc *storage, unsigned int timeoutdns, char const *ipme4, unsigned int n4, char const *ipme6, unsigned int n6, uint32_t flags) { skadns_t a = SKADNS_ZERO ; genalloc mxipi = GENALLOC_ZERO ; /* mxipinfo */ unsigned int pending = 0 ; unsigned int mxn = 0 ; + stralloc helosa = STRALLOC_ZERO ; uint16_t mxid = UINT16_MAX ; + uint16_t heloid4 = UINT16_MAX ; +#ifdef SKALIBS_IPV6_ENABLED + uint16_t heloid6 = UINT16_MAX ; +#endif tain deadline ; cnameinfo cnames[n] ; @@ -127,6 +132,20 @@ unsigned int dns_stuff (char const *host, char const *const *eaddr, unsigned int if (!skadns_startf_g(&a, &deadline)) qmailr_tempusys("start asynchronous DNS helper") ; + { + s6dns_domain_t q ; + if (!s6dns_domain_fromstring_noqualify_encode(&q, helohost, strlen(helohost))) + qmailr_dtempusys("DNS-encode helo string") ; + if (!skadns_send_g(&a, &heloid4, &q, S6DNS_T_A, &deadline, &deadline)) + qmailr_dtempusys("send ", "A", " DNS query") ; + pending++ ; +#ifdef SKALIBS_IPV6_ENABLED + if (!skadns_send_g(&a, &heloid6, &q, S6DNS_T_AAAA, &deadline, &deadline)) + qmailr_dtempusys("send ", "AAAA", " DNS query") ; + pending++ ; +#endif + } + for (unsigned int i = 0 ; i < n ; i++) { char const *at = strrchr(eaddr[i], '@') ; @@ -186,6 +205,42 @@ unsigned int dns_stuff (char const *host, char const *const *eaddr, unsigned int uint16_t packetlen = skadns_packetlen(&a, ids[j]) ; if (!packet) qmailr_dtempsys("DNS packet reading error") ; + if (ids[j] == heloid4) /* ipv4 for the helohost */ + { + s6dns_message_header_t h ; + r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_a, &helosa) ; + if (r == -1) qmailr_dtempsys("DNS packet parsing error") ; + if (!r) + { + if (errno == EBUSY || errno == EIO) qmailr_dtemp("Temporary DNS error while resolving ", "A", "for helohost") ; + else qmailr_dperm("DNS ", "A", " resolution error") ; + } + skadns_release(&a, heloid4) ; + pending-- ; + heloid4 = UINT16_MAX ; + if (helosa.len >= 4) memcpy(heloip4, helosa.s, 4) ; + helosa.len = 0 ; + } + +#ifdef SKALIBS_IPV6_ENABLED + if (ids[j] == heloid6) /* ipv4 for the helohost */ + { + s6dns_message_header_t h ; + r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_aaaa, &helosa) ; + if (r == -1) qmailr_dtempsys("DNS packet parsing error") ; + if (!r) + { + if (errno == EBUSY || errno == EIO) qmailr_dtemp("Temporary DNS error while resolving ", "AAAA", "for helohost") ; + else qmailr_dperm("DNS ", "AAAA", " resolution error") ; + } + skadns_release(&a, heloid6) ; + pending-- ; + heloid6 = UINT16_MAX ; + if (helosa.len >= 16) memcpy(heloip6, helosa.s, 16) ; + helosa.len = 0 ; + } +#endif + if (ids[j] == mxid) /* return from MX query */ { s6dns_message_header_t h ; @@ -324,6 +379,8 @@ unsigned int dns_stuff (char const *host, char const *const *eaddr, unsigned int } skadns_end(&a) ; /* we done, buddy */ + stralloc_free(&helosa) ; + for (unsigned int i = 0 ; i < n ; i++) { eaddrpos[i] = storage->len ; diff --git a/src/qmail-remote/qmail-remote.c b/src/qmail-remote/qmail-remote.c index 58cba67..cd7c746 100644 --- a/src/qmail-remote/qmail-remote.c +++ b/src/qmail-remote/qmail-remote.c @@ -152,18 +152,29 @@ int main (int argc, char const *const *argv) { genalloc mxipind = GENALLOC_ZERO ; - mxip const *mxs ; - size_t eaddrpos[argc] ; + mxip *mxs ; + int do4 = 1, do6 = 1 ; + char heloip4[4] = "\0\0\0" ; + char heloip6[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ; size_t ntot = 0 ; unsigned int pass = 1 + (qtls.flagwanttls && qtls.strictness == 1) ; - unsigned int mxn = dns_stuff(hostpos ? storage.s + hostpos : host, argv, argc, eaddrpos, &mxipind, &storage, timeoutdns, ipme4.s, ipme4.len >> 2, ipme6.s, ipme6.len >> 4, !hostpos) ; + size_t eaddrpos[argc] ; + unsigned int mxn = dns_stuff(storage.s + helopos, heloip4, heloip6, hostpos ? storage.s + hostpos : host, argv, argc, eaddrpos, &mxipind, &storage, timeoutdns, ipme4.s, ipme4.len >> 2, ipme6.s, ipme6.len >> 4, !hostpos) ; if (!mxn) qmailr_perm("No suitable MX found for remote host") ; stralloc_free(&ipme4) ; stralloc_free(&ipme6) ; mxs = genalloc_s(mxip, &mxipind) ; - for (unsigned int i = 0 ; i < mxn ; i++) ntot += mxs[i].n4 + mxs[i].n6 ; - if (!ntot) qmailr_perm("No suitable IP addresses for the MX") ; + if (!memcmp(heloip4, "\0\0\0", 4)) do4 = 0 ; + if (!memcmp(heloip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) do6 = 0 ; + if (!do4 && !do6) qmailr_perm("No suitable IP addresses for ", "helohost") ; + for (unsigned int i = 0 ; i < mxn ; i++) + { + if (!do4) mxs[i].n4 = 0 ; + if (!do6) mxs[i].n6 = 0 ; + ntot += mxs[i].n4 + mxs[i].n6 ; + } + if (!ntot) qmailr_perm("No suitable IP addresses for ", "MX") ; while (pass--) { @@ -178,7 +189,8 @@ int main (int argc, char const *const *argv) int fd ; if (qmailr_tcpto_match(ip, 1)) continue ; fd = socket_tcp6() ; - if (fd == -1) qmailr_tempusys("create socket") ; + if (fd == -1) qmailr_tempusys("create", " socket") ; + if (socket_bind6(fd, heloip6, 0) == -1) qmailr_tempusys("bind", " socket") ; qdeadline(&deadline, timeoutconnect) ; if (!socket_deadlineconnstamp6_g(fd, ip, port, &deadline)) { @@ -201,6 +213,7 @@ int main (int argc, char const *const *argv) if (qmailr_tcpto_match(ip, 0)) continue ; fd = socket_tcp4() ; if (fd == -1) qmailr_tempusys("create socket") ; + if (socket_bind4(fd, heloip4, 0) == -1) qmailr_tempusys("bind", " socket") ; qdeadline(&deadline, timeoutconnect) ; if (!socket_deadlineconnstamp4_g(fd, ip, port, &deadline)) { diff --git a/src/qmail-remote/qmail-remote.h b/src/qmail-remote/qmail-remote.h index ad36d88..7b2bd98 100644 --- a/src/qmail-remote/qmail-remote.h +++ b/src/qmail-remote/qmail-remote.h @@ -29,7 +29,7 @@ struct mxip_s } ; #define MXIP_ZERO { 0 } -extern unsigned int dns_stuff (char const *, char const *const *, unsigned int, size_t *, genalloc *, stralloc *, unsigned int, char const *, unsigned int, char const *, unsigned int, uint32_t) ; +extern unsigned int dns_stuff (char const *, char *, char *, char const *, char const *const *, unsigned int, size_t *, genalloc *, stralloc *, unsigned int, char const *, unsigned int, char const *, unsigned int, uint32_t) ; /* smtproutes */ diff --git a/src/qmail-remote/tls.c b/src/qmail-remote/tls.c index 88a2370..9689578 100644 --- a/src/qmail-remote/tls.c +++ b/src/qmail-remote/tls.c @@ -44,7 +44,7 @@ void run_tls (int fdr, char const *fmtip, unsigned int timeoutconnect, unsigned char fmtw[UINT_FMT] ; char fmtt[UINT_FMT] ; char fmtk[UINT_FMT] ; - char const *argv[23 + n] ; + char const *argv[24 + n] ; if (fdw == -1) qmailr_tempusys("duplicate file descriptor") ; if (pipe(p) == -1) qmailr_tempusys("pipe") ; @@ -74,6 +74,8 @@ void run_tls (int fdr, char const *fmtip, unsigned int timeoutconnect, unsigned argv[m++] = fmtw ; argv[m++] = "-k" ; argv[m++] = storage + mxnamepos ; + if (qtls->strictness < 2) + argv[m++] = "--no-verify-cert" ; /* don't need full webpki if SMTPS isn't enforced */ argv[m++] = "--" ; argv[m++] = SMTPD_STARTTLS_PROXY_LIBEXECPREFIX "qmail-remote-io" ; |
