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