summaryrefslogtreecommitdiffstats
path: root/src/smtpd/smtpd_haproxy.c
blob: 542c3fe3d5e3e724bc46e32df3d68444c66d1e2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*++
/* NAME
/*	smtpd_haproxy 3
/* SUMMARY
/*	Postfix SMTP server haproxy adapter
/* SYNOPSIS
/*	#include "smtpd.h"
/*
/*	int	smtpd_peer_from_haproxy(state)
/*	SMTPD_STATE *state;
/* DESCRIPTION
/*	smtpd_peer_from_haproxy() receives endpoint address and
/*	port information via the haproxy protocol.
/*
/*	The following summarizes what the Postfix SMTP server expects
/*	from an up-stream proxy adapter.
/* .IP \(bu
/*	Call smtpd_peer_from_default() if the up-stream proxy
/*	indicates that the connection is not proxied. In that case,
/*	a proxy adapter MUST NOT update any STATE fields: the
/*	smtpd_peer_from_default() function will do that instead.
/* .IP \(bu
/*	Validate protocol, address and port syntax. Permit only
/*	protocols that are configured with the main.cf:inet_protocols
/*	setting.
/* .IP \(bu
/*	Convert IPv4-in-IPv6 address syntax to IPv4 syntax when
/*	both IPv6 and IPv4 support are enabled with main.cf:inet_protocols.
/* .IP \(bu
/*	Update the following session context fields: addr, port,
/*	rfc_addr, addr_family, dest_addr, dest_port. The addr_family
/*	field applies to the client address.
/* .IP \(bu
/*	Dynamically allocate storage for string information with
/*	mystrdup(). In case of error, leave unassigned string fields
/*	at their initial zero value.
/* .IP \(bu
/*	Log a clear warning message that explains why a request
/*	fails.
/* .IP \(bu
/*	Never talk to the remote SMTP client.
/* .PP
/*	Arguments:
/* .IP state
/*	Session context.
/* DIAGNOSTICS
/*	Warnings: I/O errors, malformed haproxy line.
/*
/*	The result value is 0 in case of success, -1 in case of
/*	error.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*
/*	Wietse Venema
/*	Google, Inc.
/*	111 8th Avenue
/*	New York, NY 10011, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <sys/socket.h>

/* Utility library. */

#include <msg.h>
#include <myaddrinfo.h>
#include <mymalloc.h>
#include <stringops.h>
#include <iostuff.h>

/* Global library. */

#include <smtp_stream.h>
#include <mail_params.h>
#include <valid_mailhost_addr.h>
#include <haproxy_srvr.h>

/* Application-specific. */

#include <smtpd.h>

/* SLMs. */

#define STR(x)	vstring_str(x)
#define LEN(x)	VSTRING_LEN(x)

/* smtpd_peer_from_haproxy - initialize peer information from haproxy */

int     smtpd_peer_from_haproxy(SMTPD_STATE *state)
{
    MAI_HOSTADDR_STR smtp_client_addr;
    MAI_SERVPORT_STR smtp_client_port;
    MAI_HOSTADDR_STR smtp_server_addr;
    MAI_SERVPORT_STR smtp_server_port;
    int     non_proxy = 0;

    if (read_wait(vstream_fileno(state->client), var_smtpd_uproxy_tmout) < 0) {
	msg_warn("haproxy read: timeout error");
	return (-1);
    }
    if (haproxy_srvr_receive(vstream_fileno(state->client), &non_proxy,
			     &smtp_client_addr, &smtp_client_port,
			     &smtp_server_addr, &smtp_server_port) < 0) {
	return (-1);
    }
    if (non_proxy) {
	smtpd_peer_from_default(state);
	return (0);
    }
    state->addr = mystrdup(smtp_client_addr.buf);
    if (strrchr(state->addr, ':') != 0) {
	state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0);
	state->addr_family = AF_INET6;
    } else {
	state->rfc_addr = mystrdup(state->addr);
	state->addr_family = AF_INET;
    }
    state->port = mystrdup(smtp_client_port.buf);

    /*
     * The Dovecot authentication server needs the server IP address.
     */
    state->dest_addr = mystrdup(smtp_server_addr.buf);
    state->dest_port = mystrdup(smtp_server_port.buf);
    return (0);
}