4 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or 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.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
22 * Id: ssu.c,v 1.34 2008/01/18 23:46:58 tbox Exp
23 * Principal Author: Brian Wellington
28 #include <isc/magic.h>
30 #include <isc/netaddr.h>
31 #include <isc/result.h>
32 #include <isc/string.h>
35 #include <dns/fixedname.h>
39 #include <dst/gssapi.h>
41 #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
42 #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
44 #define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R')
45 #define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
49 isc_boolean_t grant
; /*%< is this a grant or a deny? */
50 unsigned int matchtype
; /*%< which type of pattern match? */
51 dns_name_t
*identity
; /*%< the identity to match */
52 dns_name_t
*name
; /*%< the name being updated */
53 unsigned int ntypes
; /*%< number of data types covered */
54 dns_rdatatype_t
*types
; /*%< the data types. Can include ANY, */
55 /*%< defaults to all but SIG,SOA,NS if NULL */
56 ISC_LINK(dns_ssurule_t
) link
;
62 unsigned int references
;
64 ISC_LIST(dns_ssurule_t
) rules
;
68 dns_ssutable_create(isc_mem_t
*mctx
, dns_ssutable_t
**tablep
) {
70 dns_ssutable_t
*table
;
72 REQUIRE(tablep
!= NULL
&& *tablep
== NULL
);
73 REQUIRE(mctx
!= NULL
);
75 table
= isc_mem_get(mctx
, sizeof(dns_ssutable_t
));
77 return (ISC_R_NOMEMORY
);
78 result
= isc_mutex_init(&table
->lock
);
79 if (result
!= ISC_R_SUCCESS
) {
80 isc_mem_put(mctx
, table
, sizeof(dns_ssutable_t
));
83 table
->references
= 1;
85 ISC_LIST_INIT(table
->rules
);
86 table
->magic
= SSUTABLEMAGIC
;
88 return (ISC_R_SUCCESS
);
92 destroy(dns_ssutable_t
*table
) {
95 REQUIRE(VALID_SSUTABLE(table
));
98 while (!ISC_LIST_EMPTY(table
->rules
)) {
99 dns_ssurule_t
*rule
= ISC_LIST_HEAD(table
->rules
);
100 if (rule
->identity
!= NULL
) {
101 dns_name_free(rule
->identity
, mctx
);
102 isc_mem_put(mctx
, rule
->identity
, sizeof(dns_name_t
));
104 if (rule
->name
!= NULL
) {
105 dns_name_free(rule
->name
, mctx
);
106 isc_mem_put(mctx
, rule
->name
, sizeof(dns_name_t
));
108 if (rule
->types
!= NULL
)
109 isc_mem_put(mctx
, rule
->types
,
110 rule
->ntypes
* sizeof(dns_rdatatype_t
));
111 ISC_LIST_UNLINK(table
->rules
, rule
, link
);
113 isc_mem_put(mctx
, rule
, sizeof(dns_ssurule_t
));
115 DESTROYLOCK(&table
->lock
);
117 isc_mem_put(mctx
, table
, sizeof(dns_ssutable_t
));
121 dns_ssutable_attach(dns_ssutable_t
*source
, dns_ssutable_t
**targetp
) {
122 REQUIRE(VALID_SSUTABLE(source
));
123 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
127 INSIST(source
->references
> 0);
128 source
->references
++;
129 INSIST(source
->references
!= 0);
131 UNLOCK(&source
->lock
);
137 dns_ssutable_detach(dns_ssutable_t
**tablep
) {
138 dns_ssutable_t
*table
;
139 isc_boolean_t done
= ISC_FALSE
;
141 REQUIRE(tablep
!= NULL
);
143 REQUIRE(VALID_SSUTABLE(table
));
147 INSIST(table
->references
> 0);
148 if (--table
->references
== 0)
150 UNLOCK(&table
->lock
);
159 dns_ssutable_addrule(dns_ssutable_t
*table
, isc_boolean_t grant
,
160 dns_name_t
*identity
, unsigned int matchtype
,
161 dns_name_t
*name
, unsigned int ntypes
,
162 dns_rdatatype_t
*types
)
168 REQUIRE(VALID_SSUTABLE(table
));
169 REQUIRE(dns_name_isabsolute(identity
));
170 REQUIRE(dns_name_isabsolute(name
));
171 REQUIRE(matchtype
<= DNS_SSUMATCHTYPE_MAX
);
172 if (matchtype
== DNS_SSUMATCHTYPE_WILDCARD
)
173 REQUIRE(dns_name_iswildcard(name
));
175 REQUIRE(types
!= NULL
);
178 rule
= isc_mem_get(mctx
, sizeof(dns_ssurule_t
));
180 return (ISC_R_NOMEMORY
);
182 rule
->identity
= NULL
;
188 rule
->identity
= isc_mem_get(mctx
, sizeof(dns_name_t
));
189 if (rule
->identity
== NULL
) {
190 result
= ISC_R_NOMEMORY
;
193 dns_name_init(rule
->identity
, NULL
);
194 result
= dns_name_dup(identity
, mctx
, rule
->identity
);
195 if (result
!= ISC_R_SUCCESS
)
198 rule
->name
= isc_mem_get(mctx
, sizeof(dns_name_t
));
199 if (rule
->name
== NULL
) {
200 result
= ISC_R_NOMEMORY
;
203 dns_name_init(rule
->name
, NULL
);
204 result
= dns_name_dup(name
, mctx
, rule
->name
);
205 if (result
!= ISC_R_SUCCESS
)
208 rule
->matchtype
= matchtype
;
210 rule
->ntypes
= ntypes
;
212 rule
->types
= isc_mem_get(mctx
,
213 ntypes
* sizeof(dns_rdatatype_t
));
214 if (rule
->types
== NULL
) {
215 result
= ISC_R_NOMEMORY
;
218 memcpy(rule
->types
, types
, ntypes
* sizeof(dns_rdatatype_t
));
222 rule
->magic
= SSURULEMAGIC
;
223 ISC_LIST_INITANDAPPEND(table
->rules
, rule
, link
);
225 return (ISC_R_SUCCESS
);
228 if (rule
->identity
!= NULL
) {
229 if (dns_name_dynamic(rule
->identity
))
230 dns_name_free(rule
->identity
, mctx
);
231 isc_mem_put(mctx
, rule
->identity
, sizeof(dns_name_t
));
233 if (rule
->name
!= NULL
) {
234 if (dns_name_dynamic(rule
->name
))
235 dns_name_free(rule
->name
, mctx
);
236 isc_mem_put(mctx
, rule
->name
, sizeof(dns_name_t
));
238 if (rule
->types
!= NULL
)
239 isc_mem_put(mctx
, rule
->types
,
240 ntypes
* sizeof(dns_rdatatype_t
));
241 isc_mem_put(mctx
, rule
, sizeof(dns_ssurule_t
));
246 static inline isc_boolean_t
247 isusertype(dns_rdatatype_t type
) {
248 return (ISC_TF(type
!= dns_rdatatype_ns
&&
249 type
!= dns_rdatatype_soa
&&
250 type
!= dns_rdatatype_rrsig
));
254 reverse_from_address(dns_name_t
*tcpself
, isc_netaddr_t
*tcpaddr
) {
255 char buf
[16 * 4 + sizeof("IP6.ARPA.")];
261 switch (tcpaddr
->family
) {
263 l
= ntohl(tcpaddr
->type
.in
.s_addr
);
264 result
= isc_string_printf(buf
, sizeof(buf
),
265 "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
266 (l
>> 0) & 0xff, (l
>> 8) & 0xff,
267 (l
>> 16) & 0xff, (l
>> 24) & 0xff);
268 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
271 ap
= tcpaddr
->type
.in6
.s6_addr
;
272 result
= isc_string_printf(buf
, sizeof(buf
),
273 "%x.%x.%x.%x.%x.%x.%x.%x."
274 "%x.%x.%x.%x.%x.%x.%x.%x."
275 "%x.%x.%x.%x.%x.%x.%x.%x."
276 "%x.%x.%x.%x.%x.%x.%x.%x."
278 ap
[15] & 0x0f, (ap
[15] >> 4) & 0x0f,
279 ap
[14] & 0x0f, (ap
[14] >> 4) & 0x0f,
280 ap
[13] & 0x0f, (ap
[13] >> 4) & 0x0f,
281 ap
[12] & 0x0f, (ap
[12] >> 4) & 0x0f,
282 ap
[11] & 0x0f, (ap
[11] >> 4) & 0x0f,
283 ap
[10] & 0x0f, (ap
[10] >> 4) & 0x0f,
284 ap
[9] & 0x0f, (ap
[9] >> 4) & 0x0f,
285 ap
[8] & 0x0f, (ap
[8] >> 4) & 0x0f,
286 ap
[7] & 0x0f, (ap
[7] >> 4) & 0x0f,
287 ap
[6] & 0x0f, (ap
[6] >> 4) & 0x0f,
288 ap
[5] & 0x0f, (ap
[5] >> 4) & 0x0f,
289 ap
[4] & 0x0f, (ap
[4] >> 4) & 0x0f,
290 ap
[3] & 0x0f, (ap
[3] >> 4) & 0x0f,
291 ap
[2] & 0x0f, (ap
[2] >> 4) & 0x0f,
292 ap
[1] & 0x0f, (ap
[1] >> 4) & 0x0f,
293 ap
[0] & 0x0f, (ap
[0] >> 4) & 0x0f);
294 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
299 isc_buffer_init(&b
, buf
, strlen(buf
));
300 isc_buffer_add(&b
, strlen(buf
));
301 result
= dns_name_fromtext(tcpself
, &b
, dns_rootname
, 0, NULL
);
302 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
306 stf_from_address(dns_name_t
*stfself
, isc_netaddr_t
*tcpaddr
) {
307 char buf
[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
313 switch(tcpaddr
->family
) {
315 l
= ntohl(tcpaddr
->type
.in
.s_addr
);
316 result
= isc_string_printf(buf
, sizeof(buf
),
317 "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
319 l
& 0xf, (l
>> 4) & 0xf,
320 (l
>> 8) & 0xf, (l
>> 12) & 0xf,
321 (l
>> 16) & 0xf, (l
>> 20) & 0xf,
322 (l
>> 24) & 0xf, (l
>> 28) & 0xf);
323 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
326 ap
= tcpaddr
->type
.in6
.s6_addr
;
327 result
= isc_string_printf(buf
, sizeof(buf
),
328 "%x.%x.%x.%x.%x.%x.%x.%x."
329 "%x.%x.%x.%x.IP6.ARPA.",
330 ap
[5] & 0x0f, (ap
[5] >> 4) & 0x0f,
331 ap
[4] & 0x0f, (ap
[4] >> 4) & 0x0f,
332 ap
[3] & 0x0f, (ap
[3] >> 4) & 0x0f,
333 ap
[2] & 0x0f, (ap
[2] >> 4) & 0x0f,
334 ap
[1] & 0x0f, (ap
[1] >> 4) & 0x0f,
335 ap
[0] & 0x0f, (ap
[0] >> 4) & 0x0f);
336 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
341 isc_buffer_init(&b
, buf
, strlen(buf
));
342 isc_buffer_add(&b
, strlen(buf
));
343 result
= dns_name_fromtext(stfself
, &b
, dns_rootname
, 0, NULL
);
344 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
348 dns_ssutable_checkrules(dns_ssutable_t
*table
, dns_name_t
*signer
,
349 dns_name_t
*name
, isc_netaddr_t
*tcpaddr
,
350 dns_rdatatype_t type
)
354 dns_fixedname_t fixed
;
355 dns_name_t
*wildcard
;
360 REQUIRE(VALID_SSUTABLE(table
));
361 REQUIRE(signer
== NULL
|| dns_name_isabsolute(signer
));
362 REQUIRE(dns_name_isabsolute(name
));
364 if (signer
== NULL
&& tcpaddr
== NULL
)
367 for (rule
= ISC_LIST_HEAD(table
->rules
);
369 rule
= ISC_LIST_NEXT(rule
, link
))
371 switch (rule
->matchtype
) {
372 case DNS_SSUMATCHTYPE_NAME
:
373 case DNS_SSUMATCHTYPE_SUBDOMAIN
:
374 case DNS_SSUMATCHTYPE_WILDCARD
:
375 case DNS_SSUMATCHTYPE_SELF
:
376 case DNS_SSUMATCHTYPE_SELFSUB
:
377 case DNS_SSUMATCHTYPE_SELFWILD
:
380 if (dns_name_iswildcard(rule
->identity
)) {
381 if (!dns_name_matcheswildcard(signer
,
385 if (!dns_name_equal(signer
, rule
->identity
))
389 case DNS_SSUMATCHTYPE_SELFKRB5
:
390 case DNS_SSUMATCHTYPE_SELFMS
:
391 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5
:
392 case DNS_SSUMATCHTYPE_SUBDOMAINMS
:
396 case DNS_SSUMATCHTYPE_TCPSELF
:
397 case DNS_SSUMATCHTYPE_6TO4SELF
:
403 switch (rule
->matchtype
) {
404 case DNS_SSUMATCHTYPE_NAME
:
405 if (!dns_name_equal(name
, rule
->name
))
408 case DNS_SSUMATCHTYPE_SUBDOMAIN
:
409 if (!dns_name_issubdomain(name
, rule
->name
))
412 case DNS_SSUMATCHTYPE_WILDCARD
:
413 if (!dns_name_matcheswildcard(name
, rule
->name
))
416 case DNS_SSUMATCHTYPE_SELF
:
417 if (!dns_name_equal(signer
, name
))
420 case DNS_SSUMATCHTYPE_SELFSUB
:
421 if (!dns_name_issubdomain(name
, signer
))
424 case DNS_SSUMATCHTYPE_SELFWILD
:
425 dns_fixedname_init(&fixed
);
426 wildcard
= dns_fixedname_name(&fixed
);
427 result
= dns_name_concatenate(dns_wildcardname
, signer
,
429 if (result
!= ISC_R_SUCCESS
)
431 if (!dns_name_matcheswildcard(name
, wildcard
))
434 case DNS_SSUMATCHTYPE_SELFKRB5
:
435 if (!dst_gssapi_identitymatchesrealmkrb5(signer
, name
,
439 case DNS_SSUMATCHTYPE_SELFMS
:
440 if (!dst_gssapi_identitymatchesrealmms(signer
, name
,
444 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5
:
445 if (!dns_name_issubdomain(name
, rule
->name
))
447 if (!dst_gssapi_identitymatchesrealmkrb5(signer
, NULL
,
451 case DNS_SSUMATCHTYPE_SUBDOMAINMS
:
452 if (!dns_name_issubdomain(name
, rule
->name
))
454 if (!dst_gssapi_identitymatchesrealmms(signer
, NULL
,
458 case DNS_SSUMATCHTYPE_TCPSELF
:
459 dns_fixedname_init(&fixed
);
460 tcpself
= dns_fixedname_name(&fixed
);
461 reverse_from_address(tcpself
, tcpaddr
);
462 if (dns_name_iswildcard(rule
->identity
)) {
463 if (!dns_name_matcheswildcard(tcpself
,
467 if (!dns_name_equal(tcpself
, rule
->identity
))
470 if (!dns_name_equal(tcpself
, name
))
473 case DNS_SSUMATCHTYPE_6TO4SELF
:
474 dns_fixedname_init(&fixed
);
475 stfself
= dns_fixedname_name(&fixed
);
476 stf_from_address(stfself
, tcpaddr
);
477 if (dns_name_iswildcard(rule
->identity
)) {
478 if (!dns_name_matcheswildcard(stfself
,
482 if (!dns_name_equal(stfself
, rule
->identity
))
485 if (!dns_name_equal(stfself
, name
))
490 if (rule
->ntypes
== 0) {
491 if (!isusertype(type
))
494 for (i
= 0; i
< rule
->ntypes
; i
++) {
495 if (rule
->types
[i
] == dns_rdatatype_any
||
496 rule
->types
[i
] == type
)
499 if (i
== rule
->ntypes
)
502 return (rule
->grant
);
509 dns_ssurule_isgrant(const dns_ssurule_t
*rule
) {
510 REQUIRE(VALID_SSURULE(rule
));
511 return (rule
->grant
);
515 dns_ssurule_identity(const dns_ssurule_t
*rule
) {
516 REQUIRE(VALID_SSURULE(rule
));
517 return (rule
->identity
);
521 dns_ssurule_matchtype(const dns_ssurule_t
*rule
) {
522 REQUIRE(VALID_SSURULE(rule
));
523 return (rule
->matchtype
);
527 dns_ssurule_name(const dns_ssurule_t
*rule
) {
528 REQUIRE(VALID_SSURULE(rule
));
533 dns_ssurule_types(const dns_ssurule_t
*rule
, dns_rdatatype_t
**types
) {
534 REQUIRE(VALID_SSURULE(rule
));
535 REQUIRE(types
!= NULL
&& *types
!= NULL
);
536 *types
= rule
->types
;
537 return (rule
->ntypes
);
541 dns_ssutable_firstrule(const dns_ssutable_t
*table
, dns_ssurule_t
**rule
) {
542 REQUIRE(VALID_SSUTABLE(table
));
543 REQUIRE(rule
!= NULL
&& *rule
== NULL
);
544 *rule
= ISC_LIST_HEAD(table
->rules
);
545 return (*rule
!= NULL
? ISC_R_SUCCESS
: ISC_R_NOMORE
);
549 dns_ssutable_nextrule(dns_ssurule_t
*rule
, dns_ssurule_t
**nextrule
) {
550 REQUIRE(VALID_SSURULE(rule
));
551 REQUIRE(nextrule
!= NULL
&& *nextrule
== NULL
);
552 *nextrule
= ISC_LIST_NEXT(rule
, link
);
553 return (*nextrule
!= NULL
? ISC_R_SUCCESS
: ISC_R_NOMORE
);