Annotation of src/lib/libc/nameser/ns_samedomain.c, Revision 1.5
1.5 ! christos 1: /* $NetBSD: ns_samedomain.c,v 1.4 2007/03/30 20:23:03 ghen Exp $ */
1.1 christos 2:
3: /*
4: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5: * Copyright (c) 1995,1999 by Internet Software Consortium.
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
1.2 christos 20: #include <sys/cdefs.h>
1.1 christos 21: #ifndef lint
1.2 christos 22: #ifdef notdef
1.5 ! christos 23: static const char rcsid[] = "Id: ns_samedomain.c,v 1.6 2005/04/27 04:56:40 sra Exp";
1.2 christos 24: #else
1.5 ! christos 25: __RCSID("$NetBSD: ns_samedomain.c,v 1.4 2007/03/30 20:23:03 ghen Exp $");
1.2 christos 26: #endif
1.1 christos 27: #endif
28:
29: #include "port_before.h"
30:
31: #include <sys/types.h>
32: #include <arpa/nameser.h>
33: #include <errno.h>
34: #include <string.h>
35:
36: #include "port_after.h"
37:
1.2 christos 38: #ifndef _LIBC
1.3 christos 39: /*%
1.1 christos 40: * Check whether a name belongs to a domain.
1.3 christos 41: *
1.1 christos 42: * Inputs:
1.3 christos 43: *\li a - the domain whose ancestory is being verified
44: *\li b - the potential ancestor we're checking against
45: *
1.1 christos 46: * Return:
1.3 christos 47: *\li boolean - is a at or below b?
48: *
1.1 christos 49: * Notes:
1.3 christos 50: *\li Trailing dots are first removed from name and domain.
1.1 christos 51: * Always compare complete subdomains, not only whether the
52: * domain name is the trailing string of the given name.
53: *
1.3 christos 54: *\li "host.foobar.top" lies in "foobar.top" and in "top" and in ""
1.1 christos 55: * but NOT in "bar.top"
56: */
57:
58: int
59: ns_samedomain(const char *a, const char *b) {
60: size_t la, lb;
61: int diff, i, escaped;
62: const char *cp;
63:
64: la = strlen(a);
65: lb = strlen(b);
66:
67: /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
68: if (la != 0U && a[la - 1] == '.') {
69: escaped = 0;
70: /* Note this loop doesn't get executed if la==1. */
71: for (i = la - 2; i >= 0; i--)
72: if (a[i] == '\\') {
73: if (escaped)
74: escaped = 0;
75: else
76: escaped = 1;
77: } else
78: break;
79: if (!escaped)
80: la--;
81: }
82:
83: /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
84: if (lb != 0U && b[lb - 1] == '.') {
85: escaped = 0;
86: /* note this loop doesn't get executed if lb==1 */
87: for (i = lb - 2; i >= 0; i--)
88: if (b[i] == '\\') {
89: if (escaped)
90: escaped = 0;
91: else
92: escaped = 1;
93: } else
94: break;
95: if (!escaped)
96: lb--;
97: }
98:
99: /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
100: if (lb == 0U)
101: return (1);
102:
103: /* 'b' longer than 'a' means 'a' can't be in 'b'. */
104: if (lb > la)
105: return (0);
106:
107: /* 'a' and 'b' being equal at this point indicates sameness. */
108: if (lb == la)
109: return (strncasecmp(a, b, lb) == 0);
110:
111: /* Ok, we know la > lb. */
112:
113: diff = la - lb;
114:
115: /*
116: * If 'a' is only 1 character longer than 'b', then it can't be
117: * a subdomain of 'b' (because of the need for the '.' label
118: * separator).
119: */
120: if (diff < 2)
121: return (0);
122:
123: /*
124: * If the character before the last 'lb' characters of 'b'
125: * isn't '.', then it can't be a match (this lets us avoid
126: * having "foobar.com" match "bar.com").
127: */
128: if (a[diff - 1] != '.')
129: return (0);
130:
131: /*
132: * We're not sure about that '.', however. It could be escaped
133: * and thus not a really a label separator.
134: */
135: escaped = 0;
136: for (i = diff - 2; i >= 0; i--)
137: if (a[i] == '\\') {
138: if (escaped)
139: escaped = 0;
140: else
141: escaped = 1;
142: } else
143: break;
144: if (escaped)
145: return (0);
146:
147: /* Now compare aligned trailing substring. */
148: cp = a + diff;
149: return (strncasecmp(cp, b, lb) == 0);
150: }
151:
1.3 christos 152: /*%
1.1 christos 153: * is "a" a subdomain of "b"?
154: */
155: int
156: ns_subdomain(const char *a, const char *b) {
157: return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
158: }
1.2 christos 159: #endif
1.1 christos 160:
1.3 christos 161: /*%
1.1 christos 162: * make a canonical copy of domain name "src"
1.3 christos 163: *
1.1 christos 164: * notes:
1.3 christos 165: * \code
1.1 christos 166: * foo -> foo.
167: * foo. -> foo.
168: * foo.. -> foo.
169: * foo\. -> foo\..
170: * foo\\. -> foo\\.
1.3 christos 171: * \endcode
1.1 christos 172: */
173:
174: int
175: ns_makecanon(const char *src, char *dst, size_t dstsize) {
176: size_t n = strlen(src);
177:
1.3 christos 178: if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */
1.1 christos 179: errno = EMSGSIZE;
180: return (-1);
181: }
182: strcpy(dst, src);
1.3 christos 183: while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */
184: if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */
185: (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */
1.1 christos 186: break;
187: else
188: dst[--n] = '\0';
189: dst[n++] = '.';
190: dst[n] = '\0';
191: return (0);
192: }
193:
1.3 christos 194: /*%
1.1 christos 195: * determine whether domain name "a" is the same as domain name "b"
1.3 christos 196: *
1.1 christos 197: * return:
1.3 christos 198: *\li -1 on error
199: *\li 0 if names differ
200: *\li 1 if names are the same
1.1 christos 201: */
202:
203: int
204: ns_samename(const char *a, const char *b) {
205: char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
206:
207: if (ns_makecanon(a, ta, sizeof ta) < 0 ||
208: ns_makecanon(b, tb, sizeof tb) < 0)
209: return (-1);
210: if (strcasecmp(ta, tb) == 0)
211: return (1);
212: else
213: return (0);
214: }
1.3 christos 215:
216: /*! \file */
CVSweb <webmaster@jp.NetBSD.org>