]> andersk Git - openssh.git/blob - canohost.c
- More reformatting merged from OpenBSD CVS
[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 /*
24  * Return the canonical name of the host at the other end of the socket. The
25  * caller should free the returned string with xfree.
26  */
27
28 char *
29 get_remote_hostname(int socket)
30 {
31         struct sockaddr_in from;
32         int fromlen, i;
33         struct hostent *hp;
34         char name[MAXHOSTNAMELEN];
35
36         /* Get IP address of client. */
37         fromlen = sizeof(from);
38         memset(&from, 0, sizeof(from));
39         if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
40                 debug("getpeername failed: %.100s", strerror(errno));
41                 fatal_cleanup();
42         }
43         /* Map the IP address to a host name. */
44         hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),
45                            from.sin_family);
46         if (hp) {
47                 /* Got host name, find canonic host name. */
48                 if (strchr(hp->h_name, '.') != 0)
49                         strlcpy(name, hp->h_name, sizeof(name));
50                 else if (hp->h_aliases != 0
51                          && hp->h_aliases[0] != 0
52                          && strchr(hp->h_aliases[0], '.') != 0)
53                         strlcpy(name, hp->h_aliases[0], sizeof(name));
54                 else
55                         strlcpy(name, hp->h_name, sizeof(name));
56
57                 /*
58                  * Convert it to all lowercase (which is expected by the rest
59                  * of this software).
60                  */
61                 for (i = 0; name[i]; i++)
62                         if (isupper(name[i]))
63                                 name[i] = tolower(name[i]);
64
65                 /*
66                  * Map it back to an IP address and check that the given
67                  * address actually is an address of this host.  This is
68                  * necessary because anyone with access to a name server can
69                  * define arbitrary names for an IP address. Mapping from
70                  * name to IP address can be trusted better (but can still be
71                  * fooled if the intruder has access to the name server of
72                  * the domain).
73                  */
74                 hp = gethostbyname(name);
75                 if (!hp) {
76                         log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
77                         strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
78                         goto check_ip_options;
79                 }
80                 /* Look for the address from the list of addresses. */
81                 for (i = 0; hp->h_addr_list[i]; i++)
82                         if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
83                             == 0)
84                                 break;
85                 /*
86                  * If we reached the end of the list, the address was not
87                  * there.
88                  */
89                 if (!hp->h_addr_list[i]) {
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                             inet_ntoa(from.sin_addr), name);
93                         strlcpy(name, inet_ntoa(from.sin_addr), 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, inet_ntoa(from.sin_addr), 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         {
117                 unsigned char options[200], *ucp;
118                 char text[1024], *cp;
119                 int option_size, ipproto;
120                 struct protoent *ip;
121
122                 if ((ip = getprotobyname("ip")) != NULL)
123                         ipproto = ip->p_proto;
124                 else
125                         ipproto = IPPROTO_IP;
126                 option_size = sizeof(options);
127                 if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
128                                &option_size) >= 0 && option_size != 0) {
129                         cp = text;
130                         /* Note: "text" buffer must be at least 3x as big as options. */
131                         for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
132                                 sprintf(cp, " %2.2x", *ucp);
133                         log("Connection from %.100s with IP options:%.800s",
134                             inet_ntoa(from.sin_addr), text);
135                         packet_disconnect("Connection from %.100s with IP options:%.800s",
136                                           inet_ntoa(from.sin_addr), text);
137                 }
138         }
139
140         return xstrdup(name);
141 }
142
143 static char *canonical_host_name = NULL;
144 static char *canonical_host_ip = NULL;
145
146 /*
147  * Return the canonical name of the host in the other side of the current
148  * connection.  The host name is cached, so it is efficient to call this
149  * several times.
150  */
151
152 const char *
153 get_canonical_hostname()
154 {
155         /* Check if we have previously retrieved this same name. */
156         if (canonical_host_name != NULL)
157                 return canonical_host_name;
158
159         /* Get the real hostname if socket; otherwise return UNKNOWN. */
160         if (packet_get_connection_in() == packet_get_connection_out())
161                 canonical_host_name = get_remote_hostname(packet_get_connection_in());
162         else
163                 canonical_host_name = xstrdup("UNKNOWN");
164
165         return canonical_host_name;
166 }
167
168 /*
169  * Returns the IP-address of the remote host as a string.  The returned
170  * string need not be freed.
171  */
172
173 const char *
174 get_remote_ipaddr()
175 {
176         struct sockaddr_in from;
177         int fromlen, socket;
178
179         /* Check whether we have chached the name. */
180         if (canonical_host_ip != NULL)
181                 return canonical_host_ip;
182
183         /* If not a socket, return UNKNOWN. */
184         if (packet_get_connection_in() != packet_get_connection_out()) {
185                 canonical_host_ip = xstrdup("UNKNOWN");
186                 return canonical_host_ip;
187         }
188         /* Get client socket. */
189         socket = packet_get_connection_in();
190
191         /* Get IP address of client. */
192         fromlen = sizeof(from);
193         memset(&from, 0, sizeof(from));
194         if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
195                 debug("getpeername failed: %.100s", strerror(errno));
196                 fatal_cleanup();
197         }
198         /* Get the IP address in ascii. */
199         canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
200
201         /* Return ip address string. */
202         return canonical_host_ip;
203 }
204
205 /* Returns the port of the peer of the socket. */
206
207 int 
208 get_peer_port(int sock)
209 {
210         struct sockaddr_in from;
211         int fromlen;
212
213         /* Get IP address of client. */
214         fromlen = sizeof(from);
215         memset(&from, 0, sizeof(from));
216         if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
217                 debug("getpeername failed: %.100s", strerror(errno));
218                 fatal_cleanup();
219         }
220         /* Return port number. */
221         return ntohs(from.sin_port);
222 }
223
224 /* Returns the port number of the remote host.  */
225
226 int 
227 get_remote_port()
228 {
229         int socket;
230
231         /*
232          * If the connection is not a socket, return 65535.  This is
233          * intentionally chosen to be an unprivileged port number.
234          */
235         if (packet_get_connection_in() != packet_get_connection_out())
236                 return 65535;
237
238         /* Get client socket. */
239         socket = packet_get_connection_in();
240
241         /* Get and return the peer port number. */
242         return get_peer_port(socket);
243 }
This page took 0.047795 seconds and 5 git commands to generate.