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