33#include "timeoutconn.h" 
   43#define WHO "qmail-remote" 
   45#define QMTP_MAX  200000000   
   46#define HUGESMTPTEXT   1000   
   50#define PORT_SUBMISSION 587 
   51#define PORT_QMTPS     6209 
   54#define SMTP_TIMEOUT   1200 
   75static stralloc sauninit = {0};
 
 
  115  if (buffer_puts(&
bs,s) == -1) 
 
 
  120  if (buffer_put(&
bs,
"\0",1) == -1) 
 
 
  135  for (i = 0; i < 
sa->len; ++i) {
 
  137    if (ch == 0) 
continue;
 
  138    if (ch < 33) ch = 
'?'; 
 
  139    if (ch > 126) ch = 
'?';
 
  140    if (buffer_put(&
bs,&ch,1) == -1) 
_exit(0); 
 
 
  146  out(
"ZInvalid ipaddr in control/domainips (#4.3.0)\n"); 
 
 
  151  out(
"ZOut of memory. (#4.3.0)\n"); 
 
 
  156  out(
"ZSystem resources temporarily unavailable. (#4.3.0)\n"); 
 
 
  161  out(
"ZCan't bind to local ip address: "); 
 
 
  168  out(
"ZSorry, I wasn't able to establish a SMTP connection: ");
 
 
  175  out(
"ZSorry, I wasn't able to establish a QMTP connection: ");
 
 
  182  out(
"ZUnable to read message. (#4.3.0)\n"); 
 
 
  187  out(
"ZCNAME lookup failed temporarily for: "); 
 
 
  194  out(
"ZSorry, I couldn't find any host named: "); 
 
 
  201  out(
"ZSorry, I couldn't find a mail exchanger or IP address for: ");
 
  203  out(
". Will try again. (#4.1.2)\n"); 
 
 
  208  out(
"ZUnable to switch to home directory. (#4.3.0)\n"); 
 
 
  213  out(
"ZUnable to read control files. (#4.3.0)\n"); 
 
 
  218  out(
"DSMTP cannot transfer messages with partial final line. (#5.6.2)\n"); 
 
 
  223  out(
"ZRecipient did not talk proper QMTP. (#4.3.0)\n"); 
 
 
  228  out(
"Dqmail-remote was invoked improperly. (#5.3.5)\n"); 
 
 
  233  out(
"DSorry, I couldn't find any host named: "); 
 
 
  240  out(
"DSorry, I couldn't find a mail exchanger or IP address for: ");
 
 
  247  out(
"DSorry, I could no deliver mail to MX: ");
 
  249  out(
" ; domain does not accept mails. (#5.1.10)\n"); 
 
 
  254  out(
"DSorry. Although I'm listed as a best-preference MX or A for that host,\n\ 
  255it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
 
 
  260  out(
"ZSorry, no supported AUTH method found, trying later again. (#4.7.1)\n");
 
 
  271      len = ip4_fmt(ipaddr,(
char *)&
partner.addr.ip4.d); 
break;
 
  273      len = ip6_fmt(ipaddr,(
char *)&
partner.addr.ip6.d); 
break;
 
  275  if (buffer_put(&
bs,ipaddr,len) == -1) 
_exit(0);
 
 
  282  out(
"ZConnected to ");
 
  284  out(
" but connection died. ");
 
 
  327static stralloc smtptext = {0};
 
  328static stralloc header = {0};
 
  332  buffer_get(&
bf,ch,1);
 
  335     if (!stralloc_append(&smtptext,ch)) 
temp_nomem();
 
 
  350    if (ch != 
'-') 
break;
 
  351    while (ch != 
'\n') 
get(&ch);
 
  356  while (ch != 
'\n') 
get(&ch);
 
 
  364  if (smtptext.s) 
if (smtptext.len) {
 
  365    out(
"Remote host said: ");
 
  366    for (i = 0; i < smtptext.len; ++i)
 
  367      if (!smtptext.s[i]) smtptext.s[i] = 
'?';
 
  368    if (buffer_put(&
bs,smtptext.s,smtptext.len) == -1) 
_exit(0);
 
 
  373void quit(
char *prepend,
char *append)
 
  375  buffer_putsflush(&
bo,
"QUIT\r\n");
 
 
  405        if (
inbuf[
in] == 
'\r') { 
in++;  
continue; }        
 
  421  buffer_put(&
bo,
".\r\n",3);                               
 
 
  488    if (case_startb(smtptext.s + i + 4,8,
"STARTTLS")) 
return 1; 
 
  489  } 
while ((i += str_chr(smtptext.s + i,
'\n') + 1) && 
 
  490           (i < smtptext.len - 12));
 
 
  498  STACK_OF(X509) *certs;
 
  501  cert = SSL_get_peer_certificate(
ssl);
 
  502  if (!cert) { 
flagtls = 100; 
return; }
 
  504  if ((certs = SSL_get_peer_cert_chain(
ssl)) == NULL) {
 
  505    certs = sk_X509_new_null();
 
  507    sk_X509_push(certs,cert);
 
  547  if (ncerts) sk_X509_free(certs);
 
 
  559    if (ch[i++] > 127) 
return 1;
 
 
  569  stralloc receivedline = {0};
 
  574    r = buffer_get(&
bi,&ch,1);
 
  577    if (ch == 
'\r') 
continue; 
 
  580      if (!stralloc_append(&header,
"\r")) 
temp_nomem();              
 
  581      if (!stralloc_append(&header,
"\n")) 
temp_nomem(); 
 
  582      if (case_starts(receivedline.s,
"Date:")) 
return 0;             
 
  583      if (case_starts(receivedline.s,
"Received: from")) 
received++;  
 
  585        if (case_starts(receivedline.s,
"  by ")) {
 
  586          for (i = 6; i < receivedline.len - 6; ++i) 
 
  587            if (*(receivedline.s + i) == 
' ')
 
  588              if (case_starts(receivedline.s + i + 1,
"with UTF8")) 
return 1;
 
  594      if (!stralloc_append(&header,&ch)) 
temp_nomem();
 
  595      if (!stralloc_catb(&receivedline,&ch,1)) 
temp_nomem();
 
 
  611    if (case_startb(smtptext.s + i + 4,4,
"SIZE")) 
return 1; 
 
  612  } 
while ((i += str_chr(smtptext.s + i,
'\n') + 1) && 
 
  613         (i < smtptext.len - 8)); 
 
 
  620  buffer_puts(&
bo,
"EHLO ");
 
  622  buffer_puts(&
bo,
"\r\n");
 
  626    buffer_puts(&
bo,
"HELO ");
 
  628    buffer_puts(&
bo,
"\r\n");
 
  633    if (
code >= 500) 
quit(
"DConnected to ",
" but my name was rejected");
 
  634    if (
code != 250) 
quit(
"ZConnected to ",
" but my name was rejected");
 
 
  641  buffer_puts(&
bo,
"STARTTLS\r\n");
 
  651    quit(
"ZConnected to ",
" but STARTTLS was rejected");
 
 
  657  buffer_puts(&
bo,
"MAIL FROM:<");
 
  659  buffer_puts(&
bo,
">");
 
  661    buffer_puts(&
bo,
" SMTPUTF8");
 
  663    buffer_puts(&
bo,
" SIZE=");
 
  666  buffer_puts(&
bo,
"\r\n");
 
 
  683static const char hextab[] = 
"0123456789abcdef";
 
  693  for (i = 0; i < len; i++) {
 
  695    if (c < 33 || c > 126 || c == 
'=' || c == 
'+') {
 
  696      xch[0] = hextab[(c >> 4) & 0x0f];
 
  697      xch[1] = hextab[c & 0x0f];
 
 
  709  buffer_puts(&
bo,
"MAIL FROM:<");
 
  711  buffer_puts(&
bo,
"> AUTH=");
 
  714    buffer_puts(&
bo,
" SMTPUTF8");
 
  716    buffer_puts(&
bo,
" SIZE=");
 
  719  buffer_puts(&
bo,
"\r\n");
 
 
  725  buffer_puts(&
bo,
"AUTH PLAIN\r\n");
 
  728  if (
smtpcode() != 334) 
quit(
"ZConnected to ",
" but authentication was rejected (AUTH PLAIN)");
 
  737  buffer_puts(&
bo,
"\r\n");
 
  742    case 432: 
quit(
"DConnected to ",
" but password expired"); 
 
  743    case 534: 
quit(
"ZConnected to ",
" but authentication mechamism too weak (plain)"); 
 
  744    default:  
quit(
"ZConnected to ",
" but authentication was rejected (plain)"); 
 
 
  751  buffer_puts(&
bo,
"AUTH LOGIN\r\n");
 
  754  if (
smtpcode() != 334) 
quit(
"ZConnected to ",
" but authentication was rejected (AUTH LOGIN)");
 
  759  buffer_puts(&
bo,
"\r\n");
 
  762  if (
smtpcode() != 334) 
quit(
"ZConnected to ",
" but authentication was rejected (username)");
 
  767  buffer_puts(&
bo,
"\r\n");
 
  772    case 432: 
quit(
"DConnected to ",
" but password expired"); 
 
  773    case 534: 
quit(
"ZConnected to ",
" but authentication mechanism is too weak (login)"); 
 
  774    default:  
quit(
"ZConnected to ",
" but authentication was rejected (login)"); 
 
 
  782  unsigned char digest[16];
 
  783  unsigned char digascii[33];
 
  785  buffer_puts(&
bo,
"AUTH CRAM-MD5\r\n");
 
  788  if (
smtpcode() != 334) 
quit(
"ZConnected to ",
" but authentication was rejected (AUTH CRAM-MD5)");
 
  789  if (str_chr(smtptext.s + 4,
' ')) {                                 
 
  791    if (!stralloc_copyb(&
slop,smtptext.s + 4,smtptext.len - 5)) 
temp_nomem();
 
  797  for (
j = 0; 
j < 16; 
j++) {                                         
 
  798    digascii[2 * 
j] = hextab[digest[
j] >> 4];
 
  799    digascii[2 * 
j + 1] = hextab[digest[
j] & 0x0f];
 
  812  buffer_puts(&
bo,
"\r\n");
 
  817    case 432: 
quit(
"DConnected to ",
" but password expired"); 
 
  818    case 534: 
quit(
"ZConnected to ",
" but authentication mechamism too weak (cram)"); 
 
  819    default:  
quit(
"ZConnected to ",
" but authentication was rejected (cram)"); 
 
 
  829    if (case_startb(smtptext.s + i + 4,4,
"AUTH")) 
 
  830      for (i = 4; i < smtptext.len - 5; ++i) {
 
  831        if (case_startb(smtptext.s + i,4,
"CRAM"))
 
  833        if (case_startb(smtptext.s + i,5,
"LOGIN"))
 
  835        if (case_startb(smtptext.s + i,5,
"PLAIN"))
 
  838  } 
while ((i += str_chr(smtptext.s + i,
'\n') + 1) &&
 
  839           (i < smtptext.len - 12));
 
 
  858  if (
code >= 500) 
quit(
"DConnected to ",
" but sender was rejected");
 
  859  if (
code == 421 || 
code == 450) 
quit(
"ZConnected to ",
" but probably greylisted");  
 
  860  if (
code >= 400) 
quit(
"ZConnected to ",
" but sender was rejected");
 
  861  if (
code != 220) 
quit(
"ZConnected to ",
" but greeting failed");
 
  879  if (
code >= 500) 
quit(
"DConnected to ",
" but sender was rejected");
 
  880  if (
code >= 400) 
quit(
"ZConnected to ",
" but sender was probably greylisted");
 
  884    buffer_puts(&
bo,
"RCPT TO:<");
 
  886    buffer_puts(&
bo,
">\r\n");
 
  891      if (
code == 552) 
quit(
"DConnected to ",
" but message size is too large");
 
  892      if (
code == 452) 
quit(
"ZConnected to ",
" however insufficient storage space available");
 
  897    } 
else if (
code >= 500) {
 
  900    } 
else if (
code >= 400) {
 
  908  if (!flagbother) 
quit(
"DGiving up on ",
"");
 
  910  buffer_putsflush(&
bo,
"DATA\r\n"); 
 
  913  if (
code >= 500) 
quit(
"D",
" failed on DATA command");
 
  914  if (
code >= 400) 
quit(
"Z",
" failed on DATA command");
 
  916  buffer_putflush(&
bo,header.s,header.len);
 
  921  if (
code >= 500) 
quit(
"D",
" failed after I sent the message");
 
  922  if (
code >= 400) 
quit(
"Z",
" failed after I sent the message");
 
  924    case 100: 
case 110: 
quit(
"K",
" TLS transmitted message accepted"); 
break;
 
  925    case 101: 
case 111: 
quit(
"K",
" TLS (verified CA) transmitted message accepted"); 
break;
 
  926    case 102: 
case 112: 
quit(
"K",
" TLS (validated CA+DN*) transmitted message accepted"); 
break;
 
  927    case 103: 
case 113: 
quit(
"K",
" TLS (validated CA+DN) transmitted message accepted"); 
break;
 
  928    case 104: 
case 114: 
quit(
"K",
" TLS (CERT pinning) transmitted message accepted"); 
break;
 
  929    case 105: 
case 115: 
quit(
"K",
" TLS (TLSA EE validated) transmitted message accepted"); 
break;
 
  930    case 106: 
case 116: 
quit(
"K",
" TLS (TLSA TA validated) transmitted message accepted"); 
break;
 
  931    case 107: 
case 117: 
quit(
"K",
" TLS (TLSA PKIX verified) transmitted message accepted"); 
break;
 
  932    default:  
quit(
"K",
" accepted message"); 
break;
 
 
  942  unsigned long len = 0; 
 
  960    out(
"DMessage for: "); 
outhost(); 
out(
" has zero bytes. Giving up.\n");
 
  963  buffer_put(&
bo,
num,fmt_ulong(
num,len + 1));
 
  964  buffer_put(&
bo,
":\n",2);
 
  966    n = buffer_feed(&
bi);
 
  967    if (n <= 0) 
_exit(1);                        
 
  968    x = buffer_PEEK(&
bi);
 
  973  buffer_put(&
bo,
",",1);
 
  976  buffer_put(&
bo,
num,fmt_ulong(
num,len));
 
  977  buffer_put(&
bo,
":",1);
 
  979  buffer_put(&
bo,
",",1);
 
  984  buffer_put(&
bo,
num,fmt_ulong(
num,len));
 
  985  buffer_put(&
bo,
":",1);
 
  988    buffer_put(&
bo,
":",1);
 
  990    buffer_put(&
bo,
",",1);
 
  992  buffer_put(&
bo,
",",1);
 
 1001      if (ch == 
':') 
break;
 
 1004      len = 10 * len + (ch - 
'0');
 
 1008    if ((ch != 
'Z') && (ch != 
'D') && (ch != 
'K')) 
temp_proto();
 
 1010    if (!stralloc_copyb(&smtptext,&ch,1)) 
temp_nomem();
 
 1012      if (!stralloc_cats(&smtptext,
"qmtps:")) 
temp_nomem();
 
 1014      if (!stralloc_cats(&smtptext,
"qmtp:")) 
temp_nomem();
 
 1022    for (len = 0; len < smtptext.len; ++len) {
 
 1023      ch = smtptext.s[len];
 
 1024      if ((ch < 32) || (ch > 126)) smtptext.s[len] = 
'?';
 
 1028    smtptext.s[smtptext.len - 1] = 
'\n';
 
 1030    if (smtptext.s[0] == 
'K') 
out(
"r");
 
 1031    else if (smtptext.s[0] == 
'D') {
 
 1039    if (buffer_put(&
bs,smtptext.s + 1,smtptext.len - 1) == -1) 
temp_qmtpnoc();
 
 
 1079    switch ((r = dns_cname(&cn,&
canonhost))) {
 
 
 1129int main(
int argc,
char * 
const *argv)
 
 1131  static ipalloc ip = {0};
 
 1132  stralloc netif = {0};
 
 1137  unsigned long random;
 
 1139  unsigned long prefme;
 
 1159    i = str_chr(
sender.s,
'@'); 
 
 1177    j = str_chr(localip,
'%'); 
 
 1178    if (localip[
j] != 
'%') 
j = 0;
 
 1179    k = str_chr(localip,
'|'); 
 
 1180    if (localip[
k] != 
'|') 
k = 0;
 
 1195  for (i = 0; i <= 
sender.len; ++i)
 
 1235    if (relayhost && !*relayhost) relayhost = 0;
 
 1238      for (i = 0; i <= 
host.len; ++i) {                              
 
 1239        if ((i == 0) || (i == 
host.len) || (
host.s[i] == 
'.'))
 
 1248    if (relayhost && !*relayhost) relayhost = 0;
 
 1251      i = str_chr(relayhost,
'|');
 
 1252      if (relayhost[i] == 
'|') {
 
 1253        j = str_chr(relayhost + i + 1,
'|');                          
 
 1254        if (relayhost[i + 
j + 1] == 
'|') {
 
 1256          relayhost[i + 
j + 1] = 0;
 
 1260          k = str_chr(relayhost + i + 
j + 2,
'|');                    
 
 1261          if (relayhost[i + 
j + 
k + 2] == 
'|') {
 
 1262            relayhost[i + 
j + 
k + 2] = 0;
 
 1263            localip = relayhost + i + 
j + 
k + 3;
 
 1268      p = str_chr(relayhost,
';');
 
 1269      if (relayhost[
p] == 
';') {
 
 1270        if (relayhost[
p + 1] == 
's') { 
flagsmtps = 1; 
p++; }         
 
 1271        scan_ulong(relayhost + 
p + 1,&
port);
 
 1278      char *asciihost = 0;
 
 1280      switch (idn2_lookup_u8(
host.s,(uint8_t**)&asciihost,IDN2_NFC_INPUT)) {
 
 1281        case IDN2_OK:     
break;
 
 1393  if (fstat(0,&st) == -1) 
quit(
"Z", 
" unable to fstat stdin");
 
 1406  random = 
now() + (getpid() << 16);
 
 1416#ifdef DEFERREDBOUNCES 
 1424  for (i = 0; i < ip.len; ++i)
 
 1427      if (ip.ix[i].pref == 0 && ip.ix[i].mxh[0] == 
'.') 
 
 1430      if (ip.ix[i].pref < prefme)
 
 1431        prefme = ip.ix[i].pref;
 
 1434  if (relayhost) prefme = 300000;
 
 1435  if (flagallaliases) prefme = 500000;
 
 1438    i = str_chr(localip,
':');
 
 1439    if (localip[i] == 
':') ip6flag = 1;
 
 1443  for (i = 0; i < ip.len; ++i) {                                     
 
 1444    if (ip6flag == -1 && ip.ix[i].af == AF_INET6) 
continue;       
 
 1445    if (ip6flag ==  1 && ip.ix[i].af == AF_INET) 
continue;
 
 1446    if (ip.ix[i].pref < prefme) 
break;
 
 1454  for (i = 0; i < ip.len; ++i) {
 
 1455    if (ip.ix[i].pref < prefme) {
 
 1456      if (ip6flag == -1 && ip.ix[i].af == AF_INET6) 
continue;        
 
 1457      if (ip6flag ==  1 && ip.ix[i].af == AF_INET) 
continue;
 
 1458      if (
tcpto(&ip.ix[i])) 
continue;
 
 1460      smtpfd = socket(ip.ix[i].af,SOCK_STREAM,0);
 
 1461      if (
smtpfd == -1) 
continue;
 
 1465         j = str_chr(localip,
':');
 
 1466         if (localip[
j] == 
':') {
 
 1468           if (byte_equal(ip.ix[i].addr.ip6.d,16,
ip6)) 
continue;
 
 1469           ifidx = socket_getifidx(netif.s);
 
 1473           if (byte_equal(ip.ix[i].addr.ip4.d,4,
ip4)) 
continue;
 
 1480      if (ip.ix[i].af == AF_INET6)
 
 1492      if (
flagtls == 9 && errno == EPROTO) {
 
 1495      if (errno == ETIMEDOUT || errno == ECONNREFUSED || errno == EPROTO)
 
 
int b64encode(stralloc *in, stralloc *out)
 
int b64decode(const unsigned char *in, int l, stralloc *out)
 
char outbuf[BUFSIZE_MESS]
 
int constmap_init(struct constmap *cm, char *s, int len, int flagcolon)
 
char * constmap(struct constmap *cm, char *s, int len)
 
int control_readint(unsigned long *i, char *fn)
 
int control_rldef(stralloc *sa, char *fn, int flagme, char *def)
 
int control_readfile(stralloc *sa, char *fn, int flagme)
 
int stralloc_copys(stralloc *, char const *)
 
int dns_mxip(ipalloc *ia, stralloc *sa, unsigned long random)
 
int dns_ip(ipalloc *ia, stralloc *sa)
 
void p(char *, char *, int, int, int)
 
void hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest)
 
int ipme_is(struct ip_mx *)
 
char tmpbuf[BUFSIZE_LINE]
 
GEN_ALLOC_readyplus(prioq, struct prioq_elt, p, len, a, i, n, x, 100, prioq_readyplus)
 
char bufsmall[BUFFER_SMALL]
 
ssize_t safewrite(int fd, char *buf, size_t len)
 
struct constmap mapauthsenders
 
struct constmap mapqmtproutes
 
int xtext(stralloc *sa, char *s, int len)
 
char frombuf[BUFFER_SMALL]
 
void addrmangle(stralloc *saout, char *address, int *flagalias, int flagcname)
 
struct constmap mapdomainips
 
GEN_ALLOC_typedef(GEN_ALLOC_readyplus(saa, GEN_ALLOC_readyplus(stralloc, GEN_ALLOC_readyplus(sa, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a)
 
void quit(char *prepend, char *append)
 
unsigned long verifydepth
 
void outsafe(stralloc *sa)
 
int utf8string(unsigned char *ch, int len)
 
unsigned long timeoutconnect
 
struct constmap mapsmtproutes
 
ssize_t saferead(int fd, char *buf, size_t len)
 
int quote(stralloc *, stralloc *)
 
ssize_t safewrite(int, char *, size_t)
 
void tcpto_err(struct ip_mx *, int)
 
int tcpto(struct ip_mx *)
 
void temp_tlscipher(void)
 
void temp_tlsdigest(void)
 
void temp_tlspeerverify()
 
void temp_tlsamissing(void)
 
void temp_tlsainvalid(void)
 
void temp_tlscertfp(void)
 
void temp_invaliddigest(void)
 
int tlsa_check(const STACK_OF(X509) *, const stralloc, const unsigned long)
 
struct constmap maptlsdestinations
 
struct constmap mapdomaincerts
 
int tls_domaincerts(const stralloc)
 
int tls_destination(const stralloc)
tls_destination
 
int tls_fingerprint(X509 *, const char *, const int)
 
int tls_certkey(SSL_CTX *, const char *, const char *, char *)
 
int tls_checkpeer(SSL *, X509 *, const stralloc, const int, const int)
 
int tls_timeoutconn(int, int, int, SSL *)
 
int tls_timeoutwrite(int, int, int, SSL *, char *, int)
 
int tls_timeoutread(int, int, int, SSL *, char *, int)
 
int ssl_ciphers(SSL_CTX *, const char *)
 
SSL * ssl_new(SSL_CTX *, int)
 
int ssl_ca(SSL_CTX *, const char *, const char *, int)