]> andersk Git - openssh.git/blob - canohost.c
- Merged very large OpenBSD source code reformat
[openssh.git] / canohost.c
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  */
15
16 #include "includes.h"
17 RCSID("$Id$");
18
19 #include "packet.h"
20 #include "xmalloc.h"
21 #include "ssh.h"
22
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. */
25
26 char *
27 get_remote_hostname(int socket)
28 {
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);
93         }
94
95 check_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. */
107         {
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                 }
129         }
130
131         return xstrdup(name);
132 }
133
134 static char *canonical_host_name = NULL;
135 static char *canonical_host_ip = NULL;
136
137 /* Return the canonical name of the host in the other side of the current
138    connection.  The host name is cached, so it is efficient to call this
139    several times. */
140
141 const char *
142 get_canonical_hostname()
143 {
144         /* Check if we have previously retrieved this same name. */
145         if (canonical_host_name != NULL)
146                 return canonical_host_name;
147
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");
153
154         return canonical_host_name;
155 }
156
157 /* Returns the IP-address of the remote host as a string.  The returned
158    string need not be freed. */
159
160 const char *
161 get_remote_ipaddr()
162 {
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;
190 }
191
192 /* Returns the port of the peer of the socket. */
193
194 int 
195 get_peer_port(int sock)
196 {
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);
209 }
210
211 /* Returns the port number of the remote host.  */
212
213 int 
214 get_remote_port()
215 {
216         int socket;
217
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;
222
223         /* Get client socket. */
224         socket = packet_get_connection_in();
225
226         /* Get and return the peer port number. */
227         return get_peer_port(socket);
228 }
This page took 0.243858 seconds and 5 git commands to generate.