17243fb49Sjbeck /* 27243fb49Sjbeck * CDDL HEADER START 37243fb49Sjbeck * 47243fb49Sjbeck * The contents of this file are subject to the terms of the 57243fb49Sjbeck * Common Development and Distribution License (the "License"). 67243fb49Sjbeck * You may not use this file except in compliance with the License. 77243fb49Sjbeck * 87243fb49Sjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97243fb49Sjbeck * or http://www.opensolaris.org/os/licensing. 107243fb49Sjbeck * See the License for the specific language governing permissions 117243fb49Sjbeck * and limitations under the License. 127243fb49Sjbeck * 137243fb49Sjbeck * When distributing Covered Code, include this CDDL HEADER in each 147243fb49Sjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157243fb49Sjbeck * If applicable, add the following below this CDDL HEADER, with the 167243fb49Sjbeck * fields enclosed by brackets "[]" replaced with your own identifying 177243fb49Sjbeck * information: Portions Copyright [yyyy] [name of copyright owner] 187243fb49Sjbeck * 197243fb49Sjbeck * CDDL HEADER END 207243fb49Sjbeck */ 217243fb49Sjbeck 227243fb49Sjbeck /* 237243fb49Sjbeck * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247243fb49Sjbeck * Use is subject to license terms. 257243fb49Sjbeck */ 267243fb49Sjbeck 277243fb49Sjbeck #pragma ident "%Z%%M% %I% %E% SMI" 287243fb49Sjbeck 297243fb49Sjbeck #include <sys/types.h> 307243fb49Sjbeck #include <sys/socket.h> 317243fb49Sjbeck #include <netdb.h> 327243fb49Sjbeck #include <netinet/in.h> 337243fb49Sjbeck #include <string.h> 347243fb49Sjbeck #include <syslog.h> 357243fb49Sjbeck #include <addr_match.h> 367243fb49Sjbeck 377243fb49Sjbeck /* 387243fb49Sjbeck * Function to compare IP addresses. It walks the list provided in 397243fb49Sjbeck * the res parameter, comparing to the original address in sin or sin6, 407243fb49Sjbeck * with some addition guidance provided by fromp. It returns B_TRUE 417243fb49Sjbeck * if a match is found, otherwise B_FALSE. 427243fb49Sjbeck */ 437243fb49Sjbeck 447243fb49Sjbeck static boolean_t 457243fb49Sjbeck find_match(const struct addrinfo *res, 467243fb49Sjbeck const struct sockaddr_storage *fromp, 477243fb49Sjbeck const struct sockaddr_in *sin, 487243fb49Sjbeck const struct sockaddr_in6 *sin6) 497243fb49Sjbeck { 507243fb49Sjbeck const struct addrinfo *ai; 517243fb49Sjbeck 527243fb49Sjbeck /* This is the moral equivalent of an assert. */ 537243fb49Sjbeck if ((fromp->ss_family == AF_INET && sin == NULL) || 547243fb49Sjbeck (fromp->ss_family == AF_INET6 && sin6 == NULL)) 557243fb49Sjbeck return (B_FALSE); 567243fb49Sjbeck 577243fb49Sjbeck for (ai = res; ai != NULL; ai = ai->ai_next) { 587243fb49Sjbeck struct sockaddr_in *s4; 597243fb49Sjbeck struct sockaddr_in6 *s6; 607243fb49Sjbeck void *addr1, *addr2; 617243fb49Sjbeck size_t size; 627243fb49Sjbeck 637243fb49Sjbeck if (ai->ai_family != fromp->ss_family) 647243fb49Sjbeck continue; 657243fb49Sjbeck if (ai->ai_family == AF_INET) { 667243fb49Sjbeck /* LINTED E_BAD_PTR_CAST_ALIGN */ 677243fb49Sjbeck s4 = (struct sockaddr_in *)ai->ai_addr; 687243fb49Sjbeck addr1 = &s4->sin_addr; 697243fb49Sjbeck addr2 = &((struct sockaddr_in *)sin)->sin_addr; 707243fb49Sjbeck size = sizeof (struct in_addr); 717243fb49Sjbeck } else if (ai->ai_family == AF_INET6) { 727243fb49Sjbeck /* LINTED E_BAD_PTR_CAST_ALIGN */ 737243fb49Sjbeck s6 = (struct sockaddr_in6 *)ai->ai_addr; 747243fb49Sjbeck addr1 = &s6->sin6_addr; 757243fb49Sjbeck addr2 = &((struct sockaddr_in6 *)sin6)->sin6_addr; 767243fb49Sjbeck size = sizeof (struct in6_addr); 777243fb49Sjbeck } else { 787243fb49Sjbeck continue; 797243fb49Sjbeck } 807243fb49Sjbeck if (memcmp(addr1, addr2, size) == 0) 817243fb49Sjbeck return (B_TRUE); 827243fb49Sjbeck } 837243fb49Sjbeck return (B_FALSE); 847243fb49Sjbeck } 857243fb49Sjbeck 867243fb49Sjbeck void 877243fb49Sjbeck check_address(const char *prog, 887243fb49Sjbeck const struct sockaddr_storage *fromp, 897243fb49Sjbeck const struct sockaddr_in *sin, 907243fb49Sjbeck const struct sockaddr_in6 *sin6, 917243fb49Sjbeck const char *printable_addr, 927243fb49Sjbeck char *hostname, 937243fb49Sjbeck size_t hostsize) 947243fb49Sjbeck { 957243fb49Sjbeck /* 967243fb49Sjbeck * We have to check for spoofing. So take hostname, look up its 977243fb49Sjbeck * address(es), and walk the list until we have a match with the 987243fb49Sjbeck * original IP address. If no match is found, log a warning and 997243fb49Sjbeck * use the original IP address for authentication purposes. 1007243fb49Sjbeck */ 1017243fb49Sjbeck struct addrinfo *res, hints; 1027243fb49Sjbeck boolean_t match_found = B_FALSE; 1037243fb49Sjbeck 1047243fb49Sjbeck (void) memset(&hints, 0, sizeof (hints)); 105*07070659Sjbeck hints.ai_flags = AI_CANONNAME|AI_V4MAPPED|AI_ADDRCONFIG|AI_ALL; 1067243fb49Sjbeck hints.ai_family = fromp->ss_family; 107f4071a56Sjbeck if (getaddrinfo(hostname, NULL, &hints, &res) == 0) { 1087243fb49Sjbeck match_found = find_match(res, fromp, sin, sin6); 109f4071a56Sjbeck freeaddrinfo(res); 110f4071a56Sjbeck } 1117243fb49Sjbeck if (!match_found) { 1127243fb49Sjbeck syslog(LOG_WARNING, "%s: IP address '%s' maps to host " 1137243fb49Sjbeck "name '%s',\r\n but that host name does not map to " 1147243fb49Sjbeck "the same IP address.", prog, printable_addr, hostname); 1157243fb49Sjbeck (void) strlcpy(hostname, printable_addr, hostsize); 1167243fb49Sjbeck } 1177243fb49Sjbeck } 118