7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck/*
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * CDDL HEADER START
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck *
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * The contents of this file are subject to the terms of the
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * Common Development and Distribution License (the "License").
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * You may not use this file except in compliance with the License.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck *
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * or http://www.opensolaris.org/os/licensing.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * See the License for the specific language governing permissions
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * and limitations under the License.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck *
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * When distributing Covered Code, include this CDDL HEADER in each
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * If applicable, add the following below this CDDL HEADER, with the
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * fields enclosed by brackets "[]" replaced with your own identifying
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * information: Portions Copyright [yyyy] [name of copyright owner]
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck *
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * CDDL HEADER END
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck/*
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * Use is subject to license terms.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#pragma ident "%Z%%M% %I% %E% SMI"
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <sys/types.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <sys/socket.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <netdb.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <netinet/in.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <string.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <syslog.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck#include <addr_match.h>
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck/*
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * Function to compare IP addresses. It walks the list provided in
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * the res parameter, comparing to the original address in sin or sin6,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * with some addition guidance provided by fromp. It returns B_TRUE
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * if a match is found, otherwise B_FALSE.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeckstatic boolean_t
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeckfind_match(const struct addrinfo *res,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_storage *fromp,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_in *sin,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_in6 *sin6)
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck{
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct addrinfo *ai;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck /* This is the moral equivalent of an assert. */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck if ((fromp->ss_family == AF_INET && sin == NULL) ||
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck (fromp->ss_family == AF_INET6 && sin6 == NULL))
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck return (B_FALSE);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck for (ai = res; ai != NULL; ai = ai->ai_next) {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck struct sockaddr_in *s4;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck struct sockaddr_in6 *s6;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck void *addr1, *addr2;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck size_t size;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck if (ai->ai_family != fromp->ss_family)
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck continue;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck if (ai->ai_family == AF_INET) {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck /* LINTED E_BAD_PTR_CAST_ALIGN */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck s4 = (struct sockaddr_in *)ai->ai_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck addr1 = &s4->sin_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck addr2 = &((struct sockaddr_in *)sin)->sin_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck size = sizeof (struct in_addr);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck } else if (ai->ai_family == AF_INET6) {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck /* LINTED E_BAD_PTR_CAST_ALIGN */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck s6 = (struct sockaddr_in6 *)ai->ai_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck addr1 = &s6->sin6_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck addr2 = &((struct sockaddr_in6 *)sin6)->sin6_addr;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck size = sizeof (struct in6_addr);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck } else {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck continue;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck }
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck if (memcmp(addr1, addr2, size) == 0)
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck return (B_TRUE);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck }
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck return (B_FALSE);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck}
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeckvoid
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeckcheck_address(const char *prog,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_storage *fromp,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_in *sin,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const struct sockaddr_in6 *sin6,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck const char *printable_addr,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck char *hostname,
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck size_t hostsize)
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck{
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck /*
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * We have to check for spoofing. So take hostname, look up its
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * address(es), and walk the list until we have a match with the
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * original IP address. If no match is found, log a warning and
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck * use the original IP address for authentication purposes.
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck */
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck struct addrinfo *res, hints;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck boolean_t match_found = B_FALSE;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck (void) memset(&hints, 0, sizeof (hints));
07070659d3b755175df60ae6860c2b082250982fjbeck hints.ai_flags = AI_CANONNAME|AI_V4MAPPED|AI_ADDRCONFIG|AI_ALL;
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck hints.ai_family = fromp->ss_family;
f4071a5683050f6f49339c0e37912b9778ecb8bajbeck if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck match_found = find_match(res, fromp, sin, sin6);
f4071a5683050f6f49339c0e37912b9778ecb8bajbeck freeaddrinfo(res);
f4071a5683050f6f49339c0e37912b9778ecb8bajbeck }
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck if (!match_found) {
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck syslog(LOG_WARNING, "%s: IP address '%s' maps to host "
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck "name '%s',\r\n but that host name does not map to "
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck "the same IP address.", prog, printable_addr, hostname);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck (void) strlcpy(hostname, printable_addr, hostsize);
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck }
7243fb49732852c0e9ce39939a905b2a40f2ddebjbeck}