]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
new source file aml.c, for address match list handling
authorAndreas Gustafsson <source@isc.org>
Tue, 30 Nov 1999 22:10:08 +0000 (22:10 +0000)
committerAndreas Gustafsson <source@isc.org>
Tue, 30 Nov 1999 22:10:08 +0000 (22:10 +0000)
lib/dns/Makefile.in
lib/dns/aml.c [new file with mode: 0644]
lib/dns/include/dns/aml.h [new file with mode: 0644]
util/copyrights

index 2c0144c7c96268d1c02e698bd767807b2875b19d..f36a3a03a364df711e4f18827627050aff2eb29d 100644 (file)
@@ -114,7 +114,7 @@ DNSSAFEOBJS =       sec/dnssafe/ahchdig.@O@ sec/dnssafe/ahchencr.@O@ \
                sec/dnssafe/seccbce.@O@ sec/dnssafe/surrendr.@O@
 
 # Alphabetically
-OBJS =         a6.@O@ adb.@O@ cache.@O@ callbacks.@O@ compress.@O@ \
+OBJS =         a6.@O@ adb.@O@ aml.@O@ cache.@O@ callbacks.@O@ compress.@O@ \
                db.@O@ dbiterator.@O@ dbtable.@O@ dispatch.@O@ dnssec.@O@ \
                journal.@O@ lib.@O@ log.@O@ \
                master.@O@ masterdump.@O@ message.@O@ \
@@ -127,7 +127,7 @@ OBJS =              a6.@O@ adb.@O@ cache.@O@ callbacks.@O@ compress.@O@ \
                ${DSTOBJS} ${OPENSSLOBJS} ${DNSSAFEOBJS} ${CONFOBJS}
 
 # Alphabetically
-SRCS =         a6.c adb.c cache.c callbacks.c compress.c \
+SRCS =         a6.c adb.c aml.c cache.c callbacks.c compress.c \
                db.c dbiterator.c dbtable.c dispatch.c dnssec.c \
                journal.c lib.c log.c \
                master.c masterdump.c message.c \
@@ -184,7 +184,7 @@ newrr::
 
 ${SUBDIRS}: include/dns/enumtype.h include/dns/enumclass.h
            include/dns/rdatastruct.h
-       
+
 rdata.@O@: code.h
 
 include/dns/enumtype.h: gen
diff --git a/lib/dns/aml.c b/lib/dns/aml.c
new file mode 100644 (file)
index 0000000..b9e5cb0
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 1999  Internet Software Consortium.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <isc/assertions.h>
+#include <isc/error.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+
+#include <dns/aml.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+isc_result_t
+dns_aml_checkrequest(dns_message_t *request, isc_sockaddr_t *reqaddr,
+                    dns_c_ipmatchlist_t *aml,
+                    dns_c_acltable_t *acltable, 
+                    const char *opname, isc_boolean_t default_allow)
+{
+       isc_result_t result, sig_result;
+       dns_name_t signer;
+       dns_name_t *ok_signer = NULL;
+       int match;
+
+       dns_name_init(&signer, NULL);
+       
+       /*
+        * Check for a TSIG.  We log bad TSIGs regardless of whether they
+        * cause the request to be rejected or not (it may be allowd 
+        * because of another AML).  We do not log the lack of a TSIG
+        * unless we are debugging.
+        */
+       sig_result = result = dns_message_signer(request, &signer);
+       if (result == DNS_R_SUCCESS) {
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                             DNS_LOGMODULE_AML, ISC_LOG_DEBUG(3),
+                             "request has valid signature");
+               ok_signer = &signer;
+       } else if (result == DNS_R_NOTFOUND) {
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                             DNS_LOGMODULE_AML, ISC_LOG_DEBUG(3),
+                             "request is not signed");
+       } else {
+               /* There is a signature, but it is bad. */
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                             DNS_LOGMODULE_AML, ISC_LOG_ERROR,
+                             "request has invalid signature: %s",
+                             isc_result_totext(result));
+       }
+
+       /* If there is no AML, use the default. */
+       if (aml == NULL)
+               goto use_default;
+       
+       result = dns_aml_match(reqaddr, ok_signer, aml,
+                              acltable, &match, NULL);
+       if (result != DNS_R_SUCCESS)
+               goto use_default;
+       if (match <= 0)
+               goto use_default;
+ allow:
+       isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                     DNS_LOGMODULE_AML, ISC_LOG_DEBUG(3),
+                     "%s approved", opname);
+       return (DNS_R_SUCCESS);
+ deny:
+       isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                     DNS_LOGMODULE_AML, ISC_LOG_ERROR,
+                     "%s denied", opname);
+       return (DNS_R_REFUSED);
+ use_default:
+       if (default_allow)
+               goto allow;
+       else
+               goto deny;
+
+}
+
+static isc_result_t
+signer_matches(dns_name_t *signer, char *keyname, isc_boolean_t *match)
+{
+       isc_result_t result;
+       isc_buffer_t buf;
+       dns_fixedname_t fixname;
+       unsigned int keylen;
+
+       keylen = strlen(keyname);
+       isc_buffer_init(&buf, keyname, keylen, ISC_BUFFERTYPE_TEXT);
+       isc_buffer_add(&buf, keylen);
+       dns_fixedname_init(&fixname);
+       result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf,
+                                  dns_rootname, ISC_FALSE, NULL);
+       if (result != ISC_R_SUCCESS) {
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                             DNS_LOGMODULE_AML, ISC_LOG_WARNING,
+                             "key name \"%s\" is not a valid domain name",
+                             keyname);
+               return (result);
+       }
+       *match = dns_name_equal(signer, dns_fixedname_name(&fixname));
+       return (ISC_R_SUCCESS);
+}
+     
+isc_result_t
+dns_aml_match(isc_sockaddr_t *reqaddr,
+             dns_name_t *reqsigner,
+             dns_c_ipmatchlist_t *aml,
+             dns_c_acltable_t *acltable,
+             int *match,
+             dns_c_ipmatchelement_t **matchelt)
+{
+       isc_result_t result;
+       dns_c_ipmatchelement_t *e;
+       int distance;
+       int indirectmatch;
+       dns_c_acl_t *acl = NULL;
+
+       REQUIRE(matchelt == NULL || *matchelt == NULL);
+
+       for (e = ISC_LIST_HEAD(aml->elements), distance = 1;
+            e != NULL;
+            e = ISC_LIST_NEXT(e, next), distance++)
+       {
+               dns_c_ipmatchlist_t *indirect_acl = NULL;
+               
+               switch (e->type) {
+               case dns_c_ipmatch_pattern:
+                       /* XXX "mask" is a misnomer, should be
+                          "prefix length" */
+                       if (isc_sockaddr_eqaddrprefix(reqaddr,
+                                                     &e->u.direct.address,
+                                                     e->u.direct.mask))
+                               goto matched;
+                       break;
+               
+               case dns_c_ipmatch_key:
+                       if (reqsigner != NULL) {
+                               isc_boolean_t match;
+                               result = signer_matches(reqsigner, e->u.key,
+                                                       &match);
+                               if (result != ISC_R_SUCCESS)
+                                       return (result);
+                               if (match == ISC_TRUE)
+                                       goto matched;
+                       }
+                       break;
+               
+               case dns_c_ipmatch_indirect:
+                       indirect_acl = e->u.indirect.list;
+                       goto indirect;
+
+#ifdef notyet                  
+               case dns_c_ipmatch_localhost:
+                       indirect_acl = localhost_acl;
+                       goto indirect;
+                       
+               case dns_c_ipmatch_localnets:
+                       indirect_acl = localnets_acl;
+                       goto indirect;
+#else
+               case dns_c_ipmatch_localhost:
+               case dns_c_ipmatch_localnets:                   
+                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                                     DNS_LOGMODULE_AML, ISC_LOG_WARNING,
+                                     "the \"localhost\" and \"localnets\""
+                                     "ACLs are not yet supported");
+                       return (ISC_R_NOTIMPLEMENTED);
+#endif
+
+               case dns_c_ipmatch_acl:
+                       result = dns_c_acltable_getacl(dns_lctx,
+                                                      acltable,
+                                                      e->u.aclname,
+                                                      &acl);
+                       if (result == ISC_R_SUCCESS) {
+                               indirect_acl = acl->ipml;
+                               goto indirect;
+                       }
+                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                                     DNS_LOGMODULE_AML, ISC_LOG_WARNING,
+                                     "undefined ACL \"%s\"", e->u.aclname);
+                       return (result);
+               
+               default:
+                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+                                     DNS_LOGMODULE_AML, ISC_LOG_WARNING,
+                                     "address match list contains "
+                                     "unsupported element type");
+                       break;
+
+               indirect:
+                       INSIST(indirect_acl != NULL);
+                       result = dns_aml_match(reqaddr, reqsigner,
+                                              indirect_acl, acltable,
+                                              &indirectmatch, matchelt);
+                       if (result != DNS_R_SUCCESS)
+                               return (result);
+                       /*
+                        * Treat negative matches in indirect AMLs as
+                        * "no match".
+                        * That way, a negated indirect AML will never become 
+                        * a surprise positive match through double negation.
+                        */
+                       if (indirectmatch > 0)
+                               goto matched;
+
+                       /* A negative indirect match may have set *matchelt. */
+                       if (matchelt != NULL)
+                               *matchelt = NULL;
+                       break;
+
+               matched:
+                       *match = dns_c_ipmatchelement_isneg(dns_lctx, e) ?
+                               -distance : distance;
+                       if (matchelt != NULL)
+                               *matchelt = e;
+                       return (ISC_R_SUCCESS);
+
+               }
+       }
+       /* No match. */
+       *match = 0;
+       return (ISC_R_SUCCESS);
+}
+
diff --git a/lib/dns/include/dns/aml.h b/lib/dns/include/dns/aml.h
new file mode 100644 (file)
index 0000000..1a99539
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 1999  Internet Software Consortium.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef DNS_AML_H
+#define DNS_AML_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Address match list handling.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <dns/types.h>
+#include <isc/sockaddr.h>
+#include <dns/confacl.h>
+#include <dns/confip.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_aml_checkrequest(dns_message_t *request, isc_sockaddr_t *reqaddr,
+                    dns_c_ipmatchlist_t *aml,
+                    dns_c_acltable_t *acltable, 
+                    const char *opname, isc_boolean_t default_allow);
+/*
+ * Check a request against an address match list.
+ * This is appropriate for checking allow-update, 
+ * allow-query, allow-axfr, etc.  It is not appropriate
+ * for checking the blackhole list because
+ * we log positive matches as "allow" and negative
+ * matches as "deny"; in the case of the blackhole list
+ * this would all be backwards.
+ */
+
+isc_result_t
+dns_aml_match(isc_sockaddr_t *reqaddr,
+             dns_name_t *reqsigner,
+             dns_c_ipmatchlist_t *aml,
+             dns_c_acltable_t *acltable,
+             int *match,
+             dns_c_ipmatchelement_t **matchelt);
+/*
+ * General, low-level address match list matching.  This is expected to
+ * be useful even for weird stuff like the topology and sortlist statements.
+ *
+ * Match the address 'reqaddr', and optionally the key name 'reqsigner',
+ * against the address match list 'aml'.  'reqsigner' may be NULL.
+ *
+ * If there is a positive match, '*match' will be set to a positive value
+ * indicating the distance from the beginning of the list.
+ *
+ * If there is a negative match, '*match' will be set to a negative value
+ * whose absoluate value indicates the distance from the beginning of
+ * the list.
+ *
+ * If there is a match (either positive or negative) and 'matchelt' is  
+ * non-NULL, *matchelt will be attached to the primitive
+ * (non-indirect) address match list element that matched.
+ *
+ * If there is no match, *match will be set to zero.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_AML_H */
index 34b9e8fa15b1b4816e08c79884b20d6947ce24d5..23beeeca49a81d6ca6f22b541b685a8084a2097a 100644 (file)
 ./lib/dns/Makefile.in                          MAKE    1998,1999
 ./lib/dns/a6.c                                 C       1999
 ./lib/dns/adb.c                                        C       1999
+./lib/dns/aml.c                                        C       1999
 ./lib/dns/api                                  X       1999
 ./lib/dns/callbacks.c                          C       1999
 ./lib/dns/compress.c                           C       1999
 ./lib/dns/include/dns/Makefile.in              MAKE    1998,1999
 ./lib/dns/include/dns/a6.h                     C       1999
 ./lib/dns/include/dns/adb.h                    C       1999
+./lib/dns/include/dns/aml.h                    C       1999
 ./lib/dns/include/dns/callbacks.h              C       1999
 ./lib/dns/include/dns/cert.h                   C       1999
 ./lib/dns/include/dns/compress.h               C       1999