Changeset c39cd8e for lib/misc.c


Ignore:
Timestamp:
2017-04-02T18:50:49Z (7 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Children:
df67b48
Parents:
262a82b
Message:

Add reverse_lookup() function which does a more proper (verified) DNS
reverse lookup. (Code copied from OpenSSH instead of redoing it
poorly.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/misc.c

    r262a82b rc39cd8e  
    549549}
    550550
     551/* From OpenSSH 7.4p1 canohost.c" */
     552char *reverse_lookup(const struct sockaddr *from_, const socklen_t fromlen_)
     553{
     554        struct sockaddr_storage from;
     555        socklen_t fromlen;
     556        struct addrinfo hints, *ai, *aitop;
     557        char name[NI_MAXHOST], ntop2[NI_MAXHOST];
     558        char ntop[INET6_ADDRSTRLEN];
     559
     560        fromlen = sizeof(from);
     561        memset(&from, 0, sizeof(from));
     562        memcpy(&from, from_, fromlen_);
     563        ipv64_normalise_mapped(&from, &fromlen);
     564        if (from.ss_family == AF_INET6) {
     565                fromlen = sizeof(struct sockaddr_in6);
     566        }
     567
     568        if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
     569            NULL, 0, NI_NUMERICHOST) != 0) {
     570                return NULL;
     571        }
     572
     573        /* Map the IP address to a host name. */
     574        if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
     575            NULL, 0, NI_NAMEREQD) != 0) {
     576                /* Host name not found.  Use ip address. */
     577                return g_strdup(ntop);
     578        }
     579
     580        /*
     581         * if reverse lookup result looks like a numeric hostname,
     582         * someone is trying to trick us by PTR record like following:
     583         *      1.1.1.10.in-addr.arpa.  IN PTR  2.3.4.5
     584         */
     585        memset(&hints, 0, sizeof(hints));
     586        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
     587        hints.ai_flags = AI_NUMERICHOST;
     588        if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
     589                freeaddrinfo(ai);
     590                return g_strdup(ntop);
     591        }
     592
     593        /* Names are stored in lowercase. */
     594        char *tolower = g_utf8_strdown(name, -1);
     595        g_snprintf(name, sizeof(name), "%s", tolower);
     596        g_free(tolower);
     597
     598        /*
     599         * Map it back to an IP address and check that the given
     600         * address actually is an address of this host.  This is
     601         * necessary because anyone with access to a name server can
     602         * define arbitrary names for an IP address. Mapping from
     603         * name to IP address can be trusted better (but can still be
     604         * fooled if the intruder has access to the name server of
     605         * the domain).
     606         */
     607        memset(&hints, 0, sizeof(hints));
     608        hints.ai_family = from.ss_family;
     609        hints.ai_socktype = SOCK_STREAM;
     610        if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
     611                return g_strdup(ntop);
     612        }
     613        /* Look for the address from the list of addresses. */
     614        for (ai = aitop; ai; ai = ai->ai_next) {
     615                if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
     616                    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
     617                    (strcmp(ntop, ntop2) == 0))
     618                        break;
     619        }
     620        freeaddrinfo(aitop);
     621        /* If we reached the end of the list, the address was not there. */
     622        if (ai == NULL) {
     623                /* Address not found for the host name. */
     624                return g_strdup(ntop);
     625        }
     626        return g_strdup(name);
     627}
     628
     629void
     630ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
     631{
     632        struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;
     633        struct sockaddr_in *a4 = (struct sockaddr_in *)addr;
     634        struct in_addr inaddr;
     635        u_int16_t port;
     636
     637        if (addr->ss_family != AF_INET6 ||
     638            !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr))
     639                return;
     640
     641        memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
     642        port = a6->sin6_port;
     643
     644        memset(a4, 0, sizeof(*a4));
     645
     646        a4->sin_family = AF_INET;
     647        *len = sizeof(*a4);
     648        memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr));
     649        a4->sin_port = port;
     650}
     651
    551652char *word_wrap(const char *msg, int line_len)
    552653{
Note: See TracChangeset for help on using the changeset viewer.