5
/* look up peer name/address information
9
/* void qmqpd_peer_init(state)
10
/* QMQPD_STATE *state;
12
/* void qmqpd_peer_reset(state)
13
/* QMQPD_STATE *state;
15
/* The qmqpd_peer_init() routine attempts to produce a printable
16
/* version of the peer name and address of the specified socket.
17
/* Where information is unavailable, the name and/or address
18
/* are set to "unknown".
20
/* qmqpd_peer_init() updates the following fields:
22
/* The client hostname. An unknown name is represented by the
25
/* Printable representation of the client address.
27
/* String of the form: "name[addr]".
29
/* qmqpd_peer_reset() releases memory allocate by qmqpd_peer_init().
33
/* The Secure Mailer license must be distributed with this software.
36
/* IBM T.J. Watson Research
38
/* Yorktown Heights, NY 10598, USA
44
#include <sys/socket.h>
45
#include <netinet/in.h>
46
#include <arpa/inet.h>
47
#include <stdio.h> /* strerror() */
53
* Older systems don't have h_errno. Even modern systems don't have
58
static int h_errno = TRY_AGAIN;
60
#define HSTRERROR(err) "Host not found"
64
#define HSTRERROR(err) (\
65
err == TRY_AGAIN ? "Host not found, try again" : \
66
err == HOST_NOT_FOUND ? "Host not found" : \
67
err == NO_DATA ? "Host name has no address" : \
68
err == NO_RECOVERY ? "Name server failure" : \
73
/* Utility library. */
77
#include <valid_hostname.h>
78
#include <stringops.h>
83
/* Application-specific. */
87
/* qmqpd_peer_init - initialize peer information */
89
void qmqpd_peer_init(QMQPD_STATE *state)
91
struct sockaddr_in sin;
92
SOCKADDR_SIZE len = sizeof(sin);
97
* Look up the peer address information.
99
if (getpeername(vstream_fileno(state->client),
100
(struct sockaddr *) & sin, &len) >= 0) {
105
* If peer went away, give up.
107
if (errno == ECONNRESET || errno == ECONNABORTED) {
108
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
109
state->addr = mystrdup(CLIENT_ATTR_UNKNOWN);
113
* Look up and "verify" the client hostname.
115
else if (errno == 0 && sin.sin_family == AF_INET) {
116
state->addr = mystrdup(inet_ntoa(sin.sin_addr));
117
hp = gethostbyaddr((char *) &(sin.sin_addr),
118
sizeof(sin.sin_addr), AF_INET);
120
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
121
} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
122
state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
124
state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
127
* Reject the hostname if it does not list the peer address.
129
#define REJECT_PEER_NAME(state) { \
130
myfree(state->name); \
131
state->name = mystrdup(CLIENT_ATTR_UNKNOWN); \
134
hp = gethostbyname(state->name); /* clobbers hp->name!! */
136
msg_warn("%s: hostname %s verification failed: %s",
137
state->addr, state->name, HSTRERROR(h_errno));
138
REJECT_PEER_NAME(state);
139
} else if (hp->h_length != sizeof(sin.sin_addr)) {
140
msg_warn("%s: hostname %s verification failed: bad address size %d",
141
state->addr, state->name, hp->h_length);
142
REJECT_PEER_NAME(state);
144
for (i = 0; /* void */ ; i++) {
145
if (hp->h_addr_list[i] == 0) {
146
msg_warn("%s: address not listed for hostname %s",
147
state->addr, state->name);
148
REJECT_PEER_NAME(state);
151
if (memcmp(hp->h_addr_list[i],
152
(char *) &sin.sin_addr,
153
sizeof(sin.sin_addr)) == 0)
154
break; /* keep peer name */
161
* If it's not Internet, assume the client is local, and avoid using the
162
* naming service because that can hang when the machine is disconnected.
165
state->name = mystrdup("localhost");
166
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
170
* Do the name[addr] formatting for pretty reports.
173
concatenate(state->name, "[", state->addr, "]", (char *) 0);
176
/* qmqpd_peer_reset - destroy peer information */
178
void qmqpd_peer_reset(QMQPD_STATE *state)
182
myfree(state->namaddr);