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