]> andersk Git - openssh.git/blame - canohost.c
*** empty log message ***
[openssh.git] / canohost.c
CommitLineData
8efc0c15 1/*
5260325f 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 */
8efc0c15 15
16#include "includes.h"
17RCSID("$Id$");
18
19#include "packet.h"
20#include "xmalloc.h"
21#include "ssh.h"
22
5260325f 23/* Return the canonical name of the host at the other end of the socket.
8efc0c15 24 The caller should free the returned string with xfree. */
25
5260325f 26char *
27get_remote_hostname(int socket)
8efc0c15 28{
5260325f 29 struct sockaddr_in from;
30 int fromlen, i;
31 struct hostent *hp;
32 char name[MAXHOSTNAMELEN];
33
34 /* Get IP address of client. */
35 fromlen = sizeof(from);
36 memset(&from, 0, sizeof(from));
37 if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
38 debug("getpeername failed: %.100s", strerror(errno));
39 fatal_cleanup();
40 }
41 /* Map the IP address to a host name. */
42 hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),
43 from.sin_family);
44 if (hp) {
45 /* Got host name, find canonic host name. */
46 if (strchr(hp->h_name, '.') != 0)
47 strlcpy(name, hp->h_name, sizeof(name));
48 else if (hp->h_aliases != 0
49 && hp->h_aliases[0] != 0
50 && strchr(hp->h_aliases[0], '.') != 0)
51 strlcpy(name, hp->h_aliases[0], sizeof(name));
52 else
53 strlcpy(name, hp->h_name, sizeof(name));
54
55 /* Convert it to all lowercase (which is expected by the
56 rest of this software). */
57 for (i = 0; name[i]; i++)
58 if (isupper(name[i]))
59 name[i] = tolower(name[i]);
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
64 can define arbitrary names for an IP address. Mapping
65 from name to IP address can be trusted better (but can
66 still be fooled if the intruder has access to the name
67 server of the domain). */
68 hp = gethostbyname(name);
69 if (!hp) {
70 log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
71 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
72 goto check_ip_options;
73 }
74 /* Look for the address from the list of addresses. */
75 for (i = 0; hp->h_addr_list[i]; i++)
76 if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
77 == 0)
78 break;
79 /* If we reached the end of the list, the address was not
80 there. */
81 if (!hp->h_addr_list[i]) {
82 /* Address not found for the host name. */
83 log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
84 inet_ntoa(from.sin_addr), name);
85 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
86 goto check_ip_options;
87 }
88 /* Address was found for the host name. We accept the host name. */
89 } else {
90 /* Host name not found. Use ascii representation of the address. */
91 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
92 log("Could not reverse map address %.100s.", name);
8efc0c15 93 }
5260325f 94
95check_ip_options:
96
97 /* If IP options are supported, make sure there are none (log and
98 disconnect them if any are found). Basically we are worried
99 about source routing; it can be used to pretend you are
100 somebody (ip-address) you are not. That itself may be "almost
101 acceptable" under certain circumstances, but rhosts
102 autentication is useless if source routing is accepted. Notice
103 also that if we just dropped source routing here, the other
104 side could use IP spoofing to do rest of the interaction and
105 could still bypass security. So we exit here if we detect any
106 IP options. */
8efc0c15 107 {
5260325f 108 unsigned char options[200], *ucp;
109 char text[1024], *cp;
110 int option_size, ipproto;
111 struct protoent *ip;
112
113 if ((ip = getprotobyname("ip")) != NULL)
114 ipproto = ip->p_proto;
115 else
116 ipproto = IPPROTO_IP;
117 option_size = sizeof(options);
118 if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
119 &option_size) >= 0 && option_size != 0) {
120 cp = text;
121 /* Note: "text" buffer must be at least 3x as big as options. */
122 for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
123 sprintf(cp, " %2.2x", *ucp);
124 log("Connection from %.100s with IP options:%.800s",
125 inet_ntoa(from.sin_addr), text);
126 packet_disconnect("Connection from %.100s with IP options:%.800s",
127 inet_ntoa(from.sin_addr), text);
128 }
8efc0c15 129 }
5260325f 130
131 return xstrdup(name);
8efc0c15 132}
133
134static char *canonical_host_name = NULL;
135static char *canonical_host_ip = NULL;
136
137/* Return the canonical name of the host in the other side of the current
5260325f 138 connection. The host name is cached, so it is efficient to call this
8efc0c15 139 several times. */
140
5260325f 141const char *
142get_canonical_hostname()
8efc0c15 143{
5260325f 144 /* Check if we have previously retrieved this same name. */
145 if (canonical_host_name != NULL)
146 return canonical_host_name;
8efc0c15 147
5260325f 148 /* Get the real hostname if socket; otherwise return UNKNOWN. */
149 if (packet_get_connection_in() == packet_get_connection_out())
150 canonical_host_name = get_remote_hostname(packet_get_connection_in());
151 else
152 canonical_host_name = xstrdup("UNKNOWN");
8efc0c15 153
5260325f 154 return canonical_host_name;
8efc0c15 155}
156
157/* Returns the IP-address of the remote host as a string. The returned
158 string need not be freed. */
159
5260325f 160const char *
161get_remote_ipaddr()
8efc0c15 162{
5260325f 163 struct sockaddr_in from;
164 int fromlen, socket;
165
166 /* Check if we have previously retrieved this same name. */
167 if (canonical_host_ip != NULL)
168 return canonical_host_ip;
169
170 /* If not a socket, return UNKNOWN. */
171 if (packet_get_connection_in() != packet_get_connection_out()) {
172 canonical_host_ip = xstrdup("UNKNOWN");
173 return canonical_host_ip;
174 }
175 /* Get client socket. */
176 socket = packet_get_connection_in();
177
178 /* Get IP address of client. */
179 fromlen = sizeof(from);
180 memset(&from, 0, sizeof(from));
181 if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
182 debug("getpeername failed: %.100s", strerror(errno));
183 fatal_cleanup();
184 }
185 /* Get the IP address in ascii. */
186 canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
187
188 /* Return ip address string. */
189 return canonical_host_ip;
8efc0c15 190}
191
192/* Returns the port of the peer of the socket. */
193
5260325f 194int
195get_peer_port(int sock)
8efc0c15 196{
5260325f 197 struct sockaddr_in from;
198 int fromlen;
199
200 /* Get IP address of client. */
201 fromlen = sizeof(from);
202 memset(&from, 0, sizeof(from));
203 if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
204 debug("getpeername failed: %.100s", strerror(errno));
205 fatal_cleanup();
206 }
207 /* Return port number. */
208 return ntohs(from.sin_port);
8efc0c15 209}
210
211/* Returns the port number of the remote host. */
212
5260325f 213int
214get_remote_port()
8efc0c15 215{
5260325f 216 int socket;
8efc0c15 217
5260325f 218 /* If the connection is not a socket, return 65535. This is
219 intentionally chosen to be an unprivileged port number. */
220 if (packet_get_connection_in() != packet_get_connection_out())
221 return 65535;
8efc0c15 222
5260325f 223 /* Get client socket. */
224 socket = packet_get_connection_in();
8efc0c15 225
5260325f 226 /* Get and return the peer port number. */
227 return get_peer_port(socket);
8efc0c15 228}
This page took 0.239808 seconds and 5 git commands to generate.