17
17
/* Where information is unavailable, the name and/or address
18
18
/* are set to "unknown".
20
/* This module uses the local name service via getaddrinfo()
21
/* and getnameinfo(). It does not query the DNS directly.
20
23
/* smtpd_peer_init() updates the following fields:
22
/* The client hostname. An unknown name is represented by the
25
/* The verified client hostname. This name is represented by
26
/* the string "unknown" when 1) the address->name lookup failed,
27
/* 2) the name->address mapping fails, or 3) the name->address
28
/* does not produce the client IP address.
30
/* The unverified client hostname as found with address->name
31
/* lookup; it is not verified for consistency with the client
32
/* IP address result from name->address lookup.
34
/* The unverified client hostname as found with address->name
35
/* lookup followed by name->address lookup; it is not verified
36
/* for consistency with the result from address->name lookup.
37
/* For example, when the address->name lookup produces as
38
/* hostname an alias, the name->address lookup will produce
39
/* as hostname the expansion of that alias, so that the two
40
/* lookups produce different names.
25
42
/* Printable representation of the client address.
27
44
/* String of the form: "name[addr]".
29
/* The peer_code result field specifies how the client name
46
/* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
47
/* in Received: message headers.
49
/* The name_status result field specifies how the name
30
50
/* information should be interpreted:
33
/* Both name lookup and name verification succeeded.
35
/* The name lookup or name verification failed with a recoverable
36
/* error (no address->name mapping or no name->address mapping).
38
/* The name lookup or verification failed with an unrecoverable
39
/* error (no address->name mapping, bad hostname syntax, no
40
/* name->address mapping, client address not listed for hostname).
53
/* The address->name lookup and name->address lookup produced
54
/* the client IP address.
56
/* The address->name lookup or name->address lookup failed
57
/* with a recoverable error.
59
/* The address->name lookup or name->address lookup failed
60
/* with an unrecoverable error, or the result did not match
61
/* the client IP address.
63
/* .IP reverse_name_status
64
/* The reverse_name_status result field specifies how the
65
/* reverse_name information should be interpreted:
67
/* The address->name lookup succeeded.
69
/* The address->name lookup failed with a recoverable error.
71
/* The address->name lookup failed with an unrecoverable error.
72
/* .RE .IP forward_name_status
73
/* The forward_name_status result field specifies how the
74
/* forward_name information should be interpreted:
76
/* The address->name and name->address lookup succeeded.
78
/* The address->name lookup or name->address failed with a
81
/* The address->name lookup or name->address failed with an
82
/* unrecoverable error.
43
85
/* smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
86
129
void smtpd_peer_init(SMTPD_STATE *state)
88
char *myname = "smtpd_peer_init";
131
const char *myname = "smtpd_peer_init";
132
SOCKADDR_SIZE sa_length;
90
133
struct sockaddr *sa;
91
134
INET_PROTO_INFO *proto_info = inet_proto_info();
93
136
sa = (struct sockaddr *) & (state->sockaddr);
94
sa_len = sizeof(state->sockaddr);
137
sa_length = sizeof(state->sockaddr);
97
140
* Look up the peer address information.
142
* XXX If we make local endpoint (getsockname) information available to
143
* Milter applications as {if_name} and {if_addr}, then we also must be
144
* able to provide this via the XCLIENT command for Milter testing.
146
* XXX If support were to be added for Milter applications in down-stream
147
* MTAs, then consistency demands that we propagate a lot of Sendmail
148
* macro information via the XFORWARD command. Otherwise we could end up
149
* with a very confusing situation.
99
if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) {
151
if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) {
106
158
if (errno == ECONNRESET || errno == ECONNABORTED) {
107
159
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
160
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
108
161
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
109
162
state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
110
state->peer_code = SMTPD_PEER_CODE_PERM;
163
state->addr_family = AF_UNSPEC;
164
state->name_status = SMTPD_PEER_CODE_PERM;
165
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
179
* Sorry, but there are some things that we just cannot do while
180
* connected to the network.
182
if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
183
msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
184
(unsigned long) getuid(), (unsigned long) geteuid());
185
msg_fatal("the Postfix SMTP server must run with $%s privileges",
124
190
* Convert the client address to printable form.
126
if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr,
192
if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
127
193
(MAI_SERVPORT_STR *) 0, 0)) != 0)
128
194
msg_fatal("%s: cannot convert client address to string: %s",
129
195
myname, MAI_STRERROR(aierr));
148
214
state->addr = mystrdup(colonp + 1);
149
215
state->rfc_addr = mystrdup(colonp + 1);
216
state->addr_family = AF_INET;
150
217
aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
152
219
msg_fatal("%s: cannot convert %s from string to binary: %s",
153
220
myname, state->addr, MAI_STRERROR(aierr));
154
sa_len = res0->ai_addrlen;
155
memcpy((char *) sa, res0->ai_addr, sa_len);
221
sa_length = res0->ai_addrlen;
222
if (sa_length > sizeof(state->sockaddr))
223
sa_length = sizeof(state->sockaddr);
224
memcpy((char *) sa, res0->ai_addr, sa_length);
156
225
freeaddrinfo(res0); /* 200412 */
196
267
#define REJECT_PEER_NAME(state, code) { \
197
268
myfree(state->name); \
198
269
state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
199
state->peer_code = code; \
270
state->name_status = code; \
202
if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
203
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
204
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
205
state->peer_code = (TEMP_AI_ERROR(aierr) ?
206
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
273
if (var_smtpd_peername_lookup == 0) {
274
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
275
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
276
state->name_status = SMTPD_PEER_CODE_PERM;
277
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
278
} else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name,
279
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
280
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
281
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
282
state->name_status = (TEMP_AI_ERROR(aierr) ?
283
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
284
state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
285
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
208
287
struct addrinfo *res0;
209
288
struct addrinfo *res;
211
290
state->name = mystrdup(client_name.buf);
212
state->peer_code = SMTPD_PEER_CODE_OK;
291
state->reverse_name = mystrdup(client_name.buf);
292
state->name_status = SMTPD_PEER_CODE_OK;
293
state->reverse_name_status = SMTPD_PEER_CODE_OK;
215
296
* Reject the hostname if it does not list the peer address.
297
* Without further validation or qualification, such information
298
* must not be allowed to enter the audit trail, as people would
299
* draw false conclusions.
217
301
aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
219
303
msg_warn("%s: hostname %s verification failed: %s",
220
304
state->addr, state->name, MAI_STRERROR(aierr));
221
305
REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
222
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
306
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED));
224
308
for (res = res0; /* void */ ; res = res->ai_next) {
226
310
msg_warn("%s: address not listed for hostname %s",
227
311
state->addr, state->name);
228
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
312
REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED);
231
315
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {