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

1.1       deraadt     1: /*
1.7       deraadt     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:  */
1.1       deraadt    15:
                     16: #include "includes.h"
1.10    ! markus     17: RCSID("$Id: canohost.c,v 1.9 1999/12/09 00:00:52 markus Exp $");
1.1       deraadt    18:
                     19: #include "packet.h"
                     20: #include "xmalloc.h"
                     21: #include "ssh.h"
                     22:
1.8       markus     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:  */
1.1       deraadt    27:
1.6       markus     28: char *
                     29: get_remote_hostname(int socket)
1.1       deraadt    30: {
1.10    ! markus     31:        struct sockaddr_storage from;
        !            32:        int i;
        !            33:        socklen_t fromlen;
        !            34:        struct addrinfo hints, *ai, *aitop;
1.6       markus     35:        char name[MAXHOSTNAMELEN];
1.10    ! markus     36:        char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
1.6       markus     37:
                     38:        /* Get IP address of client. */
                     39:        fromlen = sizeof(from);
                     40:        memset(&from, 0, sizeof(from));
                     41:        if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
                     42:                debug("getpeername failed: %.100s", strerror(errno));
                     43:                fatal_cleanup();
                     44:        }
1.10    ! markus     45:        if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
        !            46:             NULL, 0, NI_NUMERICHOST) != 0)
        !            47:                fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
        !            48:
1.6       markus     49:        /* Map the IP address to a host name. */
1.10    ! markus     50:        if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
        !            51:             NULL, 0, NI_NAMEREQD) == 0) {
        !            52:                /* Got host name. */
        !            53:                name[sizeof(name) - 1] = '\0';
1.8       markus     54:                /*
                     55:                 * Convert it to all lowercase (which is expected by the rest
                     56:                 * of this software).
                     57:                 */
1.6       markus     58:                for (i = 0; name[i]; i++)
                     59:                        if (isupper(name[i]))
                     60:                                name[i] = tolower(name[i]);
                     61:
1.8       markus     62:                /*
                     63:                 * Map it back to an IP address and check that the given
                     64:                 * address actually is an address of this host.  This is
                     65:                 * necessary because anyone with access to a name server can
                     66:                 * define arbitrary names for an IP address. Mapping from
                     67:                 * name to IP address can be trusted better (but can still be
                     68:                 * fooled if the intruder has access to the name server of
                     69:                 * the domain).
                     70:                 */
1.10    ! markus     71:                memset(&hints, 0, sizeof(hints));
        !            72:                hints.ai_family = from.ss_family;
        !            73:                if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
        !            74:                        log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
        !            75:                        strlcpy(name, ntop, sizeof name);
1.6       markus     76:                        goto check_ip_options;
                     77:                }
                     78:                /* Look for the address from the list of addresses. */
1.10    ! markus     79:                for (ai = aitop; ai; ai = ai->ai_next) {
        !            80:                        if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
        !            81:                            sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
        !            82:                            (strcmp(ntop, ntop2) == 0))
        !            83:                                        break;
        !            84:                }
        !            85:                freeaddrinfo(aitop);
        !            86:                /* If we reached the end of the list, the address was not there. */
        !            87:                if (!ai) {
1.6       markus     88:                        /* Address not found for the host name. */
                     89:                        log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
1.10    ! markus     90:                            ntop, name);
        !            91:                        strlcpy(name, ntop, sizeof name);
1.6       markus     92:                        goto check_ip_options;
                     93:                }
                     94:                /* Address was found for the host name.  We accept the host name. */
                     95:        } else {
                     96:                /* Host name not found.  Use ascii representation of the address. */
1.10    ! markus     97:                strlcpy(name, ntop, sizeof name);
1.6       markus     98:                log("Could not reverse map address %.100s.", name);
                     99:        }
                    100:
                    101: check_ip_options:
                    102:
1.8       markus    103:        /*
                    104:         * If IP options are supported, make sure there are none (log and
                    105:         * disconnect them if any are found).  Basically we are worried about
                    106:         * source routing; it can be used to pretend you are somebody
                    107:         * (ip-address) you are not. That itself may be "almost acceptable"
                    108:         * under certain circumstances, but rhosts autentication is useless
                    109:         * if source routing is accepted. Notice also that if we just dropped
                    110:         * source routing here, the other side could use IP spoofing to do
                    111:         * rest of the interaction and could still bypass security.  So we
                    112:         * exit here if we detect any IP options.
                    113:         */
1.10    ! markus    114:        /* IP options -- IPv4 only */
        !           115:        if (from.ss_family == AF_INET) {
1.6       markus    116:                unsigned char options[200], *ucp;
                    117:                char text[1024], *cp;
1.10    ! markus    118:                socklen_t option_size;
        !           119:                int ipproto;
1.6       markus    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,
1.10    ! markus    128:                    &option_size) >= 0 && option_size != 0) {
1.6       markus    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",
1.10    ! markus    134:                            ntop, text);
1.6       markus    135:                        packet_disconnect("Connection from %.100s with IP options:%.800s",
1.10    ! markus    136:                                          ntop, text);
1.6       markus    137:                }
                    138:        }
1.1       deraadt   139:
1.6       markus    140:        return xstrdup(name);
1.1       deraadt   141: }
                    142:
1.8       markus    143: /*
                    144:  * Return the canonical name of the host in the other side of the current
                    145:  * connection.  The host name is cached, so it is efficient to call this
                    146:  * several times.
                    147:  */
1.1       deraadt   148:
1.6       markus    149: const char *
                    150: get_canonical_hostname()
1.1       deraadt   151: {
1.10    ! markus    152:        static char *canonical_host_name = NULL;
        !           153:
1.6       markus    154:        /* Check if we have previously retrieved this same name. */
                    155:        if (canonical_host_name != NULL)
                    156:                return canonical_host_name;
                    157:
                    158:        /* Get the real hostname if socket; otherwise return UNKNOWN. */
1.10    ! markus    159:        if (packet_connection_is_on_socket())
1.6       markus    160:                canonical_host_name = get_remote_hostname(packet_get_connection_in());
                    161:        else
                    162:                canonical_host_name = xstrdup("UNKNOWN");
1.1       deraadt   163:
1.6       markus    164:        return canonical_host_name;
1.1       deraadt   165: }
                    166:
1.8       markus    167: /*
                    168:  * Returns the IP-address of the remote host as a string.  The returned
1.10    ! markus    169:  * string must not be freed.
1.8       markus    170:  */
1.1       deraadt   171:
1.6       markus    172: const char *
                    173: get_remote_ipaddr()
1.1       deraadt   174: {
1.10    ! markus    175:        static char *canonical_host_ip = NULL;
        !           176:        struct sockaddr_storage from;
        !           177:        socklen_t fromlen;
        !           178:        int socket;
        !           179:        char ntop[NI_MAXHOST];
1.1       deraadt   180:
1.8       markus    181:        /* Check whether we have chached the name. */
1.6       markus    182:        if (canonical_host_ip != NULL)
                    183:                return canonical_host_ip;
                    184:
                    185:        /* If not a socket, return UNKNOWN. */
1.10    ! markus    186:        if (!packet_connection_is_on_socket()) {
1.6       markus    187:                canonical_host_ip = xstrdup("UNKNOWN");
                    188:                return canonical_host_ip;
                    189:        }
                    190:        /* Get client socket. */
                    191:        socket = packet_get_connection_in();
1.1       deraadt   192:
1.6       markus    193:        /* Get IP address of client. */
                    194:        fromlen = sizeof(from);
                    195:        memset(&from, 0, sizeof(from));
                    196:        if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
                    197:                debug("getpeername failed: %.100s", strerror(errno));
                    198:                fatal_cleanup();
                    199:        }
                    200:        /* Get the IP address in ascii. */
1.10    ! markus    201:        if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
        !           202:             NULL, 0, NI_NUMERICHOST) != 0)
        !           203:                fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
        !           204:
        !           205:        canonical_host_ip = xstrdup(ntop);
1.1       deraadt   206:
1.6       markus    207:        /* Return ip address string. */
                    208:        return canonical_host_ip;
1.1       deraadt   209: }
                    210:
1.10    ! markus    211: /* Returns the local/remote port for the socket. */
1.1       deraadt   212:
1.10    ! markus    213: int
        !           214: get_sock_port(int sock, int local)
1.1       deraadt   215: {
1.10    ! markus    216:        struct sockaddr_storage from;
        !           217:        socklen_t fromlen;
        !           218:        char strport[NI_MAXSERV];
1.1       deraadt   219:
1.6       markus    220:        /* Get IP address of client. */
                    221:        fromlen = sizeof(from);
                    222:        memset(&from, 0, sizeof(from));
1.10    ! markus    223:        if (local) {
        !           224:                if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
        !           225:                        error("getsockname failed: %.100s", strerror(errno));
        !           226:                        return 0;
        !           227:                }
        !           228:        } else {
        !           229:                if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
        !           230:                        debug("getpeername failed: %.100s", strerror(errno));
        !           231:                        fatal_cleanup();
        !           232:                }
1.6       markus    233:        }
                    234:        /* Return port number. */
1.10    ! markus    235:        if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
        !           236:             strport, sizeof(strport), NI_NUMERICSERV) != 0)
        !           237:                fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
        !           238:        return atoi(strport);
1.1       deraadt   239: }
                    240:
1.10    ! markus    241: /* Returns remote/local port number for the current connection. */
1.1       deraadt   242:
1.6       markus    243: int
1.10    ! markus    244: get_port(int local)
1.1       deraadt   245: {
1.8       markus    246:        /*
                    247:         * If the connection is not a socket, return 65535.  This is
                    248:         * intentionally chosen to be an unprivileged port number.
                    249:         */
1.10    ! markus    250:        if (!packet_connection_is_on_socket())
1.6       markus    251:                return 65535;
1.1       deraadt   252:
1.10    ! markus    253:        /* Get socket and return the port number. */
        !           254:        return get_sock_port(packet_get_connection_in(), local);
        !           255: }
        !           256:
        !           257: int
        !           258: get_peer_port(int sock)
        !           259: {
        !           260:        return get_sock_port(sock, 0);
        !           261: }
        !           262:
        !           263: int
        !           264: get_remote_port()
        !           265: {
        !           266:        return get_port(0);
        !           267: }
1.1       deraadt   268:
1.10    ! markus    269: int
        !           270: get_local_port()
        !           271: {
        !           272:        return get_port(1);
1.1       deraadt   273: }