Postfix3.3.1
smtpd_haproxy.c
[詳解]
1 /*++
2 /* NAME
3 /* smtpd_haproxy 3
4 /* SUMMARY
5 /* Postfix SMTP server haproxy adapter
6 /* SYNOPSIS
7 /* #include "smtpd.h"
8 /*
9 /* int smtpd_peer_from_haproxy(state)
10 /* SMTPD_STATE *state;
11 /* DESCRIPTION
12 /* smtpd_peer_from_haproxy() receives endpoint address and
13 /* port information via the haproxy protocol.
14 /*
15 /* The following summarizes what the Postfix SMTP server expects
16 /* from an up-stream proxy adapter.
17 /* .IP \(bu
18 /* Validate protocol, address and port syntax. Permit only
19 /* protocols that are configured with the main.cf:inet_protocols
20 /* setting.
21 /* .IP \(bu
22 /* Convert IPv4-in-IPv6 address syntax to IPv4 syntax when
23 /* both IPv6 and IPv4 support are enabled with main.cf:inet_protocols.
24 /* .IP \(bu
25 /* Update the following session context fields: addr, port,
26 /* rfc_addr, addr_family, dest_addr, dest_port. The addr_family
27 /* field applies to the client address.
28 /* .IP \(bu
29 /* Dynamically allocate storage for string information with
30 /* mystrdup(). In case of error, leave unassigned string fields
31 /* at their initial zero value.
32 /* .IP \(bu
33 /* Log a clear warning message that explains why a request
34 /* fails.
35 /* .IP \(bu
36 /* Never talk to the remote SMTP client.
37 /* .PP
38 /* Arguments:
39 /* .IP state
40 /* Session context.
41 /* DIAGNOSTICS
42 /* Warnings: I/O errors, malformed haproxy line.
43 /*
44 /* The result value is 0 in case of success, -1 in case of
45 /* error.
46 /* LICENSE
47 /* .ad
48 /* .fi
49 /* The Secure Mailer license must be distributed with this software.
50 /* AUTHOR(S)
51 /* Wietse Venema
52 /* IBM T.J. Watson Research
53 /* P.O. Box 704
54 /* Yorktown Heights, NY 10598, USA
55 /*
56 /* Wietse Venema
57 /* Google, Inc.
58 /* 111 8th Avenue
59 /* New York, NY 10011, USA
60 /*--*/
61 
62 /* System library. */
63 
64 #include <sys_defs.h>
65 #include <sys/socket.h>
66 
67 /* Utility library. */
68 
69 #include <msg.h>
70 #include <myaddrinfo.h>
71 #include <mymalloc.h>
72 #include <stringops.h>
73 
74 /* Global library. */
75 
76 #include <smtp_stream.h>
77 #include <mail_params.h>
78 #include <valid_mailhost_addr.h>
79 #include <haproxy_srvr.h>
80 
81 /* Application-specific. */
82 
83 #include <smtpd.h>
84 
85 /* SLMs. */
86 
87 #define STR(x) vstring_str(x)
88 #define LEN(x) VSTRING_LEN(x)
89 
90 /* smtpd_peer_from_haproxy - initialize peer information from haproxy */
91 
93 {
94  const char *myname = "smtpd_peer_from_haproxy";
95  MAI_HOSTADDR_STR smtp_client_addr;
96  MAI_SERVPORT_STR smtp_client_port;
97  MAI_HOSTADDR_STR smtp_server_addr;
98  MAI_SERVPORT_STR smtp_server_port;
99  const char *proxy_err;
100  int io_err;
101  VSTRING *escape_buf;
102 
103  /*
104  * While reading HAProxy handshake information, don't buffer input beyond
105  * the end-of-line. That would break the TLS wrappermode handshake.
106  */
107  vstream_control(state->client,
110 
111  /*
112  * Note: the haproxy_srvr_parse() routine performs address protocol
113  * checks, address and port syntax checks, and converts IPv4-in-IPv6
114  * address string syntax (::ffff:1.2.3.4) to IPv4 syntax where permitted
115  * by the main.cf:inet_protocols setting, but logs no warnings.
116  */
117 #define ENABLE_DEADLINE 1
118 
120  switch (io_err = vstream_setjmp(state->client)) {
121  default:
122  msg_panic("%s: unhandled I/O error %d", myname, io_err);
123  case SMTP_ERR_EOF:
124  msg_warn("haproxy read: unexpected EOF");
125  return (-1);
126  case SMTP_ERR_TIME:
127  msg_warn("haproxy read: timeout error");
128  return (-1);
129  case 0:
130  if (smtp_get(state->buffer, state->client, HAPROXY_MAX_LEN,
131  SMTP_GET_FLAG_NONE) != '\n') {
132  msg_warn("haproxy read: line > %d characters", HAPROXY_MAX_LEN);
133  return (-1);
134  }
135  if ((proxy_err = haproxy_srvr_parse(STR(state->buffer),
136  &smtp_client_addr, &smtp_client_port,
137  &smtp_server_addr, &smtp_server_port)) != 0) {
138  escape_buf = vstring_alloc(HAPROXY_MAX_LEN + 2);
139  escape(escape_buf, STR(state->buffer), LEN(state->buffer));
140  msg_warn("haproxy read: %s: %s", proxy_err, STR(escape_buf));
141  vstring_free(escape_buf);
142  return (-1);
143  }
144  state->addr = mystrdup(smtp_client_addr.buf);
145  if (strrchr(state->addr, ':') != 0) {
146  state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0);
147  state->addr_family = AF_INET6;
148  } else {
149  state->rfc_addr = mystrdup(state->addr);
150  state->addr_family = AF_INET;
151  }
152  state->port = mystrdup(smtp_client_port.buf);
153 
154  /*
155  * The Dovecot authentication server needs the server IP address.
156  */
157  state->dest_addr = mystrdup(smtp_server_addr.buf);
158  state->dest_port = mystrdup(smtp_server_port.buf);
159 
160  /*
161  * Enable normal buffering.
162  */
163  vstream_control(state->client,
166  return (0);
167  }
168 }
int smtpd_peer_from_haproxy(SMTPD_STATE *state)
Definition: smtpd_haproxy.c:92
char * mystrdup(const char *str)
Definition: mymalloc.c:225
char * dest_port
Definition: smtpd.h:83
VSTRING * buffer
Definition: smtpd.h:71
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define VSTREAM_CTL_END
Definition: vstream.h:135
#define SMTP_ERR_TIME
Definition: smtp_stream.h:31
VSTRING * escape(VSTRING *, const char *, ssize_t)
Definition: unescape.c:133
#define ENABLE_DEADLINE
int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags)
Definition: smtp_stream.c:305
#define vstream_setjmp(stream)
Definition: vstream.h:248
const char * haproxy_srvr_parse(const char *str, MAI_HOSTADDR_STR *smtp_client_addr, MAI_SERVPORT_STR *smtp_client_port, MAI_HOSTADDR_STR *smtp_server_addr, MAI_SERVPORT_STR *smtp_server_port)
Definition: haproxy_srvr.c:160
int addr_family
Definition: smtpd.h:81
VSTREAM * client
Definition: smtpd.h:70
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
#define SMTP_ERR_EOF
Definition: smtp_stream.h:30
#define STR(x)
Definition: smtpd_haproxy.c:87
#define VSTREAM_CTL_BUFSIZE
Definition: vstream.h:149
char * port
Definition: smtpd.h:78
void msg_warn(const char *fmt,...)
Definition: msg.c:215
void smtp_stream_setup(VSTREAM *stream, int maxtime, int enable_deadline)
Definition: smtp_stream.c:209
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define IPV6_COL
char * concatenate(const char *arg0,...)
Definition: concatenate.c:42
#define VSTREAM_BUFSIZE
Definition: vstream.h:92
char * dest_addr
Definition: smtpd.h:82
char * addr
Definition: smtpd.h:77
#define LEN(x)
Definition: smtpd_haproxy.c:88
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
int var_smtpd_uproxy_tmout
Definition: smtpd.c:1417
char buf[MAI_SERVPORT_STRSIZE]
Definition: myaddrinfo.h:154
void vstream_control(VSTREAM *stream, int name,...)
Definition: vstream.c:1372
char * rfc_addr
Definition: smtpd.h:80
#define HAPROXY_MAX_LEN
Definition: haproxy_srvr.h:27
#define SMTP_GET_FLAG_NONE
Definition: smtp_stream.h:50