2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
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.
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.
20 * $Id: ssu.c,v 1.24.18.4 2006/02/16 23:51:32 marka Exp $
21 * Principal Author: Brian Wellington
26 #include <isc/magic.h>
28 #include <isc/result.h>
29 #include <isc/string.h> /* Required for HP/UX (and others?) */
32 #include <dns/fixedname.h>
36 #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
37 #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
39 #define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R')
40 #define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
44 isc_boolean_t grant; /*%< is this a grant or a deny? */
45 unsigned int matchtype; /*%< which type of pattern match? */
46 dns_name_t *identity; /*%< the identity to match */
47 dns_name_t *name; /*%< the name being updated */
48 unsigned int ntypes; /*%< number of data types covered */
49 dns_rdatatype_t *types; /*%< the data types. Can include ANY, */
50 /*%< defaults to all but SIG,SOA,NS if NULL */
51 ISC_LINK(dns_ssurule_t) link;
57 unsigned int references;
59 ISC_LIST(dns_ssurule_t) rules;
63 dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
65 dns_ssutable_t *table;
67 REQUIRE(tablep != NULL && *tablep == NULL);
68 REQUIRE(mctx != NULL);
70 table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
72 return (ISC_R_NOMEMORY);
73 result = isc_mutex_init(&table->lock);
74 if (result != ISC_R_SUCCESS) {
75 isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
78 table->references = 1;
80 ISC_LIST_INIT(table->rules);
81 table->magic = SSUTABLEMAGIC;
83 return (ISC_R_SUCCESS);
87 destroy(dns_ssutable_t *table) {
90 REQUIRE(VALID_SSUTABLE(table));
93 while (!ISC_LIST_EMPTY(table->rules)) {
94 dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
95 if (rule->identity != NULL) {
96 dns_name_free(rule->identity, mctx);
97 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
99 if (rule->name != NULL) {
100 dns_name_free(rule->name, mctx);
101 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
103 if (rule->types != NULL)
104 isc_mem_put(mctx, rule->types,
105 rule->ntypes * sizeof(dns_rdatatype_t));
106 ISC_LIST_UNLINK(table->rules, rule, link);
108 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
110 DESTROYLOCK(&table->lock);
112 isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
116 dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
117 REQUIRE(VALID_SSUTABLE(source));
118 REQUIRE(targetp != NULL && *targetp == NULL);
122 INSIST(source->references > 0);
123 source->references++;
124 INSIST(source->references != 0);
126 UNLOCK(&source->lock);
132 dns_ssutable_detach(dns_ssutable_t **tablep) {
133 dns_ssutable_t *table;
134 isc_boolean_t done = ISC_FALSE;
136 REQUIRE(tablep != NULL);
138 REQUIRE(VALID_SSUTABLE(table));
142 INSIST(table->references > 0);
143 if (--table->references == 0)
145 UNLOCK(&table->lock);
154 dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
155 dns_name_t *identity, unsigned int matchtype,
156 dns_name_t *name, unsigned int ntypes,
157 dns_rdatatype_t *types)
163 REQUIRE(VALID_SSUTABLE(table));
164 REQUIRE(dns_name_isabsolute(identity));
165 REQUIRE(dns_name_isabsolute(name));
166 REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
167 if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
168 REQUIRE(dns_name_iswildcard(name));
170 REQUIRE(types != NULL);
173 rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
175 return (ISC_R_NOMEMORY);
177 rule->identity = NULL;
183 rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
184 if (rule->identity == NULL) {
185 result = ISC_R_NOMEMORY;
188 dns_name_init(rule->identity, NULL);
189 result = dns_name_dup(identity, mctx, rule->identity);
190 if (result != ISC_R_SUCCESS)
193 rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
194 if (rule->name == NULL) {
195 result = ISC_R_NOMEMORY;
198 dns_name_init(rule->name, NULL);
199 result = dns_name_dup(name, mctx, rule->name);
200 if (result != ISC_R_SUCCESS)
203 rule->matchtype = matchtype;
205 rule->ntypes = ntypes;
207 rule->types = isc_mem_get(mctx,
208 ntypes * sizeof(dns_rdatatype_t));
209 if (rule->types == NULL) {
210 result = ISC_R_NOMEMORY;
213 memcpy(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
217 rule->magic = SSURULEMAGIC;
218 ISC_LIST_INITANDAPPEND(table->rules, rule, link);
220 return (ISC_R_SUCCESS);
223 if (rule->identity != NULL) {
224 if (dns_name_dynamic(rule->identity))
225 dns_name_free(rule->identity, mctx);
226 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
228 if (rule->name != NULL) {
229 if (dns_name_dynamic(rule->name))
230 dns_name_free(rule->name, mctx);
231 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
233 if (rule->types != NULL)
234 isc_mem_put(mctx, rule->types,
235 ntypes * sizeof(dns_rdatatype_t));
236 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
241 static inline isc_boolean_t
242 isusertype(dns_rdatatype_t type) {
243 return (ISC_TF(type != dns_rdatatype_ns &&
244 type != dns_rdatatype_soa &&
245 type != dns_rdatatype_rrsig));
249 dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
250 dns_name_t *name, dns_rdatatype_t type)
254 dns_fixedname_t fixed;
255 dns_name_t *wildcard;
258 REQUIRE(VALID_SSUTABLE(table));
259 REQUIRE(signer == NULL || dns_name_isabsolute(signer));
260 REQUIRE(dns_name_isabsolute(name));
264 rule = ISC_LIST_HEAD(table->rules);
265 rule = ISC_LIST_NEXT(rule, link);
266 for (rule = ISC_LIST_HEAD(table->rules);
268 rule = ISC_LIST_NEXT(rule, link))
270 if (dns_name_iswildcard(rule->identity)) {
271 if (!dns_name_matcheswildcard(signer, rule->identity))
273 } else if (!dns_name_equal(signer, rule->identity))
276 if (rule->matchtype == DNS_SSUMATCHTYPE_NAME) {
277 if (!dns_name_equal(name, rule->name))
279 } else if (rule->matchtype == DNS_SSUMATCHTYPE_SUBDOMAIN) {
280 if (!dns_name_issubdomain(name, rule->name))
282 } else if (rule->matchtype == DNS_SSUMATCHTYPE_WILDCARD) {
283 if (!dns_name_matcheswildcard(name, rule->name))
285 } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELF) {
286 if (!dns_name_equal(signer, name))
288 } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFSUB) {
289 if (!dns_name_issubdomain(name, signer))
291 } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFWILD) {
292 dns_fixedname_init(&fixed);
293 wildcard = dns_fixedname_name(&fixed);
294 result = dns_name_concatenate(dns_wildcardname, signer,
296 if (result != ISC_R_SUCCESS)
298 if (!dns_name_matcheswildcard(name, wildcard))
302 if (rule->ntypes == 0) {
303 if (!isusertype(type))
306 for (i = 0; i < rule->ntypes; i++) {
307 if (rule->types[i] == dns_rdatatype_any ||
308 rule->types[i] == type)
311 if (i == rule->ntypes)
314 return (rule->grant);
321 dns_ssurule_isgrant(const dns_ssurule_t *rule) {
322 REQUIRE(VALID_SSURULE(rule));
323 return (rule->grant);
327 dns_ssurule_identity(const dns_ssurule_t *rule) {
328 REQUIRE(VALID_SSURULE(rule));
329 return (rule->identity);
333 dns_ssurule_matchtype(const dns_ssurule_t *rule) {
334 REQUIRE(VALID_SSURULE(rule));
335 return (rule->matchtype);
339 dns_ssurule_name(const dns_ssurule_t *rule) {
340 REQUIRE(VALID_SSURULE(rule));
345 dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
346 REQUIRE(VALID_SSURULE(rule));
347 REQUIRE(types != NULL && *types != NULL);
348 *types = rule->types;
349 return (rule->ntypes);
353 dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
354 REQUIRE(VALID_SSUTABLE(table));
355 REQUIRE(rule != NULL && *rule == NULL);
356 *rule = ISC_LIST_HEAD(table->rules);
357 return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
361 dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
362 REQUIRE(VALID_SSURULE(rule));
363 REQUIRE(nextrule != NULL && *nextrule == NULL);
364 *nextrule = ISC_LIST_NEXT(rule, link);
365 return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);