4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <netinet/in.h>
35 #include <addr_match.h>
38 * Function to compare IP addresses. It walks the list provided in
39 * the res parameter, comparing to the original address in sin or sin6,
40 * with some addition guidance provided by fromp. It returns B_TRUE
41 * if a match is found, otherwise B_FALSE.
45 find_match(const struct addrinfo
*res
,
46 const struct sockaddr_storage
*fromp
,
47 const struct sockaddr_in
*sin
,
48 const struct sockaddr_in6
*sin6
)
50 const struct addrinfo
*ai
;
52 /* This is the moral equivalent of an assert. */
53 if ((fromp
->ss_family
== AF_INET
&& sin
== NULL
) ||
54 (fromp
->ss_family
== AF_INET6
&& sin6
== NULL
))
57 for (ai
= res
; ai
!= NULL
; ai
= ai
->ai_next
) {
58 struct sockaddr_in
*s4
;
59 struct sockaddr_in6
*s6
;
63 if (ai
->ai_family
!= fromp
->ss_family
)
65 if (ai
->ai_family
== AF_INET
) {
66 /* LINTED E_BAD_PTR_CAST_ALIGN */
67 s4
= (struct sockaddr_in
*)ai
->ai_addr
;
68 addr1
= &s4
->sin_addr
;
69 addr2
= &((struct sockaddr_in
*)sin
)->sin_addr
;
70 size
= sizeof (struct in_addr
);
71 } else if (ai
->ai_family
== AF_INET6
) {
72 /* LINTED E_BAD_PTR_CAST_ALIGN */
73 s6
= (struct sockaddr_in6
*)ai
->ai_addr
;
74 addr1
= &s6
->sin6_addr
;
75 addr2
= &((struct sockaddr_in6
*)sin6
)->sin6_addr
;
76 size
= sizeof (struct in6_addr
);
80 if (memcmp(addr1
, addr2
, size
) == 0)
87 check_address(const char *prog
,
88 const struct sockaddr_storage
*fromp
,
89 const struct sockaddr_in
*sin
,
90 const struct sockaddr_in6
*sin6
,
91 const char *printable_addr
,
96 * We have to check for spoofing. So take hostname, look up its
97 * address(es), and walk the list until we have a match with the
98 * original IP address. If no match is found, log a warning and
99 * use the original IP address for authentication purposes.
101 struct addrinfo
*res
, hints
;
102 boolean_t match_found
= B_FALSE
;
104 (void) memset(&hints
, 0, sizeof (hints
));
105 hints
.ai_flags
= AI_CANONNAME
|AI_V4MAPPED
|AI_ADDRCONFIG
|AI_ALL
;
106 hints
.ai_family
= fromp
->ss_family
;
107 if (getaddrinfo(hostname
, NULL
, &hints
, &res
) == 0) {
108 match_found
= find_match(res
, fromp
, sin
, sin6
);
112 syslog(LOG_WARNING
, "%s: IP address '%s' maps to host "
113 "name '%s',\r\n but that host name does not map to "
114 "the same IP address.", prog
, printable_addr
, hostname
);
115 (void) strlcpy(hostname
, printable_addr
, hostsize
);