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
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
580
restore_socket_timeout(int fd, int get_ok, struct timeval tvtmp, socklen_t vslen)
583
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp, vslen);
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.
597
check_proxy_protocol_host()
600
/* Cannot configure local connection as a proxy inbound */
601
if (sender_host_address == NULL) return proxy_session;
603
rc = verify_check_this_host(&proxy_required_hosts, NULL, NULL,
604
sender_host_address, NULL);
608
debug_printf("Detected proxy protocol configured host\n");
609
proxy_session = TRUE;
611
return proxy_session;
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.
628
setup_proxy_protocol_host()
640
struct { /* TCP/UDP over IPv4, len = 12 */
646
struct { /* TCP/UDP over IPv6, len = 36 */
647
uint8_t src_addr[16];
648
uint8_t dst_addr[16];
652
struct { /* AF_UNIX sockets, len = 216 */
653
uschar src_addr[108];
654
uschar dst_addr[108];
660
/* Temp variables used in PPv2 address:port parsing */
662
char tmpip[INET_ADDRSTRLEN];
663
struct sockaddr_in tmpaddr;
664
char tmpip6[INET6_ADDRSTRLEN];
665
struct sockaddr_in6 tmpaddr6;
669
const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
670
uschar *iptype; /* To display debug info */
673
struct timeval tvtmp;
675
vslen = sizeof(struct timeval);
677
fd = fileno(smtp_in);
679
/* Save current socket timeout values */
680
get_ok = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tvtmp,
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));
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);
696
while (ret == -1 && errno == EINTR);
700
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
701
return (errno == EAGAIN) ? 0 : ERRNO_PROXYFAIL;
705
memcmp(&hdr.v2, v2sig, 12) == 0)
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);
718
DEBUG(D_receive) debug_printf("Invalid Proxy Protocol version: %d\n", ver);
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;
726
DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header (%d/%d)\n",
732
case 0x01: /* PROXY command */
735
case 0x11: /* TCPv4 address type */
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))
741
DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
742
return ERRNO_PROXYFAIL;
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))
754
DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
755
return ERRNO_PROXYFAIL;
757
proxy_target_address = string_copy(US tmpip);
758
tmpport = ntohs(hdr.v2.addr.ip4.dst_port);
759
proxy_target_port = tmpport;
761
case 0x21: /* TCPv6 address type */
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))
767
DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
768
return ERRNO_PROXYFAIL;
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))
780
DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
781
return ERRNO_PROXYFAIL;
783
proxy_target_address = string_copy(US tmpip6);
784
tmpport = ntohs(hdr.v2.addr.ip6.dst_port);
785
proxy_target_port = tmpport;
789
debug_printf("Unsupported PROXYv2 connection type: 0x%02x\n",
793
/* Unsupported protocol, keep local connection address */
795
case 0x00: /* LOCAL command */
796
/* Keep local connection address for LOCAL */
800
debug_printf("Unsupported PROXYv2 command: 0x%x\n", cmd);
805
memcmp(hdr.v1.line, "PROXY", 5) == 0)
807
uschar *p = string_copy(hdr.v1.line);
808
uschar *end = memchr(p, '\r', ret - 1);
809
uschar *sp; /* Utility variables follow */
813
if (!end || end[1] != '\n')
815
DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n");
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. */
824
if (!isspace(*(p++)))
826
DEBUG(D_receive) debug_printf("Missing space after PROXY command\n");
829
if (!Ustrncmp(p, CCS"TCP4", 4))
831
else if (!Ustrncmp(p,CCS"TCP6", 4))
833
else if (!Ustrncmp(p,CCS"UNKNOWN", 7))
835
iptype = US"Unknown";
840
DEBUG(D_receive) debug_printf("Invalid TCP type\n");
844
p += Ustrlen(iptype);
845
if (!isspace(*(p++)))
847
DEBUG(D_receive) debug_printf("Missing space after TCP4/6 command\n");
850
/* Find the end of the arg */
851
if ((sp = Ustrchr(p, ' ')) == NULL)
854
debug_printf("Did not find proxied src %s\n", iptype);
858
if(!string_is_ip_address(p,NULL))
861
debug_printf("Proxied src arg is not an %s address\n", iptype);
864
proxy_host_address = sender_host_address;
865
sender_host_address = p;
867
if ((sp = Ustrchr(p, ' ')) == NULL)
870
debug_printf("Did not find proxy dest %s\n", iptype);
874
if(!string_is_ip_address(p,NULL))
877
debug_printf("Proxy dest arg is not an %s address\n", iptype);
880
proxy_target_address = p;
882
if ((sp = Ustrchr(p, ' ')) == NULL)
884
DEBUG(D_receive) debug_printf("Did not find proxied src port\n");
888
tmp_port = strtol(CCS p,&endc,10);
889
if (*endc || tmp_port == 0)
892
debug_printf("Proxied src port '%s' not an integer\n", p);
895
proxy_host_port = sender_host_port;
896
sender_host_port = tmp_port;
898
if ((sp = Ustrchr(p, '\0')) == NULL)
900
DEBUG(D_receive) debug_printf("Did not find proxy dest port\n");
903
tmp_port = strtol(CCS p,&endc,10);
904
if (*endc || tmp_port == 0)
907
debug_printf("Proxy dest port '%s' not an integer\n", p);
910
proxy_target_port = tmp_port;
911
/* Already checked for /r /n above. Good V1 header received. */
917
DEBUG(D_receive) debug_printf("Invalid proxy protocol version negotiation\n");
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 */
928
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
930
debug_printf("Valid %s sender from Proxy Protocol header\n", iptype);
931
return proxy_session;
552
935
/*************************************************
553
936
* Read one command line *
554
937
*************************************************/
3633
4161
rcpt_fail_count++;
4165
#ifdef EXPERIMENTAL_DSN
4166
/* Set the DSN flags orcpt and dsn_flags from the session*/
4172
uschar *name, *value, *end;
4175
if (!extract_option(&name, &value))
4180
if (dsn_advertised && strcmpic(name, US"ORCPT") == 0)
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");
4188
orcpt = string_copy(value);
4189
DEBUG(D_receive) debug_printf("DSN orcpt: %s\n", orcpt);
4192
else if (dsn_advertised && strcmpic(name, US"NOTIFY") == 0)
4194
/* Check if the notify flags have been already set */
4196
synprot_error(L_smtp_syntax_error, 501, NULL,
4197
US"NOTIFY can be specified once only");
4200
if (strcmpic(value, US"NEVER") == 0) flags |= rf_notify_never; else
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;
4212
else if (strcmpic(p, US"FAILURE") == 0) {
4213
DEBUG(D_receive) debug_printf("DSN: Setting notify failure\n");
4214
flags |= rf_notify_failure;
4216
else if (strcmpic(p, US"DELAY") == 0) {
4217
DEBUG(D_receive) debug_printf("DSN: Setting notify delay\n");
4218
flags |= rf_notify_delay;
4221
/* Catch any strange values */
4222
synprot_error(L_smtp_syntax_error, 501, NULL,
4223
US"Invalid value for NOTIFY parameter");
4228
DEBUG(D_receive) debug_printf("DSN Flags: %x\n", flags);
4232
/* Unknown option. Stick back the terminator characters and break
4233
the loop. An error for a malformed address will occur. */
4237
DEBUG(D_receive) debug_printf("Invalid RCPT option: %s : %s\n", name, value);
3637
4245
/* Apply SMTP rewriting then extract the working address. Don't allow "<>"
3638
4246
as a recipient address */