~ubuntu-branches/ubuntu/vivid/exim4/vivid

« back to all changes in this revision

Viewing changes to src/smtp_in.c

  • Committer: Package Import Robot
  • Author(s): Corey Bryant
  • Date: 2014-08-04 11:48:39 UTC
  • mfrom: (56.1.2 utopic)
  • Revision ID: package-import@ubuntu.com-20140804114839-xoulpcx9nxi5m72u
Tags: 4.84~RC1-3ubuntu1
* Merge from Debian unstable (LP: #1351470). Remaining changes:
  - Show Ubuntu distribution on smtp:
    + debian/patches/fix_smtp_banner.patch: updated SMTP banner
      with Ubuntu distribution
    + debian/control: added lsb-release build dependency
  - Don't provide default-mta; in Ubuntu, we want postfix to be the
    default.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
*     Exim - an Internet mail transport agent    *
3
3
*************************************************/
4
4
 
5
 
/* Copyright (c) University of Cambridge 1995 - 2012 */
 
5
/* Copyright (c) University of Cambridge 1995 - 2014 */
6
6
/* See the file NOTICE for conditions of use and distribution. */
7
7
 
8
8
/* Functions for handling an incoming SMTP call. */
94
94
 
95
95
  QUIT_CMD, HELP_CMD,
96
96
 
 
97
#ifdef EXPERIMENTAL_PROXY
 
98
  PROXY_FAIL_IGNORE_CMD,
 
99
#endif
 
100
 
97
101
  /* These are specials that don't correspond to actual commands */
98
102
 
99
103
  EOF_CMD, OTHER_CMD, BADARG_CMD, BADCHAR_CMD, BADSYN_CMD,
117
121
#ifdef SUPPORT_TLS
118
122
static BOOL tls_advertised;
119
123
#endif
 
124
#ifdef EXPERIMENTAL_DSN
 
125
static BOOL dsn_advertised;
 
126
#endif
120
127
static BOOL esmtp;
121
128
static BOOL helo_required = FALSE;
122
129
static BOOL helo_verify = FALSE;
210
217
/* Sanity check and validate optional args to MAIL FROM: envelope */
211
218
enum {
212
219
  ENV_MAIL_OPT_SIZE, ENV_MAIL_OPT_BODY, ENV_MAIL_OPT_AUTH,
213
 
#ifdef EXPERIMENTAL_PRDR
 
220
#ifndef DISABLE_PRDR
214
221
  ENV_MAIL_OPT_PRDR,
215
222
#endif
 
223
#ifdef EXPERIMENTAL_DSN
 
224
  ENV_MAIL_OPT_RET, ENV_MAIL_OPT_ENVID,
 
225
#endif
216
226
  ENV_MAIL_OPT_NULL
217
227
  };
218
228
typedef struct {
225
235
    { US"SIZE",   ENV_MAIL_OPT_SIZE,   TRUE  },
226
236
    { US"BODY",   ENV_MAIL_OPT_BODY,   TRUE  },
227
237
    { US"AUTH",   ENV_MAIL_OPT_AUTH,   TRUE  },
228
 
#ifdef EXPERIMENTAL_PRDR
 
238
#ifndef DISABLE_PRDR
229
239
    { US"PRDR",   ENV_MAIL_OPT_PRDR,   FALSE },
230
240
#endif
 
241
#ifdef EXPERIMENTAL_DSN
 
242
    { US"RET",    ENV_MAIL_OPT_RET,    TRUE },
 
243
    { US"ENVID",  ENV_MAIL_OPT_ENVID,  TRUE },
 
244
#endif
231
245
    { US"NULL",   ENV_MAIL_OPT_NULL,   FALSE }
232
246
  };
233
247
 
549
563
 
550
564
 
551
565
 
 
566
#ifdef EXPERIMENTAL_PROXY
 
567
/*************************************************
 
568
*     Restore socket timeout to previous value   *
 
569
*************************************************/
 
570
/* If the previous value was successfully retrieved, restore
 
571
it before returning control to the non-proxy routines
 
572
 
 
573
Arguments: fd     - File descriptor for input
 
574
           get_ok - Successfully retrieved previous values
 
575
           tvtmp  - Time struct with previous values
 
576
           vslen  - Length of time struct
 
577
Returns:   none
 
578
*/
 
579
static void
 
580
restore_socket_timeout(int fd, int get_ok, struct timeval tvtmp, socklen_t vslen)
 
581
{
 
582
if (get_ok == 0)
 
583
  setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp, vslen);
 
584
}
 
585
 
 
586
/*************************************************
 
587
*       Check if host is required proxy host     *
 
588
*************************************************/
 
589
/* The function determines if inbound host will be a regular smtp host
 
590
or if it is configured that it must use Proxy Protocol.
 
591
 
 
592
Arguments: none
 
593
Returns:   bool
 
594
*/
 
595
 
 
596
static BOOL
 
597
check_proxy_protocol_host()
 
598
{
 
599
int rc;
 
600
/* Cannot configure local connection as a proxy inbound */
 
601
if (sender_host_address == NULL) return proxy_session;
 
602
 
 
603
rc = verify_check_this_host(&proxy_required_hosts, NULL, NULL,
 
604
                           sender_host_address, NULL);
 
605
if (rc == OK)
 
606
  {
 
607
  DEBUG(D_receive)
 
608
    debug_printf("Detected proxy protocol configured host\n");
 
609
  proxy_session = TRUE;
 
610
  }
 
611
return proxy_session;
 
612
}
 
613
 
 
614
 
 
615
/*************************************************
 
616
*         Setup host for proxy protocol          *
 
617
*************************************************/
 
618
/* The function configures the connection based on a header from the
 
619
inbound host to use Proxy Protocol. The specification is very exact
 
620
so exit with an error if do not find the exact required pieces. This
 
621
includes an incorrect number of spaces separating args.
 
622
 
 
623
Arguments: none
 
624
Returns:   int
 
625
*/
 
626
 
 
627
static BOOL
 
628
setup_proxy_protocol_host()
 
629
{
 
630
union {
 
631
  struct {
 
632
    uschar line[108];
 
633
  } v1;
 
634
  struct {
 
635
    uschar sig[12];
 
636
    uint8_t ver_cmd;
 
637
    uint8_t fam;
 
638
    uint16_t len;
 
639
    union {
 
640
      struct { /* TCP/UDP over IPv4, len = 12 */
 
641
        uint32_t src_addr;
 
642
        uint32_t dst_addr;
 
643
        uint16_t src_port;
 
644
        uint16_t dst_port;
 
645
      } ip4;
 
646
      struct { /* TCP/UDP over IPv6, len = 36 */
 
647
        uint8_t  src_addr[16];
 
648
        uint8_t  dst_addr[16];
 
649
        uint16_t src_port;
 
650
        uint16_t dst_port;
 
651
      } ip6;
 
652
      struct { /* AF_UNIX sockets, len = 216 */
 
653
        uschar   src_addr[108];
 
654
        uschar   dst_addr[108];
 
655
      } unx;
 
656
    } addr;
 
657
  } v2;
 
658
} hdr;
 
659
 
 
660
/* Temp variables used in PPv2 address:port parsing */
 
661
uint16_t tmpport;
 
662
char tmpip[INET_ADDRSTRLEN];
 
663
struct sockaddr_in tmpaddr;
 
664
char tmpip6[INET6_ADDRSTRLEN];
 
665
struct sockaddr_in6 tmpaddr6;
 
666
 
 
667
int get_ok = 0;
 
668
int size, ret, fd;
 
669
const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
 
670
uschar *iptype;  /* To display debug info */
 
671
struct timeval tv;
 
672
socklen_t vslen = 0;
 
673
struct timeval tvtmp;
 
674
 
 
675
vslen = sizeof(struct timeval);
 
676
 
 
677
fd = fileno(smtp_in);
 
678
 
 
679
/* Save current socket timeout values */
 
680
get_ok = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp,
 
681
                    &vslen);
 
682
 
 
683
/* Proxy Protocol host must send header within a short time
 
684
(default 3 seconds) or it's considered invalid */
 
685
tv.tv_sec  = PROXY_NEGOTIATION_TIMEOUT_SEC;
 
686
tv.tv_usec = PROXY_NEGOTIATION_TIMEOUT_USEC;
 
687
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
 
688
           sizeof(struct timeval));
 
689
 
 
690
do
 
691
  {
 
692
  /* The inbound host was declared to be a Proxy Protocol host, so
 
693
     don't do a PEEK into the data, actually slurp it up. */
 
694
  ret = recv(fd, &hdr, sizeof(hdr), 0);
 
695
  }
 
696
  while (ret == -1 && errno == EINTR);
 
697
 
 
698
if (ret == -1)
 
699
  {
 
700
  restore_socket_timeout(fd, get_ok, tvtmp, vslen);
 
701
  return (errno == EAGAIN) ? 0 : ERRNO_PROXYFAIL;
 
702
  }
 
703
 
 
704
if (ret >= 16 &&
 
705
    memcmp(&hdr.v2, v2sig, 12) == 0)
 
706
  {
 
707
  uint8_t ver, cmd;
 
708
 
 
709
  /* May 2014: haproxy combined the version and command into one byte to
 
710
     allow two full bytes for the length field in order to proxy SSL
 
711
     connections.  SSL Proxy is not supported in this version of Exim, but
 
712
     must still seperate values here. */
 
713
  ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
 
714
  cmd = (hdr.v2.ver_cmd & 0x0f);
 
715
 
 
716
  if (ver != 0x02)
 
717
    {
 
718
    DEBUG(D_receive) debug_printf("Invalid Proxy Protocol version: %d\n", ver);
 
719
    goto proxyfail;
 
720
    }
 
721
  DEBUG(D_receive) debug_printf("Detected PROXYv2 header\n");
 
722
  /* The v2 header will always be 16 bytes per the spec. */
 
723
  size = 16 + hdr.v2.len;
 
724
  if (ret < size)
 
725
    {
 
726
    DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header (%d/%d)\n",
 
727
                                  ret, size);
 
728
    goto proxyfail;
 
729
    }
 
730
  switch (cmd)
 
731
    {
 
732
    case 0x01: /* PROXY command */
 
733
      switch (hdr.v2.fam)
 
734
        {
 
735
        case 0x11:  /* TCPv4 address type */
 
736
          iptype = US"IPv4";
 
737
          tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;
 
738
          inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
 
739
          if (!string_is_ip_address(US tmpip,NULL))
 
740
            {
 
741
            DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
 
742
            return ERRNO_PROXYFAIL;
 
743
            }
 
744
          proxy_host_address  = sender_host_address;
 
745
          sender_host_address = string_copy(US tmpip);
 
746
          tmpport             = ntohs(hdr.v2.addr.ip4.src_port);
 
747
          proxy_host_port     = sender_host_port;
 
748
          sender_host_port    = tmpport;
 
749
          /* Save dest ip/port */
 
750
          tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr;
 
751
          inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
 
752
          if (!string_is_ip_address(US tmpip,NULL))
 
753
            {
 
754
            DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
 
755
            return ERRNO_PROXYFAIL;
 
756
            }
 
757
          proxy_target_address = string_copy(US tmpip);
 
758
          tmpport              = ntohs(hdr.v2.addr.ip4.dst_port);
 
759
          proxy_target_port    = tmpport;
 
760
          goto done;
 
761
        case 0x21:  /* TCPv6 address type */
 
762
          iptype = US"IPv6";
 
763
          memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);
 
764
          inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
 
765
          if (!string_is_ip_address(US tmpip6,NULL))
 
766
            {
 
767
            DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
 
768
            return ERRNO_PROXYFAIL;
 
769
            }
 
770
          proxy_host_address  = sender_host_address;
 
771
          sender_host_address = string_copy(US tmpip6);
 
772
          tmpport             = ntohs(hdr.v2.addr.ip6.src_port);
 
773
          proxy_host_port     = sender_host_port;
 
774
          sender_host_port    = tmpport;
 
775
          /* Save dest ip/port */
 
776
          memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.dst_addr, 16);
 
777
          inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
 
778
          if (!string_is_ip_address(US tmpip6,NULL))
 
779
            {
 
780
            DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
 
781
            return ERRNO_PROXYFAIL;
 
782
            }
 
783
          proxy_target_address = string_copy(US tmpip6);
 
784
          tmpport              = ntohs(hdr.v2.addr.ip6.dst_port);
 
785
          proxy_target_port    = tmpport;
 
786
          goto done;
 
787
        default:
 
788
          DEBUG(D_receive)
 
789
            debug_printf("Unsupported PROXYv2 connection type: 0x%02x\n",
 
790
                         hdr.v2.fam);
 
791
          goto proxyfail;
 
792
        }
 
793
      /* Unsupported protocol, keep local connection address */
 
794
      break;
 
795
    case 0x00: /* LOCAL command */
 
796
      /* Keep local connection address for LOCAL */
 
797
      break;
 
798
    default:
 
799
      DEBUG(D_receive)
 
800
        debug_printf("Unsupported PROXYv2 command: 0x%x\n", cmd);
 
801
      goto proxyfail;
 
802
    }
 
803
  }
 
804
else if (ret >= 8 &&
 
805
         memcmp(hdr.v1.line, "PROXY", 5) == 0)
 
806
  {
 
807
  uschar *p = string_copy(hdr.v1.line);
 
808
  uschar *end = memchr(p, '\r', ret - 1);
 
809
  uschar *sp;     /* Utility variables follow */
 
810
  int     tmp_port;
 
811
  char   *endc;
 
812
 
 
813
  if (!end || end[1] != '\n')
 
814
    {
 
815
    DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n");
 
816
    goto proxyfail;
 
817
    }
 
818
  *end = '\0'; /* Terminate the string */
 
819
  size = end + 2 - hdr.v1.line; /* Skip header + CRLF */
 
820
  DEBUG(D_receive) debug_printf("Detected PROXYv1 header\n");
 
821
  /* Step through the string looking for the required fields. Ensure
 
822
     strict adherance to required formatting, exit for any error. */
 
823
  p += 5;
 
824
  if (!isspace(*(p++)))
 
825
    {
 
826
    DEBUG(D_receive) debug_printf("Missing space after PROXY command\n");
 
827
    goto proxyfail;
 
828
    }
 
829
  if (!Ustrncmp(p, CCS"TCP4", 4))
 
830
    iptype = US"IPv4";
 
831
  else if (!Ustrncmp(p,CCS"TCP6", 4))
 
832
    iptype = US"IPv6";
 
833
  else if (!Ustrncmp(p,CCS"UNKNOWN", 7))
 
834
    {
 
835
    iptype = US"Unknown";
 
836
    goto done;
 
837
    }
 
838
  else
 
839
    {
 
840
    DEBUG(D_receive) debug_printf("Invalid TCP type\n");
 
841
    goto proxyfail;
 
842
    }
 
843
 
 
844
  p += Ustrlen(iptype);
 
845
  if (!isspace(*(p++)))
 
846
    {
 
847
    DEBUG(D_receive) debug_printf("Missing space after TCP4/6 command\n");
 
848
    goto proxyfail;
 
849
    }
 
850
  /* Find the end of the arg */
 
851
  if ((sp = Ustrchr(p, ' ')) == NULL)
 
852
    {
 
853
    DEBUG(D_receive)
 
854
      debug_printf("Did not find proxied src %s\n", iptype);
 
855
    goto proxyfail;
 
856
    }
 
857
  *sp = '\0';
 
858
  if(!string_is_ip_address(p,NULL))
 
859
    {
 
860
    DEBUG(D_receive)
 
861
      debug_printf("Proxied src arg is not an %s address\n", iptype);
 
862
    goto proxyfail;
 
863
    }
 
864
  proxy_host_address = sender_host_address;
 
865
  sender_host_address = p;
 
866
  p = sp + 1;
 
867
  if ((sp = Ustrchr(p, ' ')) == NULL)
 
868
    {
 
869
    DEBUG(D_receive)
 
870
      debug_printf("Did not find proxy dest %s\n", iptype);
 
871
    goto proxyfail;
 
872
    }
 
873
  *sp = '\0';
 
874
  if(!string_is_ip_address(p,NULL))
 
875
    {
 
876
    DEBUG(D_receive)
 
877
      debug_printf("Proxy dest arg is not an %s address\n", iptype);
 
878
    goto proxyfail;
 
879
    }
 
880
  proxy_target_address = p;
 
881
  p = sp + 1;
 
882
  if ((sp = Ustrchr(p, ' ')) == NULL)
 
883
    {
 
884
    DEBUG(D_receive) debug_printf("Did not find proxied src port\n");
 
885
    goto proxyfail;
 
886
    }
 
887
  *sp = '\0';
 
888
  tmp_port = strtol(CCS p,&endc,10);
 
889
  if (*endc || tmp_port == 0)
 
890
    {
 
891
    DEBUG(D_receive)
 
892
      debug_printf("Proxied src port '%s' not an integer\n", p);
 
893
    goto proxyfail;
 
894
    }
 
895
  proxy_host_port = sender_host_port;
 
896
  sender_host_port = tmp_port;
 
897
  p = sp + 1;
 
898
  if ((sp = Ustrchr(p, '\0')) == NULL)
 
899
    {
 
900
    DEBUG(D_receive) debug_printf("Did not find proxy dest port\n");
 
901
    goto proxyfail;
 
902
    }
 
903
  tmp_port = strtol(CCS p,&endc,10);
 
904
  if (*endc || tmp_port == 0)
 
905
    {
 
906
    DEBUG(D_receive)
 
907
      debug_printf("Proxy dest port '%s' not an integer\n", p);
 
908
    goto proxyfail;
 
909
    }
 
910
  proxy_target_port = tmp_port;
 
911
  /* Already checked for /r /n above. Good V1 header received. */
 
912
  goto done;
 
913
  }
 
914
else
 
915
  {
 
916
  /* Wrong protocol */
 
917
  DEBUG(D_receive) debug_printf("Invalid proxy protocol version negotiation\n");
 
918
  goto proxyfail;
 
919
  }
 
920
 
 
921
proxyfail:
 
922
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
 
923
/* Don't flush any potential buffer contents. Any input should cause a
 
924
   synchronization failure */
 
925
return FALSE;
 
926
 
 
927
done:
 
928
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
 
929
DEBUG(D_receive)
 
930
  debug_printf("Valid %s sender from Proxy Protocol header\n", iptype);
 
931
return proxy_session;
 
932
}
 
933
#endif
 
934
 
552
935
/*************************************************
553
936
*           Read one command line                *
554
937
*************************************************/
622
1005
 
623
1006
for (p = cmd_list; p < cmd_list_end; p++)
624
1007
  {
 
1008
  #ifdef EXPERIMENTAL_PROXY
 
1009
  /* Only allow QUIT command if Proxy Protocol parsing failed */
 
1010
  if (proxy_session && proxy_session_failed)
 
1011
    {
 
1012
    if (p->cmd != QUIT_CMD)
 
1013
      continue;
 
1014
    }
 
1015
  #endif
625
1016
  if (strncmpic(smtp_cmd_buffer, US p->name, p->len) == 0 &&
626
1017
       (smtp_cmd_buffer[p->len-1] == ':' ||   /* "mail from:" or "rcpt to:" */
627
1018
        smtp_cmd_buffer[p->len] == 0 ||
669
1060
    }
670
1061
  }
671
1062
 
 
1063
#ifdef EXPERIMENTAL_PROXY
 
1064
/* Only allow QUIT command if Proxy Protocol parsing failed */
 
1065
if (proxy_session && proxy_session_failed)
 
1066
  return PROXY_FAIL_IGNORE_CMD;
 
1067
#endif
 
1068
 
672
1069
/* Enforce synchronization for unknown commands */
673
1070
 
674
1071
if (smtp_inptr < smtp_inend &&                     /* Outstanding input */
825
1222
 
826
1223
 
827
1224
 
 
1225
#ifdef SUPPORT_TLS
 
1226
/* Append TLS-related information to a log line
 
1227
 
 
1228
Arguments:
 
1229
  s             String under construction: allocated string to extend, or NULL
 
1230
  sizep         Pointer to current allocation size (update on return), or NULL
 
1231
  ptrp          Pointer to index for new entries in string (update on return), or NULL
 
1232
 
 
1233
Returns:        Allocated string or NULL
 
1234
*/
 
1235
static uschar *
 
1236
s_tlslog(uschar * s, int * sizep, int * ptrp)
 
1237
{
 
1238
  int size = sizep ? *sizep : 0;
 
1239
  int ptr = ptrp ? *ptrp : 0;
 
1240
 
 
1241
  if ((log_extra_selector & LX_tls_cipher) != 0 && tls_in.cipher != NULL)
 
1242
    s = string_append(s, &size, &ptr, 2, US" X=", tls_in.cipher);
 
1243
  if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
 
1244
       tls_in.cipher != NULL)
 
1245
    s = string_append(s, &size, &ptr, 2, US" CV=",
 
1246
      tls_in.certificate_verified? "yes":"no");
 
1247
  if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_in.peerdn != NULL)
 
1248
    s = string_append(s, &size, &ptr, 3, US" DN=\"",
 
1249
      string_printing(tls_in.peerdn), US"\"");
 
1250
  if ((log_extra_selector & LX_tls_sni) != 0 && tls_in.sni != NULL)
 
1251
    s = string_append(s, &size, &ptr, 3, US" SNI=\"",
 
1252
      string_printing(tls_in.sni), US"\"");
 
1253
 
 
1254
  if (s)
 
1255
    {
 
1256
    s[ptr] = '\0';
 
1257
    if (sizep) *sizep = size;
 
1258
    if (ptrp) *ptrp = ptr;
 
1259
    }
 
1260
  return s;
 
1261
}
 
1262
#endif
 
1263
 
828
1264
/*************************************************
829
1265
*      Log lack of MAIL if so configured         *
830
1266
*************************************************/
857
1293
  }
858
1294
 
859
1295
#ifdef SUPPORT_TLS
860
 
if ((log_extra_selector & LX_tls_cipher) != 0 && tls_in.cipher != NULL)
861
 
  s = string_append(s, &size, &ptr, 2, US" X=", tls_in.cipher);
862
 
if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
863
 
     tls_in.cipher != NULL)
864
 
  s = string_append(s, &size, &ptr, 2, US" CV=",
865
 
    tls_in.certificate_verified? "yes":"no");
866
 
if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_in.peerdn != NULL)
867
 
  s = string_append(s, &size, &ptr, 3, US" DN=\"",
868
 
    string_printing(tls_in.peerdn), US"\"");
869
 
if ((log_extra_selector & LX_tls_sni) != 0 && tls_in.sni != NULL)
870
 
  s = string_append(s, &size, &ptr, 3, US" SNI=\"",
871
 
    string_printing(tls_in.sni), US"\"");
 
1296
s = s_tlslog(s, &size, &ptr);
872
1297
#endif
873
1298
 
874
1299
sep = (smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE)?
892
1317
if (s != NULL) s[ptr] = 0; else s = US"";
893
1318
log_write(0, LOG_MAIN, "no MAIL in SMTP connection from %s D=%s%s",
894
1319
  host_and_ident(FALSE),
895
 
  readconf_printtime(time(NULL) - smtp_connection_start), s);
 
1320
  readconf_printtime( (int) ((long)time(NULL) - (long)smtp_connection_start)),
 
1321
  s);
896
1322
}
897
1323
 
898
1324
 
1073
1499
sender_verified_list = NULL;        /* No senders verified */
1074
1500
memset(sender_address_cache, 0, sizeof(sender_address_cache));
1075
1501
memset(sender_domain_cache, 0, sizeof(sender_domain_cache));
 
1502
 
 
1503
#ifdef EXPERIMENTAL_DSN
 
1504
/* Reset the DSN flags */
 
1505
dsn_ret = 0;
 
1506
dsn_envid = NULL;
 
1507
#endif
 
1508
 
1076
1509
authenticated_sender = NULL;
1077
1510
#ifdef EXPERIMENTAL_BRIGHTMAIL
1078
1511
bmi_run = 0;
1417
1850
 
1418
1851
#ifdef SUPPORT_TLS
1419
1852
tls_in.cipher = tls_in.peerdn = NULL;
 
1853
tls_in.ourcert = tls_in.peercert = NULL;
 
1854
tls_in.sni = NULL;
 
1855
tls_in.ocsp = OCSP_NOT_REQ;
1420
1856
tls_advertised = FALSE;
1421
1857
#endif
 
1858
#ifdef EXPERIMENTAL_DSN
 
1859
dsn_advertised = FALSE;
 
1860
#endif
1422
1861
 
1423
1862
/* Reset ACL connection variables */
1424
1863
 
1832
2271
 
1833
2272
if (smtp_batched_input) return TRUE;
1834
2273
 
 
2274
#ifdef EXPERIMENTAL_PROXY
 
2275
/* If valid Proxy Protocol source is connecting, set up session.
 
2276
 * Failure will not allow any SMTP function other than QUIT. */
 
2277
proxy_session = FALSE;
 
2278
proxy_session_failed = FALSE;
 
2279
if (check_proxy_protocol_host())
 
2280
  {
 
2281
  if (setup_proxy_protocol_host() == FALSE)
 
2282
    {
 
2283
    proxy_session_failed = TRUE;
 
2284
    DEBUG(D_receive)
 
2285
      debug_printf("Failure to extract proxied host, only QUIT allowed\n");
 
2286
    }
 
2287
  else
 
2288
    {
 
2289
    sender_host_name = NULL;
 
2290
    (void)host_name_lookup();
 
2291
    host_build_sender_fullhost();
 
2292
    }
 
2293
  }
 
2294
#endif
 
2295
 
1835
2296
/* Run the ACL if it exists */
1836
2297
 
1837
2298
user_msg = NULL;
2211
2672
#endif
2212
2673
  (where == ACL_WHERE_PREDATA)? US"DATA" :
2213
2674
  (where == ACL_WHERE_DATA)? US"after DATA" :
2214
 
#ifdef EXPERIMENTAL_PRDR
 
2675
#ifndef DISABLE_PRDR
2215
2676
  (where == ACL_WHERE_PRDR)? US"after DATA PRDR" :
2216
2677
#endif
2217
2678
  (smtp_cmd_data == NULL)?
2334
2795
is closing if required and return 2.  */
2335
2796
 
2336
2797
if (log_reject_target != 0)
2337
 
  log_write(0, log_reject_target, "%s %s%srejected %s%s",
2338
 
    host_and_ident(TRUE),
 
2798
  {
 
2799
#ifdef SUPPORT_TLS
 
2800
  uschar * s = s_tlslog(NULL, NULL, NULL);
 
2801
  if (!s) s = US"";
 
2802
#else
 
2803
  uschar * s = US"";
 
2804
#endif
 
2805
  log_write(0, log_reject_target, "%s%s %s%srejected %s%s",
 
2806
    host_and_ident(TRUE), s,
2339
2807
    sender_info, (rc == FAIL)? US"" : US"temporarily ", what, log_msg);
 
2808
  }
2340
2809
 
2341
2810
if (!drop) return 0;
2342
2811
 
2594
3063
 
2595
3064
 
2596
3065
 
2597
 
 
2598
3066
/*************************************************
2599
3067
*       Initialize for SMTP incoming message     *
2600
3068
*************************************************/
2679
3147
  int ptr, size, rc;
2680
3148
  int c, i;
2681
3149
  auth_instance *au;
 
3150
#ifdef EXPERIMENTAL_DSN
 
3151
  uschar *orcpt = NULL;
 
3152
  int flags;
 
3153
#endif
2682
3154
 
2683
3155
  switch(smtp_read_command(TRUE))
2684
3156
    {
3023
3495
    #ifdef SUPPORT_TLS
3024
3496
    tls_advertised = FALSE;
3025
3497
    #endif
 
3498
    #ifdef EXPERIMENTAL_DSN
 
3499
    dsn_advertised = FALSE;
 
3500
    #endif
3026
3501
 
3027
3502
    smtp_code = US"250 ";        /* Default response code plus space*/
3028
3503
    if (user_msg == NULL)
3106
3581
        s = string_cat(s, &size, &ptr, US"-8BITMIME\r\n", 11);
3107
3582
        }
3108
3583
 
 
3584
      #ifdef EXPERIMENTAL_DSN
 
3585
      /* Advertise DSN support if configured to do so. */
 
3586
      if (verify_check_host(&dsn_advertise_hosts) != FAIL) 
 
3587
        {
 
3588
        s = string_cat(s, &size, &ptr, smtp_code, 3);
 
3589
        s = string_cat(s, &size, &ptr, US"-DSN\r\n", 6);
 
3590
        dsn_advertised = TRUE;
 
3591
        }
 
3592
      #endif
 
3593
 
3109
3594
      /* Advertise ETRN if there's an ACL checking whether a host is
3110
3595
      permitted to issue it; a check is made when any host actually tries. */
3111
3596
 
3195
3680
        }
3196
3681
      #endif
3197
3682
 
3198
 
      #ifdef EXPERIMENTAL_PRDR
 
3683
      #ifndef DISABLE_PRDR
3199
3684
      /* Per Recipient Data Response, draft by Eric A. Hall extending RFC */
3200
 
      if (prdr_enable) {
 
3685
      if (prdr_enable)
 
3686
        {
3201
3687
        s = string_cat(s, &size, &ptr, smtp_code, 3);
3202
3688
        s = string_cat(s, &size, &ptr, US"-PRDR\r\n", 7);
3203
 
      }
 
3689
        }
3204
3690
      #endif
3205
3691
 
3206
3692
      /* Finish off the multiline reply with one that is always available. */
3360
3846
          arg_error = TRUE;
3361
3847
          break;
3362
3848
 
 
3849
        #ifdef EXPERIMENTAL_DSN
 
3850
  
 
3851
        /* Handle the two DSN options, but only if configured to do so (which
 
3852
        will have caused "DSN" to be given in the EHLO response). The code itself
 
3853
        is included only if configured in at build time. */
 
3854
 
 
3855
        case ENV_MAIL_OPT_RET:
 
3856
          if (dsn_advertised) {
 
3857
            /* Check if RET has already been set */
 
3858
            if (dsn_ret > 0) {
 
3859
              synprot_error(L_smtp_syntax_error, 501, NULL,
 
3860
                US"RET can be specified once only");
 
3861
              goto COMMAND_LOOP;
 
3862
            }
 
3863
            dsn_ret = (strcmpic(value, US"HDRS") == 0)? dsn_ret_hdrs :
 
3864
                    (strcmpic(value, US"FULL") == 0)? dsn_ret_full : 0;
 
3865
            DEBUG(D_receive) debug_printf("DSN_RET: %d\n", dsn_ret);
 
3866
            /* Check for invalid invalid value, and exit with error */
 
3867
            if (dsn_ret == 0) {
 
3868
              synprot_error(L_smtp_syntax_error, 501, NULL,
 
3869
                US"Value for RET is invalid");
 
3870
              goto COMMAND_LOOP;
 
3871
            }
 
3872
          }
 
3873
          break;
 
3874
        case ENV_MAIL_OPT_ENVID:
 
3875
          if (dsn_advertised) {
 
3876
            /* Check if the dsn envid has been already set */
 
3877
            if (dsn_envid != NULL) {
 
3878
              synprot_error(L_smtp_syntax_error, 501, NULL,
 
3879
                US"ENVID can be specified once only");
 
3880
              goto COMMAND_LOOP;
 
3881
            }
 
3882
            dsn_envid = string_copy(value);
 
3883
            DEBUG(D_receive) debug_printf("DSN_ENVID: %s\n", dsn_envid);
 
3884
          }
 
3885
          break;
 
3886
        #endif
 
3887
 
3363
3888
        /* Handle the AUTH extension. If the value given is not "<>" and either
3364
3889
        the ACL says "yes" or there is no ACL but the sending host is
3365
3890
        authenticated, we set it up as the authenticated sender. However, if the
3429
3954
            }
3430
3955
            break;
3431
3956
 
3432
 
#ifdef EXPERIMENTAL_PRDR
 
3957
#ifndef DISABLE_PRDR
3433
3958
        case ENV_MAIL_OPT_PRDR:
3434
 
          if ( prdr_enable )
 
3959
          if (prdr_enable)
3435
3960
            prdr_requested = TRUE;
3436
3961
          break;
3437
3962
#endif
3556
4081
    when pipelining is not advertised, do another sync check in case the ACL
3557
4082
    delayed and the client started sending in the meantime. */
3558
4083
 
3559
 
    if (acl_smtp_mail == NULL) rc = OK; else
 
4084
    if (acl_smtp_mail)
3560
4085
      {
3561
4086
      rc = acl_check(ACL_WHERE_MAIL, NULL, acl_smtp_mail, &user_msg, &log_msg);
3562
4087
      if (rc == OK && !pipelining_advertised && !check_sync())
3563
4088
        goto SYNC_FAILURE;
3564
4089
      }
 
4090
    else
 
4091
      rc = OK;
3565
4092
 
3566
4093
    if (rc == OK || rc == DISCARD)
3567
4094
      {
3568
 
      if (user_msg == NULL) 
 
4095
      if (!user_msg)
3569
4096
        smtp_printf("%s%s%s", US"250 OK",
3570
 
                  #ifdef EXPERIMENTAL_PRDR
3571
 
                    prdr_requested == TRUE ? US", PRDR Requested" :
 
4097
                  #ifndef DISABLE_PRDR
 
4098
                    prdr_requested ? US", PRDR Requested" : US"",
 
4099
                  #else
 
4100
                    US"",
3572
4101
                  #endif
3573
 
                    US"",
3574
4102
                    US"\r\n");
3575
4103
      else 
3576
4104
        {
3577
 
      #ifdef EXPERIMENTAL_PRDR
3578
 
        if ( prdr_requested == TRUE )
 
4105
      #ifndef DISABLE_PRDR
 
4106
        if (prdr_requested)
3579
4107
           user_msg = string_sprintf("%s%s", user_msg, US", PRDR Requested");
3580
4108
      #endif
3581
 
        smtp_user_msg(US"250",user_msg);
 
4109
        smtp_user_msg(US"250", user_msg);
3582
4110
        }
3583
4111
      smtp_delay_rcpt = smtp_rlr_base;
3584
4112
      recipients_discarded = (rc == DISCARD);
3633
4161
      rcpt_fail_count++;
3634
4162
      break;
3635
4163
      }
 
4164
    
 
4165
    #ifdef EXPERIMENTAL_DSN
 
4166
    /* Set the DSN flags orcpt and dsn_flags from the session*/
 
4167
    orcpt = NULL;
 
4168
    flags = 0;
 
4169
 
 
4170
    if (esmtp) for(;;)
 
4171
      {
 
4172
      uschar *name, *value, *end;
 
4173
      int size;
 
4174
 
 
4175
      if (!extract_option(&name, &value))
 
4176
        {
 
4177
        break;
 
4178
        }
 
4179
 
 
4180
      if (dsn_advertised && strcmpic(name, US"ORCPT") == 0)
 
4181
        {
 
4182
        /* Check whether orcpt has been already set */
 
4183
        if (orcpt != NULL) {
 
4184
          synprot_error(L_smtp_syntax_error, 501, NULL,
 
4185
            US"ORCPT can be specified once only");
 
4186
          goto COMMAND_LOOP;
 
4187
          }
 
4188
        orcpt = string_copy(value);
 
4189
        DEBUG(D_receive) debug_printf("DSN orcpt: %s\n", orcpt);
 
4190
        }
 
4191
 
 
4192
      else if (dsn_advertised && strcmpic(name, US"NOTIFY") == 0)
 
4193
        {
 
4194
        /* Check if the notify flags have been already set */
 
4195
        if (flags > 0) {
 
4196
          synprot_error(L_smtp_syntax_error, 501, NULL,
 
4197
              US"NOTIFY can be specified once only");
 
4198
          goto COMMAND_LOOP;
 
4199
          }
 
4200
        if (strcmpic(value, US"NEVER") == 0) flags |= rf_notify_never; else
 
4201
          {
 
4202
          uschar *p = value;
 
4203
          while (*p != 0)
 
4204
            {
 
4205
            uschar *pp = p;
 
4206
            while (*pp != 0 && *pp != ',') pp++;
 
4207
              if (*pp == ',') *pp++ = 0;
 
4208
            if (strcmpic(p, US"SUCCESS") == 0) {
 
4209
                DEBUG(D_receive) debug_printf("DSN: Setting notify success\n");
 
4210
                flags |= rf_notify_success;
 
4211
              }
 
4212
            else if (strcmpic(p, US"FAILURE") == 0) {
 
4213
                DEBUG(D_receive) debug_printf("DSN: Setting notify failure\n");
 
4214
                flags |= rf_notify_failure;
 
4215
              }
 
4216
            else if (strcmpic(p, US"DELAY") == 0) {
 
4217
                DEBUG(D_receive) debug_printf("DSN: Setting notify delay\n");
 
4218
                flags |= rf_notify_delay;
 
4219
              }
 
4220
            else {
 
4221
              /* Catch any strange values */
 
4222
              synprot_error(L_smtp_syntax_error, 501, NULL,
 
4223
                US"Invalid value for NOTIFY parameter");
 
4224
              goto COMMAND_LOOP;
 
4225
              }
 
4226
            p = pp;
 
4227
            }
 
4228
            DEBUG(D_receive) debug_printf("DSN Flags: %x\n", flags);
 
4229
          }
 
4230
        }
 
4231
 
 
4232
      /* Unknown option. Stick back the terminator characters and break
 
4233
      the loop. An error for a malformed address will occur. */
 
4234
 
 
4235
      else
 
4236
        {
 
4237
        DEBUG(D_receive) debug_printf("Invalid RCPT option: %s : %s\n", name, value);
 
4238
        name[-1] = ' ';
 
4239
        value[-1] = '=';
 
4240
        break;
 
4241
        }
 
4242
      }
 
4243
    #endif
3636
4244
 
3637
4245
    /* Apply SMTP rewriting then extract the working address. Don't allow "<>"
3638
4246
    as a recipient address */
3747
4355
      if (user_msg == NULL) smtp_printf("250 Accepted\r\n");
3748
4356
        else smtp_user_msg(US"250", user_msg);
3749
4357
      receive_add_recipient(recipient, -1);
 
4358
      
 
4359
      #ifdef EXPERIMENTAL_DSN
 
4360
      /* Set the dsn flags in the recipients_list */
 
4361
      if (orcpt != NULL)
 
4362
        recipients_list[recipients_count-1].orcpt = orcpt;
 
4363
      else
 
4364
        recipients_list[recipients_count-1].orcpt = NULL;
 
4365
 
 
4366
      if (flags != 0)
 
4367
        recipients_list[recipients_count-1].dsn_flags = flags;
 
4368
      else
 
4369
        recipients_list[recipients_count-1].dsn_flags = 0;
 
4370
      DEBUG(D_receive) debug_printf("DSN: orcpt: %s  flags: %d\n", recipients_list[recipients_count-1].orcpt, recipients_list[recipients_count-1].dsn_flags);
 
4371
      #endif
 
4372
      
3750
4373
      }
3751
4374
 
3752
4375
    /* The recipient was discarded */
4379
5002
    done = 1;   /* Pretend eof - drops connection */
4380
5003
    break;
4381
5004
 
 
5005
    #ifdef EXPERIMENTAL_PROXY
 
5006
    case PROXY_FAIL_IGNORE_CMD:
 
5007
    smtp_printf("503 Command refused, required Proxy negotiation failed\r\n");
 
5008
    break;
 
5009
    #endif
4382
5010
 
4383
5011
    default:
4384
5012
    if (unknown_command_count++ >= smtp_max_unknown_commands)
4413
5041
return done - 2;  /* Convert yield values */
4414
5042
}
4415
5043
 
 
5044
/* vi: aw ai sw=2
 
5045
*/
4416
5046
/* End of smtp_in.c */