Fix no-ssl build
[exim.git] / src / src / transports / smtp.c
index 71a9f23760feac72e949c55a6f49f36289c0024a..33c91a67ab055d28098580c46ad83c38cb455aa4 100644 (file)
@@ -69,7 +69,7 @@ optionlist smtp_transport_options[] = {
       (void *)offsetof(smtp_transport_options_block, gethostbyname) },
 #ifdef SUPPORT_TLS
   /* These are no longer honoured, as of Exim 4.80; for now, we silently
-  ignore; a later release will warn, and a later-still release will remove
+  ignore; 4.83 will warn, and a later-still release will remove
   these options, so that using them becomes an error. */
   { "gnutls_require_kx",    opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, gnutls_require_kx) },
@@ -102,14 +102,14 @@ optionlist smtp_transport_options[] = {
       (void *)offsetof(smtp_transport_options_block, hosts_override) },
   { "hosts_randomize",      opt_bool,
       (void *)offsetof(smtp_transport_options_block, hosts_randomize) },
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_OCSP)
+#if defined(SUPPORT_TLS) && !defined(DISABLE_OCSP)
   { "hosts_request_ocsp",   opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, hosts_request_ocsp) },
 #endif
   { "hosts_require_auth",   opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, hosts_require_auth) },
 #ifdef SUPPORT_TLS
-# if defined EXPERIMENTAL_OCSP
+# ifndef DISABLE_OCSP
   { "hosts_require_ocsp",   opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, hosts_require_ocsp) },
 # endif
@@ -163,6 +163,10 @@ optionlist smtp_transport_options[] = {
       (void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) },
   { "tls_try_verify_hosts", opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) },
+#ifdef EXPERIMENTAL_CERTNAMES
+  { "tls_verify_cert_hostnames", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block,tls_verify_cert_hostnames)},
+#endif
   { "tls_verify_certificates", opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) },
   { "tls_verify_hosts",     opt_stringptr,
@@ -199,7 +203,7 @@ smtp_transport_options_block smtp_transport_option_defaults = {
 #ifndef DISABLE_PRDR
   NULL,                /* hosts_try_prdr */
 #endif
-#ifdef EXPERIMENTAL_OCSP
+#ifndef DISABLE_OCSP
   US"*",               /* hosts_request_ocsp */
   NULL,                /* hosts_require_ocsp */
 #endif
@@ -245,6 +249,9 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   TRUE,                /* tls_tempfail_tryclear */
   NULL,                /* tls_verify_hosts */
   NULL                 /* tls_try_verify_hosts */
+# ifdef EXPERIMENTAL_CERTNAMES
+ ,NULL                 /* tls_verify_cert_hostnames */
+# endif
 #endif
 #ifndef DISABLE_DKIM
  ,NULL,                /* dkim_canon */
@@ -259,6 +266,16 @@ smtp_transport_options_block smtp_transport_option_defaults = {
 #endif
 };
 
+#ifdef EXPERIMENTAL_DSN
+/* some DSN flags for use later */
+
+static int     rf_list[] = {rf_notify_never, rf_notify_success,
+                            rf_notify_failure, rf_notify_delay };
+
+static uschar *rf_names[] = { "NEVER", "SUCCESS", "FAILURE", "DELAY" };
+#endif
+
+
 
 /* Local statics */
 
@@ -383,6 +400,15 @@ if (ob->hosts_override && ob->hosts != NULL) tblock->overrides_hosts = TRUE;
 for them, but do not do any lookups at this time. */
 
 host_build_hostlist(&(ob->fallback_hostlist), ob->fallback_hosts, FALSE);
+
+#ifdef SUPPORT_TLS
+if (  ob->gnutls_require_kx
+   || ob->gnutls_require_mac
+   || ob->gnutls_require_proto)
+  log_write(0, LOG_MAIN, "WARNING: smtp transport options"
+    " gnutls_require_kx, gnutls_require_mac and gnutls_require_protocols"
+    " are obsolete\n");
+#endif
 }
 
 
@@ -1189,6 +1215,9 @@ BOOL pass_message = FALSE;
 BOOL prdr_offered = FALSE;
 BOOL prdr_active;
 #endif
+#ifdef EXPERIMENTAL_DSN
+BOOL dsn_all_lasthop = TRUE;
+#endif
 smtp_inblock inblock;
 smtp_outblock outblock;
 int max_rcpt = tblock->max_addresses;
@@ -1596,6 +1625,13 @@ if (continue_hostname == NULL
     {DEBUG(D_transport) debug_printf("PRDR usable\n");}
 #endif
 
+#ifdef EXPERIMENTAL_DSN
+  /* Note if the server supports DSN */
+  smtp_use_dsn = esmtp && pcre_exec(regex_DSN, NULL, CS buffer, (int)Ustrlen(CS buffer), 0,
+       PCRE_EOPT, NULL, 0) >= 0;
+  DEBUG(D_transport) debug_printf("use_dsn=%d\n", smtp_use_dsn);
+#endif
+
   /* Note if the response to EHLO specifies support for the AUTH extension.
   If it has, check that this host is one we want to authenticate to, and do
   the business. The host name and address must be available when the
@@ -1693,6 +1729,38 @@ if (prdr_offered)
 prdr_is_active:
 #endif
 
+#ifdef EXPERIMENTAL_DSN
+/* check if all addresses have lasthop flag */
+/* do not send RET and ENVID if true */
+dsn_all_lasthop = TRUE;
+for (addr = first_addr;
+     address_count < max_rcpt && addr != NULL;
+     addr = addr->next)
+  if ((addr->dsn_flags & rf_dsnlasthop) != 1)
+    dsn_all_lasthop = FALSE;
+
+/* Add any DSN flags to the mail command */
+
+if ((smtp_use_dsn) && (dsn_all_lasthop == FALSE))
+  {
+  if (dsn_ret == dsn_ret_hdrs)
+    {
+    strcpy(p, " RET=HDRS");
+    while (*p) p++;
+    }
+  else if (dsn_ret == dsn_ret_full)
+    {
+    strcpy(p, " RET=FULL");
+    while (*p) p++;
+    }
+  if (dsn_envid != NULL)
+    {
+    string_format(p, sizeof(buffer) - (p-buffer), " ENVID=%s", dsn_envid);
+    while (*p) p++;
+    }
+  }
+#endif
+
 /* If an authenticated_sender override has been specified for this transport
 instance, expand it. If the expansion is forced to fail, and there was already
 an authenticated_sender for this message, the original value will be used.
@@ -1755,18 +1823,66 @@ for (addr = first_addr;
   int count;
   BOOL no_flush;
 
+  #ifdef EXPERIMENTAL_DSN
+  if(smtp_use_dsn)
+    addr->dsn_aware = dsn_support_yes;
+  else
+    addr->dsn_aware = dsn_support_no;
+  #endif
+
   if (addr->transport_return != PENDING_DEFER) continue;
 
   address_count++;
   no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next != NULL);
 
+  #ifdef EXPERIMENTAL_DSN
+  /* Add any DSN flags to the rcpt command and add to the sent string */
+
+  p = buffer;
+  *p = 0;
+
+  if ((smtp_use_dsn) && ((addr->dsn_flags & rf_dsnlasthop) != 1))
+    {
+    if ((addr->dsn_flags & rf_dsnflags) != 0)
+      {
+      int i;
+      BOOL first = TRUE;
+      strcpy(p, " NOTIFY=");
+      while (*p) p++;
+      for (i = 0; i < 4; i++)
+        {
+        if ((addr->dsn_flags & rf_list[i]) != 0)
+          {
+          if (!first) *p++ = ',';
+          first = FALSE;
+          strcpy(p, rf_names[i]);
+          while (*p) p++;
+          }
+        }
+      }
+
+    if (addr->dsn_orcpt != NULL) {
+      string_format(p, sizeof(buffer) - (p-buffer), " ORCPT=%s",
+        addr->dsn_orcpt);
+      while (*p) p++;
+      }
+    }
+  #endif
+
+
   /* Now send the RCPT command, and process outstanding responses when
   necessary. After a timeout on RCPT, we just end the function, leaving the
   yield as OK, because this error can often mean that there is a problem with
   just one address, so we don't want to delay the host. */
 
+  #ifdef EXPERIMENTAL_DSN
+  count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s%s\r\n",
+    transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr, buffer);
+  #else
   count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s\r\n",
     transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr);
+  #endif
+
   if (count < 0) goto SEND_FAILED;
   if (count > 0)
     {