Deleted Added
full compact
socket.c (44744) socket.c (56977)
1 /*
2 * This module determines the type of socket (datagram, stream), the client
3 * socket address and port, the server socket address and port. In addition,
4 * it provides methods to map a transport address to a printable host name
5 * or address. Socket address information results are in static memory.
6 *
7 * The result from the hostname lookup method is STRING_PARANOID when a host
8 * pretends to have someone elses name, or when a host name is available but
9 * could not be verified.
10 *
11 * When lookup or conversion fails the result is set to STRING_UNKNOWN.
12 *
13 * Diagnostics are reported through syslog(3).
14 *
15 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
1 /*
2 * This module determines the type of socket (datagram, stream), the client
3 * socket address and port, the server socket address and port. In addition,
4 * it provides methods to map a transport address to a printable host name
5 * or address. Socket address information results are in static memory.
6 *
7 * The result from the hostname lookup method is STRING_PARANOID when a host
8 * pretends to have someone elses name, or when a host name is available but
9 * could not be verified.
10 *
11 * When lookup or conversion fails the result is set to STRING_UNKNOWN.
12 *
13 * Diagnostics are reported through syslog(3).
14 *
15 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
16 *
17 * $FreeBSD: head/contrib/tcp_wrappers/socket.c 56977 2000-02-03 10:27:03Z shin $
16 */
17
18#ifndef lint
19static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
20#endif
21
22/* System libraries. */
23
24#include <sys/types.h>
25#include <sys/param.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <netdb.h>
29#include <stdio.h>
30#include <syslog.h>
31#include <string.h>
32
18 */
19
20#ifndef lint
21static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
22#endif
23
24/* System libraries. */
25
26#include <sys/types.h>
27#include <sys/param.h>
28#include <sys/socket.h>
29#include <netinet/in.h>
30#include <netdb.h>
31#include <stdio.h>
32#include <syslog.h>
33#include <string.h>
34
35#ifdef INET6
36#ifndef USE_GETIPNODEBY
37#include <resolv.h>
38#endif
39#endif
40
33extern char *inet_ntoa();
34
35/* Local stuff. */
36
37#include "tcpd.h"
38
39/* Forward declarations. */
40

--- 28 unchanged lines hidden (view full) ---

69#define gethostbyname gethostbyname_dot
70#endif
71
72/* sock_host - look up endpoint addresses and install conversion methods */
73
74void sock_host(request)
75struct request_info *request;
76{
41extern char *inet_ntoa();
42
43/* Local stuff. */
44
45#include "tcpd.h"
46
47/* Forward declarations. */
48

--- 28 unchanged lines hidden (view full) ---

77#define gethostbyname gethostbyname_dot
78#endif
79
80/* sock_host - look up endpoint addresses and install conversion methods */
81
82void sock_host(request)
83struct request_info *request;
84{
85#ifdef INET6
86 static struct sockaddr_storage client;
87 static struct sockaddr_storage server;
88#else
77 static struct sockaddr_in client;
78 static struct sockaddr_in server;
89 static struct sockaddr_in client;
90 static struct sockaddr_in server;
91#endif
79 int len;
80 char buf[BUFSIZ];
81 int fd = request->fd;
82
83 sock_methods(request);
84
85 /*
86 * Look up the client host address. Hal R. Brand <BRAND@addvax.llnl.gov>

--- 12 unchanged lines hidden (view full) ---

99 (struct sockaddr *) & client, &len) < 0) {
100 tcpd_warn("can't get client address: %m");
101 return; /* give up */
102 }
103#ifdef really_paranoid
104 memset(buf, 0 sizeof(buf));
105#endif
106 }
92 int len;
93 char buf[BUFSIZ];
94 int fd = request->fd;
95
96 sock_methods(request);
97
98 /*
99 * Look up the client host address. Hal R. Brand <BRAND@addvax.llnl.gov>

--- 12 unchanged lines hidden (view full) ---

112 (struct sockaddr *) & client, &len) < 0) {
113 tcpd_warn("can't get client address: %m");
114 return; /* give up */
115 }
116#ifdef really_paranoid
117 memset(buf, 0 sizeof(buf));
118#endif
119 }
120#ifdef INET6
121 request->client->sin = (struct sockaddr *)&client;
122#else
107 request->client->sin = &client;
123 request->client->sin = &client;
124#endif
108
109 /*
110 * Determine the server binding. This is used for client username
111 * lookups, and for access control rules that trigger on the server
112 * address or name.
113 */
114
115 len = sizeof(server);
116 if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
117 tcpd_warn("getsockname: %m");
118 return;
119 }
125
126 /*
127 * Determine the server binding. This is used for client username
128 * lookups, and for access control rules that trigger on the server
129 * address or name.
130 */
131
132 len = sizeof(server);
133 if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
134 tcpd_warn("getsockname: %m");
135 return;
136 }
137#ifdef INET6
138 request->server->sin = (struct sockaddr *)&server;
139#else
120 request->server->sin = &server;
140 request->server->sin = &server;
141#endif
121}
122
123/* sock_hostaddr - map endpoint address to printable form */
124
125void sock_hostaddr(host)
126struct host_info *host;
127{
142}
143
144/* sock_hostaddr - map endpoint address to printable form */
145
146void sock_hostaddr(host)
147struct host_info *host;
148{
149#ifdef INET6
150 struct sockaddr *sin = host->sin;
151 char *ap;
152 int alen;
153
154 if (!sin)
155 return;
156 switch (sin->sa_family) {
157 case AF_INET:
158 ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
159 alen = sizeof(struct in_addr);
160 break;
161 case AF_INET6:
162 ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
163 alen = sizeof(struct in6_addr);
164 break;
165 default:
166 return;
167 }
168 host->addr[0] = '\0';
169 inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
170#else
128 struct sockaddr_in *sin = host->sin;
129
130 if (sin != 0)
131 STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
171 struct sockaddr_in *sin = host->sin;
172
173 if (sin != 0)
174 STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
175#endif
132}
133
134/* sock_hostname - map endpoint address to host name */
135
136void sock_hostname(host)
137struct host_info *host;
138{
176}
177
178/* sock_hostname - map endpoint address to host name */
179
180void sock_hostname(host)
181struct host_info *host;
182{
183#ifdef INET6
184 struct sockaddr *sin = host->sin;
185 char addr[128];
186#ifdef USE_GETIPNODEBY
187 int h_error;
188#else
189 u_long res_options;
190#endif
191 struct hostent *hp = NULL;
192 char *ap;
193 int alen;
194#else
139 struct sockaddr_in *sin = host->sin;
140 struct hostent *hp;
195 struct sockaddr_in *sin = host->sin;
196 struct hostent *hp;
197#endif
141 int i;
142
143 /*
144 * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
145 * not fail. Instead it returns "INADDR_ANY". Unfortunately, this does
146 * not work the other way around: gethostbyname("INADDR_ANY") fails. We
147 * have to special-case 0.0.0.0, in order to avoid false alerts from the
148 * host name/address checking code below.
149 */
198 int i;
199
200 /*
201 * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
202 * not fail. Instead it returns "INADDR_ANY". Unfortunately, this does
203 * not work the other way around: gethostbyname("INADDR_ANY") fails. We
204 * have to special-case 0.0.0.0, in order to avoid false alerts from the
205 * host name/address checking code below.
206 */
207#ifdef INET6
208 if (sin != NULL) {
209 switch (sin->sa_family) {
210 case AF_INET:
211 if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0) {
212 strcpy(host->name, paranoid); /* name is bad, clobber it */
213 return;
214 }
215 ap = (char *) &((struct sockaddr_in *)sin)->sin_addr;
216 alen = sizeof(struct in_addr);
217 break;
218 case AF_INET6:
219 ap = (char *) &((struct sockaddr_in6 *)sin)->sin6_addr;
220 alen = sizeof(struct in6_addr);
221 break;
222 defalut:
223 strcpy(host->name, paranoid); /* name is bad, clobber it */
224 return;
225 }
226#ifdef USE_GETIPNODEBY
227 hp = getipnodebyaddr(ap, alen, sin->sa_family, &h_error);
228#else
229 hp = gethostbyaddr(ap, alen, sin->sa_family);
230#endif
231 }
232 if (hp) {
233#else
150 if (sin != 0 && sin->sin_addr.s_addr != 0
151 && (hp = gethostbyaddr((char *) &(sin->sin_addr),
152 sizeof(sin->sin_addr), AF_INET)) != 0) {
234 if (sin != 0 && sin->sin_addr.s_addr != 0
235 && (hp = gethostbyaddr((char *) &(sin->sin_addr),
236 sizeof(sin->sin_addr), AF_INET)) != 0) {
237#endif
153
154 STRN_CPY(host->name, hp->h_name, sizeof(host->name));
238
239 STRN_CPY(host->name, hp->h_name, sizeof(host->name));
240#if defined(INET6) && defined(USE_GETIPNODEBY)
241 freehostent(hp);
242#endif
155
156 /*
157 * Verify that the address is a member of the address list returned
158 * by gethostbyname(hostname).
159 *
160 * Verify also that gethostbyaddr() and gethostbyname() return the same
161 * hostname, or rshd and rlogind may still end up being spoofed.
162 *
163 * On some sites, gethostbyname("localhost") returns "localhost.domain".
164 * This is a DNS artefact. We treat it as a special case. When we
165 * can't believe the address list from gethostbyname("localhost")
166 * we're in big trouble anyway.
167 */
168
243
244 /*
245 * Verify that the address is a member of the address list returned
246 * by gethostbyname(hostname).
247 *
248 * Verify also that gethostbyaddr() and gethostbyname() return the same
249 * hostname, or rshd and rlogind may still end up being spoofed.
250 *
251 * On some sites, gethostbyname("localhost") returns "localhost.domain".
252 * This is a DNS artefact. We treat it as a special case. When we
253 * can't believe the address list from gethostbyname("localhost")
254 * we're in big trouble anyway.
255 */
256
257#ifdef INET6
258#ifdef USE_GETIPNODEBY
259 hp = getipnodebyname(host->name, sin->sa_family,
260 AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, &h_error);
261#else
262 if ((_res.options & RES_INIT) == 0) {
263 if (res_init() < 0) {
264 inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
265 tcpd_warn("can't verify hostname: res_init() for %s failed",
266 addr);
267 strcpy(host->name, paranoid); /* name is bad, clobber it */
268 return;
269 }
270 }
271 res_options = _res.options;
272 if (sin->sa_family == AF_INET6)
273 _res.options |= RES_USE_INET6;
274 else
275 _res.options &= ~RES_USE_INET6;
276 hp = gethostbyname2(host->name,
277 (sin->sa_family == AF_INET6 &&
278 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sin)->sin6_addr)) ?
279 AF_INET : sin->sa_family);
280 _res.options = res_options;
281#endif
282 if (!hp) {
283#else
169 if ((hp = gethostbyname(host->name)) == 0) {
284 if ((hp = gethostbyname(host->name)) == 0) {
285#endif
170
171 /*
172 * Unable to verify that the host name matches the address. This
173 * may be a transient problem or a botched name server setup.
174 */
175
286
287 /*
288 * Unable to verify that the host name matches the address. This
289 * may be a transient problem or a botched name server setup.
290 */
291
292#ifdef INET6
293#ifdef USE_GETIPNODEBY
294 tcpd_warn("can't verify hostname: getipnodebyname(%s, %s) failed",
295#else
296 tcpd_warn("can't verify hostname: gethostbyname2(%s, %s) failed",
297#endif
298 host->name,
299 (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
300#else
176 tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
177 host->name);
301 tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
302 host->name);
303#endif
178
179 } else if (STR_NE(host->name, hp->h_name)
180 && STR_NE(host->name, "localhost")) {
181
182 /*
183 * The gethostbyaddr() and gethostbyname() calls did not return
184 * the same hostname. This could be a nameserver configuration
185 * problem. It could also be that someone is trying to spoof us.

--- 7 unchanged lines hidden (view full) ---

193 /*
194 * The address should be a member of the address list returned by
195 * gethostbyname(). We should first verify that the h_addrtype
196 * field is AF_INET, but this program has already caused too much
197 * grief on systems with broken library code.
198 */
199
200 for (i = 0; hp->h_addr_list[i]; i++) {
304
305 } else if (STR_NE(host->name, hp->h_name)
306 && STR_NE(host->name, "localhost")) {
307
308 /*
309 * The gethostbyaddr() and gethostbyname() calls did not return
310 * the same hostname. This could be a nameserver configuration
311 * problem. It could also be that someone is trying to spoof us.

--- 7 unchanged lines hidden (view full) ---

319 /*
320 * The address should be a member of the address list returned by
321 * gethostbyname(). We should first verify that the h_addrtype
322 * field is AF_INET, but this program has already caused too much
323 * grief on systems with broken library code.
324 */
325
326 for (i = 0; hp->h_addr_list[i]; i++) {
327#ifdef INET6
328 if (memcmp(hp->h_addr_list[i], ap, alen) == 0) {
329#ifdef USE_GETIPNODEBY
330 freehostent(hp);
331#endif
332 return; /* name is good, keep it */
333 }
334#else
201 if (memcmp(hp->h_addr_list[i],
202 (char *) &sin->sin_addr,
203 sizeof(sin->sin_addr)) == 0)
204 return; /* name is good, keep it */
335 if (memcmp(hp->h_addr_list[i],
336 (char *) &sin->sin_addr,
337 sizeof(sin->sin_addr)) == 0)
338 return; /* name is good, keep it */
339#endif
205 }
206
207 /*
208 * The host name does not map to the initial address. Perhaps
209 * someone has messed up. Perhaps someone compromised a name
210 * server.
211 */
212
340 }
341
342 /*
343 * The host name does not map to the initial address. Perhaps
344 * someone has messed up. Perhaps someone compromised a name
345 * server.
346 */
347
348#ifdef INET6
349 inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
213 tcpd_warn("host name/address mismatch: %s != %.*s",
350 tcpd_warn("host name/address mismatch: %s != %.*s",
351 addr, STRING_LENGTH, hp->h_name);
352#else
353 tcpd_warn("host name/address mismatch: %s != %.*s",
214 inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
354 inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
355#endif
215 }
216 strcpy(host->name, paranoid); /* name is bad, clobber it */
356 }
357 strcpy(host->name, paranoid); /* name is bad, clobber it */
358#if defined(INET6) && defined(USE_GETIPNODEBY)
359 if (hp)
360 freehostent(hp);
361#endif
217 }
218}
219
220/* sock_sink - absorb unreceived IP datagram */
221
222static void sock_sink(fd)
223int fd;
224{
225 char buf[BUFSIZ];
362 }
363}
364
365/* sock_sink - absorb unreceived IP datagram */
366
367static void sock_sink(fd)
368int fd;
369{
370 char buf[BUFSIZ];
371#ifdef INET6
372 struct sockaddr_storage sin;
373#else
226 struct sockaddr_in sin;
374 struct sockaddr_in sin;
375#endif
227 int size = sizeof(sin);
228
229 /*
230 * Eat up the not-yet received datagram. Some systems insist on a
231 * non-zero source address argument in the recvfrom() call below.
232 */
233
234 (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size);
235}
376 int size = sizeof(sin);
377
378 /*
379 * Eat up the not-yet received datagram. Some systems insist on a
380 * non-zero source address argument in the recvfrom() call below.
381 */
382
383 (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size);
384}