- access-control-tag config directive.

git-svn-id: file:///svn/unbound/trunk@3754 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2016-06-06 08:33:59 +00:00
parent 17302c0e23
commit 415fc52b08
13 changed files with 1602 additions and 1453 deletions

View file

@ -71,7 +71,7 @@ acl_list_delete(struct acl_list* acl)
}
/** insert new address into acl_list structure */
static int
static struct acl_addr*
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, int net, enum acl_access control,
int complain_duplicates)
@ -79,13 +79,15 @@ acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
struct acl_addr* node = regional_alloc(acl->region,
sizeof(struct acl_addr));
if(!node)
return 0;
return NULL;
node->control = control;
node->taglist = NULL;
node->taglen = 0;
if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
if(complain_duplicates)
verbose(VERB_QUERY, "duplicate acl address ignored.");
}
return 1;
return node;
}
/** apply acl_list string */
@ -125,6 +127,40 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
return 1;
}
/** apply acl_tag string */
static int
acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
size_t bitmaplen)
{
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
struct acl_addr* node;
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
log_err("cannot parse netblock in access-control-tag: %s", str);
return 0;
}
/* find or create node */
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
addrlen, net))) {
/* create node, type 'allow' since otherwise tags are
* pointless, can override with specific access-control: cfg */
if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
addrlen, net, acl_allow, 1))) {
log_err("out of memory");
return 0;
}
}
log_assert(node);
node->taglen = bitmaplen;
node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
if(!node->taglist) {
log_err("out of memory");
return 0;
}
return 1;
}
/** read acl_list config */
static int
read_acl_list(struct acl_list* acl, struct config_file* cfg)
@ -138,6 +174,19 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
return 1;
}
/** read acl tags config */
static int
read_acl_tags(struct acl_list* acl, struct config_file* cfg)
{
struct config_strbytelist* p;
for(p = cfg->acl_tags; p; p = p->next) {
log_assert(p->str && p->str2);
if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len))
return 0;
}
return 1;
}
int
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
{
@ -145,6 +194,8 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
addr_tree_init(&acl->tree);
if(!read_acl_list(acl, cfg))
return 0;
if(!read_acl_tags(acl, cfg))
return 0;
/* insert defaults, with '0' to ignore them if they are duplicates */
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
return 0;

View file

@ -87,6 +87,10 @@ struct acl_addr {
struct addr_tree_node node;
/** access control on this netblock */
enum acl_access control;
/** tag bitlist */
uint8_t* taglist;
/** length of the taglist (in bytes) */
size_t taglen;
};
/**

View file

@ -1,5 +1,6 @@
6 June 2016: Wouter
- Better help text from -h (from Ray Griffith).
- access-control-tag config directive.
3 June 2016: Wouter
- Fix to not ignore return value of chown() in daemon startup.

View file

@ -203,6 +203,11 @@ server:
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
# tag access-control with list of tags (in "" with spaces between)
# Clients using this access control element use localzones that
# are tagged with one of these tags.
# access-control-tag: "192.0.2.0/24" "tag2 tag3"
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.

View file

@ -784,6 +784,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "qname-minimisation", qname_minimisation)
else O_IFC(opt, "define-tag", num_tags, tagname)
else O_LTG(opt, "local-zone-tag", local_zone_tags)
else O_LTG(opt, "access-control-tag", acl_tags)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@ -1022,6 +1023,7 @@ config_delete(struct config_file* cfg)
config_delstrlist(cfg->local_data);
config_del_strarray(cfg->tagname, cfg->num_tags);
config_del_strbytelist(cfg->local_zone_tags);
config_del_strbytelist(cfg->acl_tags);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);

View file

@ -298,6 +298,8 @@ struct config_file {
int insecure_lan_zones;
/** list of zonename, tagbitlist */
struct config_strbytelist* local_zone_tags;
/** list of aclname, tagbitlist */
struct config_strbytelist* acl_tags;
/** tag list, array with tagname[i] is malloced string */
char** tagname;
/** number of items in the taglist */

File diff suppressed because it is too large Load diff

View file

@ -345,6 +345,7 @@ dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) }
local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }

File diff suppressed because it is too large Load diff

View file

@ -211,7 +211,8 @@ extern int yydebug;
VAR_QNAME_MINIMISATION = 421,
VAR_IP_FREEBIND = 422,
VAR_DEFINE_TAG = 423,
VAR_LOCAL_ZONE_TAG = 424
VAR_LOCAL_ZONE_TAG = 424,
VAR_ACCESS_CONTROL_TAG = 425
};
#endif
/* Tokens. */
@ -382,6 +383,7 @@ extern int yydebug;
#define VAR_IP_FREEBIND 422
#define VAR_DEFINE_TAG 423
#define VAR_LOCAL_ZONE_TAG 424
#define VAR_ACCESS_CONTROL_TAG 425
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@ -392,7 +394,7 @@ union YYSTYPE
char* str;
#line 396 "util/configparser.h" /* yacc.c:1909 */
#line 398 "util/configparser.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View file

@ -126,6 +126,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
%token VAR_QNAME_MINIMISATION VAR_IP_FREEBIND VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG
%token VAR_ACCESS_CONTROL_TAG
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -194,7 +195,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_caps_whitelist | server_cache_max_negative_ttl |
server_permit_small_holddown | server_qname_minimisation |
server_ip_freebind | server_define_tag | server_local_zone_tag |
server_disable_dnssec_lame_check
server_disable_dnssec_lame_check | access_control_tag
;
stubstart: VAR_STUB_ZONE
{
@ -1332,6 +1333,25 @@ server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG
}
}
;
access_control_tag: VAR_ACCESS_CONTROL_TAG STRING_ARG STRING_ARG
{
size_t len = 0;
uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
&len);
free($3);
OUTYY(("P(server_access_control_tag:%s)\n", $2));
if(!bitlist)
yyerror("could not parse tags, (define-tag them first)");
if(bitlist) {
if(!cfg_strbytelist_insert(
&cfg_parser->cfg->acl_tags,
$2, bitlist, len)) {
yyerror("out of memory");
free($2);
}
}
}
;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));

View file

@ -231,6 +231,19 @@ struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
return result;
}
struct addr_tree_node* addr_tree_find(rbtree_t* tree,
struct sockaddr_storage* addr, socklen_t addrlen, int net)
{
rbnode_t* res = NULL;
struct addr_tree_node key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
key.net = net;
res = rbtree_search(tree, &key);
return (struct addr_tree_node*)res;
}
int
name_tree_next_root(rbtree_t* tree, uint16_t* dclass)
{

View file

@ -183,6 +183,18 @@ void addr_tree_init_parents(rbtree_t* tree);
struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Find element in addr tree. (search a netblock, not a match for an address)
* @param tree: addr tree
* @param addr: netblock to lookup.
* @param addrlen: length of addr
* @param net: size of subnet
* @return addr tree element, or NULL if not found.
*/
struct addr_tree_node* addr_tree_find(rbtree_t* tree,
struct sockaddr_storage* addr, socklen_t addrlen, int net);
/** compare name tree nodes */
int name_tree_compare(const void* k1, const void* k2);