[BACK]Return to canohost.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/canohost.c, Revision 1.3

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