[BZ #5186]
[glibc.git] / resolv / ns_samedomain.c
blob1fb1c552d065b07b2f08c71cee3651969afd502e
1 /*
2 * Copyright (c) 1995,1999 by Internet Software Consortium.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
18 #if !defined(_LIBC) && !defined(lint)
19 static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51 vixie Exp $";
20 #endif
22 #include <sys/types.h>
23 #include <arpa/nameser.h>
24 #include <errno.h>
25 #include <string.h>
28 * int
29 * ns_samedomain(a, b)
30 * Check whether a name belongs to a domain.
31 * Inputs:
32 * a - the domain whose ancestory is being verified
33 * b - the potential ancestor we're checking against
34 * Return:
35 * boolean - is a at or below b?
36 * Notes:
37 * Trailing dots are first removed from name and domain.
38 * Always compare complete subdomains, not only whether the
39 * domain name is the trailing string of the given name.
41 * "host.foobar.top" lies in "foobar.top" and in "top" and in ""
42 * but NOT in "bar.top"
45 int
46 ns_samedomain(const char *a, const char *b) {
47 size_t la, lb;
48 int diff, i, escaped;
49 const char *cp;
51 la = strlen(a);
52 lb = strlen(b);
54 /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
55 if (la != 0 && a[la - 1] == '.') {
56 escaped = 0;
57 /* Note this loop doesn't get executed if la==1. */
58 for (i = la - 2; i >= 0; i--)
59 if (a[i] == '\\') {
60 if (escaped)
61 escaped = 0;
62 else
63 escaped = 1;
64 } else
65 break;
66 if (!escaped)
67 la--;
70 /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
71 if (lb != 0 && b[lb - 1] == '.') {
72 escaped = 0;
73 /* note this loop doesn't get executed if lb==1 */
74 for (i = lb - 2; i >= 0; i--)
75 if (b[i] == '\\') {
76 if (escaped)
77 escaped = 0;
78 else
79 escaped = 1;
80 } else
81 break;
82 if (!escaped)
83 lb--;
86 /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
87 if (lb == 0)
88 return (1);
90 /* 'b' longer than 'a' means 'a' can't be in 'b'. */
91 if (lb > la)
92 return (0);
94 /* 'a' and 'b' being equal at this point indicates sameness. */
95 if (lb == la)
96 return (strncasecmp(a, b, lb) == 0);
98 /* Ok, we know la > lb. */
100 diff = la - lb;
103 * If 'a' is only 1 character longer than 'b', then it can't be
104 * a subdomain of 'b' (because of the need for the '.' label
105 * separator).
107 if (diff < 2)
108 return (0);
111 * If the character before the last 'lb' characters of 'b'
112 * isn't '.', then it can't be a match (this lets us avoid
113 * having "foobar.com" match "bar.com").
115 if (a[diff - 1] != '.')
116 return (0);
119 * We're not sure about that '.', however. It could be escaped
120 * and thus not a really a label separator.
122 escaped = 0;
123 for (i = diff - 2; i >= 0; i--)
124 if (a[i] == '\\')
125 if (escaped)
126 escaped = 0;
127 else
128 escaped = 1;
129 else
130 break;
131 if (escaped)
132 return (0);
134 /* Now compare aligned trailing substring. */
135 cp = a + diff;
136 return (strncasecmp(cp, b, lb) == 0);
140 * int
141 * ns_subdomain(a, b)
142 * is "a" a subdomain of "b"?
145 ns_subdomain(const char *a, const char *b) {
146 return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
150 * int
151 * ns_makecanon(src, dst, dstsize)
152 * make a canonical copy of domain name "src"
153 * notes:
154 * foo -> foo.
155 * foo. -> foo.
156 * foo.. -> foo.
157 * foo\. -> foo\..
158 * foo\\. -> foo\\.
162 ns_makecanon(const char *src, char *dst, size_t dstsize) {
163 size_t n = strlen(src);
165 if (n + sizeof "." > dstsize) {
166 __set_errno (EMSGSIZE);
167 return (-1);
169 strcpy(dst, src);
170 while (n > 0 && dst[n - 1] == '.') /* Ends in "." */
171 if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */
172 (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */
173 break;
174 else
175 dst[--n] = '\0';
176 dst[n++] = '.';
177 dst[n] = '\0';
178 return (0);
182 * int
183 * ns_samename(a, b)
184 * determine whether domain name "a" is the same as domain name "b"
185 * return:
186 * -1 on error
187 * 0 if names differ
188 * 1 if names are the same
192 ns_samename(const char *a, const char *b) {
193 char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
195 if (ns_makecanon(a, ta, sizeof ta) < 0 ||
196 ns_makecanon(b, tb, sizeof tb) < 0)
197 return (-1);
198 if (strcasecmp(ta, tb) == 0)
199 return (1);
200 else
201 return (0);