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 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