diff options
Diffstat (limited to 'src/qmail-smtpd.c')
-rw-r--r-- | src/qmail-smtpd.c | 1437 |
1 files changed, 891 insertions, 546 deletions
diff --git a/src/qmail-smtpd.c b/src/qmail-smtpd.c index f312c11..6d2d0d4 100644 --- a/src/qmail-smtpd.c +++ b/src/qmail-smtpd.c @@ -1,93 +1,102 @@ #include <unistd.h> -#include "wildmat.h" -#include "buffer.h" -#include "stralloc.h" -#include "genalloc.h" + #include "alloc.h" -#include "auto_qmail.h" -#include "control.h" -#include "received.h" +#include "base64.h" +#include "buffer.h" +#include "byte.h" +#include "case.h" +#include "cdbread.h" +#include "close.h" #include "constmap.h" -#include "logmsg.h" -#include "ipme.h" +#include "env.h" +#include "exit.h" #include "fd.h" -#include "ip.h" -#include "qmail.h" -#include "str.h" #include "fmt.h" +#include "genalloc.h" +#include "ip.h" +#include "logmsg.h" +#include "open.h" #include "scan.h" -#include "byte.h" -#include "case.h" -#include "env.h" +#include "sig.h" +#include "str.h" +#include "stralloc.h" +#include "timeout.h" +#include "wait.h" + +#include "auto_qmail.h" +#include "commands.h" +#include "control.h" +#include "dns.h" +#include "ipme.h" +#include "mfrules.h" #include "now.h" -#include "exit.h" +#include "qmail.h" #include "rcpthosts.h" +#include "received.h" #include "recipients.h" -#include "mfrules.h" -#include "tls_start.h" #include "smtpdlog.h" -#include "timeout.h" -#include "commands.h" -#include "cdbread.h" -#include "dns.h" -#include "wait.h" -#include "sig.h" -#include "close.h" -#include "open.h" -#include "base64.h" #include "spf.h" +#include "tls_start.h" +#include "wildmat.h" /** @file qmail-smtpd.c -- authenticating ESMTP/ESMTPS server @brief requires sslserver or tcpserver */ #define PAM111421 -#define AUTHSLEEP 5 +#define AUTHSLEEP 5 #define PORT_SMTPS "465" -#define MIMETYPE_LEN 9 -#define LOADER_LEN 5 +#define MIMETYPE_LEN 9 +#define LOADER_LEN 5 #define BASE64MESSAGE "content-transfer-encoding: base64" -#define FDIN 0 -#define FDOUT 1 -#define FDLOG 2 -#define FDAUTH 3 +#define FDIN 0 +#define FDOUT 1 +#define FDLOG 2 +#define FDAUTH 3 #define BUFFER_SIZE 1024 -#define MAXHOPS 100 +#define MAXHOPS 100 unsigned long databytes = 0; int timeout = 1200; int modssl_info(); -ssize_t safewrite(int fd,char *buf,int len) +ssize_t safewrite(int fd, char *buf, int len) { int r; - r = timeoutwrite(timeout,fd,buf,len); + r = timeoutwrite(timeout, fd, buf, len); if (r <= 0) _exit(1); return r; } -ssize_t saferead(int fd,char *buf,int len) +ssize_t saferead(int fd, char *buf, int len) { int r; flush(); - r = timeoutread(timeout,fd,buf,len); - if (r == -1) if (errno == ETIMEDOUT) die_alarm(); + r = timeoutread(timeout, fd, buf, len); + if (r == -1) + if (errno == ETIMEDOUT) die_alarm(); if (r <= 0) die_read(); return r; } char inbuf[BUFFER_SIZE]; -buffer bi = BUFFER_INIT(saferead,FDIN,inbuf,sizeof(inbuf)); +buffer bi = BUFFER_INIT(saferead, FDIN, inbuf, sizeof(inbuf)); -char outbuf[BUFFER_SIZE/2]; -buffer bo = BUFFER_INIT(safewrite,FDOUT,outbuf,sizeof(outbuf)); +char outbuf[BUFFER_SIZE / 2]; +buffer bo = BUFFER_INIT(safewrite, FDOUT, outbuf, sizeof(outbuf)); char logbuf[256]; -buffer bl = BUFFER_INIT(write,FDLOG,logbuf,sizeof(logbuf)); +buffer bl = BUFFER_INIT(write, FDLOG, logbuf, sizeof(logbuf)); -void flush() { buffer_flush(&bo); } // this triggers writing to STDIO -void out(char *s) { buffer_puts(&bo,s); } +void flush() +{ + buffer_flush(&bo); +} // this triggers writing to STDIO +void out(char *s) +{ + buffer_puts(&bo, s); +} stralloc sa = {0}; ipalloc ia = {0}; @@ -96,7 +105,7 @@ int bhelocheck(void); /* this file is too long -------------------------------------- DNS helper */ -int dnsq(char *arg,char type) +int dnsq(char *arg, char type) { unsigned int random; int at; @@ -106,26 +115,27 @@ int dnsq(char *arg,char type) len = str_len(arg); if (len < 1) return r; - if (arg[len-1] == ' ') len--; /* trailing blank */ + if (arg[len - 1] == ' ') len--; /* trailing blank */ if (len < 1) return r; - at = byte_rchr(arg,len,'@'); + at = byte_rchr(arg, len, '@'); if (at < len) { - if (!stralloc_copyb(&sa,arg + at + 1,len - at - 1)) die_nomem(); - } else - if (!stralloc_copyb(&sa,arg,len)) die_nomem(); + if (!stralloc_copyb(&sa, arg + at + 1, len - at - 1)) die_nomem(); + } else if (!stralloc_copyb(&sa, arg, len)) + die_nomem(); random = now() + (getpid() << 16); - switch (type) { /* Common for IPv4 and IPv6 */ - case 'A': r = dns_ip(&ia,&sa); break; - case 'M': r = dns_mxip(&ia,&sa,random); break; + switch (type) { /* Common for IPv4 and IPv6 */ + case 'A': r = dns_ip(&ia, &sa); break; + case 'M': r = dns_mxip(&ia, &sa, random); break; } switch (r) { case DNS_ERR: out("451 DNS temporary failure (#4.3.0)\r\n"); return -1; case DNS_MEM: die_nomem(); - default: if (ia.len) return 0; + default: + if (ia.len) return 0; } return 1; @@ -137,8 +147,8 @@ static stralloc greeting = {0}; void smtp_greet(char *code) { - buffer_puts(&bo,code); - buffer_put(&bo,greeting.s,greeting.len); + buffer_puts(&bo, code); + buffer_put(&bo, greeting.s, greeting.len); } void smtp_help() { @@ -146,7 +156,10 @@ void smtp_help() } void smtp_quit() { - smtp_greet("221 "); out("\r\n"); flush(); _exit(0); + smtp_greet("221 "); + out("\r\n"); + flush(); + _exit(0); } char *remoteip; @@ -172,33 +185,47 @@ char *badhelocond; void dohelo(char *helo) { - if (!stralloc_copys(&helohost,helo)) die_nomem(); + if (!stralloc_copys(&helohost, helo)) die_nomem(); if (!stralloc_0(&helohost)) die_nomem(); - fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0; + fakehelo = case_diffs(remotehost, helohost.s) ? helohost.s : 0; if (helocheck) { if (str_len(helocheck) == 1) { switch (*helocheck) { - case '=': flagbadhelo = bhelocheck(); - if (fakehelo) { flagdnshelo = 1; badhelocond = "="; } - break; - case 'A': flagbadhelo = bhelocheck(); - if (flagbadhelo == 0) { flagdnshelo = dnsq(helohost.s,'A'); badhelocond = "A"; } - break; - case 'M': flagbadhelo = bhelocheck(); - if (flagbadhelo == 0) { flagdnshelo = dnsq(helohost.s,'M'); badhelocond = "M"; } - break; - case '.': flagbadhelo = bhelocheck(); - if (!str_len(helo)) flagbadhelo = -2; - break; - case '!': if (!str_len(helo)) flagbadhelo = -2; - break; + case '=': + flagbadhelo = bhelocheck(); + if (fakehelo) { + flagdnshelo = 1; + badhelocond = "="; + } + break; + case 'A': + flagbadhelo = bhelocheck(); + if (flagbadhelo == 0) { + flagdnshelo = dnsq(helohost.s, 'A'); + badhelocond = "A"; + } + break; + case 'M': + flagbadhelo = bhelocheck(); + if (flagbadhelo == 0) { + flagdnshelo = dnsq(helohost.s, 'M'); + badhelocond = "M"; + } + break; + case '.': + flagbadhelo = bhelocheck(); + if (!str_len(helo)) flagbadhelo = -2; + break; + case '!': + if (!str_len(helo)) flagbadhelo = -2; + break; } } else { - flagbadhelo = bhelocheck(); + flagbadhelo = bhelocheck(); } if (flagbadhelo == -3) flagbadhelo = 0; } - if (!env_put("HELOHOST",helohost.s)) die_nomem(); + if (!env_put("HELOHOST", helohost.s)) die_nomem(); } int liphostok = 0; @@ -208,7 +235,7 @@ int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; -int brtok= 0; +int brtok = 0; stralloc brt = {0}; struct constmap mapbrt; @@ -220,16 +247,17 @@ static struct cdb cdbm; static struct cdb cdbl; static int fdbmt; -int flagmimetype = 0; /* 1: white; 2: cdb; 3: white+cdb; 4: !relay+white; 6: !relay+white+cdb; -1: found in cdb; -2: found white */ +int flagmimetype = + 0; /* 1: white; 2: cdb; 3: white+cdb; 4: !relay+white; 6: !relay+white+cdb; -1: found in cdb; -2: found white */ char *badmimeinit; static int fdblt; -int flagloadertype = 0; /* 1: cdb; 2: !relay+cdb; -1: found in cdb */ +int flagloadertype = 0; /* 1: cdb; 2: !relay+cdb; -1: found in cdb */ char *badloaderinit; static int fdmav; int flagmav = 0; -int localmf = 0; /* 1: domainpart->rcpthosts; 2: ->mailformrules; 3: ->remoteinfo; 4: ->DN(Email) */ +int localmf = 0; /* 1: domainpart->rcpthosts; 2: ->mailformrules; 3: ->remoteinfo; 4: ->DN(Email) */ char *localmfcheck; char *mfdnscheck; @@ -247,12 +275,14 @@ int greylist = 0; stralloc pgbind = {0}; char *auth; -int smtpauth = 0; /* -1:Cert 0:none 1:login/plain 2:cram 3:login/plain/cram 11:must_login/plain 12:must_2 13:must_3 */ +int smtpauth = + 0; /* -1:Cert 0:none 1:login/plain 2:cram 3:login/plain/cram 11:must_login/plain 12:must_2 13:must_3 */ int seenauth = 0; /* 1:ESMTPA 2:~CLIENTDN */ stralloc authmethod = {0}; -int starttls = 0; /* -1:TLS 0:none 1:STARTTLS 2:require_STARTTLS 3:relay_if_CLIENTDN 4:require_+_relay_if_CLIENTDN */ -int seentls = 0; /* 1:~STARTTLS 2:~TLS 3:~CLIENTDN */ +int starttls = + 0; /* -1:TLS 0:none 1:STARTTLS 2:require_STARTTLS 3:relay_if_CLIENTDN 4:require_+_relay_if_CLIENTDN */ +int seentls = 0; /* 1:~STARTTLS 2:~TLS 3:~CLIENTDN */ char *ucspitls = 0; char *tlsversion; char *cipher; @@ -279,39 +309,47 @@ void setup() flagip6 = 1; // GCC 10 implicit int declarition if global var if (control_init() == -1) die_control(); - if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) - die_control(); - liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0); + if (control_rldef(&greeting, "control/smtpgreeting", 1, (char *)0) != 1) die_control(); + liphostok = control_rldef(&liphost, "control/localiphost", 1, (char *)0); if (liphostok == -1) die_control(); - if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); + if (control_readint(&timeout, "control/timeoutsmtpd") == -1) die_control(); if (timeout <= 0) timeout = 1; if (rcpthosts_init() == -1) die_control(); if (recipients_init() == -1) die_control(); - bmfok = control_readfile(&bmf,"control/badmailfrom",0); + bmfok = control_readfile(&bmf, "control/badmailfrom", 0); if (bmfok == -1) die_control(); if (bmfok) - if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + if (!constmap_init(&mapbmf, bmf.s, bmf.len, 0)) die_nomem(); - brtok = control_readfile(&brt,"control/badrcptto",0); + brtok = control_readfile(&brt, "control/badrcptto", 0); if (brtok == -1) die_control(); if (brtok) - if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem(); + if (!constmap_init(&mapbrt, brt.s, brt.len, 0)) die_nomem(); - if (control_readint(&databytes,"control/databytes") == -1) die_control(); + if (control_readint(&databytes, "control/databytes") == -1) die_control(); x = env_get("DATABYTES"); - if (x) { scan_ulong(x,&u); databytes = u; } + if (x) { + scan_ulong(x, &u); + databytes = u; + } if (!(databytes + 1)) --databytes; - if (!stralloc_copys(&protocol,"ESMTP")) die_nomem(); /* RFC 3848 */ - remoteip = env_get("TCP6REMOTEIP"); /* compactified IPv6 */ - if (!remoteip) remoteip = env_get("TCPREMOTEIP"); /* allow other tcpserver/sslserver */ - if (remoteip && (str_chr(remoteip,':') < str_len(remoteip))) { - if (byte_equal(remoteip,7,V4MAPPREFIX)) - { remoteip = remoteip + 7; flagip6 = 0; } - } else flagip6 = 0; - if (!remoteip) { remoteip = "unknown"; flagip6 = -1; } + if (!stralloc_copys(&protocol, "ESMTP")) die_nomem(); /* RFC 3848 */ + remoteip = env_get("TCP6REMOTEIP"); /* compactified IPv6 */ + if (!remoteip) remoteip = env_get("TCPREMOTEIP"); /* allow other tcpserver/sslserver */ + if (remoteip && (str_chr(remoteip, ':') < str_len(remoteip))) { + if (byte_equal(remoteip, 7, V4MAPPREFIX)) { + remoteip = remoteip + 7; + flagip6 = 0; + } + } else + flagip6 = 0; + if (!remoteip) { + remoteip = "unknown"; + flagip6 = -1; + } local = env_get("TCP6LOCALHOST"); if (!local) local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCP6LOCALIP"); @@ -327,35 +365,44 @@ void setup() if (!remoteinfo) remoteinfo = env_get("TCPREMOTEINFO"); relayclient = env_get("RELAYCLIENT"); - if (!case_diffs(localport,PORT_SMTPS)) { + if (!case_diffs(localport, PORT_SMTPS)) { if (!modssl_info()) die_starttls(); starttls = -1; } mfdnscheck = env_get("MFDNSCHECK"); x = env_get("MAXRECIPIENTS"); - if (x) { scan_ulong(x,&u); maxrcptcount = u; }; + if (x) { + scan_ulong(x, &u); + maxrcptcount = u; + }; if (!(maxrcptcount + 1)) --maxrcptcount; helocheck = env_get("HELOCHECK"); if (helocheck) { - badhelook = control_readfile(&badhelo,"control/badhelo",0); + badhelook = control_readfile(&badhelo, "control/badhelo", 0); if (badhelook == -1) die_control(); if (badhelook) - if (!constmap_init(&mapbhlo,badhelo.s,badhelo.len,0)) die_nomem(); + if (!constmap_init(&mapbhlo, badhelo.s, badhelo.len, 0)) die_nomem(); } x = env_get("TARPITCOUNT"); - if (x) { scan_ulong(x,&u); tarpitcount = u; }; + if (x) { + scan_ulong(x, &u); + tarpitcount = u; + }; x = env_get("TARPITDELAY"); - if (x) { scan_ulong(x,&u); tarpitdelay = u; }; + if (x) { + scan_ulong(x, &u); + tarpitdelay = u; + }; x = env_get("POSTGREY"); // RFC 6647 if (x) { - if (case_diffs(x,"-")) { + if (case_diffs(x, "-")) { greylist = 1; - if (!stralloc_copys(&pgbind,x)) die_nomem(); - if (!stralloc_append(&pgbind,"")) die_nomem(); + if (!stralloc_copys(&pgbind, x)) die_nomem(); + if (!stralloc_append(&pgbind, "")) die_nomem(); } } @@ -365,7 +412,7 @@ void setup() if (str_len(localmfcheck) == 1 && *localmfcheck == '!') { localmf = 2; fdmav = open_read("control/mailfromrules.cdb"); - if (fdmav == -1 ) localmf = 1; + if (fdmav == -1) localmf = 1; } if (str_len(localmfcheck) == 1 && *localmfcheck == '=') { localmf = 3; @@ -386,7 +433,7 @@ void setup() if (*badmimeinit == '+') flagmimetype = 4; } } - if (fdbmt != -1 ) flagmimetype = flagmimetype + 2; + if (fdbmt != -1) flagmimetype = flagmimetype + 2; } badloaderinit = env_get("BADLOADERTYPE"); @@ -398,7 +445,7 @@ void setup() flagloadertype = 1; if (*badloaderinit == '+') flagloadertype = 2; fdblt = open_read("control/badloadertypes.cdb"); - if (fdblt == -1 ) flagloadertype = 0; + if (fdblt == -1) flagloadertype = 0; } } } @@ -408,67 +455,69 @@ void setup() auth = env_get("SMTPAUTH"); if (auth) { smtpauth = 1; - if (!case_diffs(auth,"-")) smtpauth = 0; - if (!case_diffs(auth,"!")) smtpauth = 11; - if (case_starts(auth,"cram")) smtpauth = 2; - if (case_starts(auth,"+cram")) smtpauth = 3; - if (case_starts(auth,"!cram")) smtpauth = 12; - if (case_starts(auth,"!+cram")) smtpauth = 13; + if (!case_diffs(auth, "-")) smtpauth = 0; + if (!case_diffs(auth, "!")) smtpauth = 11; + if (case_starts(auth, "cram")) smtpauth = 2; + if (case_starts(auth, "+cram")) smtpauth = 3; + if (case_starts(auth, "!cram")) smtpauth = 12; + if (case_starts(auth, "!+cram")) smtpauth = 13; } if (!seentls) { ucspitls = env_get("UCSPITLS"); if (ucspitls) { starttls = 1; - if (!case_diffs(ucspitls,"-")) starttls = 0; - if (!case_diffs(ucspitls,"!")) starttls = 2; - if (!case_diffs(ucspitls,"?")) starttls = 3; - if (!case_diffs(ucspitls,"@")) starttls = 4; + if (!case_diffs(ucspitls, "-")) starttls = 0; + if (!case_diffs(ucspitls, "!")) starttls = 2; + if (!case_diffs(ucspitls, "?")) starttls = 3; + if (!case_diffs(ucspitls, "@")) starttls = 4; } } delivermailto = env_get("DELIVERTO"); if (delivermailto) { - if (!stralloc_cats(&mailto,delivermailto)) die_nomem(); - if (!stralloc_cats(&mailto," ")) die_nomem(); + if (!stralloc_cats(&mailto, delivermailto)) die_nomem(); + if (!stralloc_cats(&mailto, " ")) die_nomem(); } rblsmtpd = env_get("RBLSMTPD"); if (rblsmtpd) { - if (!stralloc_cats(&rblinfo,rblsmtpd)) die_nomem(); + if (!stralloc_cats(&rblinfo, rblsmtpd)) die_nomem(); if (!stralloc_0(&rblinfo)) die_nomem(); } x = env_get("SPF"); - if (x) { scan_ulong(x,&u); flagspf = u; } + if (x) { + scan_ulong(x, &u); + flagspf = u; + } if (flagspf < 0 || flagspf > 6) die_control(); if (flagspf) { - r = control_readline(&spflocalrules,"control/spflocalrules"); + r = control_readline(&spflocalrules, "control/spflocalrules"); if (r == -1) die_control(); if (!stralloc_0(&spflocalrules)) die_nomem(); - if (control_rldef(&spfexplain,"control/spfexplain",0,SPF_DEFEXP) == -1) die_control(); + if (control_rldef(&spfexplain, "control/spfexplain", 0, SPF_DEFEXP) == -1) die_control(); if (!stralloc_0(&spfexplain)) die_nomem(); } x = env_get("UTF8"); if (x) flagutf8 = 1; - if (!stralloc_copys(&helohost,"")) die_nomem(); // helohost is initially empty + if (!stralloc_copys(&helohost, "")) die_nomem(); // helohost is initially empty if (!stralloc_0(&helohost)) die_nomem(); fakehelo = 0; - } void auth_info(char *method) { - if (!env_put("AUTHPROTOCOL",method)) die_nomem(); - if (!env_put("AUTHUSER",remoteinfo)) die_nomem(); - if (!env_unset("TCPREMOTEINFO")) die_read(); - if (!env_put("TCPREMOTEINFO",remoteinfo)) die_nomem(); - if (!env_unset("TCP6REMOTEINFO")) die_read(); - if (!env_put("TCP6REMOTEINFO",remoteinfo)) die_nomem(); - - if (!stralloc_append(&protocol,"A")) die_nomem(); + if (!env_put("AUTHPROTOCOL", method)) die_nomem(); + if (!env_put("AUTHUSER", remoteinfo)) die_nomem(); + if (!env_unset("TCPREMOTEINFO")) die_read(); + if (!env_put("TCPREMOTEINFO", remoteinfo)) die_nomem(); + if (!env_unset("TCP6REMOTEINFO")) die_read(); + if (!env_put("TCP6REMOTEINFO", remoteinfo)) die_nomem(); + + if (!stralloc_append(&protocol, "A")) die_nomem(); } int modssl_info() @@ -483,7 +532,8 @@ int modssl_info() cipherused = env_get("SSL_CIPHER_USEKEYSIZE"); if (!cipherused) cipherused = "unknown"; clientdn = env_get("SSL_CLIENT_S_DN"); - if (!clientdn) clientdn = "none"; + if (!clientdn) + clientdn = "none"; else { seentls = 3; seenauth = 2; @@ -491,26 +541,26 @@ int modssl_info() relayclient = ""; } - if (!stralloc_copys(&tlsinfo,tlsversion)) die_nomem(); - if (!stralloc_cats(&tlsinfo,": ")) die_nomem(); - if (!stralloc_cats(&tlsinfo,cipher)) die_nomem(); - if (!stralloc_cats(&tlsinfo," [")) die_nomem(); - if (!stralloc_cats(&tlsinfo,cipherused)) die_nomem(); - if (!stralloc_cats(&tlsinfo,"/")) die_nomem(); - if (!stralloc_cats(&tlsinfo,cipherperm)) die_nomem(); - if (!stralloc_cats(&tlsinfo,"] \n")) die_nomem(); - if (!stralloc_cats(&tlsinfo," DN=")) die_nomem(); - if (!stralloc_cats(&tlsinfo,clientdn)) die_nomem(); + if (!stralloc_copys(&tlsinfo, tlsversion)) die_nomem(); + if (!stralloc_cats(&tlsinfo, ": ")) die_nomem(); + if (!stralloc_cats(&tlsinfo, cipher)) die_nomem(); + if (!stralloc_cats(&tlsinfo, " [")) die_nomem(); + if (!stralloc_cats(&tlsinfo, cipherused)) die_nomem(); + if (!stralloc_cats(&tlsinfo, "/")) die_nomem(); + if (!stralloc_cats(&tlsinfo, cipherperm)) die_nomem(); + if (!stralloc_cats(&tlsinfo, "] \n")) die_nomem(); + if (!stralloc_cats(&tlsinfo, " DN=")) die_nomem(); + if (!stralloc_cats(&tlsinfo, clientdn)) die_nomem(); if (!stralloc_0(&tlsinfo)) die_nomem(); - if (!stralloc_append(&protocol,"S")) die_nomem(); + if (!stralloc_append(&protocol, "S")) die_nomem(); if (seentls == 3 && starttls == 4) { clientcn = env_get("SSL_CLIENT_S_DN_CN"); - remoteinfo = clientcn ? clientcn : clientdn; + remoteinfo = clientcn ? clientcn : clientdn; dnemail = env_get("SSL_CLIENT_S_DN_Email"); if (!dnemail) dnemail = "unknown"; - if (!stralloc_cats(&authmethod,"cert")) die_nomem(); + if (!stralloc_cats(&authmethod, "cert")) die_nomem(); auth_info(authmethod.s); } return 1; @@ -545,50 +595,52 @@ int addrparse(char *arg) int flagquoted; terminator = '>'; - i = str_chr(arg,'<'); + i = str_chr(arg, '<'); if (arg[i]) arg += i + 1; else return 0; /* strip source route */ - if (*arg == '@') while (*arg) if (*arg++ == ':') break; + if (*arg == '@') + while (*arg) + if (*arg++ == ':') break; - if (!stralloc_copys(&addr,"")) die_nomem(); + if (!stralloc_copys(&addr, "")) die_nomem(); flagesc = 0; flagquoted = 0; for (i = 0; ch = arg[i]; ++i) { /* copy arg to addr, stripping quotes */ if (flagesc) { - if (!stralloc_append(&addr,&ch)) die_nomem(); + if (!stralloc_append(&addr, &ch)) die_nomem(); flagesc = 0; - } - else { + } else { if (!flagquoted && (ch == terminator)) break; switch (ch) { case '\\': flagesc = 1; break; - case '"': flagquoted = !flagquoted; break; - default: if (!stralloc_append(&addr,&ch)) die_nomem(); + case '"': flagquoted = !flagquoted; break; + default: + if (!stralloc_append(&addr, &ch)) die_nomem(); } } } /* could check for termination failure here, but why bother? */ - if (!stralloc_append(&addr,"")) die_nomem(); + if (!stralloc_append(&addr, "")) die_nomem(); if (liphostok) { - i = byte_rchr(addr.s,addr.len,'@'); + i = byte_rchr(addr.s, addr.len, '@'); if (i < addr.len) /* if not, partner should go read rfc 821 */ if (addr.s[i + 1] == '[') { - if (byte_rchr(addr.s + i + 2,addr.len - i - 2,':') < str_len(addr.s)) { /* @[IPv6::] */ - if (!addr.s[i + 1 + ip6_scanbracket(addr.s + i + 1,(char *)&ip6s.d)]) - if (ipme_is6(&ip6s)) { - addr.len = i + 1; - if (!stralloc_cat(&addr,&liphost)) die_nomem(); - } - } else { /* @[IPv4] */ - if (!addr.s[i + 1 + ip4_scanbracket(addr.s + i + 1,(char *)&ip4s.d)]) + if (byte_rchr(addr.s + i + 2, addr.len - i - 2, ':') < str_len(addr.s)) { /* @[IPv6::] */ + if (!addr.s[i + 1 + ip6_scanbracket(addr.s + i + 1, (char *)&ip6s.d)]) + if (ipme_is6(&ip6s)) { + addr.len = i + 1; + if (!stralloc_cat(&addr, &liphost)) die_nomem(); + } + } else { /* @[IPv4] */ + if (!addr.s[i + 1 + ip4_scanbracket(addr.s + i + 1, (char *)&ip4s.d)]) if (ipme_is4(&ip4s)) { addr.len = i + 1; - if (!stralloc_cat(&addr,&liphost)) die_nomem(); + if (!stralloc_cat(&addr, &liphost)) die_nomem(); } } } @@ -607,19 +659,19 @@ int bhelocheck() char subvalue; if (badhelook && helohost.len > 1) { /* helohost! */ - if (!stralloc_copyb(&eddr,helohost.s,helohost.len - 1)) die_nomem(); - if (!stralloc_append(&eddr,"!")) die_nomem(); + if (!stralloc_copyb(&eddr, helohost.s, helohost.len - 1)) die_nomem(); + if (!stralloc_append(&eddr, "!")) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - if (constmap(&mapbhlo,eddr.s,eddr.len - 1)) return -3; + if (constmap(&mapbhlo, eddr.s, eddr.len - 1)) return -3; - if (constmap(&mapbhlo,helohost.s,helohost.len - 1)) return -1; + if (constmap(&mapbhlo, helohost.s, helohost.len - 1)) return -1; i = 0; for (j = 0; j < badhelo.len; ++j) if (!badhelo.s[j]) { subvalue = badhelo.s[i] != '!'; if (!subvalue) i++; - if ((k != subvalue) && wildmat(helohost.s,badhelo.s + i)) k = subvalue; + if ((k != subvalue) && wildmat(helohost.s, badhelo.s + i)) k = subvalue; i = j + 1; } return k; @@ -639,74 +691,75 @@ int bmfcheck() if (bmfok && mailfrom.len > 1) { rlen = str_len(remotehost); - at = byte_rchr(mailfrom.s,mailfrom.len,'@'); + at = byte_rchr(mailfrom.s, mailfrom.len, '@'); -/* '?' enhanced address to skip all other tests including MFDNSCHECK */ + /* '?' enhanced address to skip all other tests including MFDNSCHECK */ - if (!stralloc_copys(&eddr,"?")) die_nomem(); - if (!stralloc_cat(&eddr,&mailfrom)) die_nomem(); - case_lowerb(eddr.s,eddr.len); - if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return -110; + if (!stralloc_copys(&eddr, "?")) die_nomem(); + if (!stralloc_cat(&eddr, &mailfrom)) die_nomem(); + case_lowerb(eddr.s, eddr.len); + if (constmap(&mapbmf, eddr.s, eddr.len - 1)) return -110; -/* '+' extended address for none-RELAYCLIENTS */ + /* '+' extended address for none-RELAYCLIENTS */ if (at && !relayclient) { - if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem(); - if (!stralloc_append(&eddr,"+")) die_nomem(); + if (!stralloc_copyb(&eddr, mailfrom.s, mailfrom.len - 1)) die_nomem(); + if (!stralloc_append(&eddr, "+")) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - case_lowerb(eddr.s,eddr.len); - if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -5; + case_lowerb(eddr.s, eddr.len); + if (constmap(&mapbmf, eddr.s + at, eddr.len - at - 1)) return -5; } -/* '-' extended address from UNKNOWN */ + /* '-' extended address from UNKNOWN */ - if (at && !case_diffs(remotehost,"unknown")) { - if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem(); - if (!stralloc_append(&eddr,"-")) die_nomem(); + if (at && !case_diffs(remotehost, "unknown")) { + if (!stralloc_copyb(&eddr, mailfrom.s, mailfrom.len - 1)) die_nomem(); + if (!stralloc_append(&eddr, "-")) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - case_lowerb(eddr.s,eddr.len); - if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -4; + case_lowerb(eddr.s, eddr.len); + if (constmap(&mapbmf, eddr.s + at, eddr.len - at - 1)) return -4; } -/* '=' extended address for WELLKNOWN senders */ + /* '=' extended address for WELLKNOWN senders */ - else if (at && rlen >= mailfrom.len - at - 1) { + else if (at && rlen >= mailfrom.len - at - 1) + { dlen = mailfrom.len - at - 2; - if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem(); - if (!stralloc_append(&eddr,"=")) die_nomem(); + if (!stralloc_copyb(&eddr, mailfrom.s, mailfrom.len - 1)) die_nomem(); + if (!stralloc_append(&eddr, "=")) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - case_lowerb(eddr.s,eddr.len); - if (str_diffn(remotehost + rlen - dlen,eddr.s + at + 1,dlen)) - if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -3; + case_lowerb(eddr.s, eddr.len); + if (str_diffn(remotehost + rlen - dlen, eddr.s + at + 1, dlen)) + if (constmap(&mapbmf, eddr.s + at, eddr.len - at - 1)) return -3; -/* '~' extended address for MISMATCHED Domains */ + /* '~' extended address for MISMATCHED Domains */ - if (case_diffrs(remotehost,mailfrom.s + at + 1)) { + if (case_diffrs(remotehost, mailfrom.s + at + 1)) { j = 0; do { - if (!stralloc_copys(&eddr,"~")) die_nomem(); - if (!stralloc_cats(&eddr,remotehost + j)) die_nomem(); + if (!stralloc_copys(&eddr, "~")) die_nomem(); + if (!stralloc_cats(&eddr, remotehost + j)) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return -2; - j = byte_chr(remotehost + j,rlen - j,'.') + j + 1; + if (constmap(&mapbmf, eddr.s, eddr.len - 1)) return -2; + j = byte_chr(remotehost + j, rlen - j, '.') + j + 1; } while (j > 0 && rlen - j > 0); } } -/* Standard */ + /* Standard */ - if (constmap(&mapbmf,mailfrom.s,mailfrom.len - 1)) return -1; + if (constmap(&mapbmf, mailfrom.s, mailfrom.len - 1)) return -1; if (at && at < mailfrom.len) - if (constmap(&mapbmf,mailfrom.s + at,mailfrom.len - at - 1)) return -1; + if (constmap(&mapbmf, mailfrom.s + at, mailfrom.len - at - 1)) return -1; -/* Wildmating */ + /* Wildmating */ i = k = 0; for (j = 0; j < bmf.len; ++j) { if (!bmf.s[j]) { subvalue = bmf.s[i] != '!'; if (!subvalue) i++; - if ((k != subvalue) && wildmat(mailfrom.s,bmf.s + i)) k = subvalue; + if ((k != subvalue) && wildmat(mailfrom.s, bmf.s + i)) k = subvalue; i = j + 1; } } @@ -724,20 +777,20 @@ int brtcheck() char subvalue; if (brtok) { - if (constmap(&mapbrt,addr.s,addr.len - 1)) return -2; + if (constmap(&mapbrt, addr.s, addr.len - 1)) return -2; - int at = byte_rchr(addr.s,addr.len,'@'); + int at = byte_rchr(addr.s, addr.len, '@'); if (at < addr.len) - if (constmap(&mapbrt,addr.s + at,addr.len - at - j)) return -1; + if (constmap(&mapbrt, addr.s + at, addr.len - at - j)) return -1; -/* '#' enhanced address to consider invalid rcptto addresses for none-relayclients */ + /* '#' enhanced address to consider invalid rcptto addresses for none-relayclients */ if (!relayclient) { - if (!stralloc_copys(&eddr,"+")) die_nomem(); - if (!stralloc_cat(&eddr,&addr)) die_nomem(); + if (!stralloc_copys(&eddr, "+")) die_nomem(); + if (!stralloc_cat(&eddr, &addr)) die_nomem(); if (!stralloc_0(&eddr)) die_nomem(); - case_lowerb(eddr.s,eddr.len); - if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return 110; + case_lowerb(eddr.s, eddr.len); + if (constmap(&mapbmf, eddr.s, eddr.len - 1)) return 110; } i = 0; @@ -745,7 +798,7 @@ int brtcheck() if (!brt.s[j]) { subvalue = brt.s[i] != '!'; if (!subvalue) i++; - if ((k != subvalue) && wildmat(addr.s,brt.s + i)) k = subvalue; + if ((k != subvalue) && wildmat(addr.s, brt.s + i)) k = subvalue; i = j + 1; } return k; @@ -756,7 +809,7 @@ int brtcheck() int addrallowed(char *arg) { int r; - r = rcpthosts(arg,str_len(arg)); + r = rcpthosts(arg, str_len(arg)); if (r == -1) die_control(); return r; } @@ -764,7 +817,7 @@ int addrallowed(char *arg) int rcptallowed() { int r; - r = recipients(addr.s,str_len(addr.s)); + r = recipients(addr.s, str_len(addr.s)); #ifdef PAM111421 if (r == 111) die_recipients(); #endif @@ -780,24 +833,23 @@ int localaddr(char *mf) int mflen; mflen = str_len(mf); - if (mflen < 1 ) return 0; + if (mflen < 1) return 0; if (localmf == 4) { - if (!case_diffs(dnemail,mf)) return 2; + if (!case_diffs(dnemail, mf)) return 2; return -4; } if (localmf == 3) { - if (!case_diffs(remoteinfo,mf)) return 2; + if (!case_diffs(remoteinfo, mf)) return 2; return -3; - } - else if (localmf == 2) - return mfrules(fdmav,remoteip,remotehost,remoteinfo,mf); + } else if (localmf == 2) + return mfrules(fdmav, remoteip, remotehost, remoteinfo, mf); else { if (str_len(localmfcheck) > 1) { - case_lowerb(localmfcheck,str_len(localmfcheck)); - at = byte_rchr(mf,mflen,'@'); + case_lowerb(localmfcheck, str_len(localmfcheck)); + at = byte_rchr(mf, mflen, '@'); if (at < mflen) - if (!str_diffn(localmfcheck,mf + at + 1,mflen - at - 1)) return 2; + if (!str_diffn(localmfcheck, mf + at + 1, mflen - at - 1)) return 2; } if (addrallowed(mf)) return 3; return -2; @@ -808,47 +860,59 @@ int spf_check(int flag6) { int r; - if (mailfrom.len <= 1) { flagspf = 0; return 0; } + if (mailfrom.len <= 1) { + flagspf = 0; + return 0; + } DNS_INIT - r = spf_query(remoteip,helohost.s,mailfrom.s,local,flag6); + r = spf_query(remoteip, helohost.s, mailfrom.s, local, flag6); if (r == SPF_NOMEM) die_nomem(); if (!stralloc_0(&spfinfo)) die_nomem(); switch (r) { case SPF_ME: - case SPF_OK: - if (!env_put("SPFRESULT","pass")) die_nomem(); + case SPF_OK: + if (!env_put("SPFRESULT", "pass")) die_nomem(); flagspf = 10; break; case SPF_LOOP: - case SPF_ERROR: + case SPF_ERROR: case SPF_SYNTAX: case SPF_EXHAUST: - if (!env_put("SPFRESULT","error")) die_nomem(); - if (flagspf < 2) { flagspf = 0; break; } + if (!env_put("SPFRESULT", "error")) die_nomem(); + if (flagspf < 2) { + flagspf = 0; + break; + } out("451 SPF lookup failure (#4.3.0)\r\n"); return -1; - case SPF_NONE: - if (!env_put("SPFRESULT","none")) die_nomem(); + case SPF_NONE: + if (!env_put("SPFRESULT", "none")) die_nomem(); flagspf = 0; break; case SPF_UNKNOWN: - if (!env_put("SPFRESULT","unknown")) die_nomem(); - if (flagspf < 6) break; - else return 4; + if (!env_put("SPFRESULT", "unknown")) die_nomem(); + if (flagspf < 6) + break; + else + return 4; case SPF_NEUTRAL: - if (!env_put("SPFRESULT","neutral")) die_nomem(); - if (flagspf < 5) break; - else return 3; + if (!env_put("SPFRESULT", "neutral")) die_nomem(); + if (flagspf < 5) + break; + else + return 3; case SPF_SOFTFAIL: - if (!env_put("SPFRESULT","softfail")) die_nomem(); - if (flagspf < 4) break; - else return 2; + if (!env_put("SPFRESULT", "softfail")) die_nomem(); + if (flagspf < 4) + break; + else + return 2; case SPF_FAIL: - if (!env_put("SPFRESULT","fail")) die_nomem(); + if (!env_put("SPFRESULT", "fail")) die_nomem(); if (flagspf < 3) break; - if (!spf_parse(&spfbounce,spfexpmsg.s,expdomain.s)) die_nomem(); + if (!spf_parse(&spfbounce, spfexpmsg.s, expdomain.s)) die_nomem(); return 1; } @@ -862,32 +926,36 @@ int mailfrom_size(char *arg) unsigned long r; unsigned long sizebytes = 0; - scan_ulong(arg,&r); + scan_ulong(arg, &r); sizebytes = r; - if (databytes) if (sizebytes > databytes) return 1; + if (databytes) + if (sizebytes > databytes) return 1; return 0; } -void mailfrom_auth(char *arg,int len) +void mailfrom_auth(char *arg, int len) { - if (!stralloc_copys(&fuser,"")) die_nomem(); - if (case_starts(arg,"<>")) { - if (!stralloc_cats(&fuser,"unknown")) die_nomem(); + if (!stralloc_copys(&fuser, "")) die_nomem(); + if (case_starts(arg, "<>")) { + if (!stralloc_cats(&fuser, "unknown")) die_nomem(); } else { while (len) { if (*arg == '+') { - if (case_starts(arg,"+3D")) { - arg = arg + 2; len = len - 2; - if (!stralloc_cats(&fuser,"=")) die_nomem(); + if (case_starts(arg, "+3D")) { + arg = arg + 2; + len = len - 2; + if (!stralloc_cats(&fuser, "=")) die_nomem(); } - if (case_starts(arg,"+2B")) { - arg = arg + 2; len = len - 2; - if (!stralloc_cats(&fuser,"+")) die_nomem(); + if (case_starts(arg, "+2B")) { + arg = arg + 2; + len = len - 2; + if (!stralloc_cats(&fuser, "+")) die_nomem(); } } else { - if (!stralloc_catb(&fuser,arg,1)) die_nomem(); + if (!stralloc_catb(&fuser, arg, 1)) die_nomem(); } - arg++; len--; + arg++; + len--; } } @@ -895,9 +963,9 @@ void mailfrom_auth(char *arg,int len) if (!remoteinfo) { remoteinfo = fuser.s; if (!env_unset("TCPREMOTEINFO")) die_read(); - if (!env_put("TCPREMOTEINFO",remoteinfo)) die_nomem(); + if (!env_put("TCPREMOTEINFO", remoteinfo)) die_nomem(); if (!env_unset("TCP6REMOTEINFO")) die_read(); - if (!env_put("TCP6REMOTEINFO",remoteinfo)) die_nomem(); + if (!env_put("TCP6REMOTEINFO", remoteinfo)) die_nomem(); } } @@ -906,18 +974,23 @@ void mailfrom_parms(char *arg) int len; if ((len = str_len(arg))) { - if (!stralloc_copys(&mfparms,"")) die_nomem(); - while (len) { - arg++; len--; - if (*arg == ' ' || *arg == '\0' ) { - if (flagutf8) if (case_starts(mfparms.s,"SMTPUTF8")) flagutf8 = 2; - if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s + 5)) { flagsize = 1; return; } - if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s + 5,mfparms.len - 5); - if (!stralloc_copys(&mfparms,"")) die_nomem(); - } - else - if (!stralloc_catb(&mfparms,arg,1)) die_nomem(); - } + if (!stralloc_copys(&mfparms, "")) die_nomem(); + while (len) { + arg++; + len--; + if (*arg == ' ' || *arg == '\0') { + if (flagutf8) + if (case_starts(mfparms.s, "SMTPUTF8")) flagutf8 = 2; + if (case_starts(mfparms.s, "SIZE=")) + if (mailfrom_size(mfparms.s + 5)) { + flagsize = 1; + return; + } + if (case_starts(mfparms.s, "AUTH=")) mailfrom_auth(mfparms.s + 5, mfparms.len - 5); + if (!stralloc_copys(&mfparms, "")) die_nomem(); + } else if (!stralloc_catb(&mfparms, arg, 1)) + die_nomem(); + } } } @@ -925,8 +998,12 @@ void mailfrom_parms(char *arg) void smtp_helo(char *arg) { - smtp_greet("250 "); out("\r\n"); flush(); - seenmail = 0; rcptcount = 0; seenhelo++; + smtp_greet("250 "); + out("\r\n"); + flush(); + seenmail = 0; + rcptcount = 0; + seenhelo++; dohelo(arg); } @@ -934,30 +1011,39 @@ void smtp_ehlo(char *arg) { char size[FMT_ULONG]; - smtp_greet("250-"); out("\r\n"); + smtp_greet("250-"); + out("\r\n"); out("250-PIPELINING\r\n250-8BITMIME\r\n"); if (flagutf8) out("250-SMTPUTF8\r\n"); if (starttls > 0 && !seentls) out("250-STARTTLS\r\n"); - + switch (smtpauth) { - case 1: case 11: out("250-AUTH LOGIN PLAIN\r\n"); break; - case 2: case 12: out("250-AUTH CRAM-MD5\r\n"); break; - case 3: case 13: out("250-AUTH LOGIN PLAIN CRAM-MD5\r\n"); break; + case 1: + case 11: out("250-AUTH LOGIN PLAIN\r\n"); break; + case 2: + case 12: out("250-AUTH CRAM-MD5\r\n"); break; + case 3: + case 13: out("250-AUTH LOGIN PLAIN CRAM-MD5\r\n"); break; } - size[fmt_ulong(size,(unsigned long) databytes)] = 0; - out("250 SIZE "); out(size); out("\r\n"); + size[fmt_ulong(size, (unsigned long)databytes)] = 0; + out("250 SIZE "); + out(size); + out("\r\n"); - seenhelo++; seenmail = 0; rcptcount = 0; + seenhelo++; + seenmail = 0; + rcptcount = 0; dohelo(arg); } void smtp_rset(void) { - seenmail = 0; rcptcount = 0; /* RFC 5321: seenauth + seentls stay */ + seenmail = 0; + rcptcount = 0; /* RFC 5321: seenauth + seentls stay */ - if (!stralloc_copys(&mailfrom,"")) die_nomem(); - if (!stralloc_copys(&rcptto,"")) die_nomem(); + if (!stralloc_copys(&mailfrom, "")) die_nomem(); + if (!stralloc_copys(&rcptto, "")) die_nomem(); out("250 flushed\r\n"); } @@ -969,36 +1055,42 @@ void smtp_starttls() flush(); if (!starttls_init()) die_starttls(); - buffer_init(&bi,saferead,FDIN,inbuf,sizeof(inbuf)); + buffer_init(&bi, saferead, FDIN, inbuf, sizeof(inbuf)); seentls = 2; if (!starttls_info()) die_starttls(); if (!modssl_info()) die_starttls(); -/* reset SMTP state */ + /* reset SMTP state */ - seenhelo = 0; seenmail = 0; rcptcount = 0; - if (!stralloc_copys(&addr,"")) die_nomem(); - if (!stralloc_copys(&helohost,"")) die_nomem(); - if (!stralloc_copys(&mailfrom,"")) die_nomem(); - if (!stralloc_copys(&rcptto,"")) die_nomem(); + seenhelo = 0; + seenmail = 0; + rcptcount = 0; + if (!stralloc_copys(&addr, "")) die_nomem(); + if (!stralloc_copys(&helohost, "")) die_nomem(); + if (!stralloc_copys(&mailfrom, "")) die_nomem(); + if (!stralloc_copys(&rcptto, "")) die_nomem(); if (seenauth == 1) seenauth = 0; /* Otherwise Auth by client Cert */ } void smtp_mail(char *arg) { - if (flagutf8) if (!stralloc_cats(&protocol,"UTF8")) die_nomem(); + if (flagutf8) + if (!stralloc_cats(&protocol, "UTF8")) die_nomem(); if (!stralloc_0(&protocol)) die_nomem(); - if ((starttls > 1) && !seentls) { - err_tlsreq("Reject::TLS::missing",protocol.s,remoteip,remotehost,helohost.s); + if ((starttls > 1) && !seentls) { + err_tlsreq("Reject::TLS::missing", protocol.s, remoteip, remotehost, helohost.s); + return; + } + if (smtpauth > 10 && !seenauth) { + err_authreq("Reject::AUTH::missing", protocol.s, remoteip, remotehost, helohost.s); return; } - if (smtpauth > 10 && !seenauth) { - err_authreq("Reject::AUTH::missing",protocol.s,remoteip,remotehost,helohost.s); + if (!addrparse(arg)) { + err_syntax(); return; } - if (!addrparse(arg)) { err_syntax(); return; } flagsize = 0; rcptcount = 0; @@ -1006,16 +1098,17 @@ void smtp_mail(char *arg) seenmail++; if (relayclient && localmf) { flagmav = localaddr(addr.s); - if (flagmav > 0) if (!stralloc_append(&protocol,"M")) die_nomem(); + if (flagmav > 0) + if (!stralloc_append(&protocol, "M")) die_nomem(); } - if (!stralloc_copys(&rcptto,"")) die_nomem(); - if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); + if (!stralloc_copys(&rcptto, "")) die_nomem(); + if (!stralloc_copys(&mailfrom, addr.s)) die_nomem(); if (!stralloc_0(&mailfrom)) die_nomem(); - if (!env_put("MAILFROM",mailfrom.s)) die_nomem(); + if (!env_put("MAILFROM", mailfrom.s)) die_nomem(); flagaddr = bmfcheck(); - if (flagaddr != -110) - if (mfdnscheck) flagdnsmf = dnsq(mailfrom.s,'M'); + if (flagaddr != -110) + if (mfdnscheck) flagdnsmf = dnsq(mailfrom.s, 'M'); out("250 ok\r\n"); } @@ -1027,17 +1120,15 @@ int postgrey_scanner() int child; int wstat; - char *postgrey_scannerarg[] = {"bin/qmail-postgrey",pgbind.s,mailfrom.s,addr.s,remoteip,remotehost,0}; + char *postgrey_scannerarg[] = { + "bin/qmail-postgrey", pgbind.s, mailfrom.s, addr.s, remoteip, remotehost, 0}; switch (child = fork()) { - case -1: - return err_forkgl(); - case 0: - execv(*postgrey_scannerarg,postgrey_scannerarg); - _exit(1); + case -1: return err_forkgl(); + case 0: execv(*postgrey_scannerarg, postgrey_scannerarg); _exit(1); } - wait_pid(&wstat,child); + wait_pid(&wstat, child); if (wait_crashed(wstat)) return err_postgl(); switch (wait_exitcode(wstat)) { @@ -1049,89 +1140,164 @@ int postgrey_scanner() void smtp_rcpt(char *arg) { char *rcptok = 0; - if (!seenmail) { err_wantmail(); return; } - if (!addrparse(arg)) { err_syntax(); return; } + if (!seenmail) { + err_wantmail(); + return; + } + if (!addrparse(arg)) { + err_syntax(); + return; + } rcptcount++; -/* this file is too long --------------------------------- Split Horizon envelope checks */ + /* this file is too long --------------------------------- Split Horizon envelope checks */ if (!relayclient) { - if (!seenhelo && helocheck) /* Helo rejects */ - if (str_len(helocheck) == 1) { - err_helo("Reject::SNDR::Bad_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"0"); - return; - } + if (!seenhelo && helocheck) /* Helo rejects */ + if (str_len(helocheck) == 1) { + err_helo( + "Reject::SNDR::Bad_Helo", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + "0"); + return; + } if (flagbadhelo) { - switch (flagbadhelo) { - case -2: badhelocond = "!"; break; - case -1: badhelocond = "."; break; - default: badhelocond = "*"; break; - } - err_helo("Reject::SNDR::Bad_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badhelocond); - return; + switch (flagbadhelo) { + case -2: badhelocond = "!"; break; + case -1: badhelocond = "."; break; + default: badhelocond = "*"; break; + } + err_helo( + "Reject::SNDR::Bad_Helo", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + badhelocond); + return; } if (flagdnshelo > 0) { - err_helo("Reject::SNDR::DNS_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badhelocond); + err_helo( + "Reject::SNDR::DNS_Helo", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + badhelocond); return; } - if (flagdnsmf > 0) { /* Mail from rejects */ - err_mfdns("Reject::ORIG::DNS_MF",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + if (flagdnsmf > 0) { /* Mail from rejects */ + err_mfdns( + "Reject::ORIG::DNS_MF", protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); return; } - - if (!addrallowed(addr.s)) { /* Relaying rejects */ - err_nogateway("Reject::SNDR::Invalid_Relay",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + + if (!addrallowed(addr.s)) { /* Relaying rejects */ + err_nogateway( + "Reject::SNDR::Invalid_Relay", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } - - if (greylist && (postgrey_scanner() == 1)) { /* Greylisting */ - postgrey("Deferred::SNDR::Grey_Listed",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + + if (greylist && (postgrey_scanner() == 1)) { /* Greylisting */ + postgrey( + "Deferred::SNDR::Grey_Listed", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } - if (tarpitcount && flagerrcpts >= tarpitcount) { /* Tarpitting et al. */ + if (tarpitcount && flagerrcpts >= tarpitcount) { /* Tarpitting et al. */ if (tarpitdelay == 999) flagnotorious++; - err_rcpts("Reject::RCPT::Toomany_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_rcpts( + "Reject::RCPT::Toomany_Rcptto", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } if (tarpitcount && rcptcount >= tarpitcount) if (tarpitdelay > 0 && tarpitdelay < 999) sleep(tarpitdelay); - flagrcpt = rcptallowed(); /* Rcpt to rejects */ + flagrcpt = rcptallowed(); /* Rcpt to rejects */ if (!flagrcpt) { - err_recipient("Reject::RCPT::Failed_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_recipient( + "Reject::RCPT::Failed_Rcptto", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); flagerrcpts++; return; } - if (flagspf) /* SPF rejects */ + if (flagspf) /* SPF rejects */ if (spf_check(flagip6) > 0) { if (!stralloc_0(&spfbounce)) die_nomem(); // spfbounce is 0-terminated in any case - err_spf("Reject::SPF::Fail",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,spfbounce.s); + err_spf( + "Reject::SPF::Fail", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + spfbounce.s); return; } } -/* this file is too long --------------------------------- Local checks */ + /* this file is too long --------------------------------- Local checks */ - else { + else + { if (flagmimetype == 4 || flagmimetype == 6) flagmimetype = 0; if (flagloadertype == 2) flagloadertype = 0; if (flagmav < 0) { - err_mav("Reject::ORIG::Invalid_Mailfrom",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_mav( + "Reject::ORIG::Invalid_Mailfrom", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } --addr.len; - if (!stralloc_cats(&addr,relayclient)) die_nomem(); + if (!stralloc_cats(&addr, relayclient)) die_nomem(); if (!stralloc_0(&addr)) die_nomem(); } -/* this file is too long --------------------------------- Common checks */ + /* this file is too long --------------------------------- Common checks */ - if (flagmimetype == 2 || flagmimetype == 3 || flagmimetype == 6) cdb_init(&cdbm,fdbmt); - if (flagloadertype == 1) cdb_init(&cdbl,fdblt); + if (flagmimetype == 2 || flagmimetype == 3 || flagmimetype == 6) cdb_init(&cdbm, fdbmt); + if (flagloadertype == 1) cdb_init(&cdbl, fdblt); if (flagaddr && flagaddr != -110) { switch (flagaddr) { @@ -1142,60 +1308,96 @@ void smtp_rcpt(char *arg) case -5: badmailcond = "+"; break; default: badmailcond = "*"; break; } - err_bmf("Reject::ORIG::Bad_Mailfrom",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badmailcond); + err_bmf( + "Reject::ORIG::Bad_Mailfrom", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + badmailcond); return; } - + flagrcpt = brtcheck(); if (flagrcpt == 110) { - err_brt("Reject::RCPT::Invalid_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_brt( + "Reject::RCPT::Invalid_Rcptto", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } else if (flagrcpt > 0) { - err_brt("Reject::RCPT::Bad_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_brt( + "Reject::RCPT::Bad_Rcptto", protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); return; } if (flagsize) { - err_size("Reject::DATA::Invalid_Size",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_size( + "Reject::DATA::Invalid_Size", protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); return; } if (maxrcptcount && rcptcount > maxrcptcount) { - err_rcpts("Reject::RCPT::Toomany_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + err_rcpts( + "Reject::RCPT::Toomany_Rcptto", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); return; } -/* this file is too long --------------------------------- Checks done; mailfrom/recipient accepted */ + /* this file is too long --------------------------------- Checks done; mailfrom/recipient accepted */ - if (!stralloc_cats(&rcptto,"T")) die_nomem(); - if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_cats(&rcptto, "T")) die_nomem(); + if (!stralloc_cats(&rcptto, addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); - if (!stralloc_cats(&mailto,addr.s)) die_nomem(); - if (!stralloc_cats(&mailto," ")) die_nomem(); - if (!stralloc_copys(&deliverto,mailto.s)) die_nomem(); + if (!stralloc_cats(&mailto, addr.s)) die_nomem(); + if (!stralloc_cats(&mailto, " ")) die_nomem(); + if (!stralloc_copys(&deliverto, mailto.s)) die_nomem(); if (!stralloc_0(&deliverto)) die_nomem(); - if (!env_put("RCPTTO",deliverto.s)) die_nomem(); + if (!env_put("RCPTTO", deliverto.s)) die_nomem(); -/* this file is too long --------------------------------- Additional logging */ + /* this file is too long --------------------------------- Additional logging */ switch (flagrcpt) { - case 1: rcptok = "Recipients_Cdb"; break; - case 2: rcptok = "Recipients_Pam"; break; - case 3: rcptok = "Recipients_Users"; break; - case 4: rcptok = "Recipients_Wild"; break; - default: rcptok = "Rcpthosts_Rcptto"; break; + case 1: rcptok = "Recipients_Cdb"; break; + case 2: rcptok = "Recipients_Pam"; break; + case 3: rcptok = "Recipients_Users"; break; + case 4: rcptok = "Recipients_Wild"; break; + default: rcptok = "Rcpthosts_Rcptto"; break; } if (seenauth) - smtp_loga("Accept::AUTH::",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,remoteinfo,authmethod.s); + smtp_loga( + "Accept::AUTH::", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + remoteinfo, + authmethod.s); else if (flagmav > 0) - smtp_logg("Accept::ORIG::Local_Sender",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + smtp_logg( + "Accept::ORIG::Local_Sender", protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); else if (relayclient) - smtp_logg("Accept::SNDR::Relay_Client",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + smtp_logg( + "Accept::SNDR::Relay_Client", protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); else if (flagspf == 10) - smtp_logr("Accept::SPF::",rcptok,protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + smtp_logr("Accept::SPF::", rcptok, protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); else - smtp_logr("Accept::RCPT::",rcptok,protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); + smtp_logr( + "Accept::RCPT::", rcptok, protocol.s, remoteip, remotehost, helohost.s, mailfrom.s, addr.s); out("250 ok\r\n"); } @@ -1209,37 +1411,44 @@ stralloc badmimetype = {0}; stralloc badloadertype = {0}; unsigned int nolines = 0; -unsigned int flagb64 = 0; /* lineno with BASE64MESSAGE */ -unsigned int flagbase = 0; /* lineno with actual base64 content */ +unsigned int flagb64 = 0; /* lineno with BASE64MESSAGE */ +unsigned int flagbase = 0; /* lineno with actual base64 content */ unsigned int flagblank = 0; static void queue_put(char *ch) { int i; - if (flagmimetype > 0 || flagloadertype > 0 ) { + if (flagmimetype > 0 || flagloadertype > 0) { if (line.len <= BUFFER_SIZE) - if (!stralloc_catb(&line,ch,1)) die_nomem(); /* Reassamble chars to line; prepend with 'L' */ + if (!stralloc_catb(&line, ch, 1)) die_nomem(); /* Reassamble chars to line; prepend with 'L' */ if (*ch == '\n') { nolines++; - if (line.len == 2) { flagblank = nolines; flagbase = 0; } + if (line.len == 2) { + flagblank = nolines; + flagbase = 0; + } if (*(line.s + 1) == 'C' || *(line.s + 1) == 'c') - if (case_startb(line.s + 1,line.len - 2,BASE64MESSAGE)) flagb64 = nolines; + if (case_startb(line.s + 1, line.len - 2, BASE64MESSAGE)) flagb64 = nolines; if (flagb64 && nolines == flagblank + 1 && line.len > MIMETYPE_LEN + 2) flagbase = nolines; - if (*(line.s + 1) == '-') { flagb64 = 0; flagbase = 0; } + if (*(line.s + 1) == '-') { + flagb64 = 0; + flagbase = 0; + } - if (flagmimetype > 0 && flagbase == nolines) { /* badmimetype */ - if (!stralloc_catb(&base64types,line.s + 1,MIMETYPE_LEN)) die_nomem(); + if (flagmimetype > 0 && flagbase == nolines) { /* badmimetype */ + if (!stralloc_catb(&base64types, line.s + 1, MIMETYPE_LEN)) die_nomem(); if (!stralloc_0(&base64types)) die_nomem(); if (flagmimetype == 2 || flagmimetype == 3 || flagmimetype == 6) { - if (cdb_find(&cdbm,line.s + 1,MIMETYPE_LEN)) { - cdb_free(&cdbm); close(fdbmt); - if (!stralloc_copyb(&badmimetype,line.s + 1,MIMETYPE_LEN)) die_nomem(); + if (cdb_find(&cdbm, line.s + 1, MIMETYPE_LEN)) { + cdb_free(&cdbm); + close(fdbmt); + if (!stralloc_copyb(&badmimetype, line.s + 1, MIMETYPE_LEN)) die_nomem(); if (!stralloc_0(&badmimetype)) die_nomem(); - if (!stralloc_cats(&rcptto,"M")) die_nomem(); + if (!stralloc_cats(&rcptto, "M")) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); qmail_fail(&qqt); flagmimetype = -1; @@ -1250,22 +1459,23 @@ static void queue_put(char *ch) if (flagbase && line.len > LOADER_LEN + 2) { if (flagloadertype >= 1 || flagmimetype >= 1) { for (i = 0; i < line.len - LOADER_LEN; ++i) { - if (flagloadertype == 1 && *(line.s+i) == *badloaderinit) { /* badloadertype */ - if (cdb_find(&cdbl,line.s + i,LOADER_LEN)) { - cdb_free(&cdbl); close(fdbmt); - if (!stralloc_copyb(&badloadertype,line.s + i,LOADER_LEN)) die_nomem(); + if (flagloadertype == 1 && *(line.s + i) == *badloaderinit) { /* badloadertype */ + if (cdb_find(&cdbl, line.s + i, LOADER_LEN)) { + cdb_free(&cdbl); + close(fdbmt); + if (!stralloc_copyb(&badloadertype, line.s + i, LOADER_LEN)) die_nomem(); if (!stralloc_0(&badloadertype)) die_nomem(); - if (!stralloc_cats(&rcptto,"L")) die_nomem(); + if (!stralloc_cats(&rcptto, "L")) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); qmail_fail(&qqt); flagloadertype = -1; } } if (flagmimetype == 1 || flagmimetype == 3 || flagmimetype == 4) { - if (*(line.s + i) == ' ' || *(line.s + i) == '\t') { /* white spaces */ - if (!stralloc_copyb(&badmimetype,line.s + i - 2,MIMETYPE_LEN)) die_nomem(); + if (*(line.s + i) == ' ' || *(line.s + i) == '\t') { /* white spaces */ + if (!stralloc_copyb(&badmimetype, line.s + i - 2, MIMETYPE_LEN)) die_nomem(); if (!stralloc_0(&badmimetype)) die_nomem(); - if (!stralloc_cats(&rcptto,"M")) die_nomem(); + if (!stralloc_cats(&rcptto, "M")) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); qmail_fail(&qqt); flagmimetype = -2; @@ -1275,14 +1485,13 @@ static void queue_put(char *ch) } } line.len = 0; - if (!stralloc_copys(&line,"L")) die_nomem(); + if (!stralloc_copys(&line, "L")) die_nomem(); } } if (bytestooverflow) - if (!--bytestooverflow) - qmail_fail(&qqt); - qmail_put(&qqt,ch,1); + if (!--bytestooverflow) qmail_fail(&qqt); + qmail_put(&qqt, ch, 1); } void blast(int *hops) @@ -1291,7 +1500,7 @@ void blast(int *hops) int state; int seencr; int flaginheader; - int pos; /* number of bytes since most recent \n, if fih */ + int pos; /* number of bytes since most recent \n, if fih */ int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ int flagmaybey; /* 1 if this line might match \r\n, if fih */ int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ @@ -1299,52 +1508,90 @@ void blast(int *hops) state = 1; *hops = 0; flaginheader = 1; - pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; seencr = 0; + pos = 0; + flagmaybex = flagmaybey = flagmaybez = 1; + seencr = 0; for (;;) { - buffer_get(&bi,&ch,1); + buffer_get(&bi, &ch, 1); if (ch == '\n') { - if (seencr == 0) { buffer_seek(&bi,-1); ch = '\r'; } + if (seencr == 0) { + buffer_seek(&bi, -1); + ch = '\r'; + } } - if (ch == '\r') seencr = 1; else seencr = 0; + if (ch == '\r') + seencr = 1; + else + seencr = 0; if (flaginheader) { if (pos < 9) { - if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0; - if (flagmaybez) if (pos == 8) ++*hops; + if (ch != "delivered"[pos]) + if (ch != "DELIVERED"[pos]) flagmaybez = 0; + if (flagmaybez) + if (pos == 8) ++*hops; if (pos < 8) - if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0; - if (flagmaybex) if (pos == 7) ++*hops; - if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; - if (flagmaybey) if (pos == 1) flaginheader = 0; + if (ch != "received"[pos]) + if (ch != "RECEIVED"[pos]) flagmaybex = 0; + if (flagmaybex) + if (pos == 7) ++*hops; + if (pos < 2) + if (ch != "\r\n"[pos]) flagmaybey = 0; + if (flagmaybey) + if (pos == 1) flaginheader = 0; ++pos; } - if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } + if (ch == '\n') { + pos = 0; + flagmaybex = flagmaybey = flagmaybez = 1; + } } switch (state) { case 0: if (ch == '\n') straynewline(); - if (ch == '\r') { state = 4; continue; } + if (ch == '\r') { + state = 4; + continue; + } break; case 1: /* \r\n */ if (ch == '\n') straynewline(); - if (ch == '.') { state = 2; continue; } - if (ch == '\r') { state = 4; continue; } + if (ch == '.') { + state = 2; + continue; + } + if (ch == '\r') { + state = 4; + continue; + } state = 0; break; case 2: /* \r\n + . */ if (ch == '\n') straynewline(); - if (ch == '\r') { state = 3; continue; } + if (ch == '\r') { + state = 3; + continue; + } state = 0; break; case 3: /* \r\n + .\r */ if (ch == '\n') return; queue_put("."); queue_put("\r"); - if (ch == '\r') { state = 4; continue; } + if (ch == '\r') { + state = 4; + continue; + } state = 0; break; case 4: /* + \r */ - if (ch == '\n') { state = 1; break; } - if (ch != '\r') { queue_put("\r"); state = 0; } + if (ch == '\n') { + state = 1; + break; + } + if (ch != '\r') { + queue_put("\r"); + state = 0; + } } queue_put(&ch); } @@ -1357,10 +1604,10 @@ void acceptmessage(unsigned long qp) datetime_sec when; when = now(); out("250 ok "); - accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0; + accept_buf[fmt_ulong(accept_buf, (unsigned long)when)] = 0; out(accept_buf); out(" qp "); - accept_buf[fmt_ulong(accept_buf,qp)] = 0; + accept_buf[fmt_ulong(accept_buf, qp)] = 0; out(accept_buf); out("\r\n"); } @@ -1371,69 +1618,152 @@ void smtp_data() unsigned long qp; char *qqx; - if (!seenmail) { err_wantmail(); return; } - if (!rcptto.len) { err_wantrcpt(); return; } - if (flagnotorious) { err_notorious(); } + if (!seenmail) { + err_wantmail(); + return; + } + if (!rcptto.len) { + err_wantrcpt(); + return; + } + if (flagnotorious) { + err_notorious(); + } seenmail = 0; if (databytes) bytestooverflow = databytes + 1; - if (!stralloc_copys(&addr,"")) die_nomem(); - if (!stralloc_cats(&addr,rcptto.s + 1)) die_nomem(); + if (!stralloc_copys(&addr, "")) die_nomem(); + if (!stralloc_cats(&addr, rcptto.s + 1)) die_nomem(); if (!stralloc_0(&addr)) die_nomem(); - if (qmail_open(&qqt) == -1) { err_qqt(); return; } + if (qmail_open(&qqt) == -1) { + err_qqt(); + return; + } qp = qmail_qp(&qqt); out("354 go ahead\r\n"); - if (flagspf && !relayclient) spfheader(&qqt,spfinfo.s,local,remoteip,helohost.s,mailfrom.s); - received(&qqt,protocol.s,local,remoteip,remotehost,remoteinfo,fakehelo,tlsinfo.s,rblinfo.s); + if (flagspf && !relayclient) spfheader(&qqt, spfinfo.s, local, remoteip, helohost.s, mailfrom.s); + received(&qqt, protocol.s, local, remoteip, remotehost, remoteinfo, fakehelo, tlsinfo.s, rblinfo.s); blast(&hops); hops = (hops >= MAXHOPS); if (hops) qmail_fail(&qqt); if (base64 && base64types.len == 0) { - if (!stralloc_cats(&rcptto,"Q")) die_nomem(); + if (!stralloc_cats(&rcptto, "Q")) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); } - qmail_from(&qqt,mailfrom.s); - qmail_put(&qqt,rcptto.s,rcptto.len); + qmail_from(&qqt, mailfrom.s); + qmail_put(&qqt, rcptto.s, rcptto.len); qqx = qmail_close(&qqt); - if (!*qqx) { acceptmessage(qp); return; } - if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; } + if (!*qqx) { + acceptmessage(qp); + return; + } + if (hops) { + out("554 too many hops, this message is looping (#5.4.6)\r\n"); + return; + } if (databytes) if (!bytestooverflow) { - err_size("Reject::DATA::Invalid_Size",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s); - return; + err_size( + "Reject::DATA::Invalid_Size", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s); + return; } if (flagmimetype < 0) { - err_data("Reject::DATA::Bad_MIME",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badmimetype.s); + err_data( + "Reject::DATA::Bad_MIME", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + badmimetype.s); return; } if (flagloadertype < 0) { - err_data("Reject::DATA::Bad_Loader",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badloadertype.s); + err_data( + "Reject::DATA::Bad_Loader", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + badloadertype.s); return; } if (*qqx == 'I') { - err_data("Reject::DKIM::Signature",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"fail"); + err_data( + "Reject::DKIM::Signature", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + "fail"); return; } if (*qqx == 'S') { - err_data("Reject::DATA::Spam_Message",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"spam"); + err_data( + "Reject::DATA::Spam_Message", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + "spam"); return; } if (*qqx == 'A') { - err_data("Reject::DATA::MIME_Attach",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"MIME"); + err_data( + "Reject::DATA::MIME_Attach", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + "MIME"); return; } if (*qqx == 'V') { if (qhpsi) - err_data("Reject::DATA::Virus_Infected",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,qhpsi); + err_data( + "Reject::DATA::Virus_Infected", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + qhpsi); else - err_data("Reject::DATA::Virus_Infected",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"AV scanner"); + err_data( + "Reject::DATA::Virus_Infected", + protocol.s, + remoteip, + remotehost, + helohost.s, + mailfrom.s, + addr.s, + "AV scanner"); return; } - if (*qqx == 'D') out("554 "); else out("451 "); + if (*qqx == 'D') + out("554 "); + else + out("451 "); out(qqx + 1); out("\r\n"); } @@ -1441,33 +1771,34 @@ void smtp_data() /* this file is too long --------------------------------- SMTP Auth */ char unique[FMT_ULONG + FMT_ULONG + 3]; -static stralloc authin = {0}; /* input from SMTP client */ -static stralloc pass = {0}; /* plain passwd or digest */ -static stralloc resp = {0}; /* b64 response */ -static stralloc chal = {0}; /* CRAM-MD5 plain challenge */ -static stralloc slop = {0}; /* CRAM-MD5 b64 challenge */ +static stralloc authin = {0}; /* input from SMTP client */ +static stralloc pass = {0}; /* plain passwd or digest */ +static stralloc resp = {0}; /* b64 response */ +static stralloc chal = {0}; /* CRAM-MD5 plain challenge */ +static stralloc slop = {0}; /* CRAM-MD5 b64 challenge */ char **childargs; char authbuf[512]; -buffer ba = BUFFER_INIT(safewrite,FDAUTH,authbuf,sizeof(authbuf)); +buffer ba = BUFFER_INIT(safewrite, FDAUTH, authbuf, sizeof(authbuf)); int authgetl(void) { int i; - if (!stralloc_copys(&authin,"")) die_nomem(); + if (!stralloc_copys(&authin, "")) die_nomem(); for (;;) { - if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */ - i = buffer_get(&bi,authin.s + authin.len,1); + if (!stralloc_readyplus(&authin, 1)) die_nomem(); /* XXX */ + i = buffer_get(&bi, authin.s + authin.len, 1); if (i != 1) die_read(); if (authin.s[authin.len] == '\n') break; ++authin.len; } - if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len; + if (authin.len > 0) + if (authin.s[authin.len - 1] == '\r') --authin.len; authin.s[authin.len] = 0; if (*authin.s == '*' && *(authin.s + 1) == 0) return err_authabort(); - if (authin.len == 0) return err_authinput(); + if (authin.len == 0) return err_authinput(); return authin.len; } @@ -1480,35 +1811,37 @@ int authenticate(void) if (!stralloc_0(&user)) die_nomem(); if (!stralloc_0(&pass)) die_nomem(); if (!stralloc_0(&chal)) die_nomem(); - if (!env_put("AUTHUSER",user.s)) die_nomem(); + if (!env_put("AUTHUSER", user.s)) die_nomem(); if (pipe(pi) == -1) return err_pipe(); switch (child = fork()) { - case -1: - return err_fork(); + case -1: return err_fork(); case 0: close(pi[1]); - if (fd_copy(FDAUTH,pi[0]) == -1) return err_pipe(); + if (fd_copy(FDAUTH, pi[0]) == -1) return err_pipe(); sig_pipedefault(); - execvp(*childargs,childargs); + execvp(*childargs, childargs); _exit(1); } close(pi[0]); - buffer_init(&ba,write,pi[1],authbuf,sizeof(authbuf)); - if (buffer_put(&ba,user.s,user.len) == -1) return err_write(); - if (buffer_put(&ba,pass.s,pass.len) == -1) return err_write(); + buffer_init(&ba, write, pi[1], authbuf, sizeof(authbuf)); + if (buffer_put(&ba, user.s, user.len) == -1) return err_write(); + if (buffer_put(&ba, pass.s, pass.len) == -1) return err_write(); if (smtpauth == 2 || smtpauth == 3 || smtpauth == 12 || smtpauth == 13) - if (buffer_put(&ba,chal.s,chal.len) == -1) return err_write(); + if (buffer_put(&ba, chal.s, chal.len) == -1) return err_write(); if (buffer_flush(&ba) == -1) return err_write(); close(pi[1]); - if (!stralloc_copys(&chal,"")) die_nomem(); - if (!stralloc_copys(&slop,"")) die_nomem(); - byte_zero(authbuf,sizeof(authbuf)); - if (wait_pid(&wstat,child) == -1) return err_child(); + if (!stralloc_copys(&chal, "")) die_nomem(); + if (!stralloc_copys(&slop, "")) die_nomem(); + byte_zero(authbuf, sizeof(authbuf)); + if (wait_pid(&wstat, child) == -1) return err_child(); if (wait_crashed(wstat)) return err_child(); - if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */ + if (wait_exitcode(wstat)) { + sleep(AUTHSLEEP); + return 1; + } /* no */ return 0; /* yes */ } @@ -1518,19 +1851,20 @@ int auth_login(char *arg) if (smtpauth == 2 || smtpauth == 12) return 1; /* only login/plain */ if (*arg) { - if ((r = b64decode((unsigned char *)arg,str_len(arg),&user)) == 1) return err_authinput(); - } - else { - out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */ + if ((r = b64decode((unsigned char *)arg, str_len(arg), &user)) == 1) return err_authinput(); + } else { + out("334 VXNlcm5hbWU6\r\n"); + flush(); /* Username: */ if (authgetl() < 0) return -1; - if ((r = b64decode((unsigned char *)authin.s,authin.len,&user)) == 1) return err_authinput(); + if ((r = b64decode((unsigned char *)authin.s, authin.len, &user)) == 1) return err_authinput(); } if (r == -1) die_nomem(); - out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */ + out("334 UGFzc3dvcmQ6\r\n"); + flush(); /* Password: */ if (authgetl() < 0) return -1; - if ((r = b64decode((unsigned char *)authin.s,authin.len,&pass)) == 1) return err_authinput(); + if ((r = b64decode((unsigned char *)authin.s, authin.len, &pass)) == 1) return err_authinput(); if (r == -1) die_nomem(); if (!user.len || !pass.len) return err_authinput(); @@ -1543,20 +1877,20 @@ int auth_plain(char *arg) if (smtpauth == 2 || smtpauth == 12) return 1; /* only login/plain */ if (*arg) { - if ((r = b64decode((unsigned char *)arg,str_len(arg),&resp)) == 1) return err_authinput(); - } - else { - out("334 \r\n"); flush(); + if ((r = b64decode((unsigned char *)arg, str_len(arg), &resp)) == 1) return err_authinput(); + } else { + out("334 \r\n"); + flush(); if (authgetl() < 0) return -1; - if ((r = b64decode((unsigned char *)authin.s,authin.len,&resp)) == 1) return err_authinput(); + if ((r = b64decode((unsigned char *)authin.s, authin.len, &resp)) == 1) return err_authinput(); } if (r == -1 || !stralloc_0(&resp)) die_nomem(); - while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */ + while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */ if (resp.len > id + 1) - if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem(); + if (!stralloc_copys(&user, resp.s + id + 1)) die_nomem(); if (resp.len > id + user.len + 2) - if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem(); + if (!stralloc_copys(&pass, resp.s + id + user.len + 2)) die_nomem(); if (!user.len || !pass.len) return err_authinput(); return authenticate(); @@ -1568,34 +1902,34 @@ int auth_cram() char *s; if (smtpauth == 1 || smtpauth == 11) return 1; /* no challenge if login/plain */ - s = unique; /* generate challenge */ - s += fmt_uint(s,getpid()); + s = unique; /* generate challenge */ + s += fmt_uint(s, getpid()); *s++ = '.'; - s += fmt_ulong(s,(unsigned long) now()); + s += fmt_ulong(s, (unsigned long)now()); *s++ = '@'; *s++ = 0; - if (!stralloc_copys(&chal,"<")) die_nomem(); - if (!stralloc_cats(&chal,unique)) die_nomem(); - if (!stralloc_cats(&chal,local)) die_nomem(); - if (!stralloc_cats(&chal,">")) die_nomem(); - if (b64encode(&chal,&slop) < 0) die_nomem(); + if (!stralloc_copys(&chal, "<")) die_nomem(); + if (!stralloc_cats(&chal, unique)) die_nomem(); + if (!stralloc_cats(&chal, local)) die_nomem(); + if (!stralloc_cats(&chal, ">")) die_nomem(); + if (b64encode(&chal, &slop) < 0) die_nomem(); if (!stralloc_0(&slop)) die_nomem(); - out("334 "); /* "334 base64_challenge \r\n" */ + out("334 "); /* "334 base64_challenge \r\n" */ out(slop.s); out("\r\n"); flush(); - if (authgetl() < 0) return -1; /* got response */ - if ((r = b64decode((unsigned char *)authin.s,authin.len,&resp)) == 1) return err_authinput(); + if (authgetl() < 0) return -1; /* got response */ + if ((r = b64decode((unsigned char *)authin.s, authin.len, &resp)) == 1) return err_authinput(); if (r == -1 || !stralloc_0(&resp)) die_nomem(); - i = str_rchr(resp.s,' '); + i = str_rchr(resp.s, ' '); s = resp.s + i; while (*s == ' ') ++s; resp.s[i] = 0; - if (!stralloc_copys(&user,resp.s)) die_nomem();/* userid */ - if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */ + if (!stralloc_copys(&user, resp.s)) die_nomem(); /* userid */ + if (!stralloc_copys(&pass, s)) die_nomem(); /* digest */ if (!user.len || !pass.len) return err_authinput(); return authenticate(); @@ -1605,10 +1939,10 @@ struct authcmd { char *text; int (*fun)(); } authcmds[] = { - { "login", auth_login } -, { "plain", auth_plain } -, { "cram-md5", auth_cram } -, { 0, err_noauth } + { "login", auth_login}, + { "plain", auth_plain}, + {"cram-md5", auth_cram}, + { 0, err_noauth} }; void smtp_auth(char *arg) @@ -1618,49 +1952,60 @@ void smtp_auth(char *arg) /* prevent users to expose userid + password over unencrypted connection */ - if ((starttls > 1) && !seentls) { - if (!stralloc_append(&protocol,"A")) die_nomem(); + if ((starttls > 1) && !seentls) { + if (!stralloc_append(&protocol, "A")) die_nomem(); if (!stralloc_0(&protocol)) die_nomem(); - err_authsetup("Reject::TLS::required",protocol.s,remoteip,remotehost,helohost.s); + err_authsetup("Reject::TLS::required", protocol.s, remoteip, remotehost, helohost.s); return; } - if ((starttls > 1) && !seenhelo) { - if (!stralloc_append(&protocol,"A")) die_nomem(); + if ((starttls > 1) && !seenhelo) { + if (!stralloc_append(&protocol, "A")) die_nomem(); if (!stralloc_0(&protocol)) die_nomem(); - err_tlsreq("Reject::AUTH::invalid",protocol.s,remoteip,remotehost,helohost.s); + err_tlsreq("Reject::AUTH::invalid", protocol.s, remoteip, remotehost, helohost.s); return; } - if (!smtpauth) { out("503 auth not available (#5.3.3)\r\n"); flush(); _exit(0); } + if (!smtpauth) { + out("503 auth not available (#5.3.3)\r\n"); + flush(); + _exit(0); + } if (smtpauth && !*childargs) { - err_authsetup("Reject::AUTH::invalid",protocol.s,remoteip,remotehost,helohost.s); - flush(); _exit(1); + err_authsetup("Reject::AUTH::invalid", protocol.s, remoteip, remotehost, helohost.s); + flush(); + _exit(1); + } + if (seenauth) { + err_authd(); + return; + } + if (seenmail) { + err_authmail(); + return; } - if (seenauth) { err_authd(); return; } - if (seenmail) { err_authmail(); return; } - if (!stralloc_copys(&user,"")) die_nomem(); - if (!stralloc_copys(&pass,"")) die_nomem(); - if (!stralloc_copys(&resp,"")) die_nomem(); - if (!stralloc_copys(&chal,"")) die_nomem(); /* only needed for CRAM-MD5 */ + if (!stralloc_copys(&user, "")) die_nomem(); + if (!stralloc_copys(&pass, "")) die_nomem(); + if (!stralloc_copys(&resp, "")) die_nomem(); + if (!stralloc_copys(&chal, "")) die_nomem(); /* only needed for CRAM-MD5 */ - i = str_chr(cmd,' '); /* get AUTH type */ + i = str_chr(cmd, ' '); /* get AUTH type */ arg = cmd + i; while (*arg == ' ') ++arg; cmd[i] = 0; for (i = 0; authcmds[i].text; ++i) - if (case_equals(authcmds[i].text,cmd)) break; + if (case_equals(authcmds[i].text, cmd)) break; - if (!authcmds[i].text) { /* invalid auth cmd */ - if (!stralloc_append(&protocol,"A")) die_nomem(); + if (!authcmds[i].text) { /* invalid auth cmd */ + if (!stralloc_append(&protocol, "A")) die_nomem(); if (!stralloc_0(&protocol)) die_nomem(); - err_authinvalid("Reject::AUTH::Method",protocol.s,remoteip,remotehost,helohost.s); + err_authinvalid("Reject::AUTH::Method", protocol.s, remoteip, remotehost, helohost.s); return; } - if (!stralloc_copys(&authmethod,authcmds[i].text)) die_nomem(); + if (!stralloc_copys(&authmethod, authcmds[i].text)) die_nomem(); if (!stralloc_0(&authmethod)) die_nomem(); switch (authcmds[i].fun(arg)) { @@ -1672,9 +2017,9 @@ void smtp_auth(char *arg) out("235 ok, go ahead (#2.0.0)\r\n"); break; case 1: - if (!stralloc_append(&protocol,"A")) die_nomem(); + if (!stralloc_append(&protocol, "A")) die_nomem(); if (!stralloc_0(&protocol)) die_nomem(); - err_authfail("Reject::AUTH::",protocol.s,remoteip,remotehost,helohost.s,user.s,authmethod.s); + err_authfail("Reject::AUTH::", protocol.s, remoteip, remotehost, helohost.s, user.s, authmethod.s); return; } } @@ -1682,20 +2027,20 @@ void smtp_auth(char *arg) /* this file is too long --------------------------------- GO ON */ struct commands smtpcommands[] = { - { "rcpt", smtp_rcpt, 0 } -, { "mail", smtp_mail, 0 } -, { "data", smtp_data, flush } -, { "auth", smtp_auth, flush } -, { "quit", smtp_quit, flush } -, { "helo", smtp_helo, flush } -, { "ehlo", smtp_ehlo, flush } -, { "rset", smtp_rset, flush } -, { "help", smtp_help, flush } -, { "noop", err_noop, flush } -, { "vrfy", err_vrfy, flush } -, { "starttls", smtp_starttls, flush } -, { 0, err_unimpl, flush } -} ; + { "rcpt", smtp_rcpt, 0}, + { "mail", smtp_mail, 0}, + { "data", smtp_data, flush}, + { "auth", smtp_auth, flush}, + { "quit", smtp_quit, flush}, + { "helo", smtp_helo, flush}, + { "ehlo", smtp_ehlo, flush}, + { "rset", smtp_rset, flush}, + { "help", smtp_help, flush}, + { "noop", err_noop, flush}, + { "vrfy", err_vrfy, flush}, + {"starttls", smtp_starttls, flush}, + { 0, err_unimpl, flush} +}; int main(int argc, char **argv) { @@ -1708,7 +2053,7 @@ int main(int argc, char **argv) smtp_greet("220 "); out(" ESMTP\r\n"); flush(); - if (commands(&bi,&smtpcommands) == 0) die_read(); + if (commands(&bi, &smtpcommands) == 0) die_read(); die_nomem(); return 0; |