From 3eef7eaba00e9bd468d8036c709a296a0e5b76f1 Mon Sep 17 00:00:00 2001 From: Andreas Gustafsson Date: Tue, 22 Feb 2000 21:24:24 +0000 Subject: [PATCH] renamed dns_acl_checkrequest() to ns_client_checkacl() and moved it to bin/named/client.c to reflect the fact that it implemented BIND ACL policy more than general-purpose library functionality; resolve ACL defaults at configuration time rather than when the ACL is evaluated --- bin/named/client.c | 51 +++++++++++++++++++++++++++----- bin/named/include/named/client.h | 31 +++++++++++++++++++ bin/named/include/named/server.h | 1 - bin/named/query.c | 16 +++++----- bin/named/server.c | 7 ----- bin/named/update.c | 9 ++---- bin/named/xfrout.c | 12 +++----- bin/named/zoneconf.c | 11 ++++++- lib/dns/acl.c | 45 ---------------------------- lib/dns/include/dns/acl.h | 37 ----------------------- lib/dns/zoneconf.c | 11 ++++++- 11 files changed, 109 insertions(+), 122 deletions(-) diff --git a/bin/named/client.c b/bin/named/client.c index 480b24f954..3fa9a39a6a 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -979,13 +979,9 @@ client_request(isc_task_t *task, isc_event_t *event) { if (ns_g_server->recursion == ISC_TRUE) { /* XXX ACL should be view specific. */ /* XXX this will log too much too early */ - result = dns_acl_checkrequest(client->signer, - ns_client_getsockaddr(client), - "recursion", - ns_g_server->recursionacl, - NULL, - &ns_g_server->aclenv, - ISC_TRUE); + result = ns_client_checkacl(client, "recursion", + ns_g_server->recursionacl, + ISC_TRUE); if (result != DNS_R_SUCCESS) ra = ISC_FALSE; } @@ -1528,3 +1524,44 @@ isc_sockaddr_t * ns_client_getsockaddr(ns_client_t *client) { return (&client->peeraddr); } + +isc_result_t +ns_client_checkacl(ns_client_t *client, + const char *opname, dns_acl_t *acl, + isc_boolean_t default_allow) +{ + isc_result_t result; + int match; + isc_netaddr_t netaddr; + + if (acl == NULL) { + if (default_allow) + goto allow; + else + goto deny; + } + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + + result = dns_acl_match(&netaddr, client->signer, acl, + &ns_g_server->aclenv, + &match, NULL); + if (result != DNS_R_SUCCESS) + goto deny; /* Internal error, already logged. */ + if (match > 0) + goto allow; + goto deny; /* Negative match or no match. */ + + allow: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), + "%s approved", opname); + return (DNS_R_SUCCESS); + + deny: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, + "%s denied", opname); + return (DNS_R_REFUSED); +} + diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index f518260bf8..45004cad99 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -217,4 +217,35 @@ ns_client_getsockaddr(ns_client_t *client); * currently being processed. */ +isc_result_t +ns_client_checkacl(ns_client_t *client, + const char *opname, dns_acl_t *acl, + isc_boolean_t default_allow); +/* + * Convenience function for client request ACL checking. + * + * Check the current client request against 'acl'. If 'acl' + * is NULL, allow the request iff 'default_allow' is ISC_TRUE. + * Log the outcome of the check if deemed appropriate. + * Log messages will refer to the request as an 'opname' request. + * + * Notes: + * This is appropriate for checking allow-update, + * allow-query, allow-transfer, etc. It is not appropriate + * for checking the blackhole list because we treat positive + * matches as "allow" and negative matches as "deny"; in + * the case of the blackhole list this would be backwards. + * + * Requires: + * 'client' points to a valid client. + * 'opname' points to a null-terminated string. + * 'acl' points to a valid ACL, or is NULL. + * + * Returns: + * ISC_R_SUCCESS if the request should be allowed + * ISC_R_REFUSED if the request should be denied + * No other return values are possible. + */ + + #endif /* NS_CLIENT_H */ diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index e0f8f0988c..4b649786a4 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -47,7 +47,6 @@ struct ns_server { dns_transfer_format_t transfer_format; dns_acl_t * queryacl; dns_acl_t * recursionacl; - dns_acl_t * transferacl; isc_quota_t xfroutquota; isc_quota_t tcpquota; isc_quota_t recursionquota; diff --git a/bin/named/query.c b/bin/named/query.c index 27ab91e180..c65ca135b4 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -1798,6 +1798,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { dns_fixedname_t fixed; dns_dbversion_t *version; dns_zone_t *zone; + dns_acl_t *queryacl; CTRACE("query_find"); @@ -1923,19 +1924,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { } else version = NULL; + queryacl = NULL; + if (is_zone) + queryacl = dns_zone_getqueryacl(zone); + if (queryacl == NULL) + queryacl = ns_g_server->queryacl; /* * Check the query against the "allow-query" AMLs. * XXX there should also be a per-view one. */ - result = dns_acl_checkrequest(client->signer, - ns_client_getsockaddr(client), - "query", - (is_zone ? - dns_zone_getqueryacl(zone) : - ns_g_server->queryacl), - ns_g_server->queryacl, - &ns_g_server->aclenv, - ISC_TRUE); + result = ns_client_checkacl(client, "query", queryacl, ISC_TRUE); if (result != DNS_R_SUCCESS) { QUERY_ERROR(result); goto cleanup; diff --git a/bin/named/server.c b/bin/named/server.c index 98b19e75d3..2586f6f92a 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -788,10 +788,6 @@ load_configuration(const char *filename, ns_server_t *server, dns_c_ctx_getrecursionacl, &server->recursionacl)); - CHECK(configure_server_acl(configctx, &aclconfctx, ns_g_mctx, - dns_c_ctx_gettransferacl, - &server->transferacl)); - configure_server_quota(configctx, dns_c_ctx_gettransfersout, &server->xfroutquota, 10); configure_server_quota(configctx, dns_c_ctx_gettcpclients, @@ -1058,7 +1054,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->queryacl = NULL; server->recursionacl = NULL; - server->transferacl = NULL; result = isc_quota_init(&server->xfroutquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -1144,8 +1139,6 @@ ns_server_destroy(ns_server_t **serverp) { dns_acl_detach(&server->queryacl); if (server->recursionacl != NULL) dns_acl_detach(&server->recursionacl); - if (server->transferacl != NULL) - dns_acl_detach(&server->transferacl); dns_aclenv_destroy(&server->aclenv); diff --git a/bin/named/update.c b/bin/named/update.c index dba55bde93..37aefd42d9 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -1940,12 +1940,9 @@ update_action(isc_task_t *task, isc_event_t *event) * Check Requestor's Permissions. It seems a bit silly to do this * only after prerequisite testing, but that is what RFC2136 says. */ - CHECK(dns_acl_checkrequest(client->signer, - ns_client_getsockaddr(client), - "update", dns_zone_getupdateacl(zone), - NULL, - &ns_g_server->aclenv, - ISC_FALSE)); + CHECK(ns_client_checkacl(client, "update", + dns_zone_getupdateacl(zone), + ISC_FALSE)); /* Perform the Update Section Prescan. */ diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index 12966ff6ac..1e6834e7f9 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: xfrout.c,v 1.44 2000/02/14 23:56:46 gson Exp $ */ + /* $Id: xfrout.c,v 1.45 2000/02/22 21:24:23 gson Exp $ */ #include @@ -904,13 +904,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) mnemonic); /* Decide whether to allow this transfer. */ - CHECK(dns_acl_checkrequest(client->signer, - ns_client_getsockaddr(client), - "zone transfer", - dns_zone_getxfracl(zone), - ns_g_server->transferacl, - &ns_g_server->aclenv, - ISC_TRUE)); + CHECK(ns_client_checkacl(client, "zone transfer", + dns_zone_getxfracl(zone), + ISC_TRUE)); /* AXFR over UDP is not possible. */ if (reqtype == dns_rdatatype_axfr && diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 2fa49d5e6c..f5eaed7477 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -39,6 +39,7 @@ static isc_result_t configure_zone_acl(dns_c_zone_t *czone, dns_c_ctx_t *cctx, dns_aclconfctx_t *aclconfctx, dns_zone_t *zone, isc_result_t (*getcacl)(dns_c_zone_t *, dns_c_ipmatchlist_t **), + isc_result_t (*getdefaultcacl)(dns_c_ctx_t *, dns_c_ipmatchlist_t **), void (*setzacl)(dns_zone_t *, dns_acl_t *), void (*clearzacl)(dns_zone_t *)) { @@ -46,6 +47,9 @@ configure_zone_acl(dns_c_zone_t *czone, dns_c_ctx_t *cctx, dns_c_ipmatchlist_t *cacl; dns_acl_t *dacl = NULL; result = (*getcacl)(czone, &cacl); + if (result == ISC_R_NOTFOUND && getdefaultcacl != NULL) { + result = (*getdefaultcacl)(cctx, &cacl); + } if (result == ISC_R_SUCCESS) { result = dns_acl_fromconfig(cacl, cctx, aclconfctx, dns_zone_getmctx(zone), &dacl); @@ -130,6 +134,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, #endif result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowupd, + NULL, dns_zone_setupdateacl, dns_zone_clearupdateacl); if (result != DNS_R_SUCCESS) @@ -137,6 +142,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS) @@ -144,6 +150,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowtransfer, + dns_c_ctx_gettransferacl, dns_zone_setxfracl, dns_zone_clearxfracl); if (result != DNS_R_SUCCESS) @@ -219,6 +226,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, #endif result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS) @@ -309,7 +317,8 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, dns_zone_setchecknames(zone, dns_c_severity_warn); #endif result = configure_zone_acl(czone, cctx, ac, zone, - dns_c_zone_getallowquery, + dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS) diff --git a/lib/dns/acl.c b/lib/dns/acl.c index 3eb84eb547..9411ac8c48 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -127,51 +127,6 @@ dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) { return (dns_acl_anyornone(mctx, ISC_TRUE, target)); } -isc_result_t -dns_acl_checkrequest(dns_name_t *signer, isc_sockaddr_t *reqaddr, - const char *opname, - dns_acl_t *main_acl, - dns_acl_t *fallback_acl, - dns_aclenv_t *env, - isc_boolean_t default_allow) -{ - isc_result_t result; - int match; - isc_netaddr_t netaddr; - dns_acl_t *acl = NULL; - - if (main_acl != NULL) - acl = main_acl; - else if (fallback_acl != NULL) - acl = fallback_acl; - else if (default_allow) - goto allow; - else - goto deny; - - isc_netaddr_fromsockaddr(&netaddr, reqaddr); - - result = dns_acl_match(&netaddr, signer, acl, env, - &match, NULL); - if (result != DNS_R_SUCCESS) - goto deny; /* Internal error, already logged. */ - if (match > 0) - goto allow; - goto deny; /* Negative match or no match. */ - - allow: - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, - DNS_LOGMODULE_ACL, ISC_LOG_DEBUG(3), - "%s approved", opname); - return (DNS_R_SUCCESS); - - deny: - isc_log_write(dns_lctx, DNS_LOGCATEGORY_SECURITY, - DNS_LOGMODULE_ACL, ISC_LOG_ERROR, - "%s denied", opname); - return (DNS_R_REFUSED); -} - isc_result_t dns_acl_match(isc_netaddr_t *reqaddr, dns_name_t *reqsigner, diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index 03c7fdb997..85332fb5a5 100644 --- a/lib/dns/include/dns/acl.h +++ b/lib/dns/include/dns/acl.h @@ -122,43 +122,6 @@ void dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s); void dns_aclenv_destroy(dns_aclenv_t *env); -isc_result_t -dns_acl_checkrequest(dns_name_t *signer, isc_sockaddr_t *reqaddr, - const char *opname, - dns_acl_t *main_acl, - dns_acl_t *fallback_acl, - dns_aclenv_t *env, - isc_boolean_t default_allow); -/* - * Convenience function for "typical" DNS request permission checking. - * - * Check the DNS request signed by the key whose name is 'signer', - * from IP address 'reqaddr', against 'main_acl'. If main_acl is NULL, - * check against 'fallback_acl' instead. If fallback_acl - * is also NULL, allow the request iff 'default_allow' is ISC_TRUE. - * Log the outcome of the check if deemed appropriate. - * Log messages will refer to the request as an 'opname' request. - * - * Notes: - * This is appropriate for checking allow-update, - * allow-query, allow-transfer, etc. It is not appropriate - * for checking the blackhole list because we treat positive - * matches as "allow" and negative matches as "deny"; in - * the case of the blackhole list this would be backwards. - * - * Requires: - * 'signer' points to a valid name or is NULL. - * 'reqaddr' points to a valid socket address. - * 'opname' points to a null-terminated string. - * 'main_acl' points to a valid address match list, or is NULL. - * 'fallback_acl' points to a valid address match list, or is NULL. - * - * Returns: - * ISC_R_SUCCESS if the request should be allowed - * ISC_R_REFUSED if the request should be denied - * No other return values are possible. - */ - isc_result_t dns_acl_match(isc_netaddr_t *reqaddr, dns_name_t *reqsigner, diff --git a/lib/dns/zoneconf.c b/lib/dns/zoneconf.c index 2fa49d5e6c..f5eaed7477 100644 --- a/lib/dns/zoneconf.c +++ b/lib/dns/zoneconf.c @@ -39,6 +39,7 @@ static isc_result_t configure_zone_acl(dns_c_zone_t *czone, dns_c_ctx_t *cctx, dns_aclconfctx_t *aclconfctx, dns_zone_t *zone, isc_result_t (*getcacl)(dns_c_zone_t *, dns_c_ipmatchlist_t **), + isc_result_t (*getdefaultcacl)(dns_c_ctx_t *, dns_c_ipmatchlist_t **), void (*setzacl)(dns_zone_t *, dns_acl_t *), void (*clearzacl)(dns_zone_t *)) { @@ -46,6 +47,9 @@ configure_zone_acl(dns_c_zone_t *czone, dns_c_ctx_t *cctx, dns_c_ipmatchlist_t *cacl; dns_acl_t *dacl = NULL; result = (*getcacl)(czone, &cacl); + if (result == ISC_R_NOTFOUND && getdefaultcacl != NULL) { + result = (*getdefaultcacl)(cctx, &cacl); + } if (result == ISC_R_SUCCESS) { result = dns_acl_fromconfig(cacl, cctx, aclconfctx, dns_zone_getmctx(zone), &dacl); @@ -130,6 +134,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, #endif result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowupd, + NULL, dns_zone_setupdateacl, dns_zone_clearupdateacl); if (result != DNS_R_SUCCESS) @@ -137,6 +142,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS) @@ -144,6 +150,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowtransfer, + dns_c_ctx_gettransferacl, dns_zone_setxfracl, dns_zone_clearxfracl); if (result != DNS_R_SUCCESS) @@ -219,6 +226,7 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, #endif result = configure_zone_acl(czone, cctx, ac, zone, dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS) @@ -309,7 +317,8 @@ dns_zone_configure(dns_c_ctx_t *cctx, dns_aclconfctx_t *ac, dns_zone_setchecknames(zone, dns_c_severity_warn); #endif result = configure_zone_acl(czone, cctx, ac, zone, - dns_c_zone_getallowquery, + dns_c_zone_getallowquery, + dns_c_ctx_getqueryacl, dns_zone_setqueryacl, dns_zone_clearqueryacl); if (result != DNS_R_SUCCESS)