Esempio n. 1
0
static knot_dname_t *synth_ptrname(const char *addr_str, synth_template_t *tpl)
{
	/* PTR right-hand value is [prefix][address][zone] */
	char ptrname[KNOT_DNAME_MAXLEN] = {'\0'};
	int prefix_len = strlen(tpl->prefix);
	int addr_len = strlen(addr_str);
	int zone_len = strlen(tpl->zone);

	/* Check required space (zone requires extra leading dot). */
	if (prefix_len + addr_len + zone_len + 1 >= KNOT_DNAME_MAXLEN) {
		return NULL;
	}

	/* Write prefix string. */
	memcpy(ptrname, tpl->prefix, prefix_len);
	int written = prefix_len;

	/* Write address with substituted separator to '-'. */
	char sep = str_separator(tpl->subnet.ss.ss_family);
	memcpy(ptrname + written, addr_str, addr_len);
	str_subst(ptrname + written, addr_len, sep, '-');
	written += addr_len;

	/* Write zone name. */
	ptrname[written] = '.';
	written += 1;
	memcpy(ptrname + written, tpl->zone, zone_len);

	/* Convert to domain name. */
	return knot_dname_from_str(ptrname);
}
Esempio n. 2
0
static int rosedb_get(struct cache *cache, MDB_txn *txn, int argc, char *argv[])
{
	knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' };
	knot_dname_from_str(key, argv[0], sizeof(key));
	knot_dname_to_lower(key);

	char type_str[16] = { '\0' };

	struct iter it;
	int ret = cache_query_fetch(txn, cache->dbi, &it, key);
	while (ret == 0) {
		struct entry entry;
		cache_iter_val(&it, &entry);
		knot_rdata_t *rd = knot_rdataset_at(&entry.data.rrs, 0);
		knot_rrtype_to_string(entry.data.type, type_str, sizeof(type_str));
		printf("%s\t%s\tTTL=%u\tRDLEN=%u\t%s\t%s\n", argv[0], type_str,
		       knot_rdata_ttl(rd), knot_rdata_rdlen(rd), entry.threat_code, entry.syslog_ip);
		if (cache_iter_next(&it) != 0) {
			break;
		}
	}

	cache_iter_free(&it);

	return ret;
}
Esempio n. 3
0
static int rosedb_del(struct cache *cache, MDB_txn *txn, int argc, char *argv[])
{
	printf("DEL %s\n", argv[0]);

	knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' };
	knot_dname_from_str(key, argv[0], sizeof(key));
	knot_dname_to_lower(key);

	int ret = cache_remove(txn, cache->dbi, key);
	if (ret != 0) {
		fprintf(stderr, "%s\n", mdb_strerror(ret));
	}

	return ret;
}
Esempio n. 4
0
static int wrk_resolve(lua_State *L)
{
    struct worker_ctx *worker = wrk_luaget(L);
    if (!worker) {
        return 0;
    }
    /* Create query packet */
    knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_EDNS_MAX_UDP_PAYLOAD, NULL);
    if (!pkt) {
        lua_pushstring(L, strerror(ENOMEM));
        lua_error(L);
    }
    uint8_t dname[KNOT_DNAME_MAXLEN];
    knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname));
    /* Check class and type */
    uint16_t rrtype = lua_tointeger(L, 2);
    if (!lua_isnumber(L, 2)) {
        lua_pushstring(L, "invalid RR type");
        lua_error(L);
    }
    uint16_t rrclass = lua_tointeger(L, 3);
    if (!lua_isnumber(L, 3)) { /* Default class is IN */
        rrclass = KNOT_CLASS_IN;
    }
    knot_pkt_put_question(pkt, dname, rrclass, rrtype);
    knot_wire_set_rd(pkt->wire);
    /* Add OPT RR */
    pkt->opt_rr = knot_rrset_copy(worker->engine->resolver.opt_rr, NULL);
    if (!pkt->opt_rr) {
        return kr_error(ENOMEM);
    }
    /* Add completion callback */
    int ret = 0;
    unsigned options = lua_tointeger(L, 4);
    if (lua_isfunction(L, 5)) {
        /* Store callback in registry */
        lua_pushvalue(L, 5);
        int cb = luaL_ref(L, LUA_REGISTRYINDEX);
        ret = worker_resolve(worker, pkt, options, resolve_callback, (void *) (intptr_t)cb);
    } else {
        ret = worker_resolve(worker, pkt, options, NULL, NULL);
    }

    knot_rrset_free(&pkt->opt_rr, NULL);
    knot_pkt_free(&pkt);
    lua_pushboolean(L, ret == 0);
    return 1;
}
Esempio n. 5
0
/** Enable/disable trust anchor. */
static int l_trustanchor(lua_State *L)
{
	struct engine *engine = engine_luaget(L);
	const char *anchor = lua_tostring(L, 1);
	bool enable = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true;
	if (!anchor || strlen(anchor) == 0) {
		return 0;
	}
	/* If disabling, parse the owner string only. */
	if (!enable) {
		knot_dname_t *owner = knot_dname_from_str(NULL, anchor, KNOT_DNAME_MAXLEN);
		if (!owner) {
			lua_pushstring(L, "invalid trust anchor owner");
			lua_error(L);
		}
		lua_pushboolean(L, kr_ta_del(&engine->resolver.trust_anchors, owner) == 0);
		free(owner);
		return 1;
	}

	/* Parse the record */
	zs_scanner_t *zs = malloc(sizeof(*zs));
	if (!zs || zs_init(zs, ".", 1, 0) != 0) {
		free(zs);
		lua_pushstring(L, "not enough memory");
		lua_error(L);
	}
	int ok = zs_set_input_string(zs, anchor, strlen(anchor)) == 0 &&
	         zs_parse_all(zs) == 0;
	/* Add it to TA set and cleanup */
	if (ok) {
		ok = kr_ta_add(&engine->resolver.trust_anchors,
		               zs->r_owner, zs->r_type, zs->r_ttl, zs->r_data, zs->r_data_length) == 0;
	}
	zs_deinit(zs);
	free(zs);
	/* Report errors */
	if (!ok) {
		lua_pushstring(L, "failed to process trust anchor RR");
		lua_error(L);
	}
	lua_pushboolean(L, true);
	return 1;
}
Esempio n. 6
0
/**
 * Retrieve address hint for given name.
 *
 * Input:  name
 * Output: { address1, address2, ... }
 */
static char* hint_get(void *env, struct kr_module *module, const char *args)
{
	struct kr_zonecut *hints = module->data;
	knot_dname_t key[KNOT_DNAME_MAXLEN];
	pack_t *pack = NULL;
	if (knot_dname_from_str(key, args, sizeof(key))) {
		pack = kr_zonecut_find(hints, key);
	}
	if (!pack || pack->len == 0) {
		return NULL;
	}

	char *result = NULL;
	JsonNode *root = pack_addrs(pack);
	if (root) {
		result = json_encode(root);
		json_delete(root);
	}
	return result;
}
Esempio n. 7
0
static int yp_dname_to_bin(
	TXT_BIN_PARAMS)
{
	knot_dname_t *dname = knot_dname_from_str(bin, txt, *bin_len);
	if (dname == NULL) {
		return KNOT_EINVAL;
	}

	int ret = knot_dname_wire_check(bin, bin + *bin_len, NULL);
	if (ret <= 0) {
		return KNOT_EINVAL;
	}
	*bin_len = ret;

	ret = knot_dname_to_lower(bin);
	if (ret != KNOT_EOK) {
		return KNOT_EINVAL;
	}

	return KNOT_EOK;
}
Esempio n. 8
0
static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{
	/* Build key */
	knot_dname_t key[KNOT_DNAME_MAXLEN];
	if (!knot_dname_from_str(key, name, sizeof(key))) {
		return kr_error(EINVAL);
	}

	/* Parse address string */
	struct sockaddr_storage ss;
	if (parse_addr_str(&ss, addr) != 0) {
		return kr_error(EINVAL);
	}

	/* Build rdata */
	size_t addr_len = 0;
	uint8_t *raw_addr = sockaddr_raw(&ss, &addr_len);
	knot_rdata_t rdata[knot_rdata_array_size(addr_len)];
	knot_rdata_init(rdata, addr_len, raw_addr, 0);

	return kr_zonecut_add(hints, key, rdata);
}
Esempio n. 9
0
static int rosedb_add(struct cache *cache, MDB_txn *txn, int argc, char *argv[])
{
	printf("ADD %s\t%s\t%s\t%s\t%s\t%s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);

	knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' };
	knot_dname_from_str(key, argv[0], sizeof(key));
	knot_dname_to_lower(key);

	struct entry entry;
	int ret = parse_rdata(&entry, argv[0], argv[1], argv[3], atoi(argv[2]), cache->pool);
	entry.threat_code = argv[4];
	entry.syslog_ip   = argv[5];
	if (ret != 0) {
		fprintf(stderr, "PARSE: %s\n", knot_strerror(ret));
		return ret;
	}

	ret = cache_insert(txn, cache->dbi, key, &entry);
	if (ret != 0) {
		fprintf(stderr, "%s\n", mdb_strerror(ret));
	}

	return ret;
}
Esempio n. 10
0
File: rrl.c Progetto: dnstap/knot
int main(int argc, char *argv[])
{
	plan(10);

	/* Prepare query. */
	knot_pkt_t *query = knot_pkt_new(NULL, 512, NULL);
	if (query == NULL) {
		return KNOT_ERROR; /* Fatal */
	}

	knot_dname_t *qname = knot_dname_from_str("beef.");
	int ret = knot_pkt_put_question(query, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A);
	knot_dname_free(&qname, NULL);
	if (ret != KNOT_EOK) {
		knot_pkt_free(&query);
		return KNOT_ERROR; /* Fatal */
	}

	/* Prepare response */
	uint8_t rbuf[65535];
	size_t rlen = sizeof(rbuf);
	memcpy(rbuf, query->wire, query->size);
	knot_wire_flags_set_qr(rbuf);

	rrl_req_t rq;
	rq.w = rbuf;
	rq.len = rlen;
	rq.query = query;
	rq.flags = 0;

	/* 1. create rrl table */
	rrl_table_t *rrl = rrl_create(RRL_SIZE);
	ok(rrl != NULL, "rrl: create");

	/* 2. set rate limit */
	uint32_t rate = 10;
	rrl_setrate(rrl, rate);
	is_int(rate, rrl_rate(rrl), "rrl: setrate");

	/* 3. setlocks */
	ret = rrl_setlocks(rrl, RRL_LOCKS);
	is_int(KNOT_EOK, ret, "rrl: setlocks");

	/* 4. N unlimited requests. */
	conf_zone_t *zone_conf = malloc(sizeof(conf_zone_t));
	conf_init_zone(zone_conf);
	zone_conf->name = strdup("rrl.");
	zone_t *zone = zone_new(zone_conf);

	struct sockaddr_storage addr;
	struct sockaddr_storage addr6;
	sockaddr_set(&addr, AF_INET, "1.2.3.4", 0);
	sockaddr_set(&addr6, AF_INET6, "1122:3344:5566:7788::aabb", 0);
	ret = 0;
	for (unsigned i = 0; i < rate; ++i) {
		if (rrl_query(rrl, &addr, &rq, zone) != KNOT_EOK ||
		    rrl_query(rrl, &addr6, &rq, zone) != KNOT_EOK) {
			ret = KNOT_ELIMIT;
			break;
		}
	}
	is_int(0, ret, "rrl: unlimited IPv4/v6 requests");

#ifdef ENABLE_TIMED_TESTS
	/* 5. limited request */
	ret = rrl_query(rrl, &addr, &rq, zone);
	is_int(0, ret, "rrl: throttled IPv4 request");

	/* 6. limited IPv6 request */
	ret = rrl_query(rrl, &addr6, &rq, zone);
	is_int(0, ret, "rrl: throttled IPv6 request");
#else
	skip_block(2, "Timed tests not enabled");
#endif

	/* 7. invalid values. */
	ret = 0;
	rrl_create(0);            // NULL
	ret += rrl_setrate(0, 0); // 0
	ret += rrl_rate(0);       // 0
	ret += rrl_setlocks(0,0); // -1
	ret += rrl_query(0, 0, 0, 0); // -1
	ret += rrl_query(rrl, 0, 0, 0); // -1
	ret += rrl_query(rrl, (void*)0x1, 0, 0); // -1
	ret += rrl_destroy(0); // -1
	is_int(-488, ret, "rrl: not crashed while executing functions on NULL context");

#ifdef ENABLE_TIMED_TESTS
	/* 8. hopscotch test */
	struct runnable_data rd = {
		1, rrl, &addr, &rq, zone
	};
	rrl_hopscotch(&rd);
	ok(rd.passed, "rrl: hashtable is ~ consistent");

	/* 9. reseed */
	is_int(0, rrl_reseed(rrl), "rrl: reseed");

	/* 10. hopscotch after reseed. */
	rrl_hopscotch(&rd);
	ok(rd.passed, "rrl: hashtable is ~ consistent");
#else
	skip_block(3, "Timed tests not enabled");
#endif

	zone_free(&zone);
	knot_pkt_free(&query);
	rrl_destroy(rrl);
	return 0;
}
Esempio n. 11
0
int synth_record_load(struct query_plan *plan, struct query_module *self)
{
	/* Parse first token. */
	char *saveptr = NULL;
	char *token = strtok_r(self->param, " ", &saveptr);
	if (token == NULL) {
		return KNOT_EFEWDATA;
	}

	/* Create synthesis template. */
	struct synth_template *tpl = mm_alloc(self->mm, sizeof(struct synth_template));
	if (tpl == NULL) {
		return KNOT_ENOMEM;
	}

	/* Save in query module, it takes ownership from now on. */
	self->ctx = tpl;

	/* Supported types: reverse, forward */
	if (strcmp(token, "reverse") == 0) {
		tpl->type = SYNTH_REVERSE;
	} else if (strcmp(token, "forward") == 0) {
		tpl->type = SYNTH_FORWARD;
	} else {
		MODULE_ERR("invalid type '%s'.\n", token);
		return KNOT_ENOTSUP;
	}

	/* Parse format string. */
	tpl->prefix = strtok_r(NULL, " ", &saveptr);
	if (strchr(tpl->prefix, '.') != NULL) {
		MODULE_ERR("dots '.' are not allowed in the prefix.\n");
		return KNOT_EMALF;
	}

	/* Parse zone if generating reverse record. */
	if (tpl->type == SYNTH_REVERSE) {
		tpl->zone = strtok_r(NULL, " ", &saveptr);
		knot_dname_t *check_name = knot_dname_from_str(tpl->zone);
		if (check_name == NULL) {
			MODULE_ERR("invalid zone '%s'.\n", tpl->zone);
			return KNOT_EMALF;
		}
		knot_dname_free(&check_name, NULL);
	}

	/* Parse TTL. */
	tpl->ttl = strtol(strtok_r(NULL, " ", &saveptr), NULL, 10);

	/* Parse address. */
	token = strtok_r(NULL, " ", &saveptr);
	char *subnet = strchr(token, '/');
	if (subnet) {
		subnet[0] = '\0';
		tpl->subnet.prefix = strtol(subnet + 1, NULL, 10);
	}

	/* Estimate family. */
	int family = AF_INET;
	int prefix_max = IPV4_PREFIXLEN;
	if (strchr(token, ':') != NULL) {
		family = AF_INET6;
		prefix_max = IPV6_PREFIXLEN;
	}

	/* Check subnet. */
	if (tpl->subnet.prefix > prefix_max) {
		MODULE_ERR("invalid address prefix '%s'.\n", subnet);
		return KNOT_EMALF;
	}

	int ret = sockaddr_set(&tpl->subnet.ss, family, token, 0);
	if (ret != KNOT_EOK) {
		MODULE_ERR("invalid address '%s'.\n", token);
		return KNOT_EMALF;
	}

	return query_plan_step(plan, QPLAN_ANSWER, solve_synth_record, tpl);
}
Esempio n. 12
0
/*!
 * \brief Entry point of 'knsec3hash'.
 */
int main(int argc, char *argv[])
{
	bool enable_idn = true;

	struct option options[] = {
		{ "version", no_argument, 0, 'V' },
		{ "help",    no_argument, 0, 'h' },
		{ NULL }
	};

#ifdef LIBIDN
	// Set up localization.
	if (setlocale(LC_CTYPE, "") == NULL) {
		enable_idn = false;
	}
#endif

	int opt = 0;
	int li = 0;
	while ((opt = getopt_long(argc, argv, "hV", options, &li)) != -1) {
		switch(opt) {
		case 'V':
			printf("%s, version %s\n", PROGRAM_NAME, PACKAGE_VERSION);
			return 0;
		case 'h':
			usage(stdout);
			return 0;
		default:
			usage(stderr);
			return 1;
		}
	}

	// knsec3hash <salt> <algorithm> <iterations> <domain>
	if (argc != 5) {
		usage(stderr);
		return 1;
	}

	atexit(knot_crypto_cleanup);

	int exit_code = 1;
	knot_nsec3_params_t nsec3_params = { 0 };
	knot_dname_t *dname = NULL;
	uint8_t *digest = NULL;
	size_t digest_size = 0;
	uint8_t *b32_digest = NULL;
	int32_t b32_length = 0;
	int result = 0;

	if (!parse_nsec3_params(&nsec3_params, argv[1], argv[2], argv[3])) {
		goto fail;
	}

	if (enable_idn) {
		char *ascii_name = name_from_idn(argv[4]);
		if (ascii_name == NULL) {
			fprintf(stderr, "Cannot transform IDN domain name.\n");
			goto fail;
		}
		dname = knot_dname_from_str(ascii_name);
		free(ascii_name);
	} else {
		dname = knot_dname_from_str(argv[4]);
	}
	if (dname == NULL) {
		fprintf(stderr, "Cannot parse domain name.\n");
		goto fail;
	}

	result = knot_nsec3_hash(&nsec3_params, dname, knot_dname_size(dname),
	                         &digest, &digest_size);
	if (result != KNOT_EOK) {
		fprintf(stderr, "Cannot compute hash: %s\n",
		        knot_strerror(result));
		goto fail;
	}

	b32_length = base32hex_encode_alloc(digest, digest_size, &b32_digest);
	if (b32_length < 0) {
		fprintf(stderr, "Cannot encode computed hash: %s\n",
		        knot_strerror(b32_length));
		goto fail;
	}

	exit_code = 0;

	printf("%.*s (salt=%s, hash=%d, iterations=%d)\n", b32_length,
	       b32_digest, argv[1], nsec3_params.algorithm,
	       nsec3_params.iterations);

fail:
	knot_nsec3param_free(&nsec3_params);
	knot_dname_free(&dname, NULL);
	free(digest);
	free(b32_digest);

	return exit_code;
}