[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.5

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.5     ! markus     17: RCSID("$Id: canohost.c,v 1.4 1999/11/14 22:30:58 markus 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:     {
1.5     ! markus     38:       debug("getpeername failed: %.100s", strerror(errno));
        !            39:       fatal_cleanup();
1.1       deraadt    40:     }
                     41:
                     42:   /* Map the IP address to a host name. */
                     43:   hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),
                     44:                     from.sin_family);
                     45:   if (hp)
                     46:     {
                     47:       /* Got host name, find canonic host name. */
                     48:       if (strchr(hp->h_name, '.') != 0)
1.2       deraadt    49:        strlcpy(name, hp->h_name, sizeof(name));
1.1       deraadt    50:       else if (hp->h_aliases != 0
                     51:               && hp->h_aliases[0] != 0
                     52:               && strchr(hp->h_aliases[0], '.') != 0)
1.2       deraadt    53:        strlcpy(name, hp->h_aliases[0], sizeof(name));
1.1       deraadt    54:       else
1.2       deraadt    55:        strlcpy(name, hp->h_name, sizeof(name));
1.1       deraadt    56:
                     57:       /* Convert it to all lowercase (which is expected by the rest of this
                     58:         software). */
                     59:       for (i = 0; name[i]; i++)
                     60:        if (isupper(name[i]))
                     61:          name[i] = tolower(name[i]);
                     62:
                     63:       /* Map it back to an IP address and check that the given address actually
                     64:         is an address of this host.  This is necessary because anyone with
                     65:         access to a name server can define arbitrary names for an IP address.
                     66:         Mapping from name to IP address can be trusted better (but can still
                     67:         be fooled if the intruder has access to the name server of the
                     68:         domain). */
                     69:       hp = gethostbyname(name);
                     70:       if (!hp)
                     71:        {
                     72:          log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
1.2       deraadt    73:          strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
1.1       deraadt    74:          goto check_ip_options;
                     75:        }
                     76:       /* Look for the address from the list of addresses. */
                     77:       for (i = 0; hp->h_addr_list[i]; i++)
                     78:        if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
                     79:            == 0)
                     80:          break;
                     81:       /* If we reached the end of the list, the address was not there. */
                     82:       if (!hp->h_addr_list[i])
                     83:        {
                     84:          /* Address not found for the host name. */
                     85:          log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
                     86:              inet_ntoa(from.sin_addr), name);
1.2       deraadt    87:          strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
1.1       deraadt    88:          goto check_ip_options;
                     89:        }
                     90:       /* Address was found for the host name.  We accept the host name. */
                     91:     }
                     92:   else
                     93:     {
                     94:       /* Host name not found.  Use ascii representation of the address. */
1.2       deraadt    95:       strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
1.1       deraadt    96:       log("Could not reverse map address %.100s.", name);
                     97:     }
                     98:
                     99:  check_ip_options:
                    100:
1.4       markus    101:   /* If IP options are supported, make sure there are none (log and disconnect
1.1       deraadt   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: }
                    136:
                    137: static char *canonical_host_name = NULL;
                    138: static char *canonical_host_ip = NULL;
                    139:
                    140: /* 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
                    142:    several times. */
                    143:
                    144: const char *get_canonical_hostname()
                    145: {
                    146:   /* Check if we have previously retrieved this same name. */
                    147:   if (canonical_host_name != NULL)
                    148:     return canonical_host_name;
                    149:
                    150:   /* Get the real hostname if socket; otherwise return UNKNOWN. */
                    151:   if (packet_get_connection_in() == packet_get_connection_out())
                    152:     canonical_host_name = get_remote_hostname(packet_get_connection_in());
                    153:   else
                    154:     canonical_host_name = xstrdup("UNKNOWN");
                    155:
                    156:   return canonical_host_name;
                    157: }
                    158:
                    159: /* Returns the IP-address of the remote host as a string.  The returned
                    160:    string need not be freed. */
                    161:
                    162: const char *get_remote_ipaddr()
                    163: {
                    164:   struct sockaddr_in from;
                    165:   int fromlen, socket;
                    166:
                    167:   /* Check if we have previously retrieved this same name. */
                    168:   if (canonical_host_ip != NULL)
                    169:     return canonical_host_ip;
                    170:
                    171:   /* If not a socket, return UNKNOWN. */
                    172:   if (packet_get_connection_in() != packet_get_connection_out())
                    173:     {
                    174:       canonical_host_ip = xstrdup("UNKNOWN");
                    175:       return canonical_host_ip;
                    176:     }
                    177:
                    178:   /* Get client socket. */
                    179:   socket = packet_get_connection_in();
                    180:
                    181:   /* Get IP address of client. */
                    182:   fromlen = sizeof(from);
                    183:   memset(&from, 0, sizeof(from));
                    184:   if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
                    185:     {
1.5     ! markus    186:       debug("getpeername failed: %.100s", strerror(errno));
        !           187:       fatal_cleanup();
1.1       deraadt   188:     }
                    189:
                    190:   /* Get the IP address in ascii. */
                    191:   canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
                    192:
                    193:   /* Return ip address string. */
                    194:   return canonical_host_ip;
                    195: }
                    196:
                    197: /* Returns the port of the peer of the socket. */
                    198:
                    199: int get_peer_port(int sock)
                    200: {
                    201:   struct sockaddr_in from;
                    202:   int fromlen;
                    203:
                    204:   /* Get IP address of client. */
                    205:   fromlen = sizeof(from);
                    206:   memset(&from, 0, sizeof(from));
                    207:   if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
                    208:     {
1.5     ! markus    209:       debug("getpeername failed: %.100s", strerror(errno));
        !           210:       fatal_cleanup();
1.1       deraadt   211:     }
                    212:
                    213:   /* Return port number. */
                    214:   return ntohs(from.sin_port);
                    215: }
                    216:
                    217: /* Returns the port number of the remote host.  */
                    218:
                    219: int get_remote_port()
                    220: {
                    221:   int socket;
                    222:
                    223:   /* If the connection is not a socket, return 65535.  This is intentionally
                    224:      chosen to be an unprivileged port number. */
                    225:   if (packet_get_connection_in() != packet_get_connection_out())
                    226:     return 65535;
                    227:
                    228:   /* Get client socket. */
                    229:   socket = packet_get_connection_in();
                    230:
                    231:   /* Get and return the peer port number. */
                    232:   return get_peer_port(socket);
                    233: }