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