xref: /netbsd-src/external/ibm-public/postfix/dist/src/smtpd/smtpd_haproxy.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /*	$NetBSD: smtpd_haproxy.c,v 1.3 2020/03/18 19:05:20 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	smtpd_haproxy 3
6 /* SUMMARY
7 /*	Postfix SMTP server haproxy adapter
8 /* SYNOPSIS
9 /*	#include "smtpd.h"
10 /*
11 /*	int	smtpd_peer_from_haproxy(state)
12 /*	SMTPD_STATE *state;
13 /* DESCRIPTION
14 /*	smtpd_peer_from_haproxy() receives endpoint address and
15 /*	port information via the haproxy protocol.
16 /*
17 /*	The following summarizes what the Postfix SMTP server expects
18 /*	from an up-stream proxy adapter.
19 /* .IP \(bu
20 /*	Call smtpd_peer_from_default() if the up-stream proxy
21 /*	indicates that the connection is not proxied. In that case,
22 /*	a proxy adapter MUST NOT update any STATE fields: the
23 /*	smtpd_peer_from_default() function will do that instead.
24 /* .IP \(bu
25 /*	Validate protocol, address and port syntax. Permit only
26 /*	protocols that are configured with the main.cf:inet_protocols
27 /*	setting.
28 /* .IP \(bu
29 /*	Convert IPv4-in-IPv6 address syntax to IPv4 syntax when
30 /*	both IPv6 and IPv4 support are enabled with main.cf:inet_protocols.
31 /* .IP \(bu
32 /*	Update the following session context fields: addr, port,
33 /*	rfc_addr, addr_family, dest_addr, dest_port. The addr_family
34 /*	field applies to the client address.
35 /* .IP \(bu
36 /*	Dynamically allocate storage for string information with
37 /*	mystrdup(). In case of error, leave unassigned string fields
38 /*	at their initial zero value.
39 /* .IP \(bu
40 /*	Log a clear warning message that explains why a request
41 /*	fails.
42 /* .IP \(bu
43 /*	Never talk to the remote SMTP client.
44 /* .PP
45 /*	Arguments:
46 /* .IP state
47 /*	Session context.
48 /* DIAGNOSTICS
49 /*	Warnings: I/O errors, malformed haproxy line.
50 /*
51 /*	The result value is 0 in case of success, -1 in case of
52 /*	error.
53 /* LICENSE
54 /* .ad
55 /* .fi
56 /*	The Secure Mailer license must be distributed with this software.
57 /* AUTHOR(S)
58 /*	Wietse Venema
59 /*	IBM T.J. Watson Research
60 /*	P.O. Box 704
61 /*	Yorktown Heights, NY 10598, USA
62 /*
63 /*	Wietse Venema
64 /*	Google, Inc.
65 /*	111 8th Avenue
66 /*	New York, NY 10011, USA
67 /*--*/
68 
69 /* System library. */
70 
71 #include <sys_defs.h>
72 #include <sys/socket.h>
73 
74 /* Utility library. */
75 
76 #include <msg.h>
77 #include <myaddrinfo.h>
78 #include <mymalloc.h>
79 #include <stringops.h>
80 #include <iostuff.h>
81 
82 /* Global library. */
83 
84 #include <smtp_stream.h>
85 #include <mail_params.h>
86 #include <valid_mailhost_addr.h>
87 #include <haproxy_srvr.h>
88 
89 /* Application-specific. */
90 
91 #include <smtpd.h>
92 
93 /* SLMs. */
94 
95 #define STR(x)	vstring_str(x)
96 #define LEN(x)	VSTRING_LEN(x)
97 
98 /* smtpd_peer_from_haproxy - initialize peer information from haproxy */
99 
smtpd_peer_from_haproxy(SMTPD_STATE * state)100 int     smtpd_peer_from_haproxy(SMTPD_STATE *state)
101 {
102     MAI_HOSTADDR_STR smtp_client_addr;
103     MAI_SERVPORT_STR smtp_client_port;
104     MAI_HOSTADDR_STR smtp_server_addr;
105     MAI_SERVPORT_STR smtp_server_port;
106     int     non_proxy = 0;
107 
108     if (read_wait(vstream_fileno(state->client), var_smtpd_uproxy_tmout) < 0) {
109 	msg_warn("haproxy read: timeout error");
110 	return (-1);
111     }
112     if (haproxy_srvr_receive(vstream_fileno(state->client), &non_proxy,
113 			     &smtp_client_addr, &smtp_client_port,
114 			     &smtp_server_addr, &smtp_server_port) < 0) {
115 	return (-1);
116     }
117     if (non_proxy) {
118 	smtpd_peer_from_default(state);
119 	return (0);
120     }
121     state->addr = mystrdup(smtp_client_addr.buf);
122     if (strrchr(state->addr, ':') != 0) {
123 	state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0);
124 	state->addr_family = AF_INET6;
125     } else {
126 	state->rfc_addr = mystrdup(state->addr);
127 	state->addr_family = AF_INET;
128     }
129     state->port = mystrdup(smtp_client_port.buf);
130 
131     /*
132      * The Dovecot authentication server needs the server IP address.
133      */
134     state->dest_addr = mystrdup(smtp_server_addr.buf);
135     state->dest_port = mystrdup(smtp_server_port.buf);
136     return (0);
137 }
138