1091e9e46SCy Schubert /* 2091e9e46SCy Schubert * services/rpz.h - rpz service 3091e9e46SCy Schubert * 4091e9e46SCy Schubert * Copyright (c) 2019, NLnet Labs. All rights reserved. 5091e9e46SCy Schubert * 6091e9e46SCy Schubert * This software is open source. 7091e9e46SCy Schubert * 8091e9e46SCy Schubert * Redistribution and use in source and binary forms, with or without 9091e9e46SCy Schubert * modification, are permitted provided that the following conditions 10091e9e46SCy Schubert * are met: 11091e9e46SCy Schubert * 12091e9e46SCy Schubert * Redistributions of source code must retain the above copyright notice, 13091e9e46SCy Schubert * this list of conditions and the following disclaimer. 14091e9e46SCy Schubert * 15091e9e46SCy Schubert * Redistributions in binary form must reproduce the above copyright notice, 16091e9e46SCy Schubert * this list of conditions and the following disclaimer in the documentation 17091e9e46SCy Schubert * and/or other materials provided with the distribution. 18091e9e46SCy Schubert * 19091e9e46SCy Schubert * Neither the name of the NLNET LABS nor the names of its contributors may 20091e9e46SCy Schubert * be used to endorse or promote products derived from this software without 21091e9e46SCy Schubert * specific prior written permission. 22091e9e46SCy Schubert * 23091e9e46SCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24091e9e46SCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25091e9e46SCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26091e9e46SCy Schubert * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27091e9e46SCy Schubert * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28091e9e46SCy Schubert * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29091e9e46SCy Schubert * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30091e9e46SCy Schubert * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31091e9e46SCy Schubert * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32091e9e46SCy Schubert * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33091e9e46SCy Schubert * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34091e9e46SCy Schubert */ 35091e9e46SCy Schubert 36091e9e46SCy Schubert /** 37091e9e46SCy Schubert * \file 38091e9e46SCy Schubert * 39091e9e46SCy Schubert * This file contains functions to enable RPZ service. 40091e9e46SCy Schubert */ 41091e9e46SCy Schubert 42091e9e46SCy Schubert #ifndef SERVICES_RPZ_H 43091e9e46SCy Schubert #define SERVICES_RPZ_H 44091e9e46SCy Schubert 45091e9e46SCy Schubert #include "services/localzone.h" 46091e9e46SCy Schubert #include "util/locks.h" 47091e9e46SCy Schubert #include "util/log.h" 48091e9e46SCy Schubert #include "util/config_file.h" 49091e9e46SCy Schubert #include "services/authzone.h" 50091e9e46SCy Schubert #include "sldns/sbuffer.h" 51091e9e46SCy Schubert #include "daemon/stats.h" 52091e9e46SCy Schubert #include "respip/respip.h" 5324e36522SCy Schubert struct iter_qstate; 54091e9e46SCy Schubert 55091e9e46SCy Schubert /** 56091e9e46SCy Schubert * RPZ triggers, only the QNAME trigger is currently supported in Unbound. 57091e9e46SCy Schubert */ 58091e9e46SCy Schubert enum rpz_trigger { 59091e9e46SCy Schubert RPZ_QNAME_TRIGGER = 0, 60091e9e46SCy Schubert /* unsupported triggers */ 61091e9e46SCy Schubert RPZ_CLIENT_IP_TRIGGER, /* rpz-client-ip */ 62091e9e46SCy Schubert RPZ_RESPONSE_IP_TRIGGER, /* rpz-ip */ 63091e9e46SCy Schubert RPZ_NSDNAME_TRIGGER, /* rpz-nsdname */ 64091e9e46SCy Schubert RPZ_NSIP_TRIGGER, /* rpz-nsip */ 65091e9e46SCy Schubert RPZ_INVALID_TRIGGER, /* dname does not contain valid trigger */ 66091e9e46SCy Schubert }; 67091e9e46SCy Schubert 68091e9e46SCy Schubert /** 69091e9e46SCy Schubert * RPZ actions. 70091e9e46SCy Schubert */ 71091e9e46SCy Schubert enum rpz_action { 72091e9e46SCy Schubert RPZ_NXDOMAIN_ACTION = 0,/* CNAME . */ 73091e9e46SCy Schubert RPZ_NODATA_ACTION, /* CNAME *. */ 74091e9e46SCy Schubert RPZ_PASSTHRU_ACTION, /* CNAME rpz-passthru. */ 75091e9e46SCy Schubert RPZ_DROP_ACTION, /* CNAME rpz-drop. */ 76091e9e46SCy Schubert RPZ_TCP_ONLY_ACTION, /* CNAME rpz-tcp-only. */ 77091e9e46SCy Schubert RPZ_INVALID_ACTION, /* CNAME with (child of) TLD starting with 78091e9e46SCy Schubert "rpz-" in target, SOA, NS, DNAME and 79091e9e46SCy Schubert DNSSEC-related records. */ 80091e9e46SCy Schubert RPZ_LOCAL_DATA_ACTION, /* anything else */ 81091e9e46SCy Schubert /* RPZ override actions */ 82091e9e46SCy Schubert RPZ_DISABLED_ACTION, /* RPZ action disabled using override */ 83091e9e46SCy Schubert RPZ_NO_OVERRIDE_ACTION, /* RPZ action no override*/ 84091e9e46SCy Schubert RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/ 85091e9e46SCy Schubert }; 86091e9e46SCy Schubert 8724e36522SCy Schubert struct clientip_synthesized_rrset { 8824e36522SCy Schubert struct regional* region; 8924e36522SCy Schubert struct rbtree_type entries; 908f76bb7dSCy Schubert /** lock on the entries tree */ 918f76bb7dSCy Schubert lock_rw_type lock; 9224e36522SCy Schubert }; 9324e36522SCy Schubert 9424e36522SCy Schubert struct clientip_synthesized_rr { 9524e36522SCy Schubert /** node in address tree */ 9624e36522SCy Schubert struct addr_tree_node node; 9724e36522SCy Schubert /** lock on the node item */ 9824e36522SCy Schubert lock_rw_type lock; 9924e36522SCy Schubert /** action for this address span */ 10024e36522SCy Schubert enum rpz_action action; 10124e36522SCy Schubert /** "local data" for this node */ 10224e36522SCy Schubert struct local_rrset* data; 10324e36522SCy Schubert }; 10424e36522SCy Schubert 105091e9e46SCy Schubert /** 106091e9e46SCy Schubert * RPZ containing policies. Pointed to from corresponding auth-zone. Part of a 107091e9e46SCy Schubert * linked list to keep configuration order. Iterating or changing the linked 10825039b37SCy Schubert * list requires the rpz_lock from struct auth_zones. Changing items in this 10925039b37SCy Schubert * struct require the lock from struct auth_zone. 110091e9e46SCy Schubert */ 111091e9e46SCy Schubert struct rpz { 112091e9e46SCy Schubert struct local_zones* local_zones; 113091e9e46SCy Schubert struct respip_set* respip_set; 11424e36522SCy Schubert struct clientip_synthesized_rrset* client_set; 11524e36522SCy Schubert struct clientip_synthesized_rrset* ns_set; 11624e36522SCy Schubert struct local_zones* nsdname_zones; 117091e9e46SCy Schubert uint8_t* taglist; 118091e9e46SCy Schubert size_t taglistlen; 119091e9e46SCy Schubert enum rpz_action action_override; 120091e9e46SCy Schubert struct ub_packed_rrset_key* cname_override; 121091e9e46SCy Schubert int log; 122091e9e46SCy Schubert char* log_name; 1239cf5bc93SCy Schubert /** signal NXDOMAIN blocked with unset RA flag */ 1249cf5bc93SCy Schubert int signal_nxdomain_ra; 125091e9e46SCy Schubert struct regional* region; 126f44e67d1SCy Schubert int disabled; 127091e9e46SCy Schubert }; 128091e9e46SCy Schubert 129091e9e46SCy Schubert /** 130091e9e46SCy Schubert * Create policy from RR and add to this RPZ. 131091e9e46SCy Schubert * @param r: the rpz to add the policy to. 13225039b37SCy Schubert * @param azname: dname of the auth-zone 133091e9e46SCy Schubert * @param aznamelen: the length of the auth-zone name 134091e9e46SCy Schubert * @param dname: dname of the RR 135091e9e46SCy Schubert * @param dnamelen: length of the dname 136091e9e46SCy Schubert * @param rr_type: RR type of the RR 137091e9e46SCy Schubert * @param rr_class: RR class of the RR 138091e9e46SCy Schubert * @param rr_ttl: TTL of the RR 139091e9e46SCy Schubert * @param rdatawl: rdata of the RR, prepended with the rdata size 140091e9e46SCy Schubert * @param rdatalen: length if the RR, including the prepended rdata size 141091e9e46SCy Schubert * @param rr: the complete RR, for logging purposes 142091e9e46SCy Schubert * @param rr_len: the length of the complete RR 143091e9e46SCy Schubert * @return: 0 on error 144091e9e46SCy Schubert */ 14525039b37SCy Schubert int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, 146091e9e46SCy Schubert size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl, 147091e9e46SCy Schubert uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len); 148091e9e46SCy Schubert 149091e9e46SCy Schubert /** 150091e9e46SCy Schubert * Delete policy matching RR, used for IXFR. 151091e9e46SCy Schubert * @param r: the rpz to add the policy to. 1528f76bb7dSCy Schubert * @param azname: dname of the auth-zone 153091e9e46SCy Schubert * @param aznamelen: the length of the auth-zone name 154091e9e46SCy Schubert * @param dname: dname of the RR 155091e9e46SCy Schubert * @param dnamelen: length of the dname 156091e9e46SCy Schubert * @param rr_type: RR type of the RR 157091e9e46SCy Schubert * @param rr_class: RR class of the RR 158091e9e46SCy Schubert * @param rdatawl: rdata of the RR, prepended with the rdata size 159091e9e46SCy Schubert * @param rdatalen: length if the RR, including the prepended rdata size 160091e9e46SCy Schubert */ 1618f76bb7dSCy Schubert void rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, 1628f76bb7dSCy Schubert uint8_t* dname, size_t dnamelen, uint16_t rr_type, uint16_t rr_class, 1638f76bb7dSCy Schubert uint8_t* rdatawl, size_t rdatalen); 164091e9e46SCy Schubert 165091e9e46SCy Schubert /** 166091e9e46SCy Schubert * Walk over the RPZ zones to find and apply a QNAME trigger policy. 167091e9e46SCy Schubert * @param az: auth_zones struct, containing first RPZ item and RPZ lock 168091e9e46SCy Schubert * @param env: module env 169091e9e46SCy Schubert * @param qinfo: qinfo containing qname and qtype 170091e9e46SCy Schubert * @param edns: edns data 171091e9e46SCy Schubert * @param buf: buffer to write answer to 172091e9e46SCy Schubert * @param temp: scratchpad 173091e9e46SCy Schubert * @param repinfo: reply info 174091e9e46SCy Schubert * @param taglist: taglist to lookup. 17524e36522SCy Schubert * @param taglen: length of taglist. 176091e9e46SCy Schubert * @param stats: worker stats struct 177a39a5a69SCy Schubert * @param passthru: returns if the query can passthru further rpz processing. 178091e9e46SCy Schubert * @return: 1 if client answer is ready, 0 to continue resolving 179091e9e46SCy Schubert */ 18024e36522SCy Schubert int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, 181091e9e46SCy Schubert struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, 182091e9e46SCy Schubert struct regional* temp, struct comm_reply* repinfo, 183a39a5a69SCy Schubert uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, 184a39a5a69SCy Schubert int* passthru); 185091e9e46SCy Schubert 186091e9e46SCy Schubert /** 18724e36522SCy Schubert * Callback to process when the iterator module is about to send queries. 18824e36522SCy Schubert * Checks for nsip and nsdname triggers. 18924e36522SCy Schubert * @param qstate: the query state. 19024e36522SCy Schubert * @param iq: iterator module query state. 19124e36522SCy Schubert * @return NULL if nothing is done. Or a new message with the contents from 19224e36522SCy Schubert * the rpz, based on the delegation point. It is allocated in the 19324e36522SCy Schubert * qstate region. 19424e36522SCy Schubert */ 19524e36522SCy Schubert struct dns_msg* rpz_callback_from_iterator_module(struct module_qstate* qstate, 19624e36522SCy Schubert struct iter_qstate* iq); 19724e36522SCy Schubert 19824e36522SCy Schubert /** 19924e36522SCy Schubert * Callback to process when the iterator module has followed a cname. 20024e36522SCy Schubert * There can be a qname trigger for the new query name. 20124e36522SCy Schubert * @param qstate: the query state. 20224e36522SCy Schubert * @param iq: iterator module query state. 20324e36522SCy Schubert * @return NULL if nothing is done. Or a new message with the contents from 20424e36522SCy Schubert * the rpz, based on the iq.qchase. It is allocated in the qstate region. 20524e36522SCy Schubert */ 20624e36522SCy Schubert struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* qstate, 20724e36522SCy Schubert struct iter_qstate* iq); 20824e36522SCy Schubert 20924e36522SCy Schubert /** 210091e9e46SCy Schubert * Delete RPZ 211091e9e46SCy Schubert * @param r: RPZ struct to delete 212091e9e46SCy Schubert */ 213091e9e46SCy Schubert void rpz_delete(struct rpz* r); 214091e9e46SCy Schubert 215091e9e46SCy Schubert /** 216091e9e46SCy Schubert * Clear local-zones and respip data in RPZ, used after reloading file or 217091e9e46SCy Schubert * AXFR/HTTP transfer. 218091e9e46SCy Schubert * @param r: RPZ to use 219091e9e46SCy Schubert */ 220091e9e46SCy Schubert int rpz_clear(struct rpz* r); 221091e9e46SCy Schubert 222091e9e46SCy Schubert /** 223091e9e46SCy Schubert * Create RPZ. RPZ must be added to linked list after creation. 224091e9e46SCy Schubert * @return: the newly created RPZ 225091e9e46SCy Schubert */ 226091e9e46SCy Schubert struct rpz* rpz_create(struct config_auth* p); 227091e9e46SCy Schubert 228091e9e46SCy Schubert /** 229335c7cdaSCy Schubert * Change config on rpz, after reload. 230335c7cdaSCy Schubert * @param r: the rpz structure. 231335c7cdaSCy Schubert * @param p: the config that was read. 232335c7cdaSCy Schubert * @return false on failure. 233335c7cdaSCy Schubert */ 234335c7cdaSCy Schubert int rpz_config(struct rpz* r, struct config_auth* p); 235335c7cdaSCy Schubert 236335c7cdaSCy Schubert /** 237091e9e46SCy Schubert * String for RPZ action enum 238091e9e46SCy Schubert * @param a: RPZ action to get string for 239091e9e46SCy Schubert * @return: string for RPZ action 240091e9e46SCy Schubert */ 241091e9e46SCy Schubert const char* rpz_action_to_string(enum rpz_action a); 242091e9e46SCy Schubert 243091e9e46SCy Schubert enum rpz_action 244091e9e46SCy Schubert respip_action_to_rpz_action(enum respip_action a); 245091e9e46SCy Schubert 246091e9e46SCy Schubert /** 24724e36522SCy Schubert * Prepare RPZ after processing feed content. 248091e9e46SCy Schubert * @param r: RPZ to use 249091e9e46SCy Schubert */ 250091e9e46SCy Schubert void rpz_finish_config(struct rpz* r); 251091e9e46SCy Schubert 252091e9e46SCy Schubert /** 253091e9e46SCy Schubert * Classify respip action for RPZ action 254091e9e46SCy Schubert * @param a: RPZ action 255091e9e46SCy Schubert * @return: the respip action 256091e9e46SCy Schubert */ 257091e9e46SCy Schubert enum respip_action 258091e9e46SCy Schubert rpz_action_to_respip_action(enum rpz_action a); 259091e9e46SCy Schubert 260f44e67d1SCy Schubert /** 261f44e67d1SCy Schubert * Enable RPZ 262f44e67d1SCy Schubert * @param r: RPZ struct to enable 263f44e67d1SCy Schubert */ 264f44e67d1SCy Schubert void rpz_enable(struct rpz* r); 265f44e67d1SCy Schubert 266f44e67d1SCy Schubert /** 267f44e67d1SCy Schubert * Disable RPZ 268f44e67d1SCy Schubert * @param r: RPZ struct to disable 269f44e67d1SCy Schubert */ 270f44e67d1SCy Schubert void rpz_disable(struct rpz* r); 271f44e67d1SCy Schubert 272*be771a7bSCy Schubert /** 273*be771a7bSCy Schubert * Get memory usage of rpz. Caller must manage locks. 274*be771a7bSCy Schubert * @param r: RPZ struct. 275*be771a7bSCy Schubert * @return memory usage. 276*be771a7bSCy Schubert */ 277*be771a7bSCy Schubert size_t rpz_get_mem(struct rpz* r); 278*be771a7bSCy Schubert 279091e9e46SCy Schubert #endif /* SERVICES_RPZ_H */ 280