xref: /freebsd/contrib/unbound/services/rpz.h (revision be771a7b7f4580a30d99e41a5bb1b93a385a119d)
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