xref: /openbsd-src/usr.bin/ssh/canohost.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Functions for returning the canonical host name of the remote site.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13 
14 #include "includes.h"
15 RCSID("$OpenBSD: canohost.c,v 1.37 2003/06/02 09:17:34 markus Exp $");
16 
17 #include "packet.h"
18 #include "xmalloc.h"
19 #include "log.h"
20 #include "canohost.h"
21 
22 static void check_ip_options(int, char *);
23 
24 /*
25  * Return the canonical name of the host at the other end of the socket. The
26  * caller should free the returned string with xfree.
27  */
28 
29 static char *
30 get_remote_hostname(int socket, int use_dns)
31 {
32 	struct sockaddr_storage from;
33 	int i;
34 	socklen_t fromlen;
35 	struct addrinfo hints, *ai, *aitop;
36 	char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
37 
38 	/* Get IP address of client. */
39 	fromlen = sizeof(from);
40 	memset(&from, 0, sizeof(from));
41 	if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) {
42 		debug("getpeername failed: %.100s", strerror(errno));
43 		fatal_cleanup();
44 	}
45 
46 	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
47 	    NULL, 0, NI_NUMERICHOST) != 0)
48 		fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
49 
50 	if (!use_dns)
51 		return xstrdup(ntop);
52 
53 	if (from.ss_family == AF_INET)
54 		check_ip_options(socket, ntop);
55 
56 	debug3("Trying to reverse map address %.100s.", ntop);
57 	/* Map the IP address to a host name. */
58 	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
59 	    NULL, 0, NI_NAMEREQD) != 0) {
60 		/* Host name not found.  Use ip address. */
61 		return xstrdup(ntop);
62 	}
63 
64 	/*
65 	 * if reverse lookup result looks like a numeric hostname,
66 	 * someone is trying to trick us by PTR record like following:
67 	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5
68 	 */
69 	memset(&hints, 0, sizeof(hints));
70 	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
71 	hints.ai_flags = AI_NUMERICHOST;
72 	if (getaddrinfo(name, "0", &hints, &ai) == 0) {
73 		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
74 		    name, ntop);
75 		freeaddrinfo(ai);
76 		return xstrdup(ntop);
77 	}
78 
79 	/*
80 	 * Convert it to all lowercase (which is expected by the rest
81 	 * of this software).
82 	 */
83 	for (i = 0; name[i]; i++)
84 		if (isupper(name[i]))
85 			name[i] = tolower(name[i]);
86 	/*
87 	 * Map it back to an IP address and check that the given
88 	 * address actually is an address of this host.  This is
89 	 * necessary because anyone with access to a name server can
90 	 * define arbitrary names for an IP address. Mapping from
91 	 * name to IP address can be trusted better (but can still be
92 	 * fooled if the intruder has access to the name server of
93 	 * the domain).
94 	 */
95 	memset(&hints, 0, sizeof(hints));
96 	hints.ai_family = from.ss_family;
97 	hints.ai_socktype = SOCK_STREAM;
98 	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
99 		logit("reverse mapping checking getaddrinfo for %.700s "
100 		    "failed - POSSIBLE BREAKIN ATTEMPT!", name);
101 		return xstrdup(ntop);
102 	}
103 	/* Look for the address from the list of addresses. */
104 	for (ai = aitop; ai; ai = ai->ai_next) {
105 		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
106 		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
107 		    (strcmp(ntop, ntop2) == 0))
108 				break;
109 	}
110 	freeaddrinfo(aitop);
111 	/* If we reached the end of the list, the address was not there. */
112 	if (!ai) {
113 		/* Address not found for the host name. */
114 		logit("Address %.100s maps to %.600s, but this does not "
115 		    "map back to the address - POSSIBLE BREAKIN ATTEMPT!",
116 		    ntop, name);
117 		return xstrdup(ntop);
118 	}
119 	return xstrdup(name);
120 }
121 
122 /*
123  * If IP options are supported, make sure there are none (log and
124  * disconnect them if any are found).  Basically we are worried about
125  * source routing; it can be used to pretend you are somebody
126  * (ip-address) you are not. That itself may be "almost acceptable"
127  * under certain circumstances, but rhosts autentication is useless
128  * if source routing is accepted. Notice also that if we just dropped
129  * source routing here, the other side could use IP spoofing to do
130  * rest of the interaction and could still bypass security.  So we
131  * exit here if we detect any IP options.
132  */
133 /* IPv4 only */
134 static void
135 check_ip_options(int socket, char *ipaddr)
136 {
137 	u_char options[200];
138 	char text[sizeof(options) * 3 + 1];
139 	socklen_t option_size;
140 	int i, ipproto;
141 	struct protoent *ip;
142 
143 	if ((ip = getprotobyname("ip")) != NULL)
144 		ipproto = ip->p_proto;
145 	else
146 		ipproto = IPPROTO_IP;
147 	option_size = sizeof(options);
148 	if (getsockopt(socket, ipproto, IP_OPTIONS, options,
149 	    &option_size) >= 0 && option_size != 0) {
150 		text[0] = '\0';
151 		for (i = 0; i < option_size; i++)
152 			snprintf(text + i*3, sizeof(text) - i*3,
153 			    " %2.2x", options[i]);
154 		logit("Connection from %.100s with IP options:%.800s",
155 		    ipaddr, text);
156 		packet_disconnect("Connection from %.100s with IP options:%.800s",
157 		    ipaddr, text);
158 	}
159 }
160 
161 /*
162  * Return the canonical name of the host in the other side of the current
163  * connection.  The host name is cached, so it is efficient to call this
164  * several times.
165  */
166 
167 const char *
168 get_canonical_hostname(int use_dns)
169 {
170 	static char *canonical_host_name = NULL;
171 	static int use_dns_done = 0;
172 
173 	/* Check if we have previously retrieved name with same option. */
174 	if (canonical_host_name != NULL) {
175 		if (use_dns_done != use_dns)
176 			xfree(canonical_host_name);
177 		else
178 			return canonical_host_name;
179 	}
180 
181 	/* Get the real hostname if socket; otherwise return UNKNOWN. */
182 	if (packet_connection_is_on_socket())
183 		canonical_host_name = get_remote_hostname(
184 		    packet_get_connection_in(), use_dns);
185 	else
186 		canonical_host_name = xstrdup("UNKNOWN");
187 
188 	use_dns_done = use_dns;
189 	return canonical_host_name;
190 }
191 
192 /*
193  * Returns the local/remote IP-address/hostname of socket as a string.
194  * The returned string must be freed.
195  */
196 static char *
197 get_socket_address(int socket, int remote, int flags)
198 {
199 	struct sockaddr_storage addr;
200 	socklen_t addrlen;
201 	char ntop[NI_MAXHOST];
202 
203 	/* Get IP address of client. */
204 	addrlen = sizeof(addr);
205 	memset(&addr, 0, sizeof(addr));
206 
207 	if (remote) {
208 		if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
209 		    < 0)
210 			return NULL;
211 	} else {
212 		if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
213 		    < 0)
214 			return NULL;
215 	}
216 	/* Get the address in ascii. */
217 	if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop),
218 	    NULL, 0, flags) != 0) {
219 		error("get_socket_address: getnameinfo %d failed", flags);
220 		return NULL;
221 	}
222 	return xstrdup(ntop);
223 }
224 
225 char *
226 get_peer_ipaddr(int socket)
227 {
228 	char *p;
229 
230 	if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL)
231 		return p;
232 	return xstrdup("UNKNOWN");
233 }
234 
235 char *
236 get_local_ipaddr(int socket)
237 {
238 	char *p;
239 
240 	if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL)
241 		return p;
242 	return xstrdup("UNKNOWN");
243 }
244 
245 char *
246 get_local_name(int socket)
247 {
248 	return get_socket_address(socket, 0, NI_NAMEREQD);
249 }
250 
251 /*
252  * Returns the IP-address of the remote host as a string.  The returned
253  * string must not be freed.
254  */
255 
256 const char *
257 get_remote_ipaddr(void)
258 {
259 	static char *canonical_host_ip = NULL;
260 
261 	/* Check whether we have cached the ipaddr. */
262 	if (canonical_host_ip == NULL) {
263 		if (packet_connection_is_on_socket()) {
264 			canonical_host_ip =
265 			    get_peer_ipaddr(packet_get_connection_in());
266 			if (canonical_host_ip == NULL)
267 				fatal_cleanup();
268 		} else {
269 			/* If not on socket, return UNKNOWN. */
270 			canonical_host_ip = xstrdup("UNKNOWN");
271 		}
272 	}
273 	return canonical_host_ip;
274 }
275 
276 const char *
277 get_remote_name_or_ip(u_int utmp_len, int use_dns)
278 {
279 	static const char *remote = "";
280 	if (utmp_len > 0)
281 		remote = get_canonical_hostname(use_dns);
282 	if (utmp_len == 0 || strlen(remote) > utmp_len)
283 		remote = get_remote_ipaddr();
284 	return remote;
285 }
286 
287 /* Returns the local/remote port for the socket. */
288 
289 static int
290 get_sock_port(int sock, int local)
291 {
292 	struct sockaddr_storage from;
293 	socklen_t fromlen;
294 	char strport[NI_MAXSERV];
295 
296 	/* Get IP address of client. */
297 	fromlen = sizeof(from);
298 	memset(&from, 0, sizeof(from));
299 	if (local) {
300 		if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
301 			error("getsockname failed: %.100s", strerror(errno));
302 			return 0;
303 		}
304 	} else {
305 		if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
306 			debug("getpeername failed: %.100s", strerror(errno));
307 			fatal_cleanup();
308 		}
309 	}
310 	/* Return port number. */
311 	if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
312 	    strport, sizeof(strport), NI_NUMERICSERV) != 0)
313 		fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
314 	return atoi(strport);
315 }
316 
317 /* Returns remote/local port number for the current connection. */
318 
319 static int
320 get_port(int local)
321 {
322 	/*
323 	 * If the connection is not a socket, return 65535.  This is
324 	 * intentionally chosen to be an unprivileged port number.
325 	 */
326 	if (!packet_connection_is_on_socket())
327 		return 65535;
328 
329 	/* Get socket and return the port number. */
330 	return get_sock_port(packet_get_connection_in(), local);
331 }
332 
333 int
334 get_peer_port(int sock)
335 {
336 	return get_sock_port(sock, 0);
337 }
338 
339 int
340 get_remote_port(void)
341 {
342 	return get_port(0);
343 }
344 
345 int
346 get_local_port(void)
347 {
348 	return get_port(1);
349 }
350