Merge from vendor branch BSDTAR:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / ssu.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /*
19  * $Id: ssu.c,v 1.22.2.1 2004/03/09 06:11:08 marka Exp $
20  * Principal Author: Brian Wellington
21  */
22
23 #include <config.h>
24
25 #include <isc/magic.h>
26 #include <isc/mem.h>
27 #include <isc/string.h>         /* Required for HP/UX (and others?) */
28 #include <isc/util.h>
29
30 #include <dns/name.h>
31 #include <dns/ssu.h>
32
33 #define SSUTABLEMAGIC           ISC_MAGIC('S', 'S', 'U', 'T')
34 #define VALID_SSUTABLE(table)   ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
35
36 #define SSURULEMAGIC            ISC_MAGIC('S', 'S', 'U', 'R')
37 #define VALID_SSURULE(table)    ISC_MAGIC_VALID(table, SSURULEMAGIC)
38
39 struct dns_ssurule {
40         unsigned int magic;
41         isc_boolean_t grant;    /* is this a grant or a deny? */
42         unsigned int matchtype; /* which type of pattern match? */
43         dns_name_t *identity;   /* the identity to match */
44         dns_name_t *name;       /* the name being updated */
45         unsigned int ntypes;    /* number of data types covered */
46         dns_rdatatype_t *types; /* the data types.  Can include ANY, */
47                                 /* defaults to all but SIG,SOA,NS if NULL*/
48         ISC_LINK(dns_ssurule_t) link;
49 };
50
51 struct dns_ssutable {
52         unsigned int magic;
53         isc_mem_t *mctx;
54         unsigned int references;
55         isc_mutex_t lock;
56         ISC_LIST(dns_ssurule_t) rules;
57 };
58
59 isc_result_t
60 dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
61         isc_result_t result;
62         dns_ssutable_t *table;
63
64         REQUIRE(tablep != NULL && *tablep == NULL);
65         REQUIRE(mctx != NULL);
66
67         table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
68         if (table == NULL)
69                 return (ISC_R_NOMEMORY);
70         result = isc_mutex_init(&table->lock);
71         if (result != ISC_R_SUCCESS) {
72                 isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
73                 return (result);
74         }
75         table->references = 1;
76         table->mctx = mctx;
77         ISC_LIST_INIT(table->rules);
78         table->magic = SSUTABLEMAGIC;
79         *tablep = table;
80         return (ISC_R_SUCCESS);
81 }
82
83 static inline void
84 destroy(dns_ssutable_t *table) {
85         isc_mem_t *mctx;
86
87         REQUIRE(VALID_SSUTABLE(table));
88
89         mctx = table->mctx;
90         while (!ISC_LIST_EMPTY(table->rules)) {
91                 dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
92                 if (rule->identity != NULL) {
93                         dns_name_free(rule->identity, mctx);
94                         isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
95                 }
96                 if (rule->name != NULL) {
97                         dns_name_free(rule->name, mctx);
98                         isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
99                 }
100                 if (rule->types != NULL)
101                         isc_mem_put(mctx, rule->types,
102                                     rule->ntypes * sizeof(dns_rdatatype_t));
103                 ISC_LIST_UNLINK(table->rules, rule, link);
104                 rule->magic = 0;
105                 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
106         }
107         DESTROYLOCK(&table->lock);
108         table->magic = 0;
109         isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
110 }
111
112 void
113 dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
114         REQUIRE(VALID_SSUTABLE(source));
115         REQUIRE(targetp != NULL && *targetp == NULL);
116
117         LOCK(&source->lock);
118
119         INSIST(source->references > 0);
120         source->references++;
121         INSIST(source->references != 0);
122
123         UNLOCK(&source->lock);
124
125         *targetp = source;
126 }
127
128 void
129 dns_ssutable_detach(dns_ssutable_t **tablep) {
130         dns_ssutable_t *table;
131         isc_boolean_t done = ISC_FALSE;
132
133         REQUIRE(tablep != NULL);
134         table = *tablep;
135         REQUIRE(VALID_SSUTABLE(table));
136
137         LOCK(&table->lock);
138
139         INSIST(table->references > 0);
140         if (--table->references == 0)
141                 done = ISC_TRUE;
142         UNLOCK(&table->lock);
143
144         *tablep = NULL;
145
146         if (done)
147                 destroy(table);
148 }
149
150 isc_result_t
151 dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
152                      dns_name_t *identity, unsigned int matchtype,
153                      dns_name_t *name, unsigned int ntypes,
154                      dns_rdatatype_t *types)
155 {
156         dns_ssurule_t *rule;
157         isc_mem_t *mctx;
158         isc_result_t result;
159
160         REQUIRE(VALID_SSUTABLE(table));
161         REQUIRE(dns_name_isabsolute(identity));
162         REQUIRE(dns_name_isabsolute(name));
163         REQUIRE(matchtype <= DNS_SSUMATCHTYPE_SELF);
164         if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
165                 REQUIRE(dns_name_iswildcard(name));
166         if (ntypes > 0)
167                 REQUIRE(types != NULL);
168
169         mctx = table->mctx;
170         rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
171         if (rule == NULL)
172                 return (ISC_R_NOMEMORY);
173
174         rule->identity = NULL;
175         rule->name = NULL;
176         rule->types = NULL;
177
178         rule->grant = grant;
179
180         rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
181         if (rule->identity == NULL) {
182                 result = ISC_R_NOMEMORY;
183                 goto failure;
184         }
185         dns_name_init(rule->identity, NULL);
186         result = dns_name_dup(identity, mctx, rule->identity);
187         if (result != ISC_R_SUCCESS)
188                 goto failure;
189
190         rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
191         if (rule->name == NULL) {
192                 result = ISC_R_NOMEMORY;
193                 goto failure;
194         }
195         dns_name_init(rule->name, NULL);
196         result = dns_name_dup(name, mctx, rule->name);
197         if (result != ISC_R_SUCCESS)
198                 goto failure;
199
200         rule->matchtype = matchtype;
201
202         rule->ntypes = ntypes;
203         if (ntypes > 0) {
204                 rule->types = isc_mem_get(mctx,
205                                           ntypes * sizeof(dns_rdatatype_t));
206                 if (rule->types == NULL) {
207                         result = ISC_R_NOMEMORY;
208                         goto failure;
209                 }
210                 memcpy(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
211         }
212         else
213                 rule->types = NULL;
214
215         rule->magic = SSURULEMAGIC;
216         ISC_LIST_INITANDAPPEND(table->rules, rule, link);
217
218         return (ISC_R_SUCCESS);
219
220  failure:
221         if (rule->identity != NULL) {
222                 if (dns_name_dynamic(rule->identity))
223                         dns_name_free(rule->identity, mctx);
224                 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
225         }
226         if (rule->name != NULL) {
227                 if (dns_name_dynamic(rule->name))
228                         dns_name_free(rule->name, mctx);
229                 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
230         }
231         if (rule->types != NULL)
232                 isc_mem_put(mctx, rule->types,
233                             ntypes * sizeof(dns_rdatatype_t));
234         isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
235
236         return (result);
237 }
238
239 static inline isc_boolean_t
240 isusertype(dns_rdatatype_t type) {
241         return (ISC_TF(type != dns_rdatatype_ns &&
242                        type != dns_rdatatype_soa &&
243                        type != dns_rdatatype_sig));
244 }
245
246 isc_boolean_t
247 dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
248                         dns_name_t *name, dns_rdatatype_t type)
249 {
250         dns_ssurule_t *rule;
251         unsigned int i;
252
253         REQUIRE(VALID_SSUTABLE(table));
254         REQUIRE(signer == NULL || dns_name_isabsolute(signer));
255         REQUIRE(dns_name_isabsolute(name));
256
257         if (signer == NULL)
258                 return (ISC_FALSE);
259         rule = ISC_LIST_HEAD(table->rules);
260                 rule = ISC_LIST_NEXT(rule, link);
261         for (rule = ISC_LIST_HEAD(table->rules);
262              rule != NULL;
263              rule = ISC_LIST_NEXT(rule, link))
264         {
265                 if (dns_name_iswildcard(rule->identity)) {
266                         if (!dns_name_matcheswildcard(signer, rule->identity))
267                                 continue;
268                 }
269                 else {
270                         if (!dns_name_equal(signer, rule->identity))
271                                 continue;
272                 }
273
274                 if (rule->matchtype == DNS_SSUMATCHTYPE_NAME) {
275                         if (!dns_name_equal(name, rule->name))
276                                 continue;
277                 }
278                 else if (rule->matchtype == DNS_SSUMATCHTYPE_SUBDOMAIN) {
279                         if (!dns_name_issubdomain(name, rule->name))
280                                 continue;
281                 }
282                 else if (rule->matchtype == DNS_SSUMATCHTYPE_WILDCARD) {
283                         if (!dns_name_matcheswildcard(name, rule->name))
284                                 continue;
285
286                 }
287                 else if (rule->matchtype == DNS_SSUMATCHTYPE_SELF) {
288                         if (!dns_name_equal(signer, name))
289                                 continue;
290                 }
291
292                 if (rule->ntypes == 0) {
293                         if (!isusertype(type))
294                                 continue;
295                 }
296                 else {
297                         for (i = 0; i < rule->ntypes; i++) {
298                                 if (rule->types[i] == dns_rdatatype_any ||
299                                     rule->types[i] == type)
300                                         break;
301                         }
302                         if (i == rule->ntypes)
303                                 continue;
304                 }
305                 return (rule->grant);
306         }
307
308         return (ISC_FALSE);
309 }
310
311 isc_boolean_t
312 dns_ssurule_isgrant(const dns_ssurule_t *rule) {
313         REQUIRE(VALID_SSURULE(rule));
314         return (rule->grant);
315 }
316
317 dns_name_t *
318 dns_ssurule_identity(const dns_ssurule_t *rule) {
319         REQUIRE(VALID_SSURULE(rule));
320         return (rule->identity);
321 }
322
323 unsigned int
324 dns_ssurule_matchtype(const dns_ssurule_t *rule) {
325         REQUIRE(VALID_SSURULE(rule));
326         return (rule->matchtype);
327 }
328
329 dns_name_t *
330 dns_ssurule_name(const dns_ssurule_t *rule) {
331         REQUIRE(VALID_SSURULE(rule));
332         return (rule->name);
333 }
334
335 unsigned int
336 dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
337         REQUIRE(VALID_SSURULE(rule));
338         REQUIRE(types != NULL && *types != NULL);
339         *types = rule->types;
340         return (rule->ntypes);
341 }
342
343 isc_result_t
344 dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
345         REQUIRE(VALID_SSUTABLE(table));
346         REQUIRE(rule != NULL && *rule == NULL);
347         *rule = ISC_LIST_HEAD(table->rules);
348         return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
349 }
350
351 isc_result_t
352 dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
353         REQUIRE(VALID_SSURULE(rule));
354         REQUIRE(nextrule != NULL && *nextrule == NULL);
355         *nextrule = ISC_LIST_NEXT(rule, link);
356         return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
357 }