コード例 #1
0
ファイル: validate.c プロジェクト: Karm/knot-resolver
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();
}
コード例 #2
0
ファイル: zone-diff.c プロジェクト: gitter-badger/knot
static int knot_zone_diff_load_soas(const zone_contents_t *zone1,
                                    const zone_contents_t *zone2,
                                    changeset_t *changeset)
{
	if (zone1 == NULL || zone2 == NULL || changeset == NULL) {
		return KNOT_EINVAL;
	}

	const zone_node_t *apex1 = zone1->apex;
	const zone_node_t *apex2 = zone2->apex;
	if (apex1 == NULL || apex2 == NULL) {
		return KNOT_EINVAL;
	}

	knot_rrset_t soa_rrset1 = node_rrset(apex1, KNOT_RRTYPE_SOA);
	knot_rrset_t soa_rrset2 = node_rrset(apex2, KNOT_RRTYPE_SOA);
	if (knot_rrset_empty(&soa_rrset1) || knot_rrset_empty(&soa_rrset2)) {
		return KNOT_EINVAL;
	}

	if (soa_rrset1.rrs.rr_count == 0 ||
	    soa_rrset2.rrs.rr_count == 0) {
		return KNOT_EINVAL;
	}

	int64_t soa_serial1 = knot_soa_serial(&soa_rrset1.rrs);
	int64_t soa_serial2 = knot_soa_serial(&soa_rrset2.rrs);

	if (serial_compare(soa_serial1, soa_serial2) == 0) {
		return KNOT_ENODIFF;
	}

	if (serial_compare(soa_serial1, soa_serial2) > 0) {
		return KNOT_ERANGE;
	}

	assert(changeset);

	changeset->soa_from = knot_rrset_copy(&soa_rrset1, NULL);
	if (changeset->soa_from == NULL) {
		return KNOT_ENOMEM;
	}
	changeset->soa_to = knot_rrset_copy(&soa_rrset2, NULL);
	if (changeset->soa_to == NULL) {
		knot_rrset_free(&changeset->soa_from, NULL);
		return KNOT_ENOMEM;
	}

	dbg_zonediff_verb("zone_diff: load_soas: SOAs diffed. "
	                  "(%"PRId64" -> %"PRId64")\n",
	                  soa_serial1, soa_serial2);

	return KNOT_EOK;
}
コード例 #3
0
ファイル: validate.c プロジェクト: Karm/knot-resolver
static knot_rrset_t *update_ds(struct kr_zonecut *cut, const knot_pktsection_t *sec)
{
	/* Aggregate DS records (if using multiple keys) */
	knot_rrset_t *new_ds = NULL;
	for (unsigned i = 0; i < sec->count; ++i) {
		const knot_rrset_t *rr = knot_pkt_rr(sec, i);
		if (rr->type != KNOT_RRTYPE_DS) {
			continue;
		}
		int ret = 0;
		if (new_ds) {
			ret = knot_rdataset_merge(&new_ds->rrs, &rr->rrs, cut->pool);
		} else {
			new_ds = knot_rrset_copy(rr, cut->pool);
			if (!new_ds) {
				return NULL;
			}
		}
		if (ret != 0) {
			knot_rrset_free(&new_ds, cut->pool);
			return NULL;
		}
	}
	return new_ds;	
}
コード例 #4
0
ファイル: bindings.c プロジェクト: PaulosV/knot-resolver
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;
}
コード例 #5
0
ファイル: validate.c プロジェクト: Karm/knot-resolver
static int validate_records(struct kr_query *qry, knot_pkt_t *answer, knot_mm_t *pool, bool has_nsec3)
{
	if (!qry->zone_cut.key) {
		DEBUG_MSG(qry, "<= no DNSKEY, can't validate\n");
		return kr_error(EBADMSG);
	}

	kr_rrset_validation_ctx_t vctx = {
		.pkt		= answer,
		.section_id	= KNOT_ANSWER,
		.keys		= qry->zone_cut.key,
		.zone_name	= qry->zone_cut.name,
		.timestamp	= qry->timestamp.tv_sec,
		.has_nsec3	= has_nsec3,
		.flags		= 0,
		.result		= 0
	};

	int ret = validate_section(&vctx, pool);
	if (ret != 0) {
		return ret;
	}

	uint32_t an_flags = vctx.flags;
	vctx.section_id   = KNOT_AUTHORITY;
	/* zone_name can be changed by validate_section(), restore it */
	vctx.zone_name	  = qry->zone_cut.name;
	vctx.flags	  = 0;
	vctx.result	  = 0;

	ret = validate_section(&vctx, pool);
	if (ret != 0) {
		return ret;
	}

	/* Records were validated.
	 * If there is wildcard expansion in answer, flag the query.
         */
	if (an_flags & KR_DNSSEC_VFLG_WEXPAND) {
		qry->flags |= QUERY_DNSSEC_WEXPAND;
	}

	return ret;
}

static int validate_keyset(struct kr_query *qry, knot_pkt_t *answer, bool has_nsec3)
{
	/* Merge DNSKEY records from answer that are below/at current cut. */
	bool updated_key = false;
	const knot_pktsection_t *an = knot_pkt_section(answer, KNOT_ANSWER);
	for (unsigned i = 0; i < an->count; ++i) {
		const knot_rrset_t *rr = knot_pkt_rr(an, i);
		if ((rr->type != KNOT_RRTYPE_DNSKEY) || !knot_dname_in(qry->zone_cut.name, rr->owner)) {
			continue;
		}
		/* Merge with zone cut (or replace ancestor key). */
		if (!qry->zone_cut.key || !knot_dname_is_equal(qry->zone_cut.key->owner, rr->owner)) {
			qry->zone_cut.key = knot_rrset_copy(rr, qry->zone_cut.pool);
			if (!qry->zone_cut.key) {
				return kr_error(ENOMEM);
			}
			updated_key = true;
		} else {
			int ret = knot_rdataset_merge(&qry->zone_cut.key->rrs,
			                              &rr->rrs, qry->zone_cut.pool);
			if (ret != 0) {
				knot_rrset_free(&qry->zone_cut.key, qry->zone_cut.pool);
				return ret;
			}
			updated_key = true;
		}
	}

	/* Check if there's a key for current TA. */
	if (updated_key && !(qry->flags & QUERY_CACHED)) {

		kr_rrset_validation_ctx_t vctx = {
			.pkt		= answer,
			.section_id	= KNOT_ANSWER,
			.keys		= qry->zone_cut.key,
			.zone_name	= qry->zone_cut.name,
			.timestamp	= qry->timestamp.tv_sec,
			.has_nsec3	= has_nsec3,
			.flags		= 0,
			.result		= 0
		};
		int ret = kr_dnskeys_trusted(&vctx, qry->zone_cut.trust_anchor);
		if (ret != 0) {
			knot_rrset_free(&qry->zone_cut.key, qry->zone_cut.pool);
			return ret;
		}

		if (vctx.flags & KR_DNSSEC_VFLG_WEXPAND)
		{
			qry->flags |= QUERY_DNSSEC_WEXPAND;
		}

	}
	return kr_ok();
}