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