]> git.saurik.com Git - apple/libresolv.git/blob - ns_samedomain.c
libresolv-65.200.2.tar.gz
[apple/libresolv.git] / ns_samedomain.c
1 /*
2 * Copyright (c) 1995,1999 by Internet Software Consortium.
3 *
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.
7 *
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.
16 */
17
18 #ifndef __APPLE__
19 #ifndef lint
20 static const char rcsid[] = "$Id: ns_samedomain.c,v 1.1 2006/03/01 19:01:37 majka Exp $";
21 #endif
22 #endif
23
24 #ifndef __APPLE__
25 #include "port_before.h"
26 #endif
27
28 #include <sys/types.h>
29 #include <arpa/nameser.h>
30 #include <errno.h>
31 #include <string.h>
32
33 #ifndef __APPLE__
34 #include "port_after.h"
35 #endif
36
37 /*
38 * int
39 * ns_samedomain(a, b)
40 * Check whether a name belongs to a domain.
41 * Inputs:
42 * a - the domain whose ancestory is being verified
43 * b - the potential ancestor we're checking against
44 * Return:
45 * boolean - is a at or below b?
46 * Notes:
47 * Trailing dots are first removed from name and domain.
48 * Always compare complete subdomains, not only whether the
49 * domain name is the trailing string of the given name.
50 *
51 * "host.foobar.top" lies in "foobar.top" and in "top" and in ""
52 * but NOT in "bar.top"
53 */
54
55 int
56 ns_samedomain(const char *a, const char *b) {
57 size_t la, lb;
58 int diff, i, escaped;
59 const char *cp;
60
61 la = strlen(a);
62 lb = strlen(b);
63
64 /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
65 if (la != 0 && a[la - 1] == '.') {
66 escaped = 0;
67 /* Note this loop doesn't get executed if la==1. */
68 for (i = la - 2; i >= 0; i--)
69 if (a[i] == '\\') {
70 if (escaped)
71 escaped = 0;
72 else
73 escaped = 1;
74 } else
75 break;
76 if (!escaped)
77 la--;
78 }
79
80 /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
81 if (lb != 0 && b[lb - 1] == '.') {
82 escaped = 0;
83 /* note this loop doesn't get executed if lb==1 */
84 for (i = lb - 2; i >= 0; i--)
85 if (b[i] == '\\') {
86 if (escaped)
87 escaped = 0;
88 else
89 escaped = 1;
90 } else
91 break;
92 if (!escaped)
93 lb--;
94 }
95
96 /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
97 if (lb == 0)
98 return (1);
99
100 /* 'b' longer than 'a' means 'a' can't be in 'b'. */
101 if (lb > la)
102 return (0);
103
104 /* 'a' and 'b' being equal at this point indicates sameness. */
105 if (lb == la)
106 return (strncasecmp(a, b, lb) == 0);
107
108 /* Ok, we know la > lb. */
109
110 diff = la - lb;
111
112 /*
113 * If 'a' is only 1 character longer than 'b', then it can't be
114 * a subdomain of 'b' (because of the need for the '.' label
115 * separator).
116 */
117 if (diff < 2)
118 return (0);
119
120 /*
121 * If the character before the last 'lb' characters of 'b'
122 * isn't '.', then it can't be a match (this lets us avoid
123 * having "foobar.com" match "bar.com").
124 */
125 if (a[diff - 1] != '.')
126 return (0);
127
128 /*
129 * We're not sure about that '.', however. It could be escaped
130 * and thus not a really a label separator.
131 */
132 escaped = 0;
133 for (i = diff - 2; i >= 0; i--)
134 if (a[i] == '\\') {
135 if (escaped)
136 escaped = 0;
137 else
138 escaped = 1;
139 } else
140 break;
141 if (escaped)
142 return (0);
143
144 /* Now compare aligned trailing substring. */
145 cp = a + diff;
146 return (strncasecmp(cp, b, lb) == 0);
147 }
148
149 /*
150 * int
151 * ns_subdomain(a, b)
152 * is "a" a subdomain of "b"?
153 */
154 int
155 ns_subdomain(const char *a, const char *b) {
156 return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
157 }
158
159 /*
160 * int
161 * ns_makecanon(src, dst, dstsize)
162 * make a canonical copy of domain name "src"
163 * notes:
164 * foo -> foo.
165 * foo. -> foo.
166 * foo.. -> foo.
167 * foo\. -> foo\..
168 * foo\\. -> foo\\.
169 */
170
171 int
172 ns_makecanon(const char *src, char *dst, size_t dstsize) {
173 size_t n = strlen(src);
174
175 if (n + sizeof "." > dstsize) {
176 errno = EMSGSIZE;
177 return (-1);
178 }
179 strcpy(dst, src);
180 while (n > 0 && dst[n - 1] == '.') /* Ends in "." */
181 if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */
182 (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */
183 break;
184 else
185 dst[--n] = '\0';
186 dst[n++] = '.';
187 dst[n] = '\0';
188 return (0);
189 }
190
191 /*
192 * int
193 * ns_samename(a, b)
194 * determine whether domain name "a" is the same as domain name "b"
195 * return:
196 * -1 on error
197 * 0 if names differ
198 * 1 if names are the same
199 */
200
201 int
202 ns_samename(const char *a, const char *b) {
203 char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
204
205 if (ns_makecanon(a, ta, sizeof ta) < 0 ||
206 ns_makecanon(b, tb, sizeof tb) < 0)
207 return (-1);
208 if (strcasecmp(ta, tb) == 0)
209 return (1);
210 else
211 return (0);
212 }