djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 1 | /* $OpenBSD: canohost.c,v 1.73 2016/03/07 19:02:43 djm Exp $ */ |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 2 | /* |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
| 5 | * All rights reserved |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 6 | * Functions for returning the canonical host name of the remote site. |
Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 7 | * |
Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 8 | * As far as I am concerned, the code I have written for this software |
| 9 | * can be used freely for any purpose. Any derived versions of this |
| 10 | * software must be clearly marked as such, and if the derived work is |
| 11 | * incompatible with the protocol description in the RFC file, it must be |
| 12 | * called by a name other than "ssh" or "Secure Shell". |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 13 | */ |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 14 | |
| 15 | #include "includes.h" |
Damien Miller | c7b0636 | 2006-03-15 11:53:45 +1100 | [diff] [blame] | 16 | |
Damien Miller | e3b60b5 | 2006-07-10 21:08:03 +1000 | [diff] [blame] | 17 | #include <sys/types.h> |
Damien Miller | 8ec8c3e | 2006-07-10 20:35:38 +1000 | [diff] [blame] | 18 | #include <sys/socket.h> |
Damien Miller | 7acefbb | 2014-07-18 14:11:24 +1000 | [diff] [blame] | 19 | #include <sys/un.h> |
Damien Miller | 8ec8c3e | 2006-07-10 20:35:38 +1000 | [diff] [blame] | 20 | |
| 21 | #include <netinet/in.h> |
Darren Tucker | dace233 | 2006-09-22 19:22:17 +1000 | [diff] [blame] | 22 | #include <arpa/inet.h> |
Damien Miller | 8ec8c3e | 2006-07-10 20:35:38 +1000 | [diff] [blame] | 23 | |
Darren Tucker | 3997249 | 2006-07-12 22:22:46 +1000 | [diff] [blame] | 24 | #include <errno.h> |
Damien Miller | b8fe89c | 2006-07-24 14:51:00 +1000 | [diff] [blame] | 25 | #include <netdb.h> |
Damien Miller | a7a73ee | 2006-08-05 11:37:59 +1000 | [diff] [blame] | 26 | #include <stdio.h> |
Damien Miller | e7a1e5c | 2006-08-05 11:34:19 +1000 | [diff] [blame] | 27 | #include <stdlib.h> |
Damien Miller | e3476ed | 2006-07-24 14:13:33 +1000 | [diff] [blame] | 28 | #include <string.h> |
Damien Miller | d783435 | 2006-08-05 12:39:39 +1000 | [diff] [blame] | 29 | #include <stdarg.h> |
Darren Tucker | daaa450 | 2010-01-13 22:43:33 +1100 | [diff] [blame] | 30 | #include <unistd.h> |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 31 | |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 32 | #include "xmalloc.h" |
Damien Miller | d783435 | 2006-08-05 12:39:39 +1000 | [diff] [blame] | 33 | #include "packet.h" |
Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 34 | #include "log.h" |
Ben Lindstrom | 31ca54a | 2001-02-09 02:11:24 +0000 | [diff] [blame] | 35 | #include "canohost.h" |
Darren Tucker | 4abde77 | 2007-12-29 02:43:51 +1100 | [diff] [blame] | 36 | #include "misc.h" |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 37 | |
Darren Tucker | 2fba993 | 2005-02-02 23:30:24 +1100 | [diff] [blame] | 38 | void |
Damien Miller | 927f527 | 2003-11-24 12:57:25 +1100 | [diff] [blame] | 39 | ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) |
| 40 | { |
| 41 | struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr; |
| 42 | struct sockaddr_in *a4 = (struct sockaddr_in *)addr; |
| 43 | struct in_addr inaddr; |
| 44 | u_int16_t port; |
| 45 | |
Damien Miller | 94cf4c8 | 2005-07-17 17:04:47 +1000 | [diff] [blame] | 46 | if (addr->ss_family != AF_INET6 || |
Damien Miller | 927f527 | 2003-11-24 12:57:25 +1100 | [diff] [blame] | 47 | !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) |
| 48 | return; |
| 49 | |
| 50 | debug3("Normalising mapped IPv4 in IPv6 address"); |
| 51 | |
| 52 | memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr)); |
| 53 | port = a6->sin6_port; |
| 54 | |
Damien Miller | 1d2c456 | 2014-02-04 11:18:20 +1100 | [diff] [blame] | 55 | memset(a4, 0, sizeof(*a4)); |
Damien Miller | 927f527 | 2003-11-24 12:57:25 +1100 | [diff] [blame] | 56 | |
| 57 | a4->sin_family = AF_INET; |
| 58 | *len = sizeof(*a4); |
| 59 | memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr)); |
| 60 | a4->sin_port = port; |
| 61 | } |
| 62 | |
Damien Miller | 3380426 | 2001-02-04 23:20:18 +1100 | [diff] [blame] | 63 | /* |
Ben Lindstrom | acaac97 | 2002-12-23 02:13:37 +0000 | [diff] [blame] | 64 | * Returns the local/remote IP-address/hostname of socket as a string. |
| 65 | * The returned string must be freed. |
Damien Miller | d83ff35 | 2001-01-30 09:19:34 +1100 | [diff] [blame] | 66 | */ |
Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 67 | static char * |
Darren Tucker | 3f9fdc7 | 2004-06-22 12:56:01 +1000 | [diff] [blame] | 68 | get_socket_address(int sock, int remote, int flags) |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 69 | { |
| 70 | struct sockaddr_storage addr; |
| 71 | socklen_t addrlen; |
| 72 | char ntop[NI_MAXHOST]; |
Damien Miller | 9b8073e | 2005-03-01 21:16:18 +1100 | [diff] [blame] | 73 | int r; |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 74 | |
| 75 | /* Get IP address of client. */ |
| 76 | addrlen = sizeof(addr); |
| 77 | memset(&addr, 0, sizeof(addr)); |
| 78 | |
| 79 | if (remote) { |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 80 | if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0) |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 81 | return NULL; |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 82 | } else { |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 83 | if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0) |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 84 | return NULL; |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 85 | } |
Damien Miller | 5e4471e | 2003-01-07 10:51:23 +1100 | [diff] [blame] | 86 | |
| 87 | /* Work around Linux IPv6 weirdness */ |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 88 | if (addr.ss_family == AF_INET6) { |
Damien Miller | 5e4471e | 2003-01-07 10:51:23 +1100 | [diff] [blame] | 89 | addrlen = sizeof(struct sockaddr_in6); |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 90 | ipv64_normalise_mapped(&addr, &addrlen); |
| 91 | } |
Damien Miller | 5e4471e | 2003-01-07 10:51:23 +1100 | [diff] [blame] | 92 | |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 93 | switch (addr.ss_family) { |
| 94 | case AF_INET: |
| 95 | case AF_INET6: |
| 96 | /* Get the address in ascii. */ |
| 97 | if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop, |
| 98 | sizeof(ntop), NULL, 0, flags)) != 0) { |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 99 | error("%s: getnameinfo %d failed: %s", __func__, |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 100 | flags, ssh_gai_strerror(r)); |
| 101 | return NULL; |
| 102 | } |
| 103 | return xstrdup(ntop); |
| 104 | case AF_UNIX: |
Damien Miller | 7acefbb | 2014-07-18 14:11:24 +1000 | [diff] [blame] | 105 | /* Get the Unix domain socket path. */ |
| 106 | return xstrdup(((struct sockaddr_un *)&addr)->sun_path); |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 107 | default: |
| 108 | /* We can't look up remote Unix domain sockets. */ |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 109 | return NULL; |
| 110 | } |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 111 | } |
Damien Miller | d83ff35 | 2001-01-30 09:19:34 +1100 | [diff] [blame] | 112 | |
| 113 | char * |
Darren Tucker | 3f9fdc7 | 2004-06-22 12:56:01 +1000 | [diff] [blame] | 114 | get_peer_ipaddr(int sock) |
Damien Miller | d83ff35 | 2001-01-30 09:19:34 +1100 | [diff] [blame] | 115 | { |
Damien Miller | b2f844d | 2002-09-25 12:19:08 +1000 | [diff] [blame] | 116 | char *p; |
| 117 | |
Darren Tucker | 3f9fdc7 | 2004-06-22 12:56:01 +1000 | [diff] [blame] | 118 | if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL) |
Damien Miller | b2f844d | 2002-09-25 12:19:08 +1000 | [diff] [blame] | 119 | return p; |
| 120 | return xstrdup("UNKNOWN"); |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 121 | } |
Damien Miller | d83ff35 | 2001-01-30 09:19:34 +1100 | [diff] [blame] | 122 | |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 123 | char * |
Darren Tucker | 3f9fdc7 | 2004-06-22 12:56:01 +1000 | [diff] [blame] | 124 | get_local_ipaddr(int sock) |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 125 | { |
Damien Miller | b2f844d | 2002-09-25 12:19:08 +1000 | [diff] [blame] | 126 | char *p; |
| 127 | |
Darren Tucker | 3f9fdc7 | 2004-06-22 12:56:01 +1000 | [diff] [blame] | 128 | if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL) |
Damien Miller | b2f844d | 2002-09-25 12:19:08 +1000 | [diff] [blame] | 129 | return p; |
| 130 | return xstrdup("UNKNOWN"); |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 131 | } |
| 132 | |
| 133 | char * |
Darren Tucker | daaa450 | 2010-01-13 22:43:33 +1100 | [diff] [blame] | 134 | get_local_name(int fd) |
Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 135 | { |
Darren Tucker | daaa450 | 2010-01-13 22:43:33 +1100 | [diff] [blame] | 136 | char *host, myname[NI_MAXHOST]; |
| 137 | |
| 138 | /* Assume we were passed a socket */ |
| 139 | if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL) |
| 140 | return host; |
| 141 | |
| 142 | /* Handle the case where we were passed a pipe */ |
| 143 | if (gethostname(myname, sizeof(myname)) == -1) { |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 144 | verbose("%s: gethostname: %s", __func__, strerror(errno)); |
| 145 | host = xstrdup("UNKNOWN"); |
Darren Tucker | daaa450 | 2010-01-13 22:43:33 +1100 | [diff] [blame] | 146 | } else { |
| 147 | host = xstrdup(myname); |
| 148 | } |
| 149 | |
| 150 | return host; |
Damien Miller | d83ff35 | 2001-01-30 09:19:34 +1100 | [diff] [blame] | 151 | } |
| 152 | |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 153 | /* Returns the local/remote port for the socket. */ |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 154 | |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 155 | static int |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 156 | get_sock_port(int sock, int local) |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 157 | { |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 158 | struct sockaddr_storage from; |
| 159 | socklen_t fromlen; |
| 160 | char strport[NI_MAXSERV]; |
Damien Miller | 9b8073e | 2005-03-01 21:16:18 +1100 | [diff] [blame] | 161 | int r; |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 162 | |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 163 | /* Get IP address of client. */ |
| 164 | fromlen = sizeof(from); |
| 165 | memset(&from, 0, sizeof(from)); |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 166 | if (local) { |
| 167 | if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) { |
| 168 | error("getsockname failed: %.100s", strerror(errno)); |
| 169 | return 0; |
| 170 | } |
| 171 | } else { |
Ben Lindstrom | acaac97 | 2002-12-23 02:13:37 +0000 | [diff] [blame] | 172 | if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) { |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 173 | debug("getpeername failed: %.100s", strerror(errno)); |
Damien Miller | 677257f | 2005-06-17 12:55:03 +1000 | [diff] [blame] | 174 | return -1; |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 175 | } |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 176 | } |
Damien Miller | 5e4471e | 2003-01-07 10:51:23 +1100 | [diff] [blame] | 177 | |
| 178 | /* Work around Linux IPv6 weirdness */ |
| 179 | if (from.ss_family == AF_INET6) |
| 180 | fromlen = sizeof(struct sockaddr_in6); |
| 181 | |
millert@openbsd.org | 39e2f12 | 2015-03-01 15:44:40 +0000 | [diff] [blame] | 182 | /* Non-inet sockets don't have a port number. */ |
| 183 | if (from.ss_family != AF_INET && from.ss_family != AF_INET6) |
Damien Miller | 7acefbb | 2014-07-18 14:11:24 +1000 | [diff] [blame] | 184 | return 0; |
| 185 | |
Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 186 | /* Return port number. */ |
Damien Miller | 9b8073e | 2005-03-01 21:16:18 +1100 | [diff] [blame] | 187 | if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, |
| 188 | strport, sizeof(strport), NI_NUMERICSERV)) != 0) |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 189 | fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__, |
Darren Tucker | 4abde77 | 2007-12-29 02:43:51 +1100 | [diff] [blame] | 190 | ssh_gai_strerror(r)); |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 191 | return atoi(strport); |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 192 | } |
| 193 | |
Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 194 | int |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 195 | get_peer_port(int sock) |
| 196 | { |
| 197 | return get_sock_port(sock, 0); |
| 198 | } |
| 199 | |
Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 200 | int |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 201 | get_local_port(int sock) |
Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 202 | { |
djm@openbsd.org | 9576726 | 2016-03-07 19:02:43 +0000 | [diff] [blame] | 203 | return get_sock_port(sock, 1); |
Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 204 | } |