mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-02 13:30:44 -05:00
1797. [func] named-checkconf now check acls to verify that they
only refer to existing acls. [RT #13101]
This commit is contained in:
parent
800c85d32c
commit
0547d8d5d5
13 changed files with 145 additions and 375 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
1797. [func] named-checkconf now check acls to verify that they
|
||||
only refer to existing acls. [RT #13101]
|
||||
|
||||
1794. [func] Named and named-checkzone can now both check for
|
||||
non-terminal wildcard records.
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.80.18.4 2004/09/06 21:52:16 marka Exp $
|
||||
# $Id: Makefile.in,v 1.80.18.5 2005/01/11 03:55:55 marka Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
|
@ -63,7 +63,7 @@ SUBDIRS = unix
|
|||
|
||||
TARGETS = named@EXEEXT@ lwresd@EXEEXT@
|
||||
|
||||
OBJS = aclconf.@O@ builtin.@O@ client.@O@ config.@O@ control.@O@ \
|
||||
OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
|
||||
controlconf.@O@ interfacemgr.@O@ \
|
||||
listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \
|
||||
query.@O@ server.@O@ sortlist.@O@ \
|
||||
|
|
@ -75,7 +75,7 @@ OBJS = aclconf.@O@ builtin.@O@ client.@O@ config.@O@ control.@O@ \
|
|||
|
||||
UOBJS = unix/os.@O@
|
||||
|
||||
SRCS = aclconf.c builtin.c client.c config.c control.c \
|
||||
SRCS = builtin.c client.c config.c control.c \
|
||||
controlconf.c interfacemgr.c \
|
||||
listenlist.c log.c logconf.c main.c notify.c \
|
||||
query.c server.c sortlist.c \
|
||||
|
|
|
|||
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1999-2002 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 ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC 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.
|
||||
*/
|
||||
|
||||
/* $Id: aclconf.c,v 1.30 2004/03/05 04:57:46 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/namedconf.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/log.h>
|
||||
|
||||
#include <named/aclconf.h>
|
||||
|
||||
void
|
||||
ns_aclconfctx_init(ns_aclconfctx_t *ctx) {
|
||||
ISC_LIST_INIT(ctx->named_acl_cache);
|
||||
}
|
||||
|
||||
void
|
||||
ns_aclconfctx_destroy(ns_aclconfctx_t *ctx) {
|
||||
dns_acl_t *dacl, *next;
|
||||
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
|
||||
dacl != NULL;
|
||||
dacl = next)
|
||||
{
|
||||
next = ISC_LIST_NEXT(dacl, nextincache);
|
||||
dns_acl_detach(&dacl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the definition of the named acl whose name is "name".
|
||||
*/
|
||||
static isc_result_t
|
||||
get_acl_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
cfg_obj_t *acls = NULL;
|
||||
cfg_listelt_t *elt;
|
||||
|
||||
result = cfg_map_get(cctx, "acl", &acls);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
for (elt = cfg_list_first(acls);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
cfg_obj_t *acl = cfg_listelt_value(elt);
|
||||
const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
||||
if (strcasecmp(aclname, name) == 0) {
|
||||
*ret = cfg_tuple_get(acl, "value");
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
convert_named_acl(cfg_obj_t *nameobj, cfg_obj_t *cctx,
|
||||
ns_aclconfctx_t *ctx, isc_mem_t *mctx,
|
||||
dns_acl_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
cfg_obj_t *cacl = NULL;
|
||||
dns_acl_t *dacl;
|
||||
char *aclname = cfg_obj_asstring(nameobj);
|
||||
|
||||
/* Look for an already-converted version. */
|
||||
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
|
||||
dacl != NULL;
|
||||
dacl = ISC_LIST_NEXT(dacl, nextincache))
|
||||
{
|
||||
if (strcasecmp(aclname, dacl->name) == 0) {
|
||||
dns_acl_attach(dacl, target);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
/* Not yet converted. Convert now. */
|
||||
result = get_acl_def(cctx, aclname, &cacl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(nameobj, dns_lctx, ISC_LOG_WARNING,
|
||||
"undefined ACL '%s'", aclname);
|
||||
return (result);
|
||||
}
|
||||
result = ns_acl_fromconfig(cacl, cctx, ctx, mctx, &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dacl->name = isc_mem_strdup(dacl->mctx, aclname);
|
||||
if (dacl->name == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
ISC_LIST_APPEND(ctx->named_acl_cache, dacl, nextincache);
|
||||
dns_acl_attach(dacl, target);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
convert_keyname(cfg_obj_t *keyobj, isc_mem_t *mctx, dns_name_t *dnsname) {
|
||||
isc_result_t result;
|
||||
isc_buffer_t buf;
|
||||
dns_fixedname_t fixname;
|
||||
unsigned int keylen;
|
||||
const char *txtname = cfg_obj_asstring(keyobj);
|
||||
|
||||
keylen = strlen(txtname);
|
||||
isc_buffer_init(&buf, txtname, keylen);
|
||||
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) {
|
||||
cfg_obj_log(keyobj, dns_lctx, ISC_LOG_WARNING,
|
||||
"key name '%s' is not a valid domain name",
|
||||
txtname);
|
||||
return (result);
|
||||
}
|
||||
return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_acl_fromconfig(cfg_obj_t *caml,
|
||||
cfg_obj_t *cctx,
|
||||
ns_aclconfctx_t *ctx,
|
||||
isc_mem_t *mctx,
|
||||
dns_acl_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
unsigned int count;
|
||||
dns_acl_t *dacl = NULL;
|
||||
dns_aclelement_t *de;
|
||||
cfg_listelt_t *elt;
|
||||
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
count = 0;
|
||||
for (elt = cfg_list_first(caml);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt))
|
||||
count++;
|
||||
|
||||
result = dns_acl_create(mctx, count, &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
de = dacl->elements;
|
||||
for (elt = cfg_list_first(caml);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt))
|
||||
{
|
||||
cfg_obj_t *ce = cfg_listelt_value(elt);
|
||||
if (cfg_obj_istuple(ce)) {
|
||||
/* This must be a negated element. */
|
||||
ce = cfg_tuple_get(ce, "value");
|
||||
de->negative = ISC_TRUE;
|
||||
} else {
|
||||
de->negative = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (cfg_obj_isnetprefix(ce)) {
|
||||
/* Network prefix */
|
||||
de->type = dns_aclelementtype_ipprefix;
|
||||
|
||||
cfg_obj_asnetprefix(ce,
|
||||
&de->u.ip_prefix.address,
|
||||
&de->u.ip_prefix.prefixlen);
|
||||
} else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
|
||||
/* Key name */
|
||||
de->type = dns_aclelementtype_keyname;
|
||||
dns_name_init(&de->u.keyname, NULL);
|
||||
result = convert_keyname(ce, mctx, &de->u.keyname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
} else if (cfg_obj_islist(ce)) {
|
||||
/* Nested ACL */
|
||||
de->type = dns_aclelementtype_nestedacl;
|
||||
result = ns_acl_fromconfig(ce, cctx, ctx, mctx,
|
||||
&de->u.nestedacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
} else if (cfg_obj_isstring(ce)) {
|
||||
/* ACL name */
|
||||
char *name = cfg_obj_asstring(ce);
|
||||
if (strcasecmp(name, "localhost") == 0) {
|
||||
de->type = dns_aclelementtype_localhost;
|
||||
} else if (strcasecmp(name, "localnets") == 0) {
|
||||
de->type = dns_aclelementtype_localnets;
|
||||
} else if (strcasecmp(name, "any") == 0) {
|
||||
de->type = dns_aclelementtype_any;
|
||||
} else if (strcasecmp(name, "none") == 0) {
|
||||
de->type = dns_aclelementtype_any;
|
||||
de->negative = ISC_TF(! de->negative);
|
||||
} else {
|
||||
de->type = dns_aclelementtype_nestedacl;
|
||||
result = convert_named_acl(ce, cctx, ctx, mctx,
|
||||
&de->u.nestedacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
cfg_obj_log(ce, dns_lctx, ISC_LOG_WARNING,
|
||||
"address match list contains "
|
||||
"unsupported element type");
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
de++;
|
||||
dacl->length++;
|
||||
}
|
||||
|
||||
*target = dacl;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
dns_acl_detach(&dacl);
|
||||
return (result);
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: controlconf.c,v 1.40 2004/03/05 04:57:46 marka Exp $ */
|
||||
/* $Id: controlconf.c,v 1.40.18.1 2005/01/11 03:55:56 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -915,7 +915,7 @@ static void
|
|||
update_listener(ns_controls_t *cp,
|
||||
controllistener_t **listenerp, cfg_obj_t *control,
|
||||
cfg_obj_t *config, isc_sockaddr_t *addr,
|
||||
ns_aclconfctx_t *aclconfctx, const char *socktext)
|
||||
cfg_aclconfctx_t *aclconfctx, const char *socktext)
|
||||
{
|
||||
controllistener_t *listener;
|
||||
cfg_obj_t *allow;
|
||||
|
|
@ -995,8 +995,9 @@ update_listener(ns_controls_t *cp,
|
|||
*/
|
||||
if (control != NULL) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = ns_acl_fromconfig(allow, config, aclconfctx,
|
||||
listener->mctx, &new_acl);
|
||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||
aclconfctx, listener->mctx,
|
||||
&new_acl);
|
||||
} else {
|
||||
result = dns_acl_any(listener->mctx, &new_acl);
|
||||
}
|
||||
|
|
@ -1018,7 +1019,7 @@ update_listener(ns_controls_t *cp,
|
|||
static void
|
||||
add_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
||||
cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr,
|
||||
ns_aclconfctx_t *aclconfctx, const char *socktext)
|
||||
cfg_aclconfctx_t *aclconfctx, const char *socktext)
|
||||
{
|
||||
isc_mem_t *mctx = cp->server->mctx;
|
||||
controllistener_t *listener;
|
||||
|
|
@ -1050,8 +1051,8 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
|||
*/
|
||||
if (control != NULL) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = ns_acl_fromconfig(allow, config, aclconfctx,
|
||||
mctx, &new_acl);
|
||||
result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
|
||||
aclconfctx, mctx, &new_acl);
|
||||
} else {
|
||||
result = dns_acl_any(mctx, &new_acl);
|
||||
}
|
||||
|
|
@ -1136,7 +1137,7 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp,
|
|||
|
||||
isc_result_t
|
||||
ns_controls_configure(ns_controls_t *cp, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *aclconfctx)
|
||||
cfg_aclconfctx_t *aclconfctx)
|
||||
{
|
||||
controllistener_t *listener;
|
||||
controllistenerlist_t new_listeners;
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1999-2001 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 ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC 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.
|
||||
*/
|
||||
|
||||
/* $Id: aclconf.h,v 1.13 2004/03/05 04:57:55 marka Exp $ */
|
||||
|
||||
#ifndef NS_ACLCONF_H
|
||||
#define NS_ACLCONF_H 1
|
||||
|
||||
#include <isc/lang.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
typedef struct ns_aclconfctx {
|
||||
ISC_LIST(dns_acl_t) named_acl_cache;
|
||||
} ns_aclconfctx_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
ns_aclconfctx_init(ns_aclconfctx_t *ctx);
|
||||
/*
|
||||
* Initialize an ACL configuration context.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_aclconfctx_destroy(ns_aclconfctx_t *ctx);
|
||||
/*
|
||||
* Destroy an ACL configuration context.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_acl_fromconfig(cfg_obj_t *caml,
|
||||
cfg_obj_t *cctx,
|
||||
ns_aclconfctx_t *ctx,
|
||||
isc_mem_t *mctx,
|
||||
dns_acl_t **target);
|
||||
/*
|
||||
* Construct a new dns_acl_t from configuration data in 'caml' and
|
||||
* 'cctx'. Memory is allocated through 'mctx'.
|
||||
*
|
||||
* Any named ACLs referred to within 'caml' will be be converted
|
||||
* inte nested dns_acl_t objects. Multiple references to the same
|
||||
* named ACLs will be converted into shared references to a single
|
||||
* nested dns_acl_t object when the referring objects were created
|
||||
* passing the same ACL configuration context 'ctx'.
|
||||
*
|
||||
* On success, attach '*target' to the new dns_acl_t object.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* NS_ACLCONF_H */
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: control.h,v 1.14.18.2 2004/10/11 05:30:01 marka Exp $ */
|
||||
/* $Id: control.h,v 1.14.18.3 2005/01/11 03:55:57 marka Exp $ */
|
||||
|
||||
#ifndef NAMED_CONTROL_H
|
||||
#define NAMED_CONTROL_H 1
|
||||
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
#include <isccc/types.h>
|
||||
|
||||
#include <named/aclconf.h>
|
||||
#include <isccfg/aclconf.h>
|
||||
|
||||
#include <named/types.h>
|
||||
|
||||
#define NS_CONTROL_PORT 953
|
||||
|
|
@ -70,7 +71,7 @@ ns_controls_destroy(ns_controls_t **ctrlsp);
|
|||
|
||||
isc_result_t
|
||||
ns_controls_configure(ns_controls_t *controls, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *aclconfctx);
|
||||
cfg_aclconfctx_t *aclconfctx);
|
||||
/*
|
||||
* Configure zero or more command channels into 'controls'
|
||||
* as defined in the configuration parse tree 'config'.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zoneconf.h,v 1.19 2004/03/05 04:57:57 marka Exp $ */
|
||||
/* $Id: zoneconf.h,v 1.19.18.1 2005/01/11 03:55:57 marka Exp $ */
|
||||
|
||||
#ifndef NS_ZONECONF_H
|
||||
#define NS_ZONECONF_H 1
|
||||
|
|
@ -23,15 +23,14 @@
|
|||
#include <isc/lang.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#include <isccfg/aclconf.h>
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
#include <named/aclconf.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_result_t
|
||||
ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig,
|
||||
ns_aclconfctx_t *ac, dns_zone_t *zone);
|
||||
cfg_aclconfctx_t *ac, dns_zone_t *zone);
|
||||
/*
|
||||
* Configure or reconfigure a zone according to the named.conf
|
||||
* data in 'cctx' and 'czone'.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.419.18.15 2004/12/21 10:58:56 jinmei Exp $ */
|
||||
/* $Id: server.c,v 1.419.18.16 2005/01/11 03:55:56 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -165,11 +165,11 @@ ns_server_reload(isc_task_t *task, isc_event_t *event);
|
|||
|
||||
static isc_result_t
|
||||
ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *actx,
|
||||
cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, ns_listenelt_t **target);
|
||||
static isc_result_t
|
||||
ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *actx,
|
||||
cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, ns_listenlist_t **target);
|
||||
|
||||
static isc_result_t
|
||||
|
|
@ -183,7 +183,7 @@ configure_alternates(cfg_obj_t *config, dns_view_t *view,
|
|||
static isc_result_t
|
||||
configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
|
||||
isc_mem_t *mctx, dns_view_t *view,
|
||||
ns_aclconfctx_t *aclconf);
|
||||
cfg_aclconfctx_t *aclconf);
|
||||
|
||||
static void
|
||||
end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
|
||||
|
|
@ -195,7 +195,7 @@ end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
|
|||
*/
|
||||
static isc_result_t
|
||||
configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config,
|
||||
const char *aclname, ns_aclconfctx_t *actx,
|
||||
const char *aclname, cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, dns_acl_t **aclp)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
|
@ -222,7 +222,8 @@ configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config,
|
|||
*/
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp);
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
|
||||
actx, mctx, aclp);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
|
@ -715,7 +716,7 @@ disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
|
|||
*/
|
||||
static isc_result_t
|
||||
configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
||||
isc_mem_t *mctx, ns_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, cfg_aclconfctx_t *actx,
|
||||
isc_boolean_t need_hints)
|
||||
{
|
||||
cfg_obj_t *maps[4];
|
||||
|
|
@ -1608,7 +1609,7 @@ create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) {
|
|||
static isc_result_t
|
||||
configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
|
||||
isc_mem_t *mctx, dns_view_t *view,
|
||||
ns_aclconfctx_t *aclconf)
|
||||
cfg_aclconfctx_t *aclconf)
|
||||
{
|
||||
dns_view_t *pview = NULL; /* Production view */
|
||||
dns_zone_t *zone = NULL; /* New or reused zone */
|
||||
|
|
@ -2183,14 +2184,14 @@ load_configuration(const char *filename, ns_server_t *server,
|
|||
dns_view_t *view_next;
|
||||
dns_viewlist_t viewlist;
|
||||
dns_viewlist_t tmpviewlist;
|
||||
ns_aclconfctx_t aclconfctx;
|
||||
cfg_aclconfctx_t aclconfctx;
|
||||
isc_uint32_t interface_interval;
|
||||
isc_uint32_t heartbeat_interval;
|
||||
isc_uint32_t udpsize;
|
||||
in_port_t listen_port;
|
||||
int i;
|
||||
|
||||
ns_aclconfctx_init(&aclconfctx);
|
||||
cfg_aclconfctx_init(&aclconfctx);
|
||||
ISC_LIST_INIT(viewlist);
|
||||
|
||||
/* Ensure exclusive access to configuration data. */
|
||||
|
|
@ -2770,7 +2771,7 @@ load_configuration(const char *filename, ns_server_t *server,
|
|||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
ns_aclconfctx_destroy(&aclconfctx);
|
||||
cfg_aclconfctx_destroy(&aclconfctx);
|
||||
|
||||
if (parser != NULL) {
|
||||
if (config != NULL)
|
||||
|
|
@ -3552,7 +3553,7 @@ ns_server_togglequerylog(ns_server_t *server) {
|
|||
|
||||
static isc_result_t
|
||||
ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *actx,
|
||||
cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, ns_listenlist_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
|
@ -3591,7 +3592,7 @@ ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
|
|||
*/
|
||||
static isc_result_t
|
||||
ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *actx,
|
||||
cfg_aclconfctx_t *actx,
|
||||
isc_mem_t *mctx, ns_listenelt_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
|
@ -3623,8 +3624,8 @@ ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
|
|||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"),
|
||||
config, actx, mctx, &delt->acl);
|
||||
result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
|
||||
config, ns_g_lctx, actx, mctx, &delt->acl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_listenelt_destroy(delt);
|
||||
return (result);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zoneconf.c,v 1.110.18.6 2005/01/11 01:39:37 marka Exp $ */
|
||||
/* $Id: zoneconf.c,v 1.110.18.7 2005/01/11 03:55:56 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
*/
|
||||
static isc_result_t
|
||||
configure_zone_acl(cfg_obj_t *zconfig, cfg_obj_t *vconfig, cfg_obj_t *config,
|
||||
const char *aclname, ns_aclconfctx_t *actx,
|
||||
const char *aclname, cfg_aclconfctx_t *actx,
|
||||
dns_zone_t *zone,
|
||||
void (*setzacl)(dns_zone_t *, dns_acl_t *),
|
||||
void (*clearzacl)(dns_zone_t *))
|
||||
|
|
@ -85,8 +85,8 @@ configure_zone_acl(cfg_obj_t *zconfig, cfg_obj_t *vconfig, cfg_obj_t *config,
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = ns_acl_fromconfig(aclobj, config, actx,
|
||||
dns_zone_getmctx(zone), &dacl);
|
||||
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
|
||||
dns_zone_getmctx(zone), &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
(*setzacl)(zone, dacl);
|
||||
|
|
@ -309,7 +309,7 @@ checknames(dns_zonetype_t ztype, cfg_obj_t **maps, cfg_obj_t **objp) {
|
|||
|
||||
isc_result_t
|
||||
ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig,
|
||||
ns_aclconfctx_t *ac, dns_zone_t *zone)
|
||||
cfg_aclconfctx_t *ac, dns_zone_t *zone)
|
||||
{
|
||||
isc_result_t result;
|
||||
char *zname;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.19 2005/01/10 00:05:29 marka Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.20 2005/01/11 03:55:58 marka Exp $ -->
|
||||
|
||||
<book>
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
|
@ -1836,7 +1836,7 @@ which constitute an address match list can be any of the following:</para>
|
|||
<listitem>
|
||||
<simpara>a key ID, as defined by the <command>key</command> statement</simpara></listitem>
|
||||
<listitem>
|
||||
<simpara>the name of an address match list previously defined with
|
||||
<simpara>the name of an address match list defined with
|
||||
the <command>acl</command> statement</simpara></listitem>
|
||||
<listitem>
|
||||
<simpara>a nested address match list enclosed in braces</simpara></listitem></itemizedlist>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: check.c,v 1.44.18.9 2005/01/11 01:39:38 marka Exp $ */
|
||||
/* $Id: check.c,v 1.44.18.10 2005/01/11 03:55:58 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -33,11 +33,13 @@
|
|||
#include <isc/symtab.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/rdataclass.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/secalg.h>
|
||||
|
||||
#include <isccfg/aclconf.h>
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
#include <bind9/check.h>
|
||||
|
|
@ -344,6 +346,57 @@ mustbesecure(cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
|
|||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
checkacl(const char *aclname, cfg_obj_t *zconfig, cfg_obj_t *voptions,
|
||||
cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
|
||||
{
|
||||
isc_result_t result;
|
||||
cfg_obj_t *aclobj = NULL;
|
||||
cfg_obj_t *options;
|
||||
dns_acl_t *acl = NULL;
|
||||
cfg_aclconfctx_t actx;
|
||||
|
||||
if (zconfig != NULL) {
|
||||
options = cfg_tuple_get(zconfig, "options");
|
||||
cfg_map_get(options, aclname, &aclobj);
|
||||
}
|
||||
if (voptions != NULL && aclobj == NULL)
|
||||
cfg_map_get(voptions, aclname, &aclobj);
|
||||
if (config != NULL && aclobj == NULL) {
|
||||
options = NULL;
|
||||
cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
cfg_map_get(options, aclname, &aclobj);
|
||||
}
|
||||
if (aclobj == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
cfg_aclconfctx_init(&actx);
|
||||
result = cfg_acl_fromconfig(aclobj, config, logctx, &actx, mctx, &acl);
|
||||
if (acl != NULL)
|
||||
dns_acl_detach(&acl);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
check_viewacls(cfg_obj_t *voptions, cfg_obj_t *config,
|
||||
isc_log_t *logctx, isc_mem_t *mctx)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS, tresult;
|
||||
int i = 0;
|
||||
|
||||
static const char *acls[] = { "allow-query", "allow-query-cache",
|
||||
"allow-recursion", "blackhole", "match-clients",
|
||||
"match-destinations", "sortlist", NULL };
|
||||
|
||||
while (acls[i] != NULL) {
|
||||
tresult = checkacl(acls[i++], NULL, voptions, config,
|
||||
logctx, mctx);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
unsigned int scale;
|
||||
|
|
@ -682,6 +735,7 @@ validate_masters(cfg_obj_t *obj, cfg_obj_t *config, isc_uint32_t *countp,
|
|||
#define HINTZONE 8
|
||||
#define FORWARDZONE 16
|
||||
#define DELEGATIONZONE 32
|
||||
#define CHECKACL 64
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
|
|
@ -689,8 +743,9 @@ typedef struct {
|
|||
} optionstable;
|
||||
|
||||
static isc_result_t
|
||||
check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
|
||||
dns_rdataclass_t defclass, isc_log_t *logctx, isc_mem_t *mctx)
|
||||
check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *voptions, cfg_obj_t *config,
|
||||
isc_symtab_t *symtab, dns_rdataclass_t defclass,
|
||||
isc_log_t *logctx, isc_mem_t *mctx)
|
||||
{
|
||||
const char *zname;
|
||||
const char *typestr;
|
||||
|
|
@ -705,9 +760,9 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
|
|||
isc_buffer_t b;
|
||||
|
||||
static optionstable options[] = {
|
||||
{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE },
|
||||
{ "allow-notify", SLAVEZONE },
|
||||
{ "allow-transfer", MASTERZONE | SLAVEZONE },
|
||||
{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL },
|
||||
{ "allow-notify", SLAVEZONE | CHECKACL },
|
||||
{ "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
|
||||
{ "notify", MASTERZONE | SLAVEZONE },
|
||||
{ "also-notify", MASTERZONE | SLAVEZONE },
|
||||
{ "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
|
||||
|
|
@ -730,8 +785,8 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
|
|||
{ "min-refresh-time", SLAVEZONE | STUBZONE },
|
||||
{ "sig-validity-interval", MASTERZONE },
|
||||
{ "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
|
||||
{ "allow-update", MASTERZONE },
|
||||
{ "allow-update-forwarding", SLAVEZONE },
|
||||
{ "allow-update", MASTERZONE | CHECKACL },
|
||||
{ "allow-update-forwarding", SLAVEZONE | CHECKACL },
|
||||
{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
|
||||
{ "journal", MASTERZONE | SLAVEZONE },
|
||||
{ "ixfr-base", MASTERZONE | SLAVEZONE },
|
||||
|
|
@ -833,6 +888,7 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
|
|||
|
||||
/*
|
||||
* Look for inappropriate options for the given zone type.
|
||||
* Check that ACLs expand correctly.
|
||||
*/
|
||||
for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
|
||||
obj = NULL;
|
||||
|
|
@ -853,6 +909,16 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
|
|||
"in '%s' zone '%s'",
|
||||
options[i].name, typestr, zname);
|
||||
}
|
||||
obj = NULL;
|
||||
if ((options[i].allowed & ztype) != 0 &&
|
||||
(options[i].allowed & CHECKACL) != 0) {
|
||||
|
||||
tresult = checkacl(options[i].name, zconfig,
|
||||
voptions, config, logctx, mctx);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1090,7 +1156,7 @@ check_servers(cfg_obj_t *servers, isc_log_t *logctx) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
|
||||
check_viewconf(cfg_obj_t *config, cfg_obj_t *voptions, dns_rdataclass_t vclass,
|
||||
isc_log_t *logctx, isc_mem_t *mctx)
|
||||
{
|
||||
cfg_obj_t *servers = NULL;
|
||||
|
|
@ -1110,8 +1176,8 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
|
|||
if (tresult != ISC_R_SUCCESS)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
if (vconfig != NULL)
|
||||
(void)cfg_map_get(vconfig, "zone", &zones);
|
||||
if (voptions != NULL)
|
||||
(void)cfg_map_get(voptions, "zone", &zones);
|
||||
else
|
||||
(void)cfg_map_get(config, "zone", &zones);
|
||||
|
||||
|
|
@ -1122,8 +1188,8 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
|
|||
isc_result_t tresult;
|
||||
cfg_obj_t *zone = cfg_listelt_value(element);
|
||||
|
||||
tresult = check_zoneconf(zone, config, symtab, vclass,
|
||||
logctx, mctx);
|
||||
tresult = check_zoneconf(zone, voptions, config, symtab,
|
||||
vclass, logctx, mctx);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
|
@ -1147,9 +1213,9 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
|
|||
return (tresult);
|
||||
}
|
||||
|
||||
if (vconfig != NULL) {
|
||||
if (voptions != NULL) {
|
||||
keys = NULL;
|
||||
(void)cfg_map_get(vconfig, "key", &keys);
|
||||
(void)cfg_map_get(voptions, "key", &keys);
|
||||
tresult = check_keylist(keys, symtab, logctx);
|
||||
if (tresult == ISC_R_EXISTS)
|
||||
result = ISC_R_FAILURE;
|
||||
|
|
@ -1164,52 +1230,56 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
|
|||
/*
|
||||
* Check that forwarding is reasonable.
|
||||
*/
|
||||
if (vconfig == NULL) {
|
||||
if (voptions == NULL) {
|
||||
cfg_obj_t *options = NULL;
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
if (check_forward(options, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
} else {
|
||||
if (check_forward(vconfig, logctx) != ISC_R_SUCCESS)
|
||||
if (check_forward(voptions, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
/*
|
||||
* Check that dual-stack-servers is reasonable.
|
||||
*/
|
||||
if (vconfig == NULL) {
|
||||
if (voptions == NULL) {
|
||||
cfg_obj_t *options = NULL;
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
} else {
|
||||
if (check_dual_stack(vconfig, logctx) != ISC_R_SUCCESS)
|
||||
if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that rrset-order is reasonable.
|
||||
*/
|
||||
if (vconfig != NULL) {
|
||||
if (check_order(vconfig, logctx) != ISC_R_SUCCESS)
|
||||
if (voptions != NULL) {
|
||||
if (check_order(voptions, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (vconfig != NULL) {
|
||||
(void)cfg_map_get(vconfig, "server", &servers);
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "server", &servers);
|
||||
if (servers != NULL &&
|
||||
check_servers(servers, logctx) != ISC_R_SUCCESS)
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (vconfig != NULL)
|
||||
tresult = check_options(vconfig, logctx, mctx);
|
||||
if (voptions != NULL)
|
||||
tresult = check_options(voptions, logctx, mctx);
|
||||
else
|
||||
tresult = check_options(config, logctx, mctx);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
|
||||
tresult = check_viewacls(voptions, config, logctx, mctx);
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.12.18.1 2004/07/20 07:03:30 marka Exp $
|
||||
# $Id: Makefile.in,v 1.12.18.2 2005/01/11 03:55:59 marka Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
|
@ -43,10 +43,10 @@ LIBS = @LIBS@
|
|||
SUBDIRS = include
|
||||
|
||||
# Alphabetically
|
||||
OBJS = log.@O@ namedconf.@O@ parser.@O@ version.@O@
|
||||
OBJS = aclconf.@O@ log.@O@ namedconf.@O@ parser.@O@ version.@O@
|
||||
|
||||
# Alphabetically
|
||||
SRCS = log.c namedconf.c parser.c version.c
|
||||
SRCS = aclconf.c log.c namedconf.c parser.c version.c
|
||||
|
||||
TARGETS = timestamp
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.8 2004/03/05 05:12:26 marka Exp $
|
||||
# $Id: Makefile.in,v 1.8.18.1 2005/01/11 03:55:59 marka Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
|
@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@
|
|||
# machine generated. The latter are handled specially in the
|
||||
# install target below.
|
||||
#
|
||||
HEADERS = cfg.h grammar.h log.h namedconf.h version.h
|
||||
HEADERS = aclconf.h cfg.h grammar.h log.h namedconf.h version.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
|
|
|||
Loading…
Reference in a new issue