Beispiel #1
0
static int validate_section(kr_rrset_validation_ctx_t *vctx, knot_mm_t *pool)
{
	if (!vctx) {
		return kr_error(EINVAL);
	}

	const knot_pktsection_t *sec = knot_pkt_section(vctx->pkt,
							vctx->section_id);
	if (!sec) {
		return kr_ok();
	}

	int ret = kr_ok();

	map_t stash = map_make();
	stash.malloc = (map_alloc_f) mm_alloc;
	stash.free = (map_free_f) mm_free;
	stash.baton = pool;

	/* Determine RR types contained in the section. */
	for (unsigned i = 0; i < sec->count; ++i) {
		const knot_rrset_t *rr = knot_pkt_rr(sec, i);
		if (rr->type == KNOT_RRTYPE_RRSIG) {
			continue;
		}
		if ((rr->type == KNOT_RRTYPE_NS) && (vctx->section_id == KNOT_AUTHORITY)) {
			continue;
		}
		/* Only validate answers from current cut, records above the cut are stripped. */
		if (!knot_dname_in(vctx->zone_name, rr->owner)) {
			continue;
		}
		ret = kr_rrmap_add(&stash, rr, 0, pool);
		if (ret != 0) {
			goto fail;
		}
	}

	/* Can't use qry->zone_cut.name directly, as this name can
	 * change when updating cut information before validation.
	 */
	vctx->zone_name = vctx->keys ? vctx->keys->owner  : NULL;

	ret = map_walk(&stash, &validate_rrset, vctx);
	if (ret != 0) {
		return ret;
	}
	ret = vctx->result;

fail:
	return ret;
}
Beispiel #2
0
static int free_key(const char *key, void *val, void *ext)
{
	endpoint_array_t *ep_array = val;
	array_clear(*ep_array);
	free(ep_array);
	return kr_ok();
}
Beispiel #3
0
/**
 * Name error response check (RFC4035 3.1.3.2; RFC4035 5.4, bullet 2).
 * @note Returned flags must be checked in order to prove denial.
 * @param flags Flags to be set according to check outcome.
 * @param nsec  NSEC RR.
 * @param name  Name to be checked.
 * @param pool
 * @return      0 or error code.
 */
static int name_error_response_check_rr(int *flags, const knot_rrset_t *nsec,
                                        const knot_dname_t *name)
{
	assert(flags && nsec && name);

	if (nsec_nonamematch(nsec, name) == 0) {
		*flags |= FLG_NOEXIST_RRSET;
	}

	/* Try to find parent wildcard that is proved by this NSEC. */ 
	uint8_t namebuf[KNOT_DNAME_MAXLEN];
	int ret = knot_dname_to_wire(namebuf, name, sizeof(namebuf));
	if (ret < 0)
		return ret;
	knot_dname_t *ptr = namebuf;
	while (ptr[0]) {
		/* Remove leftmost label and replace it with '\1*'. */
		ptr = (uint8_t *) knot_wire_next_label(ptr, NULL);
		*(--ptr) = '*';
		*(--ptr) = 1;
		/* True if this wildcard provably doesn't exist. */
		if (nsec_nonamematch(nsec, ptr) == 0) {
			*flags |= FLG_NOEXIST_WILDCARD;
			break;
		}
		/* Remove added leftmost asterisk. */
		ptr += 2;
	}

	return kr_ok();
}
Beispiel #4
0
static int run_worker(uv_loop_t *loop, struct engine *engine)
{
	/* Control sockets or TTY */
	auto_free char *sock_file = NULL;
	uv_pipe_t pipe;
	uv_pipe_init(loop, &pipe, 0);
	pipe.data = engine;
	if (g_interactive) {
		printf("[system] interactive mode\n> ");
		fflush(stdout);
		uv_pipe_open(&pipe, 0);
		uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_read);
	} else {
		(void) mkdir("tty", S_IRWXU|S_IRWXG);
		sock_file = afmt("tty/%ld", getpid());
		if (sock_file) {
			uv_pipe_bind(&pipe, sock_file);
			uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
		}
	}
	/* Run event loop */
	uv_run(loop, UV_RUN_DEFAULT);
	if (sock_file) {
		unlink(sock_file);
	}
	return kr_ok();
}
Beispiel #5
0
int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name)
{
	/* Register module in Lua */
	lua_State *L = engine->L;
	lua_getglobal(L, "require");
	lua_pushstring(L, name);
	if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
		fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
		lua_pop(L, 1);
		return kr_error(ENOENT);
	}
	lua_setglobal(L, name);
	lua_getglobal(L, name);

	/* Create FFI module with trampolined functions. */
	memset(module, 0, sizeof(*module));
	module->name = strdup(name);
	module->init = &l_ffi_init;
	module->deinit = &l_ffi_deinit;
	/* Bake layer API if defined in module */
	lua_getfield(L, -1, "layer");
	if (!lua_isnil(L, -1)) {
		module->layer = &l_ffi_layer;
		module->data = l_ffi_layer_create(L, module);
	}
	module->lib = L;
	lua_pop(L, 2); /* Clear the layer + module global */
	if (module->init) {
		return module->init(module);
	}
	return kr_ok();
}
Beispiel #6
0
static int update_parent_keys(struct kr_query *qry, uint16_t answer_type)
{
	struct kr_query *parent = qry->parent;
	assert(parent);
	switch(answer_type) {
	case KNOT_RRTYPE_DNSKEY:
		DEBUG_MSG(qry, "<= parent: updating DNSKEY\n");
		parent->zone_cut.key = knot_rrset_copy(qry->zone_cut.key, parent->zone_cut.pool);
		if (!parent->zone_cut.key) {
			return KNOT_STATE_FAIL;
		}
		break;
	case KNOT_RRTYPE_DS:
		DEBUG_MSG(qry, "<= parent: updating DS\n");
		if (qry->flags & QUERY_DNSSEC_INSECURE) { /* DS non-existence proven. */
			parent->flags &= ~QUERY_DNSSEC_WANT;
			parent->flags |= QUERY_DNSSEC_INSECURE;
		} else { /* DS existence proven. */
			parent->zone_cut.trust_anchor = knot_rrset_copy(qry->zone_cut.trust_anchor, parent->zone_cut.pool);
			if (!parent->zone_cut.trust_anchor) {
				return KNOT_STATE_FAIL;
			}
		}
		break;
	default: break;
	}
	return kr_ok();
}
Beispiel #7
0
int kr_nsrep_update_rtt(struct kr_nsrep *ns, unsigned score, kr_nsrep_lru_t *cache)
{
	if (!ns || !cache || ns->addr.ip.sa_family == AF_UNSPEC) {
		return kr_error(EINVAL);
	}

	char *addr = kr_nsrep_inaddr(ns->addr);
	size_t addr_len = kr_nsrep_inaddr_len(ns->addr);
	unsigned *cur = lru_set(cache, addr, addr_len);
	if (!cur) {
		return kr_error(ENOMEM);
	}
	/* Score limits */
	if (score > KR_NS_MAX_SCORE) {
		score = KR_NS_MAX_SCORE;
	}
	if (score <= KR_NS_GLUED) {
		score = KR_NS_GLUED + 1;
	}
	/* Set initial value or smooth over last two measurements */
	if (*cur != 0) {
		*cur = (*cur + score) / 2;
	} else {
	/* First measurement, reset */
		*cur = score;
	}
	return kr_ok();
}
Beispiel #8
0
int engine_register(struct engine *engine, const char *name, const char *precedence, const char* ref)
{
	if (engine == NULL || name == NULL) {
		return kr_error(EINVAL);
	}
	/* Make sure module is unloaded */
	(void) engine_unregister(engine, name);
	/* Find the index of referenced module. */
	module_array_t *mod_list = &engine->modules;
	size_t ref_pos = mod_list->len;
	if (precedence && ref) {
		ref_pos = module_find(mod_list, ref);
		if (ref_pos >= mod_list->len) {
			return kr_error(EIDRM);
		}
	}
	/* Attempt to load binary module */
	struct kr_module *module = malloc(sizeof(*module));
	if (!module) {
		return kr_error(ENOMEM);
	}
	module->data = engine;
	int ret = kr_module_load(module, name, NULL);
	/* Load Lua module if not a binary */
	if (ret == kr_error(ENOENT)) {
		ret = ffimodule_register_lua(engine, module, name);
	}
	if (ret != 0) {
		free(module);
		return ret;
	}
	if (array_push(engine->modules, module) < 0) {
		engine_unload(engine, module);
		return kr_error(ENOMEM);
	}
	/* Evaluate precedence operator */
	if (precedence) {
		struct kr_module **arr = mod_list->at;
		size_t emplacement = mod_list->len;
		if (strcasecmp(precedence, ">") == 0) {
			if (ref_pos + 1 < mod_list->len)
				emplacement = ref_pos + 1; /* Insert after target */
		}
		if (strcasecmp(precedence, "<") == 0) {
			emplacement = ref_pos; /* Insert at target */
		}
		/* Move the tail if it has some elements. */
		if (emplacement + 1 < mod_list->len) {
			memmove(&arr[emplacement + 1], &arr[emplacement], sizeof(*arr) * (mod_list->len - (emplacement + 1)));
			arr[emplacement] = module;
		}
	}

	/* Register properties */
	if (module->props || module->config) {
		return register_properties(engine, module);
	}

	return kr_ok();
}
Beispiel #9
0
static int update_delegation(struct kr_request *req, struct kr_query *qry, knot_pkt_t *answer, bool has_nsec3)
{
	struct kr_zonecut *cut = &qry->zone_cut;

	/* RFC4035 3.1.4. authoritative must send either DS or proof of non-existence.
	 * If it contains neither, the referral is bogus (or an attempted downgrade attack).
	 */

	unsigned section = KNOT_ANSWER;
	if (!knot_wire_get_aa(answer->wire)) { /* Referral */
		section = KNOT_AUTHORITY;
	} else if (knot_pkt_qtype(answer) == KNOT_RRTYPE_DS) { /* Subrequest */
		section = KNOT_ANSWER;
	} else { /* N/A */
		return kr_ok();
	}

	int ret = 0;
	const knot_dname_t *proved_name = knot_pkt_qname(answer);
	/* Aggregate DS records (if using multiple keys) */
	knot_rrset_t *new_ds = update_ds(cut, knot_pkt_section(answer, section));
	if (!new_ds) {
		/* No DS provided, check for proof of non-existence. */
		if (!has_nsec3) {
			if (!knot_wire_get_aa(answer->wire)) {
				/* Referral, check if it is referral to unsigned, rfc4035 5.2 */
				ret = kr_nsec_ref_to_unsigned(answer);
			} else {
				/* No-data answer */
				ret = kr_nsec_existence_denial(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
			}
		} else {
			if (!knot_wire_get_aa(answer->wire)) {
				/* Referral, check if it is referral to unsigned, rfc5155 8.9 */
				ret = kr_nsec3_ref_to_unsigned(answer);
			} else {
				/* No-data answer, QTYPE is DS, rfc5155 8.6 */
				ret = kr_nsec3_no_data(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
			}
			if (ret == kr_error(DNSSEC_NOT_FOUND)) {
				/* Not bogus, going insecure due to optout */
				ret = 0;
			}
		}
		if (ret != 0) {
			DEBUG_MSG(qry, "<= bogus proof of DS non-existence\n");
			qry->flags |= QUERY_DNSSEC_BOGUS;
		} else {
			DEBUG_MSG(qry, "<= DS doesn't exist, going insecure\n");
			qry->flags &= ~QUERY_DNSSEC_WANT;
			qry->flags |= QUERY_DNSSEC_INSECURE;
		}
		return ret;
	}

	/* Extend trust anchor */
	DEBUG_MSG(qry, "<= DS: OK\n");
	cut->trust_anchor = new_ds;
	return ret;
}
Beispiel #10
0
int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name)
{
    /* Register module in Lua */
    lua_State *L = engine->L;
    lua_getglobal(L, "require");
    lua_pushstring(L, name);
    if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
        fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
        lua_pop(L, 1);
        return kr_error(ENOENT);
    }
    lua_setglobal(L, name);
    lua_getglobal(L, name);

    /* Create FFI module with trampolined functions. */
    memset(module, 0, sizeof(*module));
    module->name = strdup(name);
    module->init = &l_ffi_init;
    module->deinit = &l_ffi_deinit;
    REGISTER_FFI_CALL(L, module->layer,  "layer",  &l_ffi_layer);
    module->data = (void *)(intptr_t)luaL_ref(L, LUA_REGISTRYINDEX);
    module->lib = L;
    lua_pop(L, 1); /* Clear the module global */
    if (module->init) {
        return module->init(module);
    }
    return kr_ok();
}
Beispiel #11
0
/**
 * Adjust TTL in wire format.
 * @param wire      RR Set in wire format.
 * @param wire_size Size of the wire data portion.
 * @param new_ttl   TTL value to be set for all RRs.
 * @return          0 or error code.
 */
static int adjust_wire_ttl(uint8_t *wire, size_t wire_size, uint32_t new_ttl)
{
	assert(wire);
	assert(sizeof(uint16_t) == 2);
	assert(sizeof(uint32_t) == 4);
	uint16_t rdlen;

	int ret;

	new_ttl = htonl(new_ttl);

	size_t i = 0;
	/* RR wire format in RFC1035 3.2.1 */
	while(i < wire_size) {
		ret = knot_dname_size(wire + i);
		if (ret < 0) {
			return ret;
		}
		i += ret + 4;
		memcpy(wire + i, &new_ttl, sizeof(uint32_t));
		i += sizeof(uint32_t);

		memcpy(&rdlen, wire + i, sizeof(uint16_t));
		rdlen = ntohs(rdlen);
		i += sizeof(uint16_t) + rdlen;

		assert(i <= wire_size);
	}

	return kr_ok();
}
Beispiel #12
0
int kr_nsec_existence_denial(const knot_pkt_t *pkt, knot_section_t section_id,
                             const knot_dname_t *sname, uint16_t stype)
{
	const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
	if (!sec || !sname) {
		return kr_error(EINVAL);
	}

	int flags = 0;
	for (unsigned i = 0; i < sec->count; ++i) {
		const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
		if (rrset->type != KNOT_RRTYPE_NSEC) {
			continue;
		}
		/* NSEC proves that name exists, but has no data (RFC4035 4.9, 1) */
		if (knot_dname_is_equal(rrset->owner, sname)) {
			no_data_response_check_rrtype(&flags, rrset, stype);
		} else {
			/* NSEC proves that name doesn't exist (RFC4035, 4.9, 2) */
			name_error_response_check_rr(&flags, rrset, sname);
		}
		no_data_wildcard_existence_check(&flags, rrset, sec);
	}

	return kr_nsec_existence_denied(flags) ? kr_ok() : kr_error(ENOENT);
}
Beispiel #13
0
int network_close(struct network *net, const char *addr, uint16_t port)
{
	endpoint_array_t *ep_array = map_get(&net->endpoints, addr);
	if (ep_array == NULL) {
		return kr_error(ENOENT);
	}

	/* Close endpoint in array. */
	for (size_t i = ep_array->len; i--;) {
		struct endpoint *ep = ep_array->at[i];
		if (ep->port == port) {
			close_endpoint(ep);
			array_del(*ep_array, i);
			break;
		}
	}

	/* Collapse key if it has no endpoint. */
	if (ep_array->len == 0) {
		free(ep_array);
		map_del(&net->endpoints, addr);
	}

	return kr_ok();
}
Beispiel #14
0
static int init_state(struct engine *engine)
{
	/* Initialize Lua state */
	engine->L = luaL_newstate();
	if (engine->L == NULL) {
		return kr_error(ENOMEM);
	}
	/* Initialize used libraries. */
	lua_gc(engine->L, LUA_GCSTOP, 0);
	luaL_openlibs(engine->L);
	/* Global functions */
	lua_pushcfunction(engine->L, l_help);
	lua_setglobal(engine->L, "help");
	lua_pushcfunction(engine->L, l_quit);
	lua_setglobal(engine->L, "quit");
	lua_pushcfunction(engine->L, l_hostname);
	lua_setglobal(engine->L, "hostname");
	lua_pushcfunction(engine->L, l_verbose);
	lua_setglobal(engine->L, "verbose");
	lua_pushcfunction(engine->L, l_option);
	lua_setglobal(engine->L, "option");
	lua_pushcfunction(engine->L, l_setuser);
	lua_setglobal(engine->L, "user");
	lua_pushcfunction(engine->L, l_trustanchor);
	lua_setglobal(engine->L, "trustanchor");
	lua_pushcfunction(engine->L, l_libpath);
	lua_setglobal(engine->L, "libpath");
	lua_pushliteral(engine->L, MODULEDIR);
	lua_setglobal(engine->L, "moduledir");
	lua_pushliteral(engine->L, ETCDIR);
	lua_setglobal(engine->L, "etcdir");
	lua_pushlightuserdata(engine->L, engine);
	lua_setglobal(engine->L, "__engine");
	return kr_ok();
}
Beispiel #15
0
/**
 * Check whether the NSEC RR proves that there is no closer match for <SNAME, SCLASS>.
 * @param nsec  NSEC RRSet.
 * @param sname Searched name.
 * @return      0 or error code.
 */
static int nsec_nonamematch(const knot_rrset_t *nsec, const knot_dname_t *sname)
{
	assert(nsec && sname);
	const knot_dname_t *next = knot_nsec_next(&nsec->rrs);
	/* If NSEC 'owner' >= 'next', it means that there is nothing after 'owner' */
	const bool is_last_nsec = (knot_dname_cmp(nsec->owner, next) >= 0);
	if (is_last_nsec) { /* SNAME is after owner => provably doesn't exist */
		if (knot_dname_cmp(nsec->owner, sname) < 0) {
			return kr_ok();
		}
	} else {
		/* Prove that SNAME is between 'owner' and 'next' */
		if ((knot_dname_cmp(nsec->owner, sname) < 0) && (knot_dname_cmp(sname, next) < 0)) {
			return kr_ok();
		}
	}
	return kr_error(EINVAL);
}
Beispiel #16
0
static int eval_nsrep(const char *k, void *v, void *baton)
{
	struct kr_query *qry = baton;
	struct kr_nsrep *ns = &qry->ns;
	struct kr_context *ctx = ns->ctx;
	unsigned score = KR_NS_MAX_SCORE;
	unsigned reputation = 0;
	uint8_t *addr = NULL;

	/* Fetch NS reputation */
	if (ctx->cache_rep) {
		unsigned *cached = lru_get(ctx->cache_rep, k, knot_dname_size((const uint8_t *)k));
		if (cached) {
			reputation = *cached;
		}
	}

	/* Favour nameservers with unknown addresses to probe them,
	 * otherwise discover the current best address for the NS. */
	pack_t *addr_set = (pack_t *)v;
	if (addr_set->len == 0) {
		score = KR_NS_UNKNOWN;
		/* If the server doesn't have IPv6, give it disadvantage. */
		if (reputation & KR_NS_NOIP6) {
			score += FAVOUR_IPV6;
			/* If the server is unknown but has rep record, treat it as timeouted */
			if (reputation & KR_NS_NOIP4) {
				score = KR_NS_TIMEOUT;
				reputation = 0; /* Start with clean slate */
			}
		}
	} else {
		score = eval_addr_set(addr_set, ctx->cache_rtt, score, &addr);
	}

	/* Probabilistic bee foraging strategy (naive).
	 * The fastest NS is preferred by workers until it is depleted (timeouts or degrades),
	 * at the same time long distance scouts probe other sources (low probability).
	 * Servers on TIMEOUT (depleted) can be probed by the dice roll only */
	if (score < ns->score && (qry->flags & QUERY_NO_THROTTLE || score < KR_NS_TIMEOUT)) {
		update_nsrep(ns, (const knot_dname_t *)k, addr, score);
		ns->reputation = reputation;
	} else {
		/* With 5% chance, probe server with a probability given by its RTT / MAX_RTT */
		if ((kr_rand_uint(100) < 5) && (kr_rand_uint(KR_NS_MAX_SCORE) >= score)) {
			/* If this is a low-reliability probe, go with TCP to get ICMP reachability check. */
			if (score >= KR_NS_LONG) {
				qry->flags |= QUERY_TCP;
			}
			update_nsrep(ns, (const knot_dname_t *)k, addr, score);
			ns->reputation = reputation;
			return 1; /* Stop evaluation */
		}
	}

	return kr_ok();
}
Beispiel #17
0
/** Load C module symbols. */
static int load_sym_c(struct kr_module *module, uint32_t api_required)
{
    /* Check if it's embedded first */
    for (unsigned i = 0; i < sizeof(embedded_modules)/sizeof(embedded_modules[0]); ++i) {
        const struct kr_module *embedded = &embedded_modules[i];
        if (strcmp(module->name, embedded->name) == 0) {
            module->init = embedded->init;
            module->deinit = embedded->deinit;
            module->config = embedded->config;
            module->layer = embedded->layer;
            module->props = embedded->props;
            return kr_ok();
        }
    }
    /* Load dynamic library module */
    auto_free char *module_prefix = kr_strcatdup(2, module->name, "_");
    ABI_CHECK(module, module_prefix, "api", api_required);
    ABI_LOAD(module, module_prefix, "init", "deinit", "config", "layer", "props");
    return kr_ok();
}
Beispiel #18
0
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len)
{
	if (!qry || !addr) {
		return kr_error(EINVAL);
	}
	qry->ns.name = (const uint8_t *)"";
	qry->ns.score = KR_NS_UNKNOWN;
	qry->ns.reputation = 0;
	update_nsrep(&qry->ns, 0, addr, addr_len);
	update_nsrep(&qry->ns, 1, NULL, 0);
	return kr_ok();
}
Beispiel #19
0
int engine_unregister(struct engine *engine, const char *name)
{
	module_array_t *mod_list = &engine->modules;
	size_t found = module_find(mod_list, name);
	if (found < mod_list->len) {
		engine_unload(engine, mod_list->at[found]);
		array_del(*mod_list, found);
		return kr_ok();
	}

	return kr_error(ENOENT);
}
Beispiel #20
0
/** Close endpoint protocols. */
static int close_endpoint(struct endpoint *ep)
{
	if (ep->flags & NET_UDP) {
		udp_unbind(ep);
	}
	if (ep->flags & NET_TCP) {
		tcp_unbind(ep);
	}

	free(ep);
	return kr_ok();
}
Beispiel #21
0
/** Retrieve hint list. */
static int pack_hint(const char *k, void *v, void *baton)
{
	char nsname_str[KNOT_DNAME_MAXLEN] = {'\0'};
	knot_dname_to_str(nsname_str, (const uint8_t *)k, sizeof(nsname_str));
	JsonNode *root_node = baton;
	JsonNode *addr_list = pack_addrs((pack_t *)v);
	if (!addr_list) {
		return kr_error(ENOMEM);
	}
	json_append_member(root_node, nsname_str, addr_list);
	return kr_ok();
}
Beispiel #22
0
/**
 * @internal Defer execution of current query.
 * The current layer state and input will be pushed to a stack and resumed on next iteration.
 */
static int consume_yield(knot_layer_t *ctx, knot_pkt_t *pkt)
{
	struct kr_request *req = ctx->data;
	knot_pkt_t *pkt_copy = knot_pkt_new(NULL, pkt->size, &req->pool);
	struct kr_layer_pickle *pickle = mm_alloc(&req->pool, sizeof(*pickle));
	if (pickle && pkt_copy && knot_pkt_copy(pkt_copy, pkt) == 0) {
		struct kr_query *qry = req->current_query;
		pickle->api = ctx->api;
		pickle->state = ctx->state;
		pickle->pkt = pkt_copy;
		pickle->next = qry->deferred;
		qry->deferred = pickle;
		return kr_ok();
	}
	return kr_error(ENOMEM);
}
Beispiel #23
0
int kr_nsrep_update_rep(struct kr_nsrep *ns, unsigned reputation, kr_nsrep_lru_t *cache)
{
	if (!ns || !cache ) {
		return kr_error(EINVAL);
	}

	/* Store in the struct */
	ns->reputation = reputation;
	/* Store reputation in the LRU cache */
	unsigned *cur = lru_set(cache, (const char *)ns->name, knot_dname_size(ns->name));
	if (!cur) {
		return kr_error(ENOMEM);
	}
	*cur = reputation;
	return kr_ok();
}
Beispiel #24
0
int engine_start(struct engine *engine, const char *config_path)
{
	/* Load configuration. */
	int ret = engine_loadconf(engine, config_path);
	if (ret != 0) {
		return ret;
	}

	/* Clean up stack and restart GC */
	lua_settop(engine->L, 0);
	lua_gc(engine->L, LUA_GCCOLLECT, 0);
	lua_gc(engine->L, LUA_GCSETSTEPMUL, 50);
	lua_gc(engine->L, LUA_GCSETPAUSE, 400);
	lua_gc(engine->L, LUA_GCRESTART, 0);
	return kr_ok();
}
Beispiel #25
0
/** Append 'addr = {port = int, udp = bool, tcp = bool}' */
static int net_list_add(const char *key, void *val, void *ext)
{
    lua_State *L = (lua_State *)ext;
    endpoint_array_t *ep_array = val;
    lua_newtable(L);
    for (size_t i = ep_array->len; i--;) {
        struct endpoint *ep = ep_array->at[i];
        lua_pushinteger(L, ep->port);
        lua_setfield(L, -2, "port");
        lua_pushboolean(L, ep->flags & NET_UDP);
        lua_setfield(L, -2, "udp");
        lua_pushboolean(L, ep->flags & NET_TCP);
        lua_setfield(L, -2, "tcp");
    }
    lua_setfield(L, -2, key);
    return kr_ok();
}
Beispiel #26
0
/**
 * Check the RRSIG RR validity according to RFC4035 5.3.1 .
 * @param flags     The flags are going to be set according to validation result.
 * @param cov_labels Covered RRSet owner label count.
 * @param rrsigs    RRSet containing the signatures.
 * @param sig_pos   Specifies the signature within the RRSIG RRSet.
 * @param keys      Associated DNSKEY RRSet.
 * @param key_pos   Specifies the key within the DNSKEY RRSet,
 * @param keytag    Used key tag.
 * @param zone_name The name of the zone cut.
 * @param timestamp Validation time.
 */
static int validate_rrsig_rr(int *flags, int cov_labels,
                             const knot_rrset_t *rrsigs, size_t sig_pos,
                             const knot_rrset_t *keys, size_t key_pos, uint16_t keytag,
                             const knot_dname_t *zone_name, uint32_t timestamp)
{
	if (!flags || !rrsigs || !keys || !zone_name) {
		return kr_error(EINVAL);
	}
	/* bullet 5 */
	if (knot_rrsig_sig_expiration(&rrsigs->rrs, sig_pos) < timestamp) {
		return kr_error(EINVAL);
	}
	/* bullet 6 */
	if (knot_rrsig_sig_inception(&rrsigs->rrs, sig_pos) > timestamp) {
		return kr_error(EINVAL);
	}
	/* bullet 2 */
	const knot_dname_t *signer_name = knot_rrsig_signer_name(&rrsigs->rrs, sig_pos);
	if (!signer_name || !knot_dname_is_equal(signer_name, zone_name)) {
		return kr_error(EINVAL);
	}
	/* bullet 4 */
	{
		int rrsig_labels = knot_rrsig_labels(&rrsigs->rrs, sig_pos);
		if (rrsig_labels > cov_labels) {
			return kr_error(EINVAL);
		}
		if (rrsig_labels < cov_labels) {
			*flags |= FLG_WILDCARD_EXPANSION;
		}
	}

	/* bullet 7 */
	if ((!knot_dname_is_equal(keys->owner, signer_name)) ||
	    (knot_dnskey_alg(&keys->rrs, key_pos) != knot_rrsig_algorithm(&rrsigs->rrs, sig_pos)) ||
	    (keytag != knot_rrsig_key_tag(&rrsigs->rrs, sig_pos))) {
		return kr_error(EINVAL);
	}
	/* bullet 8 */
	/* Checked somewhere else. */
	/* bullet 9 and 10 */
	/* One of the requirements should be always fulfilled. */

	return kr_ok();
}
Beispiel #27
0
/**
 * Perform check of RR type existence denial according to RFC4035 5.4, bullet 1.
 * @param flags Flags to be set according to check outcome.
 * @param nsec  NSEC RR.
 * @param type  Type to be checked.
 * @return      0 or error code.
 */
static int no_data_response_check_rrtype(int *flags, const knot_rrset_t *nsec,
                                         uint16_t type)
{
	assert(flags && nsec);

	uint8_t *bm = NULL;
	uint16_t bm_size;
	knot_nsec_bitmap(&nsec->rrs, &bm, &bm_size);
	if (!bm) {
		return kr_error(EINVAL);
	}

	if (!kr_nsec_bitmap_contains_type(bm, bm_size, type)) {
		/* The type is not listed in the NSEC bitmap. */
		*flags |= FLG_NOEXIST_RRTYPE;
	}

	return kr_ok();
}
Beispiel #28
0
int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx)
{
	if (!qry || !ctx) {
		return kr_error(EINVAL);
	}

	/* Get address list for this NS */
	struct kr_nsrep *ns = &qry->ns;
	ELECT_INIT(ns, ctx);
	pack_t *addr_set = map_get(&qry->zone_cut.nsset, (const char *)ns->name);
	if (!addr_set) {
		return kr_error(ENOENT);
	}
	/* Evaluate addr list */
	uint8_t *addr = NULL;
	unsigned score = eval_addr_set(addr_set, ctx->cache_rtt, ns->score, &addr);
	update_nsrep(ns, ns->name, addr, score);
	return kr_ok();
}
Beispiel #29
0
int kr_check_signature(const knot_rrset_t *rrsigs, size_t pos,
                       const dnssec_key_t *key, const knot_rrset_t *covered,
                       int trim_labels)
{
	if (!rrsigs || !key || !dnssec_key_can_verify(key)) {
		return kr_error(EINVAL);
	}

	int ret = 0;
	dnssec_sign_ctx_t *sign_ctx = NULL;
	dnssec_binary_t signature = {0, };

	knot_rrsig_signature(&rrsigs->rrs, pos, &signature.data, &signature.size);
	if (!signature.data || !signature.size) {
		ret = kr_error(EINVAL);
		goto fail;
	}

	if (dnssec_sign_new(&sign_ctx, key) != 0) {
		ret = kr_error(ENOMEM);
		goto fail;
	}

	uint32_t orig_ttl = knot_rrsig_original_ttl(&rrsigs->rrs, pos);
	const knot_rdata_t *rr_data = knot_rdataset_at(&rrsigs->rrs, pos);
	uint8_t *rdata = knot_rdata_data(rr_data);

	if (sign_ctx_add_data(sign_ctx, rdata, covered, orig_ttl, trim_labels) != 0) {
		ret = kr_error(ENOMEM);
		goto fail;
	}

	if (dnssec_sign_verify(sign_ctx, &signature) != 0) {
		ret = kr_error(EBADMSG);
		goto fail;
	}

	ret = kr_ok();

fail:
	dnssec_sign_free(sign_ctx);
	return ret;
}
Beispiel #30
0
int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
                                           const knot_dname_t *sname)
{
	const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
	if (!sec || !sname) {
		return kr_error(EINVAL);
	}

	for (unsigned i = 0; i < sec->count; ++i) {
		const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
		if (rrset->type != KNOT_RRTYPE_NSEC) {
			continue;
		}
		if (nsec_nonamematch(rrset, sname) == 0) {
			return kr_ok();
		}
	}

	return kr_error(ENOENT);
}