PROXY: fix v2 protocol decode. Bugs 2003, 1747
[exim.git] / src / src / smtp_in.c
index 9282352aca2793622929a78c1bca82149b1c9ddd..0935d212b11f1581dac7c16e176d0b1f05f58c53 100644 (file)
@@ -143,8 +143,6 @@ static BOOL pipelining_advertised;
 static BOOL rcpt_smtp_response_same;
 static BOOL rcpt_in_progress;
 static int  nonmail_command_count;
-static int  off = 0;
-static int  on = 1;
 static BOOL smtp_exit_function_called = 0;
 #ifdef SUPPORT_I18N
 static BOOL smtputf8_advertised;
@@ -880,17 +878,15 @@ do
 if (ret == -1)
   goto proxyfail;
 
-if (ret >= 16 &&
-    memcmp(&hdr.v2, v2sig, 12) == 0)
+if (ret >= 16 && memcmp(&hdr.v2, v2sig, 12) == 0)
   {
-  uint8_t ver, cmd;
+  uint8_t ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
+  uint8_t cmd = (hdr.v2.ver_cmd & 0x0f);
 
   /* May 2014: haproxy combined the version and command into one byte to
      allow two full bytes for the length field in order to proxy SSL
      connections.  SSL Proxy is not supported in this version of Exim, but
      must still seperate values here. */
-  ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
-  cmd = (hdr.v2.ver_cmd & 0x0f);
 
   if (ver != 0x02)
     {
@@ -899,7 +895,7 @@ if (ret >= 16 &&
     }
   DEBUG(D_receive) debug_printf("Detected PROXYv2 header\n");
   /* The v2 header will always be 16 bytes per the spec. */
-  size = 16 + hdr.v2.len;
+  size = 16 + ntohs(hdr.v2.len);
   if (ret < size)
     {
     DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header (%d/%d)\n",
@@ -914,8 +910,8 @@ if (ret >= 16 &&
         case 0x11:  /* TCPv4 address type */
           iptype = US"IPv4";
           tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;
-          inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
-          if (!string_is_ip_address(US tmpip,NULL))
+          inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));
+          if (!string_is_ip_address(US tmpip, NULL))
             {
             DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
             goto proxyfail;
@@ -927,8 +923,8 @@ if (ret >= 16 &&
           sender_host_port    = tmpport;
           /* Save dest ip/port */
           tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr;
-          inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
-          if (!string_is_ip_address(US tmpip,NULL))
+          inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));
+          if (!string_is_ip_address(US tmpip, NULL))
             {
             DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
             goto proxyfail;
@@ -940,8 +936,8 @@ if (ret >= 16 &&
         case 0x21:  /* TCPv6 address type */
           iptype = US"IPv6";
           memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);
-          inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
-          if (!string_is_ip_address(US tmpip6,NULL))
+          inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));
+          if (!string_is_ip_address(US tmpip6, NULL))
             {
             DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
             goto proxyfail;
@@ -953,8 +949,8 @@ if (ret >= 16 &&
           sender_host_port    = tmpport;
           /* Save dest ip/port */
           memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.dst_addr, 16);
-          inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
-          if (!string_is_ip_address(US tmpip6,NULL))
+          inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));
+          if (!string_is_ip_address(US tmpip6, NULL))
             {
             DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
             goto proxyfail;
@@ -980,8 +976,7 @@ if (ret >= 16 &&
       goto proxyfail;
     }
   }
-else if (ret >= 8 &&
-         memcmp(hdr.v1.line, "PROXY", 5) == 0)
+else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0)
   {
   uschar *p = string_copy(hdr.v1.line);
   uschar *end = memchr(p, '\r', ret - 1);
@@ -1034,7 +1029,7 @@ else if (ret >= 8 &&
     goto proxyfail;
     }
   *sp = '\0';
-  if(!string_is_ip_address(p,NULL))
+  if(!string_is_ip_address(p, NULL))
     {
     DEBUG(D_receive)
       debug_printf("Proxied src arg is not an %s address\n", iptype);
@@ -1050,7 +1045,7 @@ else if (ret >= 8 &&
     goto proxyfail;
     }
   *sp = '\0';
-  if(!string_is_ip_address(p,NULL))
+  if(!string_is_ip_address(p, NULL))
     {
     DEBUG(D_receive)
       debug_printf("Proxy dest arg is not an %s address\n", iptype);
@@ -1064,7 +1059,7 @@ else if (ret >= 8 &&
     goto proxyfail;
     }
   *sp = '\0';
-  tmp_port = strtol(CCS p,&endc,10);
+  tmp_port = strtol(CCS p, &endc, 10);
   if (*endc || tmp_port == 0)
     {
     DEBUG(D_receive)
@@ -1079,7 +1074,7 @@ else if (ret >= 8 &&
     DEBUG(D_receive) debug_printf("Did not find proxy dest port\n");
     goto proxyfail;
     }
-  tmp_port = strtol(CCS p,&endc,10);
+  tmp_port = strtol(CCS p, &endc, 10);
   if (*endc || tmp_port == 0)
     {
     DEBUG(D_receive)
@@ -1378,8 +1373,8 @@ Returns:     a string describing the connection
 uschar *
 smtp_get_connection_info(void)
 {
-uschar *hostname = (sender_fullhost == NULL)?
-  sender_host_address : sender_fullhost;
+const uschar * hostname = sender_fullhost
+  ? sender_fullhost : sender_host_address;
 
 if (host_checking)
   return string_sprintf("SMTP connection from %s", hostname);
@@ -3514,7 +3509,7 @@ while (done <= 0)
   uschar *orcpt = NULL;
   int flags;
 
-#if defined(SUPPORT_TLS) && defined(AUTH_TLS)
+#ifdef AUTH_TLS
   /* Check once per STARTTLS or SSL-on-connect for a TLS AUTH */
   if (  tls_in.active >= 0
      && tls_in.peercert
@@ -3930,7 +3925,7 @@ while (done <= 0)
       them in either case in the AUTH command. */
 
       if (  auths
-#if defined(SUPPORT_TLS) && defined(AUTH_TLS)
+#ifdef AUTH_TLS
         && !sender_host_authenticated
 #endif
          && verify_check_host(&auth_advertise_hosts) == OK
@@ -4655,20 +4650,22 @@ while (done <= 0)
     there may be a delay in this, re-check for a synchronization error
     afterwards, unless pipelining was advertised. */
 
-    if (recipients_discarded) rc = DISCARD; else
-      {
-      rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg,
-        &log_msg);
-      if (rc == OK && !pipelining_advertised && !check_sync())
+    if (recipients_discarded)
+      rc = DISCARD;
+    else
+      if (  (rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg,
+                   &log_msg)) == OK
+        && !pipelining_advertised && !check_sync())
         goto SYNC_FAILURE;
-      }
 
     /* The ACL was happy */
 
     if (rc == OK)
       {
-      if (user_msg == NULL) smtp_printf("250 Accepted\r\n");
-        else smtp_user_msg(US"250", user_msg);
+      if (user_msg)
+        smtp_user_msg(US"250", user_msg);
+      else
+        smtp_printf("250 Accepted\r\n");
       receive_add_recipient(recipient, -1);
 
       /* Set the dsn flags in the recipients_list */
@@ -4684,8 +4681,10 @@ while (done <= 0)
 
     else if (rc == DISCARD)
       {
-      if (user_msg == NULL) smtp_printf("250 Accepted\r\n");
-        else smtp_user_msg(US"250", user_msg);
+      if (user_msg)
+        smtp_user_msg(US"250", user_msg);
+      else
+        smtp_printf("250 Accepted\r\n");
       rcpt_fail_count++;
       discarded = TRUE;
       log_write(0, LOG_MAIN|LOG_REJECT, "%s F=<%s> RCPT %s: "
@@ -4799,9 +4798,7 @@ while (done <= 0)
       }
 
     if (chunking_state > CHUNKING_OFFERED)
-      {                                /* No predata ACL or go-ahead output for BDAT */
-      rc = OK;
-      }
+      rc = OK;                 /* No predata ACL or go-ahead output for BDAT */
     else
       {
       /* If there is an ACL, re-check the synchronization afterwards, since the