Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: rpz.h,v 1.13 2026/01/29 18:37:51 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #pragma once
     17 
     18 /* Add -DDNS_RPZ_TRACE=1 to CFLAGS for detailed reference tracing */
     19 
     20 #include <inttypes.h>
     21 #include <stdbool.h>
     22 
     23 #include <isc/atomic.h>
     24 #include <isc/ht.h>
     25 #include <isc/lang.h>
     26 #include <isc/refcount.h>
     27 #include <isc/rwlock.h>
     28 #include <isc/time.h>
     29 #include <isc/timer.h>
     30 
     31 #include <dns/fixedname.h>
     32 #include <dns/qp.h>
     33 #include <dns/rdata.h>
     34 #include <dns/types.h>
     35 
     36 ISC_LANG_BEGINDECLS
     37 
     38 #define DNS_RPZ_PREFIX "rpz-"
     39 /*
     40  * Sub-zones of various trigger types.
     41  */
     42 #define DNS_RPZ_CLIENT_IP_ZONE DNS_RPZ_PREFIX "client-ip"
     43 #define DNS_RPZ_IP_ZONE	       DNS_RPZ_PREFIX "ip"
     44 #define DNS_RPZ_NSIP_ZONE      DNS_RPZ_PREFIX "nsip"
     45 #define DNS_RPZ_NSDNAME_ZONE   DNS_RPZ_PREFIX "nsdname"
     46 /*
     47  * Special policies.
     48  */
     49 #define DNS_RPZ_PASSTHRU_NAME DNS_RPZ_PREFIX "passthru"
     50 #define DNS_RPZ_DROP_NAME     DNS_RPZ_PREFIX "drop"
     51 #define DNS_RPZ_TCP_ONLY_NAME DNS_RPZ_PREFIX "tcp-only"
     52 
     53 typedef uint8_t dns_rpz_prefix_t;
     54 
     55 typedef enum {
     56 	DNS_RPZ_TYPE_BAD,
     57 	DNS_RPZ_TYPE_CLIENT_IP,
     58 	DNS_RPZ_TYPE_QNAME,
     59 	DNS_RPZ_TYPE_IP,
     60 	DNS_RPZ_TYPE_NSDNAME,
     61 	DNS_RPZ_TYPE_NSIP
     62 } dns_rpz_type_t;
     63 
     64 /*
     65  * Require DNS_RPZ_POLICY_PASSTHRU < DNS_RPZ_POLICY_DROP
     66  * < DNS_RPZ_POLICY_TCP_ONLY DNS_RPZ_POLICY_NXDOMAIN < DNS_RPZ_POLICY_NODATA
     67  * < DNS_RPZ_POLICY_CNAME to choose among competing policies.
     68  */
     69 typedef enum {
     70 	DNS_RPZ_POLICY_GIVEN = 0,    /* 'given': what policy record says */
     71 	DNS_RPZ_POLICY_DISABLED = 1, /* log what would have happened */
     72 	DNS_RPZ_POLICY_PASSTHRU = 2, /* 'passthru': do not rewrite */
     73 	DNS_RPZ_POLICY_DROP = 3,     /* 'drop': do not respond */
     74 	DNS_RPZ_POLICY_TCP_ONLY = 4, /* 'tcp-only': answer UDP with TC=1 */
     75 	DNS_RPZ_POLICY_NXDOMAIN = 5, /* 'nxdomain': answer with NXDOMAIN */
     76 	DNS_RPZ_POLICY_NODATA = 6,   /* 'nodata': answer with ANCOUNT=0 */
     77 	DNS_RPZ_POLICY_CNAME = 7,    /* 'cname x': answer with x's rrsets */
     78 	DNS_RPZ_POLICY_DNS64,	     /* Apply DN64 to the A rewrite */
     79 	DNS_RPZ_POLICY_RECORD,
     80 	DNS_RPZ_POLICY_WILDCNAME,
     81 	DNS_RPZ_POLICY_MISS,
     82 	DNS_RPZ_POLICY_ERROR
     83 } dns_rpz_policy_t;
     84 
     85 typedef uint8_t dns_rpz_num_t;
     86 
     87 #define DNS_RPZ_MAX_ZONES 64
     88 /*
     89  * Type dns_rpz_zbits_t must be an unsigned int wide enough to contain
     90  * at least DNS_RPZ_MAX_ZONES bits.
     91  */
     92 typedef uint64_t dns_rpz_zbits_t;
     93 
     94 #define DNS_RPZ_ALL_ZBITS ((dns_rpz_zbits_t) - 1)
     95 
     96 #define DNS_RPZ_INVALID_NUM DNS_RPZ_MAX_ZONES
     97 
     98 #define DNS_RPZ_ZBIT(n) (((dns_rpz_zbits_t)1) << (dns_rpz_num_t)(n))
     99 
    100 /*
    101  * Mask of the specified and higher numbered policy zones
    102  * Avoid hassles with (1<<33) or (1<<65)
    103  */
    104 #define DNS_RPZ_ZMASK(n)                                     \
    105 	((dns_rpz_zbits_t)((((n) >= DNS_RPZ_MAX_ZONES - 1)   \
    106 				    ? 0                      \
    107 				    : (1ULL << ((n) + 1))) - \
    108 			   1))
    109 
    110 /*
    111  * The trigger counter type.
    112  */
    113 typedef size_t dns_rpz_trigger_counter_t;
    114 
    115 /*
    116  * The number of triggers of each type in a response policy zone.
    117  */
    118 typedef struct dns_rpz_triggers dns_rpz_triggers_t;
    119 struct dns_rpz_triggers {
    120 	dns_rpz_trigger_counter_t client_ipv4;
    121 	dns_rpz_trigger_counter_t client_ipv6;
    122 	dns_rpz_trigger_counter_t qname;
    123 	dns_rpz_trigger_counter_t ipv4;
    124 	dns_rpz_trigger_counter_t ipv6;
    125 	dns_rpz_trigger_counter_t nsdname;
    126 	dns_rpz_trigger_counter_t nsipv4;
    127 	dns_rpz_trigger_counter_t nsipv6;
    128 };
    129 
    130 /*
    131  * A single response policy zone.
    132  */
    133 typedef struct dns_rpz_zone  dns_rpz_zone_t;
    134 typedef struct dns_rpz_zones dns_rpz_zones_t;
    135 
    136 struct dns_rpz_zone {
    137 	unsigned int magic;
    138 	isc_loop_t  *loop;
    139 
    140 	dns_rpz_num_t	 num;	    /* ordinal in list of policy zones */
    141 	dns_name_t	 origin;    /* Policy zone name */
    142 	dns_name_t	 client_ip; /* DNS_RPZ_CLIENT_IP_ZONE.origin. */
    143 	dns_name_t	 ip;	    /* DNS_RPZ_IP_ZONE.origin. */
    144 	dns_name_t	 nsdname;   /* DNS_RPZ_NSDNAME_ZONE.origin */
    145 	dns_name_t	 nsip;	    /* DNS_RPZ_NSIP_ZONE.origin. */
    146 	dns_name_t	 passthru;  /* DNS_RPZ_PASSTHRU_NAME. */
    147 	dns_name_t	 drop;	    /* DNS_RPZ_DROP_NAME. */
    148 	dns_name_t	 tcp_only;  /* DNS_RPZ_TCP_ONLY_NAME. */
    149 	dns_name_t	 cname;	    /* override value for ..._CNAME */
    150 	dns_ttl_t	 max_policy_ttl;
    151 	dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */
    152 	uint16_t	 ede;	 /* Extended DNS Error */
    153 
    154 	uint32_t min_update_interval;	/* minimal interval between
    155 					 * updates */
    156 	isc_ht_t	*nodes;		/* entries in zone */
    157 	dns_rpz_zones_t *rpzs;		/* owner */
    158 	isc_time_t	 lastupdated;	/* last time the zone was processed
    159 					 * */
    160 	bool		 processed;	/* the zone is processed. */
    161 	bool		 dbregistered;	/* db callback notify is registered. */
    162 	bool		 updatepending; /* there is an update pending */
    163 	bool		 updaterunning; /* there is an update running */
    164 	isc_result_t	 updateresult;	/* result from the offloaded work */
    165 	dns_db_t	*db;		/* zones database */
    166 	dns_dbversion_t *dbversion;	/* version we will be updating to */
    167 	dns_db_t	*updb;		/* zones database we're working on */
    168 	dns_dbversion_t *updbversion;	/* version we're currently working
    169 					 * on */
    170 	bool	     addsoa;		/* add soa to the additional section */
    171 	isc_timer_t *updatetimer;
    172 };
    173 
    174 /*
    175  * Radix tree node for response policy IP addresses
    176  */
    177 typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t;
    178 
    179 /*
    180  * Bitfields indicating which policy zones have policies of
    181  * which type.
    182  */
    183 typedef struct dns_rpz_have dns_rpz_have_t;
    184 struct dns_rpz_have {
    185 	dns_rpz_zbits_t client_ipv4;
    186 	dns_rpz_zbits_t client_ipv6;
    187 	dns_rpz_zbits_t client_ip;
    188 	dns_rpz_zbits_t qname;
    189 	dns_rpz_zbits_t ipv4;
    190 	dns_rpz_zbits_t ipv6;
    191 	dns_rpz_zbits_t ip;
    192 	dns_rpz_zbits_t nsdname;
    193 	dns_rpz_zbits_t nsipv4;
    194 	dns_rpz_zbits_t nsipv6;
    195 	dns_rpz_zbits_t nsip;
    196 	dns_rpz_zbits_t qname_skip_recurse;
    197 };
    198 
    199 /*
    200  * Policy options
    201  */
    202 typedef struct dns_rpz_popt dns_rpz_popt_t;
    203 struct dns_rpz_popt {
    204 	dns_rpz_zbits_t no_rd_ok;
    205 	dns_rpz_zbits_t no_log;
    206 	dns_rpz_zbits_t nsip_on;
    207 	dns_rpz_zbits_t nsdname_on;
    208 	bool		dnsrps_enabled;
    209 	bool		break_dnssec;
    210 	bool		qname_wait_recurse;
    211 	bool		nsip_wait_recurse;
    212 	bool		nsdname_wait_recurse;
    213 	bool		servfail_until_ready;
    214 	bool		slow_mode; /* Used for system tests with '-T rpzslow' */
    215 	unsigned int	min_ns_labels;
    216 	dns_rpz_num_t	num_zones;
    217 };
    218 
    219 /*
    220  * Response policy zones known to a view.
    221  */
    222 struct dns_rpz_zones {
    223 	unsigned int   magic;
    224 	isc_refcount_t references;
    225 	isc_mem_t     *mctx;
    226 	isc_loopmgr_t *loopmgr;
    227 
    228 	dns_rpz_popt_t	   p;
    229 	dns_rpz_zone_t	  *zones[DNS_RPZ_MAX_ZONES];
    230 	dns_rpz_triggers_t triggers[DNS_RPZ_MAX_ZONES];
    231 
    232 	_Atomic(dns_rpz_num_t) zones_registered;
    233 	_Atomic(dns_rpz_num_t) zones_processed;
    234 
    235 	/*
    236 	 * RPZ policy version number.
    237 	 * It is initially 0 and it increases whenever the server is
    238 	 * reconfigured with new zones or policy.
    239 	 */
    240 	int rpz_ver;
    241 
    242 	dns_rpz_zbits_t defined;
    243 
    244 	/*
    245 	 * The set of records for a policy zone are in one of these states:
    246 	 *	never loaded		    load_begun=0  have=0
    247 	 *	during initial loading	    load_begun=1  have=0
    248 	 *				and rbtdb->rpzsp == rbtdb->load_rpzsp
    249 	 *	after good load		    load_begun=1  have!=0
    250 	 *	after failed initial load   load_begun=1  have=0
    251 	 *				and rbtdb->load_rpzsp == NULL
    252 	 *	reloading after failure	    load_begun=1  have=0
    253 	 *	reloading after success
    254 	 *		main rpzs	    load_begun=1  have!=0
    255 	 *		load rpzs	    load_begun=1  have=0
    256 	 */
    257 	dns_rpz_zbits_t load_begun;
    258 	dns_rpz_have_t	have;
    259 
    260 	/*
    261 	 * total_triggers maintains the total number of triggers in all
    262 	 * policy zones in the view. It is only used to print summary
    263 	 * statistics after a zone load of how the trigger counts
    264 	 * changed.
    265 	 */
    266 	dns_rpz_triggers_t total_triggers;
    267 
    268 	/*
    269 	 * One lock for short term read-only search that guarantees the
    270 	 * consistency of the pointers.
    271 	 * A second lock for maintenance that guarantees no other thread
    272 	 * is adding or deleting nodes.
    273 	 */
    274 	isc_rwlock_t search_lock;
    275 	isc_mutex_t  maint_lock;
    276 
    277 	bool first_time;
    278 	bool shuttingdown;
    279 
    280 	dns_rpz_cidr_node_t *cidr;
    281 	dns_qpmulti_t	    *table;
    282 
    283 	/*
    284 	 * DNSRPZ librpz configuration string and handle on librpz connection
    285 	 */
    286 	char		     *rps_cstr;
    287 	size_t		      rps_cstr_size;
    288 	struct librpz_client *rps_client;
    289 };
    290 
    291 /*
    292  * context for finding the best policy
    293  */
    294 typedef struct {
    295 	unsigned int state;
    296 #define DNS_RPZ_REWRITTEN      0x0001
    297 #define DNS_RPZ_DONE_CLIENT_IP 0x0002 /* client IP address checked */
    298 #define DNS_RPZ_DONE_QNAME     0x0004 /* qname checked */
    299 #define DNS_RPZ_DONE_QNAME_IP  0x0008 /* IP addresses of qname checked */
    300 #define DNS_RPZ_DONE_NSDNAME   0x0010 /* NS name missed; checking addresses */
    301 #define DNS_RPZ_DONE_IPv4      0x0020
    302 #define DNS_RPZ_RECURSING      0x0040
    303 #define DNS_RPZ_ACTIVE	       0x0080
    304 	/*
    305 	 * Best match so far.
    306 	 */
    307 	struct {
    308 		dns_rpz_type_t	 type;
    309 		dns_rpz_zone_t	*rpz;
    310 		dns_rpz_prefix_t prefix;
    311 		dns_rpz_policy_t policy;
    312 		dns_ttl_t	 ttl;
    313 		isc_result_t	 result;
    314 		dns_zone_t	*zone;
    315 		dns_db_t	*db;
    316 		dns_dbversion_t *version;
    317 		dns_dbnode_t	*node;
    318 		dns_rdataset_t	*rdataset;
    319 	} m;
    320 	/*
    321 	 * State for chasing IP addresses and NS names including recursion.
    322 	 */
    323 	struct {
    324 		unsigned int	label;
    325 		dns_db_t       *db;
    326 		dns_rdataset_t *ns_rdataset;
    327 		dns_rdatatype_t r_type;
    328 		isc_result_t	r_result;
    329 		dns_rdataset_t *r_rdataset;
    330 	} r;
    331 
    332 	/*
    333 	 * State of real query while recursing for NSIP or NSDNAME.
    334 	 */
    335 	struct {
    336 		isc_result_t	result;
    337 		bool		is_zone;
    338 		bool		authoritative;
    339 		dns_zone_t     *zone;
    340 		dns_db_t       *db;
    341 		dns_dbnode_t   *node;
    342 		dns_rdataset_t *rdataset;
    343 		dns_rdataset_t *sigrdataset;
    344 		dns_rdatatype_t qtype;
    345 	} q;
    346 
    347 	/*
    348 	 * A copy of the 'have' and 'p' structures and the RPZ
    349 	 * policy version as of the beginning of RPZ processing,
    350 	 * used to avoid problems when policy is updated while
    351 	 * RPZ recursion is ongoing.
    352 	 */
    353 	dns_rpz_have_t have;
    354 	dns_rpz_popt_t popt;
    355 	int	       rpz_ver;
    356 
    357 	/*
    358 	 * Shim db between BIND and DNRPS librpz.
    359 	 */
    360 	dns_db_t *rpsdb;
    361 
    362 	/*
    363 	 * p_name: current policy owner name
    364 	 * r_name: recursing for this name to possible policy triggers
    365 	 * f_name: saved found name from before recursion
    366 	 */
    367 	dns_name_t     *p_name;
    368 	dns_name_t     *r_name;
    369 	dns_name_t     *fname;
    370 	dns_fixedname_t _p_namef;
    371 	dns_fixedname_t _r_namef;
    372 	dns_fixedname_t _fnamef;
    373 } dns_rpz_st_t;
    374 
    375 #define DNS_RPZ_TTL_DEFAULT		  5
    376 #define DNS_RPZ_MAX_TTL_DEFAULT		  DNS_RPZ_TTL_DEFAULT
    377 #define DNS_RPZ_MINUPDATEINTERVAL_DEFAULT 60
    378 
    379 /*
    380  * So various response policy zone messages can be turned up or down.
    381  */
    382 #define DNS_RPZ_ERROR_LEVEL  ISC_LOG_WARNING
    383 #define DNS_RPZ_INFO_LEVEL   ISC_LOG_INFO
    384 #define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1)
    385 #define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2)
    386 #define DNS_RPZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3)
    387 #define DNS_RPZ_DEBUG_QUIET  (DNS_RPZ_DEBUG_LEVEL3 + 1)
    388 
    389 const char *
    390 dns_rpz_type2str(dns_rpz_type_t type);
    391 
    392 dns_rpz_policy_t
    393 dns_rpz_str2policy(const char *str);
    394 
    395 const char *
    396 dns_rpz_policy2str(dns_rpz_policy_t policy);
    397 
    398 uint16_t
    399 dns_rpz_str2ede(const char *str);
    400 
    401 dns_rpz_policy_t
    402 dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
    403 		     dns_name_t *selfname);
    404 
    405 isc_result_t
    406 dns_rpz_new_zones(dns_view_t *view, isc_loopmgr_t *loopmgr, char *rps_cstr,
    407 		  size_t rps_cstr_size, dns_rpz_zones_t **rpzsp,
    408 		  bool first_time);
    409 
    410 isc_result_t
    411 dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp);
    412 
    413 isc_result_t
    414 dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg);
    415 void
    416 dns_rpz_dbupdate_unregister(dns_db_t *db, dns_rpz_zone_t *rpz);
    417 void
    418 dns_rpz_dbupdate_register(dns_db_t *db, dns_rpz_zone_t *rpz);
    419 
    420 void
    421 dns_rpz_zones_shutdown(dns_rpz_zones_t *rpzs);
    422 
    423 #ifdef DNS_RPZ_TRACE
    424 #define dns_rpz_zones_detach(rpzsp) \
    425 	dns_rpz_zones__detach(rpzsp, __func__, __FILE__, __LINE__)
    426 #define dns_rpz_zones_attach(rpzs, rpzsp) \
    427 	dns_rpz_zones__attach(rpzs, rpzsp, __func__, __FILE__, __LINE__)
    428 #define dns_rpz_zones_ref(ptr) \
    429 	dns_rpz_zones__ref(ptr, __func__, __FILE__, __LINE__)
    430 #define dns_rpz_zones_unref(ptr) \
    431 	dns_rpz_zones__unref(ptr, __func__, __FILE__, __LINE__)
    432 
    433 ISC_REFCOUNT_TRACE_DECL(dns_rpz_zones);
    434 #else
    435 ISC_REFCOUNT_DECL(dns_rpz_zones);
    436 #endif
    437 
    438 dns_rpz_num_t
    439 dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
    440 		dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr,
    441 		dns_name_t *ip_name, dns_rpz_prefix_t *prefixp);
    442 
    443 dns_rpz_zbits_t
    444 dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
    445 		  dns_rpz_zbits_t zbits, dns_name_t *trig_name);
    446 
    447 ISC_LANG_ENDDECLS
    448