process_query.c 15.2 KB
Newer Older
1 2 3
#include <stdio.h>
#include <urcu.h>

4
#include "knot/nameserver/process_query.h"
5 6 7 8 9
#include "knot/nameserver/chaos.h"
#include "knot/nameserver/internet.h"
#include "knot/nameserver/axfr.h"
#include "knot/nameserver/ixfr.h"
#include "knot/nameserver/update.h"
10
#include "knot/nameserver/nsec_proofs.h"
11
#include "knot/nameserver/notify.h"
12 13
#include "knot/server/server.h"
#include "knot/server/rrl.h"
14
#include "knot/updates/acl.h"
15
#include "knot/conf/conf.h"
16 17 18
#include "libknot/tsig-op.h"
#include "common/descriptor.h"
#include "common/debug.h"
19

20
/* Forward decls. */
21
static const zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb);
22 23 24 25
static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx);
static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx);
static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx);
static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx);
26 27

/*! \brief Module implementation. */
28 29 30 31 32 33 34
const knot_process_module_t _process_query = {
        &process_query_begin,
        &process_query_reset,
        &process_query_finish,
        &process_query_in,
        &process_query_out,
        &process_query_err
35 36
};

37
/*! \brief Accessor to query-specific data. */
38 39
#define QUERY_DATA(ctx) ((struct query_data *)(ctx)->data)

40
/*! \brief Reinitialize query data structure. */
41
static void query_data_init(knot_process_t *ctx, void *module_param)
42
{
43
	/* Initialize persistent data. */
44 45 46
	struct query_data *data = QUERY_DATA(ctx);
	memset(data, 0, sizeof(struct query_data));
	data->mm = &ctx->mm;
47
	data->param = (struct process_query_param*)module_param;
48

49
	/* Initialize lists. */
50
	init_list(&data->wildcards);
51
	init_list(&data->rrsigs);
52 53
}

54
int process_query_begin(knot_process_t *ctx, void *module_param)
55 56 57 58
{
	/* Initialize context. */
	assert(ctx);
	ctx->type = NS_PROC_QUERY_ID;
59
	ctx->data = mm_alloc(&ctx->mm, sizeof(struct query_data));
60 61 62

	/* Initialize persistent data. */
	query_data_init(ctx, module_param);
63 64 65 66 67

	/* Await packet. */
	return NS_PROC_MORE;
}

68
int process_query_reset(knot_process_t *ctx)
69 70
{
	assert(ctx);
71
	struct query_data *qdata = QUERY_DATA(ctx);
72

73
	/* Remember persistent parameters. */
74
	struct process_query_param *module_param = qdata->param;
75

76 77 78
	/* Free allocated data. */
	knot_pkt_free(&qdata->query);
	ptrlist_free(&qdata->wildcards, qdata->mm);
79
	nsec_clear_rrsigs(qdata);
80 81 82
	if (qdata->ext_cleanup != NULL) {
		qdata->ext_cleanup(qdata);
	}
83 84 85

	/* Initialize persistent data. */
	query_data_init(ctx, module_param);
86

87 88 89
	/* Await packet. */
	return NS_PROC_MORE;
}
90
int process_query_finish(knot_process_t *ctx)
91
{
92
	process_query_reset(ctx);
93 94 95
	ctx->mm.free(ctx->data);
	ctx->data = NULL;

96
	return NS_PROC_NOOP;
97
}
98
int process_query_in(knot_pkt_t *pkt, knot_process_t *ctx)
99 100
{
	assert(pkt && ctx);
101
	struct query_data *qdata = QUERY_DATA(ctx);
102

103 104
	/* Check if at least header is parsed. */
	if (pkt->parsed < KNOT_WIRE_HEADER_SIZE) {
105
		knot_pkt_free(&pkt);
106 107
		return NS_PROC_NOOP; /* Ignore. */
	}
108

109 110
	/* Accept only queries. */
	if (knot_wire_get_qr(pkt->wire)) {
111 112
		knot_pkt_free(&pkt);
		return NS_PROC_NOOP; /* Ignore. */
113 114 115
	}

	/* Store for processing. */
116
	qdata->query = pkt;
117
	qdata->packet_type = knot_pkt_type(pkt);
118 119 120 121 122

	/* Declare having response. */
	return NS_PROC_FULL;
}

123
int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
124 125
{
	assert(pkt && ctx);
126
	struct query_data *qdata = QUERY_DATA(ctx);
127 128

	rcu_read_lock();
129

130
	/* Check parse state. */
131 132
	knot_pkt_t *query = qdata->query;
	int next_state = NS_PROC_DONE;
133
	if (query->parsed < query->size) {
134
		dbg_ns("%s: incompletely parsed query, FORMERR\n", __func__);
135
		knot_pkt_clear(pkt);
136 137 138 139
		qdata->rcode = KNOT_RCODE_FORMERR;
		next_state = NS_PROC_FAIL;
		goto finish;
	}
140

141
	/*
142
	 * Preprocessing.
143 144
	 */

145
	int ret = prepare_answer(query, pkt, ctx);
146
	if (ret != KNOT_EOK) {
147 148
		next_state = NS_PROC_FAIL;
		goto finish;
149 150
	}

151
	/* Answer based on qclass. */
152 153
	switch (knot_pkt_qclass(pkt)) {
	case KNOT_CLASS_CH:
154
		next_state = query_chaos(pkt, ctx);
155 156 157
		break;
	case KNOT_CLASS_ANY:
	case KNOT_CLASS_IN:
158
		next_state = query_internet(pkt, ctx);
159 160
		break;
	default:
161
		qdata->rcode = KNOT_RCODE_REFUSED;
162 163 164
		next_state = NS_PROC_FAIL;
		break;
	}
165

166 167 168
	/*
	 * Postprocessing.
	 */
169

170
	/* Transaction security (if applicable). */
171
	if (next_state == NS_PROC_DONE || next_state == NS_PROC_FULL) {
172
		if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
173 174
			next_state = NS_PROC_FAIL;
		}
175 176
	}

177
finish:
178 179 180 181 182
	/* Default RCODE is SERVFAIL if not specified otherwise. */
	if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR) {
		qdata->rcode = KNOT_RCODE_SERVFAIL;
	}

183
	/* Rate limits (if applicable). */
184
	if (qdata->param->proc_flags & NS_QUERY_LIMIT_RATE) {
185 186
		next_state = ratelimit_apply(next_state, pkt, ctx);
	}
187

188 189 190 191
	rcu_read_unlock();
	return next_state;
}

192
int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
193 194
{
	assert(pkt && ctx);
195 196 197
	struct query_data *qdata = QUERY_DATA(ctx);
	dbg_ns("%s: making error response, rcode = %d (TSIG rcode = %d)\n",
	       __func__, qdata->rcode, qdata->rcode_tsig);
198

199
	/* Initialize response from query packet. */
200
	knot_pkt_t *query = qdata->query;
201 202
	knot_pkt_init_response(pkt, query);

203 204
	/* If original QNAME is empty, Query is either unparsed or for root domain.
	 * Either way, letter case doesn't matter. */
205 206 207
	if (qdata->orig_qname[0] != '\0') {
		memcpy(pkt->wire + KNOT_WIRE_HEADER_SIZE,
		       qdata->orig_qname, query->qname_size);
208
	}
209 210

	/* Set RCODE. */
211
	knot_wire_set_rcode(pkt->wire, qdata->rcode);
212

213
	/* Transaction security (if applicable). */
214
	if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
215 216
		return NS_PROC_FAIL;
	}
217

218
	return NS_PROC_DONE;
219
}
220

221
bool process_query_acl_check(acl_t *acl, struct query_data *qdata)
222
{
223
	knot_pkt_t *query = qdata->query;
224
	struct sockaddr_storage *query_source = qdata->param->remote;
225 226 227
	const knot_dname_t *key_name = NULL;
	knot_tsig_algorithm_t key_alg = KNOT_TSIG_ALG_NULL;

228 229 230 231 232 233 234
	/* Skip if already checked and valid. */
	if (qdata->sign.tsig_key != NULL) {
		return true;
	}

	/* Authenticate with NOKEY if the packet isn't signed. */
	if (query->tsig_rr) {
235
		key_name = query->tsig_rr->owner;
236 237 238 239 240 241 242 243 244 245
		key_alg = tsig_rdata_alg(query->tsig_rr);
	}
	acl_match_t *match = acl_find(acl, query_source, key_name);

	/* Did not authenticate, no fitting rule found. */
	if (match == NULL || (match->key && match->key->algorithm != key_alg)) {
		dbg_ns("%s: no ACL match => NOTAUTH\n", __func__);
		qdata->rcode = KNOT_RCODE_NOTAUTH;
		qdata->rcode_tsig = KNOT_RCODE_BADKEY;
		return false;
246
	}
247 248 249

	/* Remember used TSIG key. */
	qdata->sign.tsig_key = match->key;
250 251 252
	return true;
}

253
int process_query_verify(struct query_data *qdata)
254
{
255
	knot_pkt_t *query = qdata->query;
256
	knot_sign_context_t *ctx = &qdata->sign;
257

258 259 260 261
	/* NOKEY => no verification. */
	if (query->tsig_rr == NULL) {
		return KNOT_EOK;
	}
262

263 264 265 266
	/* Keep digest for signing response. */
	/*! \note This memory will be rewritten for multi-pkt answers. */
	ctx->tsig_digest = (uint8_t *)tsig_rdata_mac(query->tsig_rr);
	ctx->tsig_digestlen = tsig_rdata_mac_length(query->tsig_rr);
267

268 269 270
	/* Checking query. */
	int ret = knot_tsig_server_check(query->tsig_rr, query->wire,
	                                 query->size, ctx->tsig_key);
271

272 273
	dbg_ns("%s: QUERY TSIG check result = %s\n", __func__, knot_strerror(ret));

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	/* Evaluate TSIG check results. */
	switch(ret) {
	case KNOT_EOK:
		qdata->rcode = KNOT_RCODE_NOERROR;
		break;
	case KNOT_TSIG_EBADKEY:
		qdata->rcode = KNOT_RCODE_NOTAUTH;
		qdata->rcode_tsig = KNOT_RCODE_BADKEY;
		break;
	case KNOT_TSIG_EBADSIG:
		qdata->rcode = KNOT_RCODE_NOTAUTH;
		qdata->rcode_tsig = KNOT_RCODE_BADSIG;
		break;
	case KNOT_TSIG_EBADTIME:
		qdata->rcode = KNOT_RCODE_NOTAUTH;
		qdata->rcode_tsig = KNOT_RCODE_BADTIME;
		ctx->tsig_time_signed = tsig_rdata_time_signed(query->tsig_rr);
		break;
	case KNOT_EMALF:
		qdata->rcode = KNOT_RCODE_FORMERR;
		break;
	default:
		qdata->rcode = KNOT_RCODE_SERVFAIL;
		break;
	}

	return ret;
}

303
int process_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata)
304 305
{
	int ret = KNOT_EOK;
306
	knot_pkt_t *query = qdata->query;
307
	knot_sign_context_t *ctx = &qdata->sign;
308

309 310
	/* KEY provided and verified TSIG or BADTIME allows signing. */
	if (ctx->tsig_key != NULL && knot_tsig_can_sign(qdata->rcode_tsig)) {
311

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
		/* Sign query response. */
		dbg_ns("%s: signing response using key %p\n", __func__, ctx->tsig_key);
		size_t new_digest_len = knot_tsig_digest_length(ctx->tsig_key->algorithm);
		if (ctx->pkt_count == 0) {
			ret = knot_tsig_sign(pkt->wire, &pkt->size, pkt->max_size,
			                     ctx->tsig_digest, ctx->tsig_digestlen,
			                     ctx->tsig_digest, &new_digest_len,
			                     ctx->tsig_key, qdata->rcode_tsig,
			                     ctx->tsig_time_signed);
		} else {
			ret = knot_tsig_sign_next(pkt->wire, &pkt->size, pkt->max_size,
			                          ctx->tsig_digest, ctx->tsig_digestlen,
			                          ctx->tsig_digest, &new_digest_len,
			                          ctx->tsig_key,
			                          pkt->wire, pkt->size);
		}
		if (ret != KNOT_EOK) {
			goto fail; /* Failed to sign. */
		} else {
			++ctx->pkt_count;
		}
	} else {
		/* Copy TSIG from query and set RCODE. */
		if (query->tsig_rr && qdata->rcode_tsig != KNOT_RCODE_NOERROR) {
			dbg_ns("%s: appending original TSIG\n", __func__);
			ret = knot_tsig_add(pkt->wire, &pkt->size, pkt->max_size,
			                    qdata->rcode_tsig, query->tsig_rr);
			if (ret != KNOT_EOK) {
				goto fail; /* Whatever it is, it's server fail. */
			}
		}
	}
344

345 346 347 348 349 350 351 352
	return ret;

	/* Server failure in signing. */
fail:
	dbg_ns("%s: signing failed (%s)\n", __func__, knot_strerror(ret));
	qdata->rcode = KNOT_RCODE_SERVFAIL;
	qdata->rcode_tsig = KNOT_RCODE_NOERROR; /* Don't sign again. */
	return ret;
353 354 355
}

/*!
356
 * \brief Create a response for a given query in the INTERNET class.
357
 */
358
static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx)
359
{
360 361
	struct query_data *data = QUERY_DATA(ctx);
	int next_state = NS_PROC_FAIL;
362
	dbg_ns("%s(%p, %p, pkt_type=%u)\n", __func__, pkt, ctx, data->packet_type);
363

364
	switch(data->packet_type) {
365
	case KNOT_QUERY_NORMAL:
366
		next_state = internet_query(pkt, data);
367 368
		break;
	case KNOT_QUERY_NOTIFY:
369
		next_state = notify_query(pkt, data);
370
		break;
371
	case KNOT_QUERY_AXFR:
372
		next_state = axfr_query(pkt, data);
373 374
		break;
	case KNOT_QUERY_IXFR:
375
		next_state = ixfr_query(pkt, data);
376 377
		break;
	case KNOT_QUERY_UPDATE:
378
		next_state = update_answer(pkt, data);
379
		break;
380
	default:
381 382 383
		/* Nothing else is supported. */
		data->rcode = KNOT_RCODE_NOTIMPL;
		next_state = NS_PROC_FAIL;
384
		break;
385 386 387
	}

	return next_state;
388 389
}

390 391 392
/*!
 * \brief Apply rate limit.
 */
393
static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx)
394 395 396
{
	/* Check if rate limiting applies. */
	struct query_data *qdata = QUERY_DATA(ctx);
397
	server_t *server = qdata->param->server;
398 399 400
	if (server->rrl == NULL) {
		return state;
	}
401

402 403
	rrl_req_t rrl_rq = {0};
	rrl_rq.w = pkt->wire;
404
	rrl_rq.query = qdata->query;
405
	if (!EMPTY_LIST(qdata->wildcards)) {
406
		rrl_rq.flags = RRL_WILDCARD;
407
	}
408
	if (rrl_query(server->rrl, qdata->param->remote,
409 410 411 412
	              &rrl_rq, qdata->zone) == KNOT_EOK) {
		/* Rate limiting not applied. */
		return state;
	}
413

414 415 416
	/* Now it is slip or drop. */
	if (rrl_slip_roll(conf()->rrl_slip)) {
		/* Answer slips. */
417
		if (process_query_err(pkt, ctx) != KNOT_EOK) {
418 419 420 421 422 423 424
			return NS_PROC_FAIL;
		}
		knot_wire_set_tc(pkt->wire);
	} else {
		/* Drop answer. */
		pkt->size = 0;
	}
425

426
	return NS_PROC_DONE;
427 428
}

429 430 431
/*!
 * \brief Create a response for a given query in the CHAOS class.
 */
432
static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx)
433
{
434
	dbg_ns("%s(%p, %p)\n", __func__, pkt, ctx);
435
	struct query_data *data = QUERY_DATA(ctx);
436

437 438 439 440 441
	/* Nothing except normal queries is supported. */
	if (data->packet_type != KNOT_QUERY_NORMAL) {
		data->rcode = KNOT_RCODE_NOTIMPL;
		return NS_PROC_FAIL;
	}
442

443
	data->rcode = knot_chaos_answer(pkt);
444
	if (data->rcode != KNOT_RCODE_NOERROR) {
Marek Vavrusa's avatar
Marek Vavrusa committed
445
		dbg_ns("%s: failed with RCODE=%d\n", __func__, data->rcode);
446 447 448
		return NS_PROC_FAIL;
	}

449
	return NS_PROC_DONE;
450 451
}

452
/*! \brief Find zone for given question. */
453
static const zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb)
454
{
455 456 457
	uint16_t qtype = knot_pkt_qtype(query);
	uint16_t qclass = knot_pkt_qclass(query);
	const knot_dname_t *qname = knot_pkt_qname(query);
458
	const zone_t *zone = NULL;
459 460 461

	// search for zone only for IN and ANY classes
	if (qclass != KNOT_CLASS_IN && qclass != KNOT_CLASS_ANY) {
462
		return NULL;
463 464
	}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
	/* In case of DS query, we strip the leftmost label when searching for
	 * the zone (but use whole qname in search for the record), as the DS
	 * records are only present in a parent zone.
	 */
	if (qtype == KNOT_RRTYPE_DS) {
		const knot_dname_t *parent = knot_wire_next_label(qname, NULL);
		zone = knot_zonedb_find_suffix(zonedb, parent);
		/* If zone does not exist, search for its parent zone,
		   this will later result to NODATA answer. */
		/*! \note This is not 100% right, it may lead to DS name for example
		 *        when following a CNAME chain, that should also be answered
		 *        from the parent zone (if it exists).
		 */
	}
	if (zone == NULL) {
480 481 482 483 484 485
		if (knot_pkt_type(query) != KNOT_QUERY_UPDATE) {
			zone = knot_zonedb_find_suffix(zonedb, qname);
		} else {
			// Direct matches only for DDNS.
			zone = knot_zonedb_find(zonedb, qname);
		}
486
	}
487

488
	return zone;
489 490
}

491
/*! \brief Initialize response, sizes and find zone from which we're going to answer. */
492
static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx)
493
{
494
	struct query_data *qdata = QUERY_DATA(ctx);
495
	server_t *server = qdata->param->server;
496

497 498 499 500 501 502 503
	/* Initialize response. */
	int ret = knot_pkt_init_response(resp, query);
	if (ret != KNOT_EOK) {
		dbg_ns("%s: can't init response pkt (%d)\n", __func__, ret);
		return ret;
	}

504 505 506 507 508 509
	/* Query MUST carry a question. */
	const knot_dname_t *qname = knot_pkt_qname(query);
	if (qname == NULL) {
		dbg_ns("%s: query missing QNAME, FORMERR\n", __func__);
		qdata->rcode = KNOT_RCODE_FORMERR;
		return KNOT_EMALF;
510
	}
511

512
	/* Convert query QNAME to lowercase, but keep original QNAME case.
513
	 * Already checked for absence of compression and length.
514 515
	 */
	memcpy(qdata->orig_qname, qname, query->qname_size);
516
	ret = knot_dname_to_lower((knot_dname_t *)qname);
517 518 519 520
	if (ret != KNOT_EOK) {
		dbg_ns("%s: can't convert QNAME to lowercase (%d)\n", __func__, ret);
		return ret;
	}
521

522
	/* Find zone for QNAME. */
523
	qdata->zone = answer_zone_find(query, server->zone_db);
524 525

	/* Update maximal answer size. */
526
	if (qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE) {
527 528
		resp->max_size = KNOT_WIRE_MIN_PKTSIZE;
	}
529 530 531 532 533

	/* Check if EDNS is supported. */
	if (!knot_pkt_have_edns(query)) {
		return KNOT_EOK;
	}
534
	ret = knot_pkt_add_opt(resp, server->opt_rr, knot_pkt_have_nsid(query));
535
	if (ret != KNOT_EOK) {
536 537
		dbg_ns("%s: can't add OPT RR (%d)\n", __func__, ret);
		return ret;
538 539
	}

540 541 542
	/* Copy DO bit if set (DNSSEC requested). */
	if (knot_pkt_have_dnssec(query)) {
		dbg_ns("%s: setting DO=1 in OPT RR\n", __func__);
543
		knot_edns_set_do(&resp->opt_rr);
544
	}
545

546
	/* Set minimal supported size from EDNS(0). */
547 548 549 550 551
	uint16_t client_maxlen = knot_edns_get_payload(&query->opt_rr);
	uint16_t server_maxlen = knot_edns_get_payload(&resp->opt_rr);
	resp->opt_rr.payload = MIN(client_maxlen, server_maxlen);

	/* Update packet size limit. */
552
	if (qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE) {
553
		resp->max_size =  MAX(resp->max_size, resp->opt_rr.payload);
554
		dbg_ns("%s: packet size limit <= %zuB\n", __func__, resp->max_size);
555 556
	}

557 558
	return ret;
}