summaryrefslogtreecommitdiff
path: root/canohost.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-11-25 00:26:21 +1100
committerDamien Miller <djm@mindrot.org>1999-11-25 00:26:21 +1100
commit95def09838fc61b37b6ea7cd5c234a465b4b129b (patch)
tree042744f76f40a326b873cb1c3690a6d7d966bc3e /canohost.c
parent4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff)
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates - [channels.c cipher.c compat.c log-client.c scp.c serverloop.c] [ssh.h sshd.8 sshd.c] syslog changes: * Unified Logmessage for all auth-types, for success and for failed * Standard connections get only ONE line in the LOG when level==LOG: Auth-attempts are logged only, if authentication is: a) successfull or b) with passwd or c) we had more than AUTH_FAIL_LOG failues * many log() became verbose() * old behaviour with level=VERBOSE - [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c] tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE messages. allows use of s/key in windows (ttssh, securecrt) and ssh-1.2.27 clients without 'ssh -v', ok: niels@ - [sshd.8] -V, for fallback to openssh in SSH2 compatibility mode - [sshd.c] fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'canohost.c')
-rw-r--r--canohost.c371
1 files changed, 183 insertions, 188 deletions
diff --git a/canohost.c b/canohost.c
index 08f798758..3179ddc25 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,233 +1,228 @@
1/* 1/*
2 2 *
3canohost.c 3 * canohost.c
4 4 *
5Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 6 *
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved 8 * All rights reserved
9 9 *
10Created: Sun Jul 2 17:52:22 1995 ylo 10 * Created: Sun Jul 2 17:52:22 1995 ylo
11 11 *
12Functions for returning the canonical host name of the remote site. 12 * Functions for returning the canonical host name of the remote site.
13 13 *
14*/ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: canohost.c,v 1.2 1999/11/15 04:25:10 damien Exp $"); 17RCSID("$Id: canohost.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
18 18
19#include "packet.h" 19#include "packet.h"
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "ssh.h" 21#include "ssh.h"
22 22
23/* Return the canonical name of the host at the other end of the socket. 23/* Return the canonical name of the host at the other end of the socket.
24 The caller should free the returned string with xfree. */ 24 The caller should free the returned string with xfree. */
25 25
26char *get_remote_hostname(int socket) 26char *
27get_remote_hostname(int socket)
27{ 28{
28 struct sockaddr_in from; 29 struct sockaddr_in from;
29 int fromlen, i; 30 int fromlen, i;
30 struct hostent *hp; 31 struct hostent *hp;
31 char name[MAXHOSTNAMELEN]; 32 char name[MAXHOSTNAMELEN];
32 33
33 /* Get IP address of client. */ 34 /* Get IP address of client. */
34 fromlen = sizeof(from); 35 fromlen = sizeof(from);
35 memset(&from, 0, sizeof(from)); 36 memset(&from, 0, sizeof(from));
36 if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) 37 if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
37 { 38 debug("getpeername failed: %.100s", strerror(errno));
38 debug("getpeername failed: %.100s", strerror(errno)); 39 fatal_cleanup();
39 fatal_cleanup(); 40 }
40 } 41 /* Map the IP address to a host name. */
41 42 hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),
42 /* Map the IP address to a host name. */ 43 from.sin_family);
43 hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr), 44 if (hp) {
44 from.sin_family); 45 /* Got host name, find canonic host name. */
45 if (hp) 46 if (strchr(hp->h_name, '.') != 0)
46 { 47 strlcpy(name, hp->h_name, sizeof(name));
47 /* Got host name, find canonic host name. */ 48 else if (hp->h_aliases != 0
48 if (strchr(hp->h_name, '.') != 0) 49 && hp->h_aliases[0] != 0
49 strlcpy(name, hp->h_name, sizeof(name)); 50 && strchr(hp->h_aliases[0], '.') != 0)
50 else if (hp->h_aliases != 0 51 strlcpy(name, hp->h_aliases[0], sizeof(name));
51 && hp->h_aliases[0] != 0 52 else
52 && strchr(hp->h_aliases[0], '.') != 0) 53 strlcpy(name, hp->h_name, sizeof(name));
53 strlcpy(name, hp->h_aliases[0], sizeof(name)); 54
54 else 55 /* Convert it to all lowercase (which is expected by the
55 strlcpy(name, hp->h_name, sizeof(name)); 56 rest of this software). */
56 57 for (i = 0; name[i]; i++)
57 /* Convert it to all lowercase (which is expected by the rest of this 58 if (isupper(name[i]))
58 software). */ 59 name[i] = tolower(name[i]);
59 for (i = 0; name[i]; i++) 60
60 if (isupper(name[i])) 61 /* Map it back to an IP address and check that the given
61 name[i] = tolower(name[i]); 62 address actually is an address of this host. This is
62 63 necessary because anyone with access to a name server
63 /* Map it back to an IP address and check that the given address actually 64 can define arbitrary names for an IP address. Mapping
64 is an address of this host. This is necessary because anyone with 65 from name to IP address can be trusted better (but can
65 access to a name server can define arbitrary names for an IP address. 66 still be fooled if the intruder has access to the name
66 Mapping from name to IP address can be trusted better (but can still 67 server of the domain). */
67 be fooled if the intruder has access to the name server of the 68 hp = gethostbyname(name);
68 domain). */ 69 if (!hp) {
69 hp = gethostbyname(name); 70 log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
70 if (!hp) 71 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
71 { 72 goto check_ip_options;
72 log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name); 73 }
73 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name); 74 /* Look for the address from the list of addresses. */
74 goto check_ip_options; 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);
75 } 93 }
76 /* Look for the address from the list of addresses. */ 94
77 for (i = 0; hp->h_addr_list[i]; i++) 95check_ip_options:
78 if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr)) 96
79 == 0) 97 /* If IP options are supported, make sure there are none (log and
80 break; 98 disconnect them if any are found). Basically we are worried
81 /* If we reached the end of the list, the address was not there. */ 99 about source routing; it can be used to pretend you are
82 if (!hp->h_addr_list[i]) 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. */
83 { 107 {
84 /* Address not found for the host name. */ 108 unsigned char options[200], *ucp;
85 log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!", 109 char text[1024], *cp;
86 inet_ntoa(from.sin_addr), name); 110 int option_size, ipproto;
87 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name); 111 struct protoent *ip;
88 goto check_ip_options; 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 }
89 } 129 }
90 /* Address was found for the host name. We accept the host name. */ 130
91 } 131 return xstrdup(name);
92 else
93 {
94 /* Host name not found. Use ascii representation of the address. */
95 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
96 log("Could not reverse map address %.100s.", name);
97 }
98
99 check_ip_options:
100
101 /* If IP options are supported, make sure there are none (log and disconnect
102 them if any are found). Basically we are worried about source routing;
103 it can be used to pretend you are somebody (ip-address) you are not.
104 That itself may be "almost acceptable" under certain circumstances,
105 but rhosts autentication is useless if source routing is accepted.
106 Notice also that if we just dropped source routing here, the other
107 side could use IP spoofing to do rest of the interaction and could still
108 bypass security. So we exit here if we detect any IP options. */
109 {
110 unsigned char options[200], *ucp;
111 char text[1024], *cp;
112 int option_size, ipproto;
113 struct protoent *ip;
114
115 if ((ip = getprotobyname("ip")) != NULL)
116 ipproto = ip->p_proto;
117 else
118 ipproto = IPPROTO_IP;
119 option_size = sizeof(options);
120 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)options,
121 &option_size) >= 0 && option_size != 0)
122 {
123 cp = text;
124 /* Note: "text" buffer must be at least 3x as big as options. */
125 for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
126 sprintf(cp, " %2.2x", *ucp);
127 log("Connection from %.100s with IP options:%.800s",
128 inet_ntoa(from.sin_addr), text);
129 packet_disconnect("Connection from %.100s with IP options:%.800s",
130 inet_ntoa(from.sin_addr), text);
131 }
132 }
133
134 return xstrdup(name);
135} 132}
136 133
137static char *canonical_host_name = NULL; 134static char *canonical_host_name = NULL;
138static char *canonical_host_ip = NULL; 135static char *canonical_host_ip = NULL;
139 136
140/* Return the canonical name of the host in the other side of the current 137/* Return the canonical name of the host in the other side of the current
141 connection. The host name is cached, so it is efficient to call this 138 connection. The host name is cached, so it is efficient to call this
142 several times. */ 139 several times. */
143 140
144const char *get_canonical_hostname() 141const char *
142get_canonical_hostname()
145{ 143{
146 /* Check if we have previously retrieved this same name. */ 144 /* Check if we have previously retrieved this same name. */
147 if (canonical_host_name != NULL) 145 if (canonical_host_name != NULL)
148 return canonical_host_name; 146 return canonical_host_name;
149 147
150 /* Get the real hostname if socket; otherwise return UNKNOWN. */ 148 /* Get the real hostname if socket; otherwise return UNKNOWN. */
151 if (packet_get_connection_in() == packet_get_connection_out()) 149 if (packet_get_connection_in() == packet_get_connection_out())
152 canonical_host_name = get_remote_hostname(packet_get_connection_in()); 150 canonical_host_name = get_remote_hostname(packet_get_connection_in());
153 else 151 else
154 canonical_host_name = xstrdup("UNKNOWN"); 152 canonical_host_name = xstrdup("UNKNOWN");
155 153
156 return canonical_host_name; 154 return canonical_host_name;
157} 155}
158 156
159/* Returns the IP-address of the remote host as a string. The returned 157/* Returns the IP-address of the remote host as a string. The returned
160 string need not be freed. */ 158 string need not be freed. */
161 159
162const char *get_remote_ipaddr() 160const char *
161get_remote_ipaddr()
163{ 162{
164 struct sockaddr_in from; 163 struct sockaddr_in from;
165 int fromlen, socket; 164 int fromlen, socket;
166 165
167 /* Check if we have previously retrieved this same name. */ 166 /* Check if we have previously retrieved this same name. */
168 if (canonical_host_ip != NULL) 167 if (canonical_host_ip != NULL)
169 return canonical_host_ip; 168 return canonical_host_ip;
170 169
171 /* If not a socket, return UNKNOWN. */ 170 /* If not a socket, return UNKNOWN. */
172 if (packet_get_connection_in() != packet_get_connection_out()) 171 if (packet_get_connection_in() != packet_get_connection_out()) {
173 { 172 canonical_host_ip = xstrdup("UNKNOWN");
174 canonical_host_ip = xstrdup("UNKNOWN"); 173 return canonical_host_ip;
175 return canonical_host_ip; 174 }
176 } 175 /* Get client socket. */
177 176 socket = packet_get_connection_in();
178 /* Get client socket. */ 177
179 socket = packet_get_connection_in(); 178 /* Get IP address of client. */
180 179 fromlen = sizeof(from);
181 /* Get IP address of client. */ 180 memset(&from, 0, sizeof(from));
182 fromlen = sizeof(from); 181 if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
183 memset(&from, 0, sizeof(from)); 182 debug("getpeername failed: %.100s", strerror(errno));
184 if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) 183 fatal_cleanup();
185 { 184 }
186 debug("getpeername failed: %.100s", strerror(errno)); 185 /* Get the IP address in ascii. */
187 fatal_cleanup(); 186 canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
188 } 187
189 188 /* Return ip address string. */
190 /* Get the IP address in ascii. */ 189 return canonical_host_ip;
191 canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
192
193 /* Return ip address string. */
194 return canonical_host_ip;
195} 190}
196 191
197/* Returns the port of the peer of the socket. */ 192/* Returns the port of the peer of the socket. */
198 193
199int get_peer_port(int sock) 194int
195get_peer_port(int sock)
200{ 196{
201 struct sockaddr_in from; 197 struct sockaddr_in from;
202 int fromlen; 198 int fromlen;
203 199
204 /* Get IP address of client. */ 200 /* Get IP address of client. */
205 fromlen = sizeof(from); 201 fromlen = sizeof(from);
206 memset(&from, 0, sizeof(from)); 202 memset(&from, 0, sizeof(from));
207 if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) 203 if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
208 { 204 debug("getpeername failed: %.100s", strerror(errno));
209 debug("getpeername failed: %.100s", strerror(errno)); 205 fatal_cleanup();
210 fatal_cleanup(); 206 }
211 } 207 /* Return port number. */
212 208 return ntohs(from.sin_port);
213 /* Return port number. */
214 return ntohs(from.sin_port);
215} 209}
216 210
217/* Returns the port number of the remote host. */ 211/* Returns the port number of the remote host. */
218 212
219int get_remote_port() 213int
214get_remote_port()
220{ 215{
221 int socket; 216 int socket;
222 217
223 /* If the connection is not a socket, return 65535. This is intentionally 218 /* If the connection is not a socket, return 65535. This is
224 chosen to be an unprivileged port number. */ 219 intentionally chosen to be an unprivileged port number. */
225 if (packet_get_connection_in() != packet_get_connection_out()) 220 if (packet_get_connection_in() != packet_get_connection_out())
226 return 65535; 221 return 65535;
227 222
228 /* Get client socket. */ 223 /* Get client socket. */
229 socket = packet_get_connection_in(); 224 socket = packet_get_connection_in();
230 225
231 /* Get and return the peer port number. */ 226 /* Get and return the peer port number. */
232 return get_peer_port(socket); 227 return get_peer_port(socket);
233} 228}