Annotation of src/usr.bin/ssh/canohost.c, Revision 1.15
1.1 deraadt 1: /*
1.7 deraadt 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.
1.12 markus 6: *
1.14 deraadt 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".
1.7 deraadt 12: */
1.1 deraadt 13:
14: #include "includes.h"
1.15 ! markus 15: RCSID("$OpenBSD: canohost.c,v 1.14 2000/09/07 20:27:50 deraadt Exp $");
1.1 deraadt 16:
17: #include "packet.h"
18: #include "xmalloc.h"
19: #include "ssh.h"
20:
1.8 markus 21: /*
22: * Return the canonical name of the host at the other end of the socket. The
23: * caller should free the returned string with xfree.
24: */
1.1 deraadt 25:
1.6 markus 26: char *
27: get_remote_hostname(int socket)
1.1 deraadt 28: {
1.10 markus 29: struct sockaddr_storage from;
30: int i;
31: socklen_t fromlen;
32: struct addrinfo hints, *ai, *aitop;
1.6 markus 33: char name[MAXHOSTNAMELEN];
1.10 markus 34: char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
1.6 markus 35:
36: /* Get IP address of client. */
37: fromlen = sizeof(from);
38: memset(&from, 0, sizeof(from));
39: if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
40: debug("getpeername failed: %.100s", strerror(errno));
41: fatal_cleanup();
42: }
1.10 markus 43: if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
44: NULL, 0, NI_NUMERICHOST) != 0)
45: fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
46:
1.6 markus 47: /* Map the IP address to a host name. */
1.10 markus 48: if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
49: NULL, 0, NI_NAMEREQD) == 0) {
50: /* Got host name. */
51: name[sizeof(name) - 1] = '\0';
1.8 markus 52: /*
53: * Convert it to all lowercase (which is expected by the rest
54: * of this software).
55: */
1.6 markus 56: for (i = 0; name[i]; i++)
57: if (isupper(name[i]))
58: name[i] = tolower(name[i]);
59:
1.8 markus 60: /*
61: * Map it back to an IP address and check that the given
62: * address actually is an address of this host. This is
63: * necessary because anyone with access to a name server can
64: * define arbitrary names for an IP address. Mapping from
65: * name to IP address can be trusted better (but can still be
66: * fooled if the intruder has access to the name server of
67: * the domain).
68: */
1.10 markus 69: memset(&hints, 0, sizeof(hints));
70: hints.ai_family = from.ss_family;
1.11 markus 71: hints.ai_socktype = SOCK_STREAM;
1.10 markus 72: if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
73: log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
74: strlcpy(name, ntop, sizeof name);
1.6 markus 75: goto check_ip_options;
76: }
77: /* Look for the address from the list of addresses. */
1.10 markus 78: for (ai = aitop; ai; ai = ai->ai_next) {
79: if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
80: sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
81: (strcmp(ntop, ntop2) == 0))
82: break;
83: }
84: freeaddrinfo(aitop);
85: /* If we reached the end of the list, the address was not there. */
86: if (!ai) {
1.6 markus 87: /* Address not found for the host name. */
88: log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
1.10 markus 89: ntop, name);
90: strlcpy(name, ntop, sizeof name);
1.6 markus 91: goto check_ip_options;
92: }
93: /* Address was found for the host name. We accept the host name. */
94: } else {
95: /* Host name not found. Use ascii representation of the address. */
1.10 markus 96: strlcpy(name, ntop, sizeof name);
1.6 markus 97: log("Could not reverse map address %.100s.", name);
98: }
99:
100: check_ip_options:
101:
1.8 markus 102: /*
103: * If IP options are supported, make sure there are none (log and
104: * disconnect them if any are found). Basically we are worried about
105: * source routing; it can be used to pretend you are somebody
106: * (ip-address) you are not. That itself may be "almost acceptable"
107: * under certain circumstances, but rhosts autentication is useless
108: * if source routing is accepted. Notice also that if we just dropped
109: * source routing here, the other side could use IP spoofing to do
110: * rest of the interaction and could still bypass security. So we
111: * exit here if we detect any IP options.
112: */
1.10 markus 113: /* IP options -- IPv4 only */
114: if (from.ss_family == AF_INET) {
1.6 markus 115: unsigned char options[200], *ucp;
116: char text[1024], *cp;
1.10 markus 117: socklen_t option_size;
118: int ipproto;
1.6 markus 119: struct protoent *ip;
120:
121: if ((ip = getprotobyname("ip")) != NULL)
122: ipproto = ip->p_proto;
123: else
124: ipproto = IPPROTO_IP;
125: option_size = sizeof(options);
126: if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
1.10 markus 127: &option_size) >= 0 && option_size != 0) {
1.6 markus 128: cp = text;
129: /* Note: "text" buffer must be at least 3x as big as options. */
130: for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
131: sprintf(cp, " %2.2x", *ucp);
132: log("Connection from %.100s with IP options:%.800s",
1.10 markus 133: ntop, text);
1.6 markus 134: packet_disconnect("Connection from %.100s with IP options:%.800s",
1.10 markus 135: ntop, text);
1.6 markus 136: }
137: }
1.1 deraadt 138:
1.6 markus 139: return xstrdup(name);
1.1 deraadt 140: }
141:
1.8 markus 142: /*
143: * Return the canonical name of the host in the other side of the current
144: * connection. The host name is cached, so it is efficient to call this
145: * several times.
146: */
1.1 deraadt 147:
1.6 markus 148: const char *
149: get_canonical_hostname()
1.1 deraadt 150: {
1.10 markus 151: static char *canonical_host_name = NULL;
152:
1.6 markus 153: /* Check if we have previously retrieved this same name. */
154: if (canonical_host_name != NULL)
155: return canonical_host_name;
156:
157: /* Get the real hostname if socket; otherwise return UNKNOWN. */
1.10 markus 158: if (packet_connection_is_on_socket())
1.6 markus 159: canonical_host_name = get_remote_hostname(packet_get_connection_in());
160: else
161: canonical_host_name = xstrdup("UNKNOWN");
1.1 deraadt 162:
1.6 markus 163: return canonical_host_name;
1.1 deraadt 164: }
165:
1.8 markus 166: /*
167: * Returns the IP-address of the remote host as a string. The returned
1.10 markus 168: * string must not be freed.
1.8 markus 169: */
1.1 deraadt 170:
1.6 markus 171: const char *
172: get_remote_ipaddr()
1.1 deraadt 173: {
1.10 markus 174: static char *canonical_host_ip = NULL;
175: struct sockaddr_storage from;
176: socklen_t fromlen;
177: int socket;
178: char ntop[NI_MAXHOST];
1.1 deraadt 179:
1.8 markus 180: /* Check whether we have chached the name. */
1.6 markus 181: if (canonical_host_ip != NULL)
182: return canonical_host_ip;
183:
184: /* If not a socket, return UNKNOWN. */
1.10 markus 185: if (!packet_connection_is_on_socket()) {
1.6 markus 186: canonical_host_ip = xstrdup("UNKNOWN");
187: return canonical_host_ip;
188: }
189: /* Get client socket. */
190: socket = packet_get_connection_in();
1.1 deraadt 191:
1.6 markus 192: /* Get IP address of client. */
193: fromlen = sizeof(from);
194: memset(&from, 0, sizeof(from));
195: if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
196: debug("getpeername failed: %.100s", strerror(errno));
197: fatal_cleanup();
198: }
199: /* Get the IP address in ascii. */
1.10 markus 200: if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
201: NULL, 0, NI_NUMERICHOST) != 0)
202: fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
203:
204: canonical_host_ip = xstrdup(ntop);
1.1 deraadt 205:
1.6 markus 206: /* Return ip address string. */
207: return canonical_host_ip;
1.1 deraadt 208: }
209:
1.10 markus 210: /* Returns the local/remote port for the socket. */
1.1 deraadt 211:
1.10 markus 212: int
213: get_sock_port(int sock, int local)
1.1 deraadt 214: {
1.10 markus 215: struct sockaddr_storage from;
216: socklen_t fromlen;
217: char strport[NI_MAXSERV];
1.1 deraadt 218:
1.6 markus 219: /* Get IP address of client. */
220: fromlen = sizeof(from);
221: memset(&from, 0, sizeof(from));
1.10 markus 222: if (local) {
223: if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
224: error("getsockname failed: %.100s", strerror(errno));
225: return 0;
226: }
227: } else {
228: if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
229: debug("getpeername failed: %.100s", strerror(errno));
230: fatal_cleanup();
231: }
1.6 markus 232: }
233: /* Return port number. */
1.10 markus 234: if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
235: strport, sizeof(strport), NI_NUMERICSERV) != 0)
236: fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
237: return atoi(strport);
1.1 deraadt 238: }
239:
1.10 markus 240: /* Returns remote/local port number for the current connection. */
1.1 deraadt 241:
1.12 markus 242: int
1.10 markus 243: get_port(int local)
1.1 deraadt 244: {
1.8 markus 245: /*
246: * If the connection is not a socket, return 65535. This is
247: * intentionally chosen to be an unprivileged port number.
248: */
1.10 markus 249: if (!packet_connection_is_on_socket())
1.6 markus 250: return 65535;
1.1 deraadt 251:
1.10 markus 252: /* Get socket and return the port number. */
253: return get_sock_port(packet_get_connection_in(), local);
254: }
255:
1.12 markus 256: int
1.10 markus 257: get_peer_port(int sock)
258: {
259: return get_sock_port(sock, 0);
260: }
261:
1.12 markus 262: int
1.10 markus 263: get_remote_port()
264: {
265: return get_port(0);
266: }
1.1 deraadt 267:
1.10 markus 268: int
269: get_local_port()
270: {
271: return get_port(1);
1.1 deraadt 272: }