diff options
Diffstat (limited to 'src/qmail-remote.c')
-rw-r--r-- | src/qmail-remote.c | 1275 |
1 files changed, 671 insertions, 604 deletions
diff --git a/src/qmail-remote.c b/src/qmail-remote.c index 5ef9465..2a7498c 100644 --- a/src/qmail-remote.c +++ b/src/qmail-remote.c @@ -1,76 +1,77 @@ #ifdef IDN2 -#include <idn2.h> + #include <idn2.h> #endif -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <netinet/in.h> #include <arpa/inet.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> -#include "sig.h" -#include "stralloc.h" + +#include "alloc.h" +#include "base64.h" #include "buffer.h" -#include "scan.h" -#include "case.h" #include "byte.h" +#include "case.h" +#include "constmap.h" +#include "exit.h" +#include "fmt.h" +#include "genalloc.h" +#include "ip.h" #include "logmsg.h" +#include "scan.h" +#include "sig.h" +#include "socket_if.h" +#include "str.h" +#include "stralloc.h" +#include "timeout.h" +#include "timeoutconn.h" +#include "uint_t.h" + #include "auto_qmail.h" #include "control.h" #include "dns.h" -#include "alloc.h" -#include "genalloc.h" -#include "quote.h" -#include "fmt.h" -#include "ip.h" +#include "hmac_md5.h" #include "ipalloc.h" #include "ipme.h" -#include "str.h" #include "now.h" -#include "exit.h" -#include "constmap.h" +#include "quote.h" #include "tcpto.h" -#include "timeout.h" -#include "timeoutconn.h" -#include "base64.h" -#include "socket_if.h" -#include "ucspissl.h" -#include "hmac_md5.h" -#include "tls_remote.h" #include "tls_errors.h" +#include "tls_remote.h" #include "tls_timeoutio.h" -#include "uint_t.h" +#include "ucspissl.h" #define WHO "qmail-remote" -#define MAX_SIZE 200000000 -#define HUGESMTPTEXT 1000 /* RFC 5322; was 5000 chars/line */ -#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ -#define PORT_QMTP 209 -#define PORT_SMTPS 465 +#define MAX_SIZE 200000000 +#define HUGESMTPTEXT 1000 /* RFC 5322; was 5000 chars/line */ +#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ +#define PORT_QMTP 209 +#define PORT_SMTPS 465 #define PORT_SUBMISSION 587 -#define PORT_QMTPS 6209 -#define VERIFYDEPTH 1 +#define PORT_QMTPS 6209 +#define VERIFYDEPTH 1 unsigned long port = PORT_SMTP; /** @file qmail-remote.c -- versatile SMTP(S)/QMTP(S) client */ -int flagauth = 0; /* 1 = login; 2 = plain; 3 = crammd5 */ -int flagsmtps = 0; /* RFC 8314 - 'implicit TLS' */ -int flagtlsdomain = 0; /* 0 = no; 1 = yes; 2 = cert */ -int flagtls = 0; /* flagtls: XYZ +int flagauth = 0; /* 1 = login; 2 = plain; 3 = crammd5 */ +int flagsmtps = 0; /* RFC 8314 - 'implicit TLS' */ +int flagtlsdomain = 0; /* 0 = no; 1 = yes; 2 = cert */ +int flagtls = 0; /* flagtls: XYZ (mode) Z: -2 = rejected; -1 = not; 0 = no, default; Z > 0 see tls_remote.c (prot) Y: 0 = StartTLS; 1 = SMTPS; 2 = QMTPS (active) X: 1 = running TLS connection (after DNS lookup) (done) Z: 1: CA chain; 2: Cert wildname; 3: Cert exactname; 4: Cert fingerprint; 5: TLSA record */ -int flagverify = 0; /* 1 = verify Cert against CA; 2 = verify against Dir; 3 = triggerd by TLSA; - -2 = Cert pinning; -1 = no TLSA validation */ +int flagverify = 0; /* 1 = verify Cert against CA; 2 = verify against Dir; 3 = triggerd by TLSA; + -2 = Cert pinning; -1 = no TLSA validation */ int flagutf8 = 0; -GEN_ALLOC_typedef(saa,stralloc,sa,len,a) -GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) -static stralloc sauninit = {0}; +GEN_ALLOC_typedef(saa, stralloc, sa, len, a) GEN_ALLOC_readyplus( + saa, stralloc, sa, len, a, i, n, x, 10, saa_readyplus) static stralloc sauninit = {0}; stralloc helohost = {0}; stralloc eaihost = {0}; @@ -103,22 +104,20 @@ unsigned long msize = 0; struct ip_mx partner; SSL *ssl; -SSL_CTX *ctx; +SSL_CTX *ctx; char smallbuf[BUFFER_SMALL]; -buffer bs = BUFFER_INIT(write,1,smallbuf,sizeof(smallbuf)); - -void out(char *s) -{ - if (buffer_puts(&bs,s) == -1) - _exit(0); - } -void zero() -{ - if (buffer_put(&bs,"\0",1) == -1) - _exit(0); +buffer bs = BUFFER_INIT(write, 1, smallbuf, sizeof(smallbuf)); + +void out(char *s) +{ + if (buffer_puts(&bs, s) == -1) _exit(0); +} +void zero() +{ + if (buffer_put(&bs, "\0", 1) == -1) _exit(0); } -void zerodie() +void zerodie() { zero(); buffer_flush(&bs); @@ -126,127 +125,127 @@ void zerodie() _exit(0); } -void outsafe(stralloc *sa) -{ - int i; +void outsafe(stralloc *sa) +{ + int i; char ch; for (i = 0; i < sa->len; ++i) { - ch = sa->s[i]; + ch = sa->s[i]; if (ch == 0) continue; - if (ch < 33) ch = '?'; + if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; - if (buffer_put(&bs,&ch,1) == -1) _exit(0); - } + if (buffer_put(&bs, &ch, 1) == -1) _exit(0); + } } -void temp_noip() -{ - out("ZInvalid ipaddr in control/domainips (#4.3.0)\n"); - zerodie(); +void temp_noip() +{ + out("ZInvalid ipaddr in control/domainips (#4.3.0)\n"); + zerodie(); } -void temp_nomem() -{ - out("ZOut of memory. (#4.3.0)\n"); - zerodie(); +void temp_nomem() +{ + out("ZOut of memory. (#4.3.0)\n"); + zerodie(); } -void temp_oserr() -{ - out("ZSystem resources temporarily unavailable. (#4.3.0)\n"); - zerodie(); +void temp_oserr() +{ + out("ZSystem resources temporarily unavailable. (#4.3.0)\n"); + zerodie(); } -void temp_osip() -{ - out("ZCan't bind to local ip address: "); - outsafe(&sendip); +void temp_osip() +{ + out("ZCan't bind to local ip address: "); + outsafe(&sendip); out(". (#4.3.0)\n"); - zerodie(); + zerodie(); } -void temp_noconn() -{ +void temp_noconn() +{ out("ZSorry, I wasn't able to establish an SMTP connection: "); - outsafe(&canonhost); + outsafe(&canonhost); out(". (#4.3.0)\n"); - zerodie(); + zerodie(); } -void temp_qmtpnoc() -{ +void temp_qmtpnoc() +{ out("ZSorry, I wasn't able to establish an QMTP connection: "); - outsafe(&canonhost); + outsafe(&canonhost); out(". (#4.3.1)\n"); - zerodie(); + zerodie(); } -void temp_read() -{ - out("ZUnable to read message. (#4.3.0)\n"); - zerodie(); +void temp_read() +{ + out("ZUnable to read message. (#4.3.0)\n"); + zerodie(); } -void temp_dnscanon() -{ - out("ZCNAME lookup failed temporarily for: "); - outsafe(&canonhost); +void temp_dnscanon() +{ + out("ZCNAME lookup failed temporarily for: "); + outsafe(&canonhost); out(". (#4.4.3)\n"); - zerodie(); + zerodie(); } -void temp_dns() -{ - out("ZSorry, I couldn't find any host named: "); - outsafe(&host); - out(". (#4.1.2)\n"); - zerodie(); +void temp_dns() +{ + out("ZSorry, I couldn't find any host named: "); + outsafe(&host); + out(". (#4.1.2)\n"); + zerodie(); } -void temp_nomx() -{ +void temp_nomx() +{ out("ZSorry, I couldn't find a mail exchanger or IP address for: "); - outsafe(&host); - out(". Will try again. (#4.1.2)\n"); - zerodie(); + outsafe(&host); + out(". Will try again. (#4.1.2)\n"); + zerodie(); } -void temp_chdir() -{ - out("ZUnable to switch to home directory. (#4.3.0)\n"); - zerodie(); +void temp_chdir() +{ + out("ZUnable to switch to home directory. (#4.3.0)\n"); + zerodie(); } -void temp_control() -{ - out("ZUnable to read control files. (#4.3.0)\n"); - zerodie(); +void temp_control() +{ + out("ZUnable to read control files. (#4.3.0)\n"); + zerodie(); } -void perm_partialline() -{ - out("DSMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); - zerodie(); +void perm_partialline() +{ + out("DSMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); + zerodie(); } -void temp_proto() -{ - out("ZRecipient did not talk proper QMTP (#4.3.0)\n"); - zerodie(); +void temp_proto() +{ + out("ZRecipient did not talk proper QMTP (#4.3.0)\n"); + zerodie(); } -void perm_usage() -{ - out("Dqmail-remote was invoked improperly. (#5.3.5)\n"); - zerodie(); +void perm_usage() +{ + out("Dqmail-remote was invoked improperly. (#5.3.5)\n"); + zerodie(); } -void perm_dns() -{ - out("DSorry, I couldn't find any host named: "); - outsafe(&host); - out(". (#5.1.2)\n"); - zerodie(); +void perm_dns() +{ + out("DSorry, I couldn't find any host named: "); + outsafe(&host); + out(". (#5.1.2)\n"); + zerodie(); } -void perm_nomx() -{ +void perm_nomx() +{ out("DSorry, I couldn't find a mail exchanger or IP address for: "); - outsafe(&host); - out(". (#5.4.4)\n"); - zerodie(); + outsafe(&host); + out(". (#5.4.4)\n"); + zerodie(); } -void perm_ambigmx() -{ +void perm_ambigmx() +{ out("DSorry. Although I'm listed as a best-preference MX or A for that host,\n\ it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n"); - zerodie(); + zerodie(); } -void err_authprot() +void err_authprot() { out("KNo supported AUTH method found, continuing without authentication.\n"); } @@ -257,17 +256,15 @@ void outhost() int len; switch (partner.af) { - case AF_INET: - len = ip4_fmt(ipaddr,(char *)&partner.addr.ip4.d); break; - case AF_INET6: - len = ip6_fmt(ipaddr,(char *)&partner.addr.ip6.d); break; - } - if (buffer_put(&bs,ipaddr,len) == -1) _exit(0); + case AF_INET: len = ip4_fmt(ipaddr, (char *)&partner.addr.ip4.d); break; + case AF_INET6: len = ip6_fmt(ipaddr, (char *)&partner.addr.ip6.d); break; + } + if (buffer_put(&bs, ipaddr, len) == -1) _exit(0); } int flagcritical = 0; -void dropped() +void dropped() { out("ZConnected to "); outhost(); @@ -281,48 +278,48 @@ int timeoutconnect = 60; int smtpfd; int timeout = 1200; -ssize_t saferead(int fd,char *buf,int len) +ssize_t saferead(int fd, char *buf, int len) { int r; if (ssl) { - r = tls_timeoutread(timeout,smtpfd,smtpfd,ssl,buf,len); + r = tls_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len); if (r < 0) temp_tlserr(); } else { - r = timeoutread(timeout,smtpfd,buf,len); + r = timeoutread(timeout, smtpfd, buf, len); } if (r <= 0) dropped(); return r; } -ssize_t safewrite(int fd,char *buf,int len) +ssize_t safewrite(int fd, char *buf, int len) { int r; if (ssl) { - r = tls_timeoutwrite(timeout,smtpfd,smtpfd,ssl,buf,len); + r = tls_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len); if (r < 0) temp_tlserr(); } else { - r = timeoutwrite(timeout,smtpfd,buf,len); + r = timeoutwrite(timeout, smtpfd, buf, len); } if (r <= 0) dropped(); return r; } char inbuf[BUFFER_MTUSIZE]; -buffer bi = BUFFER_INIT(read,0,inbuf,sizeof(inbuf)); +buffer bi = BUFFER_INIT(read, 0, inbuf, sizeof(inbuf)); char outbuf[BUFFER_MTUSIZE]; -buffer bo = BUFFER_INIT(safewrite,-1,outbuf,sizeof(outbuf)); +buffer bo = BUFFER_INIT(safewrite, -1, outbuf, sizeof(outbuf)); char frombuf[BUFFER_SMALL]; -buffer bf = BUFFER_INIT(saferead,-1,frombuf,sizeof(frombuf)); +buffer bf = BUFFER_INIT(saferead, -1, frombuf, sizeof(frombuf)); static stralloc smtptext = {0}; static stralloc header = {0}; - + void get(char *ch) { - buffer_get(&bf,ch,1); + buffer_get(&bf, ch, 1); if (*ch != '\r') if (smtptext.len < HUGESMTPTEXT) - if (!stralloc_append(&smtptext,ch)) temp_nomem(); + if (!stralloc_append(&smtptext, ch)) temp_nomem(); } unsigned long smtpcode() @@ -330,11 +327,14 @@ unsigned long smtpcode() unsigned char ch; unsigned long code; - if (!stralloc_copys(&smtptext,"")) temp_nomem(); + if (!stralloc_copys(&smtptext, "")) temp_nomem(); - get(&ch); code = ch - '0'; - get(&ch); code = code * 10 + (ch - '0'); - get(&ch); code = code * 10 + (ch - '0'); + get(&ch); + code = ch - '0'; + get(&ch); + code = code * 10 + (ch - '0'); + get(&ch); + code = code * 10 + (ch - '0'); for (;;) { get(&ch); if (ch != '-') break; @@ -350,19 +350,20 @@ unsigned long smtpcode() void outsmtptext() { - int i; - if (smtptext.s) if (smtptext.len) { - out("Remote host said: "); - for (i = 0; i < smtptext.len; ++i) - if (!smtptext.s[i]) smtptext.s[i] = '?'; - if (buffer_put(&bs,smtptext.s,smtptext.len) == -1) _exit(0); - smtptext.len = 0; - } + int i; + if (smtptext.s) + if (smtptext.len) { + out("Remote host said: "); + for (i = 0; i < smtptext.len; ++i) + if (!smtptext.s[i]) smtptext.s[i] = '?'; + if (buffer_put(&bs, smtptext.s, smtptext.len) == -1) _exit(0); + smtptext.len = 0; + } } -void quit(char *prepend,char *append) +void quit(char *prepend, char *append) { - buffer_putsflush(&bo,"QUIT\r\n"); + buffer_putsflush(&bo, "QUIT\r\n"); /* waiting for remote side is just too ridiculous */ out(prepend); outhost(); @@ -378,23 +379,22 @@ void blast() char ch; for (;;) { - r = buffer_get(&bi,&ch,1); + r = buffer_get(&bi, &ch, 1); if (r == 0) break; if (r == -1) temp_read(); - if (ch == '.') buffer_put(&bo,".",1); + if (ch == '.') buffer_put(&bo, ".", 1); while (ch != '\n') { - if (ch != '\r') - buffer_put(&bo,&ch,1); // DKIM input - r = buffer_get(&bi,&ch,1); + if (ch != '\r') buffer_put(&bo, &ch, 1); // DKIM input + r = buffer_get(&bi, &ch, 1); if (r == 0) perm_partialline(); if (r == -1) temp_read(); } - buffer_put(&bo,"\r\n",2); + buffer_put(&bo, "\r\n", 2); } flagcritical = 1; - buffer_put(&bo,".\r\n",3); + buffer_put(&bo, ".\r\n", 3); buffer_flush(&bo); } @@ -422,47 +422,46 @@ void tls_init() ssl_errstr(); if (!ctx) temp_tlsctx(); -/* Fetch CA infos for dest */ + /* Fetch CA infos for dest */ - if (flagverify > 0) - if (cafile.len || cadir.len) - if (!ssl_ca(ctx,cafile.s,cadir.s,(int) verifydepth)) temp_tlsca(); + if (flagverify > 0) + if (cafile.len || cadir.len) + if (!ssl_ca(ctx, cafile.s, cadir.s, (int)verifydepth)) temp_tlsca(); - if (ciphers.len) - if (!ssl_ciphers(ctx,ciphers.s)) temp_tlscipher(); + if (ciphers.len) + if (!ssl_ciphers(ctx, ciphers.s)) temp_tlscipher(); -/* Prepare for Certificate Request */ + /* Prepare for Certificate Request */ - if (flagtlsdomain == 2) - switch (tls_certkey(ctx,certfile.s,keyfile.s,keypwd.s)) { - case 0: break; - case -1: temp_tlscert(); + if (flagtlsdomain == 2) switch (tls_certkey(ctx, certfile.s, keyfile.s, keypwd.s)) + { + case 0: break; + case -1: temp_tlscert(); case -2: temp_tlskey(); - case -3: temp_tlschk(); + case -3: temp_tlschk(); } -/* Set SSL Context */ + /* Set SSL Context */ - ssl = ssl_new(ctx,smtpfd); + ssl = ssl_new(ctx, smtpfd); if (!ssl) temp_tlsctx(); -/* Setup SSL FDs */ - - if (!tls_conn(ssl,smtpfd)) temp_tlscon(); + /* Setup SSL FDs */ + + if (!tls_conn(ssl, smtpfd)) temp_tlscon(); -/* Go on in none-blocking mode */ + /* Go on in none-blocking mode */ - if (tls_timeoutconn(timeout,smtpfd,smtpfd,ssl) <= 0) - temp_tlserr(); + if (tls_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0) temp_tlserr(); } int starttls_peer() { int i = 0; - while ((i += str_chr(smtptext.s+i,'\n') + 1) && - (i + 8 < smtptext.len) ) { - if (!str_diffn(smtptext.s + i + 4,"STARTTLS",8)) return 1; } + while ((i += str_chr(smtptext.s + i, '\n') + 1) && (i + 8 < smtptext.len)) { + if (!str_diffn(smtptext.s + i + 4, "STARTTLS", 8)) return 1; + } return 0; } @@ -470,48 +469,61 @@ int starttls_peer() void tls_peercheck() { X509 *cert; - STACK_OF(X509) *certs; - + STACK_OF(X509) * certs; + cert = SSL_get_peer_certificate(ssl); - if (!cert) { flagtls = 100; return; } + if (!cert) { + flagtls = 100; + return; + } if ((certs = SSL_get_peer_cert_chain(ssl)) == NULL) { certs = sk_X509_new_null(); sk_X509_push(certs, cert); } - if (flagverify == -2) { // fingerprinting is silent - if (cafile.len) case_lowerb(cafile.s,cafile.len); - switch (tls_fingerprint(cert,cafile.s + 1,cafile.len - 2)) { - case -1: temp_tlspeercert(); - case -2: temp_tlsdigest(); - case -3: temp_invaliddigest(); - case 0: temp_tlscertfp(); - case 1: flagtls = 104; break; + if (flagverify == -2) { // fingerprinting is silent + if (cafile.len) case_lowerb(cafile.s, cafile.len); + switch (tls_fingerprint(cert, cafile.s + 1, cafile.len - 2)) { + case -1: temp_tlspeercert(); + case -2: temp_tlsdigest(); + case -3: temp_invaliddigest(); + case 0: temp_tlscertfp(); + case 1: flagtls = 104; break; } - } - - if (flagverify >= 0) { // TLSA is default - switch (tlsa_check(certs,remotehost,port)) { - case -4: temp_tlsamissing(); break; /* FIXME */ - case -3: temp_tlsainvalid(); break; - case -2: break; // unsupported type; may happen - case -1: break; // weird TLSA record - case 0: break; // no TLSA record given - case 1: case 2: flagtls = 107; flagverify = 3; break; // full certchain available (-PKIX) - case 3: flagtls = 106; flagverify = 0; break; // TA-CA; verify wont work - case 4: flagtls = 105; flagverify = 0; break; // Endpoint only + } + + if (flagverify >= 0) { // TLSA is default + switch (tlsa_check(certs, remotehost, port)) { + case -4: temp_tlsamissing(); break; /* FIXME */ + case -3: temp_tlsainvalid(); break; + case -2: break; // unsupported type; may happen + case -1: break; // weird TLSA record + case 0: break; // no TLSA record given + case 1: + case 2: + flagtls = 107; + flagverify = 3; + break; // full certchain available (-PKIX) + case 3: + flagtls = 106; + flagverify = 0; + break; // TA-CA; verify wont work + case 4: + flagtls = 105; + flagverify = 0; + break; // Endpoint only } } if (flagverify > 0) { - switch (tls_checkpeer(ssl,cert,remotehost,flagtls,flagverify)) { + switch (tls_checkpeer(ssl, cert, remotehost, flagtls, flagverify)) { case -1: temp_tlspeercert(); - case -2: temp_tlspeerverify(); - case -3: temp_tlspeervalid(); - case 1: flagtls = 101; break; - case 2: flagtls = 102; break; - case 3: flagtls = 103; break; + case -2: temp_tlspeerverify(); + case -3: temp_tlspeervalid(); + case 1: flagtls = 101; break; + case 2: flagtls = 102; break; + case 3: flagtls = 103; break; } } @@ -519,13 +531,13 @@ void tls_peercheck() X509_free(cert); X509_free(certs); - + return; } /* this file is too long --------------------------------------- smtp UTF8 */ -int utf8string(unsigned char *ch,int len) +int utf8string(unsigned char *ch, int len) { int i = 0; while (i < len) @@ -541,31 +553,31 @@ int utf8received() char ch; stralloc receivedline = {0}; -/* we consider only our own last written header */ + /* we consider only our own last written header */ for (;;) { - r = buffer_get(&bi,&ch,1); + r = buffer_get(&bi, &ch, 1); if (r == 0) break; if (r == -1) temp_read(); - if (ch == '\r') continue; // DKIM + if (ch == '\r') continue; // DKIM if (ch == '\n') { - if (!stralloc_append(&header,"\r")) temp_nomem(); /* received.c does not add '\r' */ - if (!stralloc_append(&header,"\n")) temp_nomem(); - if (case_starts(receivedline.s,"Date:")) return 0; /* header to quit asap */ - if (case_starts(receivedline.s,"Received: from")) received++; /* found Received header */ + if (!stralloc_append(&header, "\r")) temp_nomem(); /* received.c does not add '\r' */ + if (!stralloc_append(&header, "\n")) temp_nomem(); + if (case_starts(receivedline.s, "Date:")) return 0; /* header to quit asap */ + if (case_starts(receivedline.s, "Received: from")) received++; /* found Received header */ if (received) { - if (case_starts(receivedline.s," by ")) { - for (i = 6; i < receivedline.len - 6; ++i) + if (case_starts(receivedline.s, " by ")) { + for (i = 6; i < receivedline.len - 6; ++i) if (*(receivedline.s + i) == ' ') - if (case_starts(receivedline.s + i + 1,"with UTF8")) return 1; + if (case_starts(receivedline.s + i + 1, "with UTF8")) return 1; return 0; - } + } } - if (!stralloc_copys(&receivedline,"")) temp_nomem(); + if (!stralloc_copys(&receivedline, "")) temp_nomem(); } else { - if (!stralloc_append(&header,&ch)) temp_nomem(); - if (!stralloc_catb(&receivedline,&ch,1)) temp_nomem(); + if (!stralloc_append(&header, &ch)) temp_nomem(); + if (!stralloc_catb(&receivedline, &ch, 1)) temp_nomem(); } } return 0; @@ -581,60 +593,59 @@ int smtp_size() int i; if (smtptext.len > 10) for (i = 0; i < smtptext.len; ++i) { - if (case_starts(smtptext.s + i,"SIZE ")) return 1; - } - return 0;; + if (case_starts(smtptext.s + i, "SIZE ")) return 1; + } + return 0; + ; } void smtp_greeting() { - buffer_puts(&bo,"EHLO "); - buffer_put(&bo,helohost.s,helohost.len); - buffer_puts(&bo,"\r\n"); + buffer_puts(&bo, "EHLO "); + buffer_put(&bo, helohost.s, helohost.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); if (smtpcode() != 250) { - buffer_puts(&bo,"HELO "); - buffer_put(&bo,helohost.s,helohost.len); - buffer_puts(&bo,"\r\n"); + buffer_puts(&bo, "HELO "); + buffer_put(&bo, helohost.s, helohost.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); code = smtpcode(); authsender = 0; - if (code >= 500) quit("DConnected to "," but my name was rejected"); - if (code != 250) quit("ZConnected to "," but my name was rejected"); + if (code >= 500) quit("DConnected to ", " but my name was rejected"); + if (code != 250) quit("ZConnected to ", " but my name was rejected"); } flagsize = smtp_size(); } void smtp_starttls() { - buffer_puts(&bo,"STARTTLS\r\n"); + buffer_puts(&bo, "STARTTLS\r\n"); buffer_flush(&bo); if (smtpcode() == 220) { tls_init(); tls_peercheck(); smtp_greeting(); - } - else { + } else { flagtls = -2; - quit("ZConnected to "," but STARTTLS was rejected"); + quit("ZConnected to ", " but STARTTLS was rejected"); } } void mailfrom() { - buffer_puts(&bo,"MAIL FROM:<"); - buffer_put(&bo,sender.s,sender.len); - buffer_puts(&bo,">"); - if (flagutf8 || utf8received()) - buffer_puts(&bo," SMTPUTF8"); + buffer_puts(&bo, "MAIL FROM:<"); + buffer_put(&bo, sender.s, sender.len); + buffer_puts(&bo, ">"); + if (flagutf8 || utf8received()) buffer_puts(&bo, " SMTPUTF8"); if (flagsize && msize) { - buffer_puts(&bo," SIZE="); - buffer_puts(&bo,msgsize); + buffer_puts(&bo, " SIZE="); + buffer_puts(&bo, msgsize); } - buffer_puts(&bo,"\r\n"); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); } @@ -653,22 +664,22 @@ stralloc xuser = {0}; static const char hextab[] = "0123456789abcdef"; -int xtext(stralloc *sa,char *s,int len) +int xtext(stralloc *sa, char *s, int len) { int i; unsigned char c; char xch[2]; - if (!stralloc_copys(sa,"")) temp_nomem(); + if (!stralloc_copys(sa, "")) temp_nomem(); for (i = 0; i < len; i++) { c = s[i]; if (c < 33 || c > 126 || c == '=' || c == '+') { xch[0] = hextab[(c >> 4) & 0x0f]; xch[1] = hextab[c & 0x0f]; - if (!stralloc_catb(sa,xch,2)) temp_nomem(); - } else - if (!stralloc_catb(sa,s + i,1)) temp_nomem(); + if (!stralloc_catb(sa, xch, 2)) temp_nomem(); + } else if (!stralloc_catb(sa, s + i, 1)) + temp_nomem(); } return sa->len; @@ -676,73 +687,72 @@ int xtext(stralloc *sa,char *s,int len) void mailfrom_xtext() { - if (!xtext(&xuser,user.s,user.len)) temp_nomem(); - buffer_puts(&bo,"MAIL FROM:<"); - buffer_put(&bo,sender.s,sender.len); - buffer_puts(&bo,"> AUTH="); - buffer_put(&bo,xuser.s,xuser.len); - if (flagutf8 || utf8received()) - buffer_puts(&bo," SMTPUTF8"); + if (!xtext(&xuser, user.s, user.len)) temp_nomem(); + buffer_puts(&bo, "MAIL FROM:<"); + buffer_put(&bo, sender.s, sender.len); + buffer_puts(&bo, "> AUTH="); + buffer_put(&bo, xuser.s, xuser.len); + if (flagutf8 || utf8received()) buffer_puts(&bo, " SMTPUTF8"); if (flagsize && msize) { - buffer_puts(&bo," SIZE="); - buffer_puts(&bo,msgsize); + buffer_puts(&bo, " SIZE="); + buffer_puts(&bo, msgsize); } - buffer_puts(&bo,"\r\n"); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); } - + int mailfrom_plain() { - buffer_puts(&bo,"AUTH PLAIN\r\n"); + buffer_puts(&bo, "AUTH PLAIN\r\n"); buffer_flush(&bo); - if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH PLAIN)"); + if (smtpcode() != 334) quit("ZConnected to ", " but authentication was rejected (AUTH PLAIN)"); - if (!stralloc_cats(&plain,"")) temp_nomem(); /* RFC 4616 section 2 */ + if (!stralloc_cats(&plain, "")) temp_nomem(); /* RFC 4616 section 2 */ if (!stralloc_0(&plain)) temp_nomem(); - if (!stralloc_cat(&plain,&user)) temp_nomem(); /* user-id */ + if (!stralloc_cat(&plain, &user)) temp_nomem(); /* user-id */ if (!stralloc_0(&plain)) temp_nomem(); - if (!stralloc_cat(&plain,&pass)) temp_nomem(); /* password */ - if (b64encode(&plain,&auth)) quit("ZConnected to "," but unable to base64encode (plain)"); - buffer_put(&bo,auth.s,auth.len); - buffer_puts(&bo,"\r\n"); + if (!stralloc_cat(&plain, &pass)) temp_nomem(); /* password */ + if (b64encode(&plain, &auth)) quit("ZConnected to ", " but unable to base64encode (plain)"); + buffer_put(&bo, auth.s, auth.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); switch (smtpcode()) { case 235: mailfrom_xtext(); break; - case 432: quit("DConnected to "," but password expired"); - case 534: quit("ZConnected to "," but authentication mechamism too weak (plain)"); - default: quit("ZConnected to "," but authentication was rejected (plain)"); + case 432: quit("DConnected to ", " but password expired"); + case 534: quit("ZConnected to ", " but authentication mechamism too weak (plain)"); + default: quit("ZConnected to ", " but authentication was rejected (plain)"); } return 0; } int mailfrom_login() { - buffer_puts(&bo,"AUTH LOGIN\r\n"); + buffer_puts(&bo, "AUTH LOGIN\r\n"); buffer_flush(&bo); - if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)"); - if (!stralloc_copys(&auth,"")) temp_nomem(); - if (b64encode(&user,&auth)) quit("ZConnected to "," but unable to base64encode user"); + if (smtpcode() != 334) quit("ZConnected to ", " but authentication was rejected (AUTH LOGIN)"); + if (!stralloc_copys(&auth, "")) temp_nomem(); + if (b64encode(&user, &auth)) quit("ZConnected to ", " but unable to base64encode user"); - buffer_put(&bo,auth.s,auth.len); - buffer_puts(&bo,"\r\n"); + buffer_put(&bo, auth.s, auth.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); - if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)"); + if (smtpcode() != 334) quit("ZConnected to ", " but authentication was rejected (username)"); - if (!stralloc_copys(&auth,"")) temp_nomem(); - if (b64encode(&pass,&auth)) quit("ZConnected to "," but unable to base64encode pass"); - buffer_put(&bo,auth.s,auth.len); - buffer_puts(&bo,"\r\n"); + if (!stralloc_copys(&auth, "")) temp_nomem(); + if (b64encode(&pass, &auth)) quit("ZConnected to ", " but unable to base64encode pass"); + buffer_put(&bo, auth.s, auth.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); switch (smtpcode()) { case 235: mailfrom_xtext(); break; - case 432: quit("DConnected to "," but password expired"); - case 534: quit("ZConnected to "," but authentication mechanism is too weak (login)"); - default: quit("ZConnected to "," but authentication was rejected (login)"); + case 432: quit("DConnected to ", " but password expired"); + case 534: quit("ZConnected to ", " but authentication mechanism is too weak (login)"); + default: quit("ZConnected to ", " but authentication was rejected (login)"); } return 0; } @@ -753,41 +763,42 @@ int mailfrom_cram() unsigned char digest[16]; unsigned char digascii[33]; - buffer_puts(&bo,"AUTH CRAM-MD5\r\n"); + buffer_puts(&bo, "AUTH CRAM-MD5\r\n"); buffer_flush(&bo); - if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH CRAM-MD5)"); - if (str_chr(smtptext.s + 4,' ')) { /* Challenge */ - if (!stralloc_copys(&slop,"")) temp_nomem(); - if (!stralloc_copyb(&slop,smtptext.s + 4,smtptext.len - 5)) temp_nomem(); - if (b64decode(slop.s,slop.len,&chal)) quit("ZConnected to "," but unable to base64decode challenge"); + if (smtpcode() != 334) quit("ZConnected to ", " but authentication was rejected (AUTH CRAM-MD5)"); + if (str_chr(smtptext.s + 4, ' ')) { /* Challenge */ + if (!stralloc_copys(&slop, "")) temp_nomem(); + if (!stralloc_copyb(&slop, smtptext.s + 4, smtptext.len - 5)) temp_nomem(); + if (b64decode(slop.s, slop.len, &chal)) + quit("ZConnected to ", " but unable to base64decode challenge"); } - hmac_md5((unsigned char *)chal.s,chal.len,pass.s,pass.len,digest); + hmac_md5((unsigned char *)chal.s, chal.len, pass.s, pass.len, digest); - for (j = 0; j < 16; j++) { /* HEX => ASCII */ + for (j = 0; j < 16; j++) { /* HEX => ASCII */ digascii[2 * j] = hextab[digest[j] >> 4]; digascii[2 * j + 1] = hextab[digest[j] & 0x0f]; } - digascii[32]=0; + digascii[32] = 0; - if (!stralloc_copys(&slop,"")) temp_nomem(); - if (!stralloc_cat(&slop,&user)) temp_nomem(); /* user-id */ - if (!stralloc_cats(&slop," ")) temp_nomem(); - if (!stralloc_catb(&slop,digascii,32)) temp_nomem(); /* digest */ + if (!stralloc_copys(&slop, "")) temp_nomem(); + if (!stralloc_cat(&slop, &user)) temp_nomem(); /* user-id */ + if (!stralloc_cats(&slop, " ")) temp_nomem(); + if (!stralloc_catb(&slop, digascii, 32)) temp_nomem(); /* digest */ - if (!stralloc_copys(&auth,"")) temp_nomem(); - if (b64encode(&slop,&auth)) quit("ZConnected to "," but unable to base64encode username+digest"); + if (!stralloc_copys(&auth, "")) temp_nomem(); + if (b64encode(&slop, &auth)) quit("ZConnected to ", " but unable to base64encode username+digest"); - buffer_put(&bo,auth.s,auth.len); - buffer_puts(&bo,"\r\n"); + buffer_put(&bo, auth.s, auth.len); + buffer_puts(&bo, "\r\n"); buffer_flush(&bo); switch (smtpcode()) { case 235: mailfrom_xtext(); break; - case 432: quit("DConnected to "," but password expired"); - case 534: quit("ZConnected to "," but authentication mechamism too weak (cram)"); - default: quit("ZConnected to "," but authentication was rejected (cram)"); + case 432: quit("DConnected to ", " but password expired"); + case 534: quit("ZConnected to ", " but authentication mechamism too weak (cram)"); + default: quit("ZConnected to ", " but authentication was rejected (cram)"); } return 0; } @@ -796,13 +807,13 @@ void smtp_auth() { int i; - if (smtptext.len > 8) + if (smtptext.len > 8) for (i = 4; i < smtptext.len - 5; ++i) { - if (case_starts(smtptext.s + i,"CRAM")) + if (case_starts(smtptext.s + i, "CRAM")) if (mailfrom_cram() >= 0) return; - if (case_starts(smtptext.s + i,"LOGIN")) + if (case_starts(smtptext.s + i, "LOGIN")) if (mailfrom_login() >= 0) return; - if (case_starts(smtptext.s + i,"PLAIN")) + if (case_starts(smtptext.s + i, "PLAIN")) if (mailfrom_plain() >= 0) return; } err_authprot(); @@ -816,87 +827,105 @@ void smtp() int flagbother; int i; - if (flagtls > 10 && flagtls < 20) { /* SMTPS */ + if (flagtls > 10 && flagtls < 20) { /* SMTPS */ tls_init(); - tls_peercheck(); + tls_peercheck(); } code = smtpcode(); - if (code >= 500) quit("DConnected to "," but sender was rejected"); - if (code == 421 || code == 450) quit("ZConnected to "," but probably greylisted"); /* RFC 6647 */ - if (code >= 400) quit("ZConnected to "," but sender was rejected"); - if (code != 220) quit("ZConnected to "," but greeting failed"); + if (code >= 500) quit("DConnected to ", " but sender was rejected"); + if (code == 421 || code == 450) quit("ZConnected to ", " but probably greylisted"); /* RFC 6647 */ + if (code >= 400) quit("ZConnected to ", " but sender was rejected"); + if (code != 220) quit("ZConnected to ", " but greeting failed"); smtp_greeting(); - if (flagtls > 0 && flagtls < 10) { /* STARTTLS */ - if (starttls_peer()) - smtp_starttls(); + if (flagtls > 0 && flagtls < 10) { /* STARTTLS */ + if (starttls_peer()) + smtp_starttls(); else if (flagtls > 3 && flagtls != 9) { - if (!stralloc_0(&host)) temp_nomem(); - temp_tlshost(); + if (!stralloc_0(&host)) temp_nomem(); + temp_tlshost(); } } - if (user.len && pass.len) /* AUTH */ + if (user.len && pass.len) /* AUTH */ smtp_auth(); - else - mailfrom(); /* Mail From */ + else + mailfrom(); /* Mail From */ code = smtpcode(); - if (code >= 500) quit("DConnected to "," but sender was rejected"); - if (code >= 400) quit("ZConnected to "," but sender was probably greylisted"); + if (code >= 500) quit("DConnected to ", " but sender was rejected"); + if (code >= 400) quit("ZConnected to ", " but sender was probably greylisted"); - flagbother = 0; /* Rcpt To */ + flagbother = 0; /* Rcpt To */ for (i = 0; i < reciplist.len; ++i) { - buffer_puts(&bo,"RCPT TO:<"); - buffer_put(&bo,reciplist.sa[i].s,reciplist.sa[i].len); - buffer_puts(&bo,">\r\n"); + buffer_puts(&bo, "RCPT TO:<"); + buffer_put(&bo, reciplist.sa[i].s, reciplist.sa[i].len); + buffer_puts(&bo, ">\r\n"); buffer_flush(&bo); - code = smtpcode(); /* Data */ + code = smtpcode(); /* Data */ if (flagsize) { - if (code == 552) quit("DConnected to "," but message size is too large"); - if (code == 452) quit("ZConnected to "," however insufficient storage space available"); - } + if (code == 552) quit("DConnected to ", " but message size is too large"); + if (code == 452) quit("ZConnected to ", " however insufficient storage space available"); + } if (code == 421 || code == 450) { // Postfix merde ;-) - out("s"); outhost(); out(" sender is greylisting.\n"); - outsmtptext(); zero(); + out("s"); + outhost(); + out(" sender is greylisting.\n"); + outsmtptext(); + zero(); } else if (code >= 500) { - out("h"); outhost(); out(" does not like recipient.\n"); - outsmtptext(); zero(); + out("h"); + outhost(); + out(" does not like recipient.\n"); + outsmtptext(); + zero(); } else if (code >= 400) { - out("s"); outhost(); out(" does not like recipient.\n"); - outsmtptext(); zero(); + out("s"); + outhost(); + out(" does not like recipient.\n"); + outsmtptext(); + zero(); } else { - out("r"); zero(); + out("r"); + zero(); flagbother = 1; } } - if (!flagbother) quit("DGiving up on ",""); + if (!flagbother) quit("DGiving up on ", ""); - buffer_putsflush(&bo,"DATA\r\n"); + buffer_putsflush(&bo, "DATA\r\n"); code = smtpcode(); - if (code >= 500) quit("D"," failed on DATA command"); - if (code >= 400) quit("Z"," failed on DATA command"); + if (code >= 500) quit("D", " failed on DATA command"); + if (code >= 400) quit("Z", " failed on DATA command"); + + buffer_putflush(&bo, header.s, header.len); - buffer_putflush(&bo,header.s,header.len); - blast(); code = smtpcode(); flagcritical = 0; - if (code >= 500) quit("D"," failed after I sent the message"); - if (code >= 400) quit("Z"," failed after I sent the message"); + if (code >= 500) quit("D", " failed after I sent the message"); + if (code >= 400) quit("Z", " failed after I sent the message"); switch (flagtls) { // StartTLS + SMTPS - case 100: case 110: quit("K"," TLS transmitted message accepted"); break; - case 101: case 111: quit("K"," TLS (verified CA) transmitted message accepted"); break; - case 102: case 112: quit("K"," TLS (validated CA+DN*) transmitted message accepted"); break; - case 103: case 113: quit("K"," TLS (validated CA+DN) transmitted message accepted"); break; - case 104: case 114: quit("K"," TLS (CERT pinning) transmitted message accepted"); break; - case 105: case 115: quit("K"," TLS (TLSA EE validated) transmitted message accepted"); break; - case 106: case 116: quit("K"," TLS (TLSA TA validated) transmitted message accepted"); break; - case 107: case 117: quit("K"," TLS (TLSA PKIX verified) transmitted message accepted"); break; - default: quit("K"," accepted message"); break; + case 100: + case 110: quit("K", " TLS transmitted message accepted"); break; + case 101: + case 111: quit("K", " TLS (verified CA) transmitted message accepted"); break; + case 102: + case 112: quit("K", " TLS (validated CA+DN*) transmitted message accepted"); break; + case 103: + case 113: quit("K", " TLS (validated CA+DN) transmitted message accepted"); break; + case 104: + case 114: quit("K", " TLS (CERT pinning) transmitted message accepted"); break; + case 105: + case 115: quit("K", " TLS (TLSA EE validated) transmitted message accepted"); break; + case 106: + case 116: quit("K", " TLS (TLSA TA validated) transmitted message accepted"); break; + case 107: + case 117: quit("K", " TLS (TLSA PKIX verified) transmitted message accepted"); break; + default: quit("K", " accepted message"); break; } } @@ -914,44 +943,44 @@ void qmtp() char num[FMT_ULONG]; int flagallok; - if (qmtpsend == 2) { /* QMTPS */ + if (qmtpsend == 2) { /* QMTPS */ tls_init(); tls_peercheck(); } -/* the following code was substantially taken from serialmail's serialqmtp.c */ + /* the following code was substantially taken from serialmail's serialqmtp.c */ - scan_ulong(msgsize,&len); - buffer_put(&bo,num,fmt_ulong(num,len + 1)); - buffer_put(&bo,":\n",2); + scan_ulong(msgsize, &len); + buffer_put(&bo, num, fmt_ulong(num, len + 1)); + buffer_put(&bo, ":\n", 2); while (len > 0) { n = buffer_feed(&bi); - if (n <= 0) _exit(1); /* wise guy again */ + if (n <= 0) _exit(1); /* wise guy again */ x = buffer_PEEK(&bi); - buffer_put(&bo,x,n); - buffer_SEEK(&bi,n); + buffer_put(&bo, x, n); + buffer_SEEK(&bi, n); len -= n; } - buffer_put(&bo,",",1); + buffer_put(&bo, ",", 1); len = sender.len; - buffer_put(&bo,num,fmt_ulong(num,len)); - buffer_put(&bo,":",1); - buffer_put(&bo,sender.s,sender.len); - buffer_put(&bo,",",1); + buffer_put(&bo, num, fmt_ulong(num, len)); + buffer_put(&bo, ":", 1); + buffer_put(&bo, sender.s, sender.len); + buffer_put(&bo, ",", 1); len = 0; for (i = 0; i < reciplist.len; ++i) - len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1; - buffer_put(&bo,num,fmt_ulong(num,len)); - buffer_put(&bo,":",1); + len += fmt_ulong(num, reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1; + buffer_put(&bo, num, fmt_ulong(num, len)); + buffer_put(&bo, ":", 1); for (i = 0; i < reciplist.len; ++i) { - buffer_put(&bo,num,fmt_ulong(num,reciplist.sa[i].len)); - buffer_put(&bo,":",1); - buffer_put(&bo,reciplist.sa[i].s,reciplist.sa[i].len); - buffer_put(&bo,",",1); + buffer_put(&bo, num, fmt_ulong(num, reciplist.sa[i].len)); + buffer_put(&bo, ":", 1); + buffer_put(&bo, reciplist.sa[i].s, reciplist.sa[i].len); + buffer_put(&bo, ",", 1); } - buffer_put(&bo,",",1); + buffer_put(&bo, ",", 1); buffer_flush(&bo); flagallok = 1; @@ -966,14 +995,15 @@ void qmtp() len = 10 * len + (ch - '0'); } if (!len) temp_proto(); - get(&ch); --len; + get(&ch); + --len; if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto(); - if (!stralloc_copyb(&smtptext,&ch,1)) temp_proto(); + if (!stralloc_copyb(&smtptext, &ch, 1)) temp_proto(); if (flagtls == 100) { - if (!stralloc_cats(&smtptext,"qmtps:")) temp_nomem(); + if (!stralloc_cats(&smtptext, "qmtps:")) temp_nomem(); } else { - if (!stralloc_cats(&smtptext,"qmtp:")) temp_nomem(); + if (!stralloc_cats(&smtptext, "qmtp:")) temp_nomem(); } while (len > 0) { @@ -989,22 +1019,26 @@ void qmtp() if (ch != ',') temp_proto(); smtptext.s[smtptext.len - 1] = '\n'; - if (smtptext.s[0] == 'K') out("r"); + if (smtptext.s[0] == 'K') + out("r"); else if (smtptext.s[0] == 'D') { out("h"); flagallok = 0; - } - else { /* if (smtptext.s[0] == 'Z') */ + } else { /* if (smtptext.s[0] == 'Z') */ out("s"); flagallok = 0; } - if (buffer_put(&bs,smtptext.s + 1,smtptext.len - 1) == -1) temp_qmtpnoc(); + if (buffer_put(&bs, smtptext.s + 1, smtptext.len - 1) == -1) temp_qmtpnoc(); zero(); } if (!flagallok) { - out("DGiving up on "); outhost(); out("\n"); + out("DGiving up on "); + outhost(); + out("\n"); } else { - out("KAll received okay by "); outhost(); out("\n"); + out("KAll received okay by "); + outhost(); + out("\n"); } zerodie(); } @@ -1013,86 +1047,108 @@ void qmtp() /* host has to be canonical [A/AAAA record], box has to be quoted */ -void addrmangle(stralloc *saout,char *address,int *flagalias,int flagcname) +void addrmangle(stralloc *saout, char *address, int *flagalias, int flagcname) { int at; int r = 0; stralloc cn = {0}; - *flagalias = flagcname; /* saout + flagalias are output */ - if (!flagutf8) - flagutf8 = utf8string(address,str_len(address)); + *flagalias = flagcname; /* saout + flagalias are output */ + if (!flagutf8) flagutf8 = utf8string(address, str_len(address)); - at = str_rchr(address,'@'); + at = str_rchr(address, '@'); if (!address[at]) { - if (!stralloc_copys(saout,address)) temp_nomem(); + if (!stralloc_copys(saout, address)) temp_nomem(); return; } - if (!stralloc_copys(&canonbox,address)) temp_nomem(); + if (!stralloc_copys(&canonbox, address)) temp_nomem(); canonbox.len = at; - if (!quote(saout,&canonbox)) temp_nomem(); /* saout = 'inbox' name without quotes ;-) */ - if (!stralloc_cats(saout,"@")) temp_nomem(); + if (!quote(saout, &canonbox)) temp_nomem(); /* saout = 'inbox' name without quotes ;-) */ + if (!stralloc_cats(saout, "@")) temp_nomem(); - if (!stralloc_copys(&canonhost,address + at + 1)) temp_nomem(); - if (flagcname) { /* no relayhost */ + if (!stralloc_copys(&canonhost, address + at + 1)) temp_nomem(); + if (flagcname) { /* no relayhost */ DNS_INIT - switch ((r = dns_cname(&cn,&canonhost))) { - case DNS_MEM: temp_nomem(); + switch ((r = dns_cname(&cn, &canonhost))) { + case DNS_MEM: temp_nomem(); case DNS_SOFT: temp_dnscanon(); case DNS_HARD: ; /* alias loop, not our problem */ - default: if (r > 0) *flagalias = 0; + default: + if (r > 0) *flagalias = 0; } } - if (!stralloc_cat(saout,&canonhost)) temp_nomem(); + if (!stralloc_cat(saout, &canonhost)) temp_nomem(); } void getcontrols() { if (control_init() == -1) temp_control(); - if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control(); - if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) - temp_control(); - if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1) - temp_control(); - switch (control_readfile(&smtproutes,"control/smtproutes",0)) { + if (control_readint(&timeout, "control/timeoutremote") == -1) temp_control(); + if (control_readint(&timeoutconnect, "control/timeoutconnect") == -1) temp_control(); + if (control_rldef(&helohost, "control/helohost", 1, (char *)0) != 1) temp_control(); + switch (control_readfile(&smtproutes, "control/smtproutes", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&mapsmtproutes,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapsmtproutes,smtproutes.s,smtproutes.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapsmtproutes, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapsmtproutes, smtproutes.s, smtproutes.len, 1)) temp_nomem(); + break; } - switch (control_readfile(&domainips,"control/domainips",0)) { + switch (control_readfile(&domainips, "control/domainips", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&mapdomainips,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapdomainips,domainips.s,domainips.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapdomainips, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapdomainips, domainips.s, domainips.len, 1)) temp_nomem(); + break; } - switch (control_readfile(&authsenders,"control/authsenders",0)) { + switch (control_readfile(&authsenders, "control/authsenders", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&mapauthsenders,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapauthsenders,authsenders.s,authsenders.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapauthsenders, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapauthsenders, authsenders.s, authsenders.len, 1)) temp_nomem(); + break; } - switch (control_readfile(&qmtproutes,"control/qmtproutes",0)) { + switch (control_readfile(&qmtproutes, "control/qmtproutes", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&mapqmtproutes,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapqmtproutes,qmtproutes.s,qmtproutes.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapqmtproutes, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapqmtproutes, qmtproutes.s, qmtproutes.len, 1)) temp_nomem(); + break; } - switch (control_readfile(&domaincerts,"control/domaincerts",0)) { + switch (control_readfile(&domaincerts, "control/domaincerts", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&mapdomaincerts,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapdomaincerts,domaincerts.s,domaincerts.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapdomaincerts, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapdomaincerts, domaincerts.s, domaincerts.len, 1)) temp_nomem(); + break; } - switch (control_readfile(&tlsdestinations,"control/tlsdestinations",0)) { + switch (control_readfile(&tlsdestinations, "control/tlsdestinations", 0)) { case -1: temp_control(); - case 0: if (!constmap_init(&maptlsdestinations,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&maptlsdestinations,tlsdestinations.s,tlsdestinations.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&maptlsdestinations, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&maptlsdestinations, tlsdestinations.s, tlsdestinations.len, 1)) temp_nomem(); + break; } } -int main(int argc,char **argv) +int main(int argc, char **argv) { static ipalloc ip = {0}; stralloc netif = {0}; struct stat st; - int i, j, k; + int i, j, k; int p; /* reserved for port */ int r; /* reserved for return code */ unsigned long random; @@ -1109,184 +1165,191 @@ int main(int argc,char **argv) if (chdir(auto_qmail) == -1) temp_chdir(); getcontrols(); - if (!stralloc_copys(&host,argv[1])) temp_nomem(); + if (!stralloc_copys(&host, argv[1])) temp_nomem(); authsender = 0; relayhost = 0; - addrmangle(&sender,argv[2],&flagalias,0); + addrmangle(&sender, argv[2], &flagalias, 0); if (sender.len > 1) { - i = str_chr(sender.s,'@'); + i = str_chr(sender.s, '@'); if (sender.s[i] == '@') - if (!stralloc_copyb(&senddomain,sender.s + i + 1,sender.len - i - 1)) temp_nomem(); // un-terminated + if (!stralloc_copyb(&senddomain, sender.s + i + 1, sender.len - i - 1)) + temp_nomem(); // un-terminated } -/* this file is too long -------------------------------------- set domain ip + helohost */ + /* this file is too long -------------------------------------- set domain ip + helohost */ localip = 0; - + for (i = 0; i <= senddomain.len; ++i) - if ((i == 0) || (senddomain.s[i] == '.')) - if ((localip = constmap(&mapdomainips,senddomain.s + i,senddomain.len - i))) - break; + if ((i == 0) || (senddomain.s[i] == '.')) + if ((localip = constmap(&mapdomainips, senddomain.s + i, senddomain.len - i))) break; - if (!localip) - localip = constmap(&mapdomainips,"*",1); /* one for all */ + if (!localip) localip = constmap(&mapdomainips, "*", 1); /* one for all */ if (localip) { - j = str_chr(localip,'%'); + j = str_chr(localip, '%'); if (localip[j] != '%') j = 0; - k = str_chr(localip,'|'); + k = str_chr(localip, '|'); if (localip[k] != '|') k = 0; - if (k) { /* helohost */ - if (!stralloc_copys(&helohost,localip + k + 1)) temp_nomem(); + if (k) { /* helohost */ + if (!stralloc_copys(&helohost, localip + k + 1)) temp_nomem(); if (!stralloc_0(&helohost)) temp_nomem(); localip[k] = 0; } - if (j) { /* IF index */ + if (j) { /* IF index */ localip[j] = 0; - if (!stralloc_copys(&netif,localip + j + 1)) temp_nomem(); + if (!stralloc_copys(&netif, localip + j + 1)) temp_nomem(); if (!stralloc_0(&netif)) temp_nomem(); } } -/* this file is too long -------------------------------------- authsender routes */ + /* this file is too long -------------------------------------- authsender routes */ for (i = 0; i <= sender.len; ++i) if ((i == 0) || (i == sender.len) || (sender.s[i] == '.') || (sender.s[i] == '@')) - if ((authsender = constmap(&mapauthsenders,sender.s + i,sender.len - i))) - break; + if ((authsender = constmap(&mapauthsenders, sender.s + i, sender.len - i))) break; if (authsender && !*authsender) authsender = 0; if (authsender) { - i = str_chr(authsender,'|'); + i = str_chr(authsender, '|'); if (authsender[i] == '|') { - j = str_chr(authsender + i + 1,'|'); + j = str_chr(authsender + i + 1, '|'); if (authsender[i + j + 1] == '|') { authsender[i] = 0; authsender[i + j + 1] = 0; - if (!stralloc_copys(&user,"")) temp_nomem(); - if (!stralloc_copys(&user,authsender + i + 1)) temp_nomem(); - if (!stralloc_copys(&pass,"")) temp_nomem(); - if (!stralloc_copys(&pass,authsender + i + j + 2)) temp_nomem(); + if (!stralloc_copys(&user, "")) temp_nomem(); + if (!stralloc_copys(&user, authsender + i + 1)) temp_nomem(); + if (!stralloc_copys(&pass, "")) temp_nomem(); + if (!stralloc_copys(&pass, authsender + i + j + 2)) temp_nomem(); } } - p = str_chr(authsender,';'); + p = str_chr(authsender, ';'); if (authsender[p] == ';') { - if (authsender[p + 1] == 's') { flagsmtps = 1, p++; } - scan_ulong(authsender + p + 1,&port); + if (authsender[p + 1] == 's') { + flagsmtps = 1, p++; + } + scan_ulong(authsender + p + 1, &port); authsender[p] = 0; } relayhost = authsender; - if (!stralloc_copys(&host,authsender)) temp_nomem(); + if (!stralloc_copys(&host, authsender)) temp_nomem(); } -/* this file is too long -------------------------------------- standard routes */ + /* this file is too long -------------------------------------- standard routes */ if (!authsender) { - if (sender.len == 0) { /* bounce routes */ - if ((relayhost = constmap(&mapqmtproutes,"!@",2))) { - qmtpsend = 1; port = PORT_QMTP; + if (sender.len == 0) { /* bounce routes */ + if ((relayhost = constmap(&mapqmtproutes, "!@", 2))) { + qmtpsend = 1; + port = PORT_QMTP; } else - relayhost = constmap(&mapsmtproutes,"!@",2); + relayhost = constmap(&mapsmtproutes, "!@", 2); } if (relayhost && !*relayhost) relayhost = 0; if (!relayhost) { - for (i = 0; i <= host.len; ++i) { /* qmtproutes */ + for (i = 0; i <= host.len; ++i) { /* qmtproutes */ if ((i == 0) || (i == host.len) || (host.s[i] == '.')) - if ((relayhost = constmap(&mapqmtproutes,host.s + i,host.len - i))) { - qmtpsend = 1; port = PORT_QMTP; - break; - } /* default smtproutes */ - if ((relayhost = constmap(&mapsmtproutes,host.s + i,host.len - i))) + if ((relayhost = constmap(&mapqmtproutes, host.s + i, host.len - i))) { + qmtpsend = 1; + port = PORT_QMTP; break; + } /* default smtproutes */ + if ((relayhost = constmap(&mapsmtproutes, host.s + i, host.len - i))) break; } } if (relayhost && !*relayhost) relayhost = 0; - if (relayhost) { /* default smtproutes -- authenticated */ - i = str_chr(relayhost,'|'); + if (relayhost) { /* default smtproutes -- authenticated */ + i = str_chr(relayhost, '|'); if (relayhost[i] == '|') { - j = str_chr(relayhost + i + 1,'|'); // authenticate + j = str_chr(relayhost + i + 1, '|'); // authenticate if (relayhost[i + j + 1] == '|') { relayhost[i] = 0; relayhost[i + j + 1] = 0; - if (!stralloc_copys(&user,"")) temp_nomem(); - if (!stralloc_copys(&user,relayhost + i + 1)) temp_nomem(); - if (!stralloc_copys(&pass,"")) temp_nomem(); - k = str_chr(relayhost + i + j + 2,'|'); // local ip + if (!stralloc_copys(&user, "")) temp_nomem(); + if (!stralloc_copys(&user, relayhost + i + 1)) temp_nomem(); + if (!stralloc_copys(&pass, "")) temp_nomem(); + k = str_chr(relayhost + i + j + 2, '|'); // local ip if (relayhost[i + j + k + 2] == '|') { relayhost[i + j + k + 2] = 0; localip = relayhost + i + j + k + 3; } - if (!stralloc_copys(&pass,relayhost + i + j + 2)) temp_nomem(); + if (!stralloc_copys(&pass, relayhost + i + j + 2)) temp_nomem(); } } - p = str_chr(relayhost,';'); + p = str_chr(relayhost, ';'); if (relayhost[p] == ';') { - if (relayhost[p + 1] == 's') { flagsmtps = 1; p++; } // RFC 8314 - scan_ulong(relayhost + p + 1,&port); + if (relayhost[p + 1] == 's') { + flagsmtps = 1; + p++; + } // RFC 8314 + scan_ulong(relayhost + p + 1, &port); if (qmtpsend && port == PORT_QMTPS) qmtpsend = 2; relayhost[p] = 0; } - if (!stralloc_copys(&host,relayhost)) temp_nomem(); + if (!stralloc_copys(&host, relayhost)) temp_nomem(); #ifdef IDN2 } else { char *asciihost = 0; if (!stralloc_0(&host)) temp_nomem(); - switch (idn2_lookup_u8(host.s,(uint8_t**)&asciihost,IDN2_NFC_INPUT)) { + switch (idn2_lookup_u8(host.s, (uint8_t **)&asciihost, IDN2_NFC_INPUT)) { case IDN2_OK: break; case IDN2_MALLOC: temp_nomem(); default: perm_dns(); } - if (!stralloc_copys(&idnhost,asciihost)) temp_nomem(); + if (!stralloc_copys(&idnhost, asciihost)) temp_nomem(); #endif } } -/* this file is too long -------------------------------------- TLS destinations */ + /* this file is too long -------------------------------------- TLS destinations */ - flagtls = tls_destination((const stralloc) host); // host may not be 0-terminated + flagtls = tls_destination((const stralloc)host); // host may not be 0-terminated if (flagtls > 0) { - if (tlsdestinfo) { - i = str_chr(tlsdestinfo,'|'); /* ca file/dir or cert fingerprint */ + if (tlsdestinfo) { + i = str_chr(tlsdestinfo, '|'); /* ca file/dir or cert fingerprint */ if (tlsdestinfo[i] == '|') { tlsdestinfo[i] = 0; - j = str_chr(tlsdestinfo + i + 1,'|'); /* cipher */ + j = str_chr(tlsdestinfo + i + 1, '|'); /* cipher */ if (tlsdestinfo[i + j + 1] == '|') { - tlsdestinfo[i + j + 1] = 0; - k = str_chr(tlsdestinfo + i + j + 2,'|'); /* cone domain */ + tlsdestinfo[i + j + 1] = 0; + k = str_chr(tlsdestinfo + i + j + 2, '|'); /* cone domain */ if (tlsdestinfo[i + j + k + 2] == '|') { - tlsdestinfo[i + j + k + 2] = 0; - if (str_diffn(tlsdestinfo + j + k + 3,canonhost.s,canonhost.len)) flagtls = 0; + tlsdestinfo[i + j + k + 2] = 0; + if (str_diffn(tlsdestinfo + j + k + 3, canonhost.s, canonhost.len)) flagtls = 0; } - p = str_chr(tlsdestinfo + i + j + 2,';'); /* verifydepth;port */ + p = str_chr(tlsdestinfo + i + j + 2, ';'); /* verifydepth;port */ if (tlsdestinfo[i + j + p + 2] == ';') { tlsdestinfo[i + j + p + 2] = 0; - if (p > 0) scan_ulong(tlsdestinfo + i + j + 2,&verifydepth); - if (tlsdestinfo[i + j + p + 3] == 's') { flagsmtps = 1; p++; } /* RFC 8314 */ - scan_ulong(tlsdestinfo + i + j + p + 3,&port); + if (p > 0) scan_ulong(tlsdestinfo + i + j + 2, &verifydepth); + if (tlsdestinfo[i + j + p + 3] == 's') { + flagsmtps = 1; + p++; + } /* RFC 8314 */ + scan_ulong(tlsdestinfo + i + j + p + 3, &port); } } if (j) - if (!stralloc_copys(&ciphers,tlsdestinfo + i + 1)) temp_nomem(); - } + if (!stralloc_copys(&ciphers, tlsdestinfo + i + 1)) temp_nomem(); + } /* either ':[=]cafile/cadir' -or- ':;port' */ - if (tlsdestinfo[0] == ';') - scan_ulong(tlsdestinfo + 1,&port); - else - if (!stralloc_copys(&cafile,tlsdestinfo)) temp_nomem(); + if (tlsdestinfo[0] == ';') + scan_ulong(tlsdestinfo + 1, &port); + else if (!stralloc_copys(&cafile, tlsdestinfo)) + temp_nomem(); } -/* cafile starts with '=' => it is a fingerprint + /* cafile starts with '=' => it is a fingerprint cafile ends with '/' => consider it as cadir cafile and cadir are now 0-terminated ciphers are alway 0-terminated if given */ @@ -1296,7 +1359,7 @@ int main(int argc,char **argv) if (cafile.s[cafile.len] == '/') { cafile.len = 0; flagverify = 2; - if (!stralloc_copys(&cadir,tlsdestinfo)) temp_nomem(); + if (!stralloc_copys(&cadir, tlsdestinfo)) temp_nomem(); if (!stralloc_0(&cadir)) temp_nomem(); } else { if (cafile.s[0] == '=') flagverify = -2; @@ -1305,60 +1368,61 @@ int main(int argc,char **argv) } else cafile.len = cadir.len = 0; - if (ciphers.len > 4) /* otherwise garbage */ - if (!stralloc_0(&ciphers)) temp_nomem(); - else - ciphers.len = 0; + if (ciphers.len > 4) /* otherwise garbage */ + if (!stralloc_0(&ciphers)) + temp_nomem(); + else + ciphers.len = 0; if (port == PORT_SMTPS || flagsmtps) flagtls += 10; if (port == PORT_QMTPS) flagtls += 20; } - if (flagtls == 8) flagverify = -1; - if (!flagtls && qmtpsend == 2) flagtls = 20; /* QMTPS */ + if (flagtls == 8) flagverify = -1; + if (!flagtls && qmtpsend == 2) flagtls = 20; /* QMTPS */ -/* this file is too long -------------------------------------- Our Certs - per senddomain */ + /* this file is too long -------------------------------------- Our Certs - per senddomain */ if (flagtls > 0) { - flagtlsdomain = tls_domaincerts((const stralloc) senddomain); // senddomain un-terminated + flagtlsdomain = tls_domaincerts((const stralloc)senddomain); // senddomain un-terminated if (flagtlsdomain && tlsdomaininfo) { - i = str_chr(tlsdomaininfo,'|'); + i = str_chr(tlsdomaininfo, '|'); if (tlsdomaininfo[i] == '|') { tlsdomaininfo[i] = 0; - j = str_chr(tlsdomaininfo + i + 1,'|'); + j = str_chr(tlsdomaininfo + i + 1, '|'); if (tlsdomaininfo[i + j + 1] == '|') { tlsdomaininfo[i + j + 1] = 0; - if (!stralloc_copys(&keypwd,"")) temp_nomem(); - if (!stralloc_copys(&keypwd,tlsdomaininfo + i + j + 2)) temp_nomem(); + if (!stralloc_copys(&keypwd, "")) temp_nomem(); + if (!stralloc_copys(&keypwd, tlsdomaininfo + i + j + 2)) temp_nomem(); if (!stralloc_0(&keypwd)) temp_nomem(); } - if (!stralloc_copys(&keyfile,tlsdomaininfo + i + 1)) temp_nomem(); + if (!stralloc_copys(&keyfile, tlsdomaininfo + i + 1)) temp_nomem(); if (!stralloc_0(&keyfile)) temp_nomem(); } - if (!stralloc_copys(&certfile,tlsdomaininfo)) temp_nomem(); + if (!stralloc_copys(&certfile, tlsdomaininfo)) temp_nomem(); if (!stralloc_0(&certfile)) temp_nomem(); flagtlsdomain = 2; } } -/* this file is too long -------------------------------------- work thru reciplist */ + /* this file is too long -------------------------------------- work thru reciplist */ - if (!saa_readyplus(&reciplist,0)) temp_nomem(); + if (!saa_readyplus(&reciplist, 0)) temp_nomem(); if (ipme_init() != 1) temp_oserr(); - + flagallaliases = 1; recips = argv + 3; - if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin"); + if (fstat(0, &st) == -1) quit("Z", " unable to fstat stdin"); msize = st.st_size; - fmt_ulong(msgsize,msize); + fmt_ulong(msgsize, msize); while (*recips) { - if (!saa_readyplus(&reciplist,1)) temp_nomem(); + if (!saa_readyplus(&reciplist, 1)) temp_nomem(); reciplist.sa[reciplist.len] = sauninit; - addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost); + addrmangle(reciplist.sa + reciplist.len, *recips, &flagalias, !relayhost); if (!flagalias) flagallaliases = 0; ++reciplist.len; ++recips; @@ -1366,91 +1430,94 @@ int main(int argc,char **argv) random = now() + (getpid() << 16); #ifdef IDN2 - switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&idnhost,random)) { + switch (relayhost ? dns_ip(&ip, &host) : dns_mxip(&ip, &idnhost, random)) { #else - switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { + switch (relayhost ? dns_ip(&ip, &host) : dns_mxip(&ip, &host, random)) { #endif - case DNS_MEM: temp_nomem(); - case DNS_ERR: temp_dns(); - case DNS_COM: temp_dns(); + case DNS_MEM: temp_nomem(); + case DNS_ERR: temp_dns(); + case DNS_COM: temp_dns(); case DNS_SOFT: temp_dns(); #ifdef DEFERREDBOUNCES - default: if (!ip.len) temp_nomx(); + default: + if (!ip.len) temp_nomx(); #else - default: if (!ip.len) perm_nomx(); + default: + if (!ip.len) perm_nomx(); #endif } prefme = 100000; for (i = 0; i < ip.len; ++i) if (ipme_is(&ip.ix[i])) - if (ip.ix[i].pref < prefme) - prefme = ip.ix[i].pref; - + if (ip.ix[i].pref < prefme) prefme = ip.ix[i].pref; + if (relayhost) prefme = 300000; if (flagallaliases) prefme = 500000; - + if (localip) { - i = str_chr(localip,':'); - if (localip[i] == ':') ip6flag = 1; - else ip6flag = -1; + i = str_chr(localip, ':'); + if (localip[i] == ':') + ip6flag = 1; + else + ip6flag = -1; } - for (i = 0; i < ip.len; ++i) { /* MX with smallest distance */ - if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue; - if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue; + for (i = 0; i < ip.len; ++i) { /* MX with smallest distance */ + if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue; + if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue; if (ip.ix[i].pref < prefme) break; } - if (i >= ip.len) - perm_ambigmx(); + if (i >= ip.len) perm_ambigmx(); - if (!stralloc_copys(&remotehost,ip.ix[i].mxh)) temp_nomem(); /* take MX hostname for TLSA */ + if (!stralloc_copys(&remotehost, ip.ix[i].mxh)) temp_nomem(); /* take MX hostname for TLSA */ if (!stralloc_0(&remotehost)) temp_nomem(); for (i = 0; i < ip.len; ++i) { if (ip.ix[i].pref < prefme) { - if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue; /* explicit binding */ - if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue; + if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue; /* explicit binding */ + if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue; if (tcpto(&ip.ix[i])) continue; - - smtpfd = socket(ip.ix[i].af,SOCK_STREAM,0); + + smtpfd = socket(ip.ix[i].af, SOCK_STREAM, 0); if (smtpfd == -1) continue; - if (localip) { /* set domain ip */ - if (!stralloc_copyb(&sendip,localip,str_len(localip))) temp_nomem(); - j = str_chr(localip,':'); - if (localip[j] == ':') { - if (!ip6_scan(localip,ip6)) temp_noip(); /* IPv6 */ - if (byte_equal(ip.ix[i].addr.ip6.d,16,ip6)) continue; - ifidx = socket_getifidx(netif.s); - if (socket_bind6(smtpfd,ip6,0,ifidx) < 0) temp_osip(); - } else { - if (!ip4_scan(localip,ip4)) temp_noip(); /* IPv4 */ - if (byte_equal(ip.ix[i].addr.ip4.d,4,ip4)) continue; - if (socket_bind4(smtpfd,ip4,0) < 0) temp_osip(); - } - } - - - AGAIN: + if (localip) { /* set domain ip */ + if (!stralloc_copyb(&sendip, localip, str_len(localip))) temp_nomem(); + j = str_chr(localip, ':'); + if (localip[j] == ':') { + if (!ip6_scan(localip, ip6)) temp_noip(); /* IPv6 */ + if (byte_equal(ip.ix[i].addr.ip6.d, 16, ip6)) continue; + ifidx = socket_getifidx(netif.s); + if (socket_bind6(smtpfd, ip6, 0, ifidx) < 0) temp_osip(); + } else { + if (!ip4_scan(localip, ip4)) temp_noip(); /* IPv4 */ + if (byte_equal(ip.ix[i].addr.ip4.d, 4, ip4)) continue; + if (socket_bind4(smtpfd, ip4, 0) < 0) temp_osip(); + } + } + + + AGAIN: if (ip.ix[i].af == AF_INET6) - r = timeoutconn6(smtpfd,(char *)&ip.ix[i].addr.ip6.d,(unsigned int) port,timeoutconnect,ifidx); + r = timeoutconn6( + smtpfd, (char *)&ip.ix[i].addr.ip6.d, (unsigned int)port, timeoutconnect, ifidx); else - r = timeoutconn4(smtpfd,(char *)&ip.ix[i].addr.ip4.d,(unsigned int) port,timeoutconnect); + r = timeoutconn4(smtpfd, (char *)&ip.ix[i].addr.ip4.d, (unsigned int)port, timeoutconnect); if (r == 0) { - tcpto_err(&ip.ix[i],0); + tcpto_err(&ip.ix[i], 0); partner = ip.ix[i]; - if (qmtpsend) - qmtp(); - else - smtp(); /* read qmail/THOUGHTS; section 6 */ + if (qmtpsend) + qmtp(); + else + smtp(); /* read qmail/THOUGHTS; section 6 */ } if (flagtls == 9 && errno == EPROTO) { - flagtls = 0; goto AGAIN; + flagtls = 0; + goto AGAIN; } - if (errno == ETIMEDOUT || errno == ECONNREFUSED || errno == EPROTO) - tcpto_err(&ip.ix[i],1); + if (errno == ETIMEDOUT || errno == ECONNREFUSED || errno == EPROTO) tcpto_err(&ip.ix[i], 1); close(smtpfd); } } |