diff options
Diffstat (limited to 'src/qmail-remote.c')
-rw-r--r-- | src/qmail-remote.c | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/src/qmail-remote.c b/src/qmail-remote.c index 2a7498c..ddb4d65 100644 --- a/src/qmail-remote.c +++ b/src/qmail-remote.c @@ -1,6 +1,3 @@ -#ifdef IDN2 - #include <idn2.h> -#endif #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> @@ -42,6 +39,10 @@ #include "tls_timeoutio.h" #include "ucspissl.h" +#ifdef IDN2 + #include <idn2.h> +#endif + #define WHO "qmail-remote" #define MAX_SIZE 200000000 @@ -60,18 +61,19 @@ unsigned long port = PORT_SMTP; 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 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; +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}; @@ -113,10 +115,12 @@ 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() { zero(); @@ -143,16 +147,19 @@ 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_oserr() { out("ZSystem resources temporarily unavailable. (#4.3.0)\n"); zerodie(); } + void temp_osip() { out("ZCan't bind to local ip address: "); @@ -160,6 +167,7 @@ void temp_osip() out(". (#4.3.0)\n"); zerodie(); } + void temp_noconn() { out("ZSorry, I wasn't able to establish an SMTP connection: "); @@ -167,6 +175,7 @@ void temp_noconn() out(". (#4.3.0)\n"); zerodie(); } + void temp_qmtpnoc() { out("ZSorry, I wasn't able to establish an QMTP connection: "); @@ -174,11 +183,13 @@ void temp_qmtpnoc() out(". (#4.3.1)\n"); zerodie(); } + void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } + void temp_dnscanon() { out("ZCNAME lookup failed temporarily for: "); @@ -186,6 +197,7 @@ void temp_dnscanon() out(". (#4.4.3)\n"); zerodie(); } + void temp_dns() { out("ZSorry, I couldn't find any host named: "); @@ -193,6 +205,7 @@ void temp_dns() out(". (#4.1.2)\n"); zerodie(); } + void temp_nomx() { out("ZSorry, I couldn't find a mail exchanger or IP address for: "); @@ -200,31 +213,37 @@ void temp_nomx() 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_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 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_dns() { out("DSorry, I couldn't find any host named: "); @@ -232,6 +251,7 @@ void perm_dns() out(". (#5.1.2)\n"); zerodie(); } + void perm_nomx() { out("DSorry, I couldn't find a mail exchanger or IP address for: "); @@ -239,12 +259,14 @@ void perm_nomx() out(". (#5.4.4)\n"); zerodie(); } + 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"); + 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(); } + void err_authprot() { out("KNo supported AUTH method found, continuing without authentication.\n"); @@ -433,13 +455,14 @@ void tls_init() /* Prepare for Certificate Request */ - if (flagtlsdomain == 2) switch (tls_certkey(ctx, certfile.s, keyfile.s, keypwd.s)) - { + 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(); } + } /* Set SSL Context */ @@ -591,12 +614,12 @@ int flagsize = 0; int smtp_size() { int i; - if (smtptext.len > 10) + if (smtptext.len > 10) { for (i = 0; i < smtptext.len; ++i) { if (case_starts(smtptext.s + i, "SIZE ")) return 1; } + } return 0; - ; } void smtp_greeting() @@ -807,7 +830,7 @@ 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 (mailfrom_cram() >= 0) return; @@ -816,6 +839,7 @@ void smtp_auth() if (case_starts(smtptext.s + i, "PLAIN")) if (mailfrom_plain() >= 0) return; } + } err_authprot(); mailfrom(); } @@ -841,9 +865,9 @@ void smtp() smtp_greeting(); if (flagtls > 0 && flagtls < 10) { /* STARTTLS */ - if (starttls_peer()) + if (starttls_peer()) { smtp_starttls(); - else if (flagtls > 3 && flagtls != 9) { + } else if (flagtls > 3 && flagtls != 9) { if (!stralloc_0(&host)) temp_nomem(); temp_tlshost(); } @@ -1019,9 +1043,9 @@ void qmtp() if (ch != ',') temp_proto(); smtptext.s[smtptext.len - 1] = '\n'; - if (smtptext.s[0] == 'K') + if (smtptext.s[0] == 'K') { out("r"); - else if (smtptext.s[0] == 'D') { + } else if (smtptext.s[0] == 'D') { out("h"); flagallok = 0; } else { /* if (smtptext.s[0] == 'Z') */ @@ -1350,8 +1374,8 @@ int main(int argc, char **argv) } /* cafile starts with '=' => it is a fingerprint - cafile ends with '/' => consider it as cadir - cafile and cadir are now 0-terminated + cafile ends with '/' => consider it as cadir + cafile and cadir are now 0-terminated ciphers are alway 0-terminated if given */ if (cafile.len > 2) { @@ -1365,14 +1389,15 @@ int main(int argc, char **argv) if (cafile.s[0] == '=') flagverify = -2; if (!stralloc_0(&cafile)) temp_nomem(); } - } else + } 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; |