Beispiel #1
0
/*! \brief Check constraints (position, uniqueness, validity) for special types
 *         (TSIG, OPT).
 */
static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_size,
                                unsigned flags)
{
	/* Check RR constraints. */
	switch(rr->type) {
	case KNOT_RRTYPE_TSIG:
		CHECK_AR_CONSTRAINTS(pkt, rr, tsig_rr, knot_tsig_rdata_is_ok);

		/* Strip TSIG RR from wireformat and decrease ARCOUNT. */
		if (!(flags & KNOT_PF_KEEPWIRE)) {
			pkt->parsed -= rr_size;
			pkt->size -= rr_size;
			knot_wire_set_id(pkt->wire, knot_tsig_rdata_orig_id(rr));
			knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1);
		}
		break;
	case KNOT_RRTYPE_OPT:
		CHECK_AR_CONSTRAINTS(pkt, rr, opt_rr, knot_edns_check_record);
		break;
	default:
		break;
	}

	return KNOT_EOK;
}
Beispiel #2
0
_public_
int knot_sig0_sign(uint8_t *wire, size_t *wire_size, size_t wire_max_size,
                   knot_dnssec_key_t *key)
{
	knot_rrset_t *sig_rrset = sig0_create_rrset();
	if (!sig_rrset) {
		return KNOT_ENOMEM;
	}

	// SIG(0) headers without signature

	uint8_t *sig_rdata = sig0_create_rdata(sig_rrset, key);
	if (!sig_rdata) {
		knot_rrset_free(&sig_rrset, NULL);
		return KNOT_ENOMEM;
	}

	// convert to wire

	uint8_t *wire_end = wire + *wire_size;
	size_t wire_avail_size = wire_max_size - *wire_size;
	size_t wire_sig_size = 0;

	int result = knot_rrset_to_wire(sig_rrset, wire_end, wire_avail_size, NULL);

	knot_rrset_free(&sig_rrset, NULL);

	if (result < 0) {
		return result;
	}

	wire_sig_size = result;

	// create signature

	result = sig0_write_signature(wire, *wire_size, wire_sig_size, key);
	if (result != KNOT_EOK) {
		return result;
	}

	uint16_t wire_arcount = knot_wire_get_arcount(wire);
	knot_wire_set_arcount(wire, wire_arcount + 1);

	*wire_size += wire_sig_size;

	return KNOT_EOK;
}
Beispiel #3
0
/*! \brief Clear packet payload and free allocated data. */
static void pkt_clear_payload(knot_pkt_t *pkt)
{
	assert(pkt);

	/* Keep question. */
	pkt->parsed = 0;
	pkt->size = KNOT_WIRE_HEADER_SIZE + knot_pkt_question_size(pkt);
	knot_wire_set_ancount(pkt->wire, 0);
	knot_wire_set_nscount(pkt->wire, 0);
	knot_wire_set_arcount(pkt->wire, 0);

	/* Free RRSets if applicable. */
	pkt_free_data(pkt);

	/* Reset sections. */
	pkt_reset_sections(pkt);
}
Beispiel #4
0
int knot_tsig_append(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                     const knot_rrset_t *tsig_rr)
{
	size_t tsig_wire_len = 0;
	uint16_t rr_count = 0;

	/* Write RRSet to wire */
	int ret = KNOT_ERROR;
	ret = knot_rrset_to_wire(tsig_rr, msg + *msg_len,
	                         &tsig_wire_len, msg_max_len - *msg_len,
	                         &rr_count, NULL);
	if (ret != KNOT_EOK) {
		dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
		return ret;
	}

	*msg_len += tsig_wire_len;

	knot_wire_set_arcount(msg, knot_wire_get_arcount(msg) + 1);

	return KNOT_EOK;
}
Beispiel #5
0
int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                        const uint8_t *prev_digest, size_t prev_digest_len,
                        uint8_t *digest, size_t *digest_len,
                        const knot_tsig_key_t *key, uint8_t *to_sign,
                        size_t to_sign_len)
{
	if (!msg || !msg_len || !key || !digest || !digest_len) {
		return KNOT_EINVAL;
	}

	uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
	size_t digest_tmp_len = 0;
	knot_rrset_t *tmp_tsig = knot_rrset_new(key->name, KNOT_RRTYPE_TSIG,
	                                        KNOT_CLASS_ANY, NULL);
	if (!tmp_tsig) {
		return KNOT_ENOMEM;
	}

	/* Create rdata for TSIG RR. */
	tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
	                  knot_tsig_digest_length(key->algorithm), 0);
	tsig_rdata_store_current_time(tmp_tsig);
	tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);

	/* Create wire to be signed. */
	size_t wire_len = prev_digest_len + to_sign_len
	                  + KNOT_TSIG_TIMERS_LENGTH + 2;
	uint8_t *wire = malloc(wire_len);
	if (!wire) {
		ERR_ALLOC_FAILED;
		knot_rrset_free(&tmp_tsig, NULL);
		return KNOT_ENOMEM;
	}
	memset(wire, 0, wire_len);

	/* Write previous digest length. */
	knot_wire_write_u16(wire, prev_digest_len);
	/* Write previous digest. */
	memcpy(wire + 2, prev_digest, sizeof(uint8_t) * prev_digest_len);
	/* Write original message. */
	memcpy(wire + prev_digest_len + 2, to_sign, to_sign_len);
	/* Write timers. */
	knot_tsig_wire_write_timers(wire + prev_digest_len + to_sign_len + 2,
	                            tmp_tsig);

	dbg_tsig_detail("Previous digest: \n");
	dbg_tsig_hex_detail((char *)prev_digest, prev_digest_len);

	dbg_tsig_detail("Timers: \n");
	dbg_tsig_hex_detail((char *)(wire + prev_digest_len + *msg_len),
			    KNOT_TSIG_TIMERS_LENGTH);

	int ret = KNOT_ERROR;
	ret = knot_tsig_compute_digest(wire, wire_len,
	                               digest_tmp, &digest_tmp_len, key);

	/* No matter how the function did, this data is no longer needed. */
	free(wire);
	if (ret != KNOT_EOK) {
		knot_rrset_free(&tmp_tsig, NULL);
		*digest_len = 0;
		return ret;
	}

	if (digest_tmp_len > *digest_len) {
		knot_rrset_free(&tmp_tsig, NULL);
		*digest_len = 0;
		return KNOT_ESPACE;
	}

	/* Set the MAC. */
	tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);

	/* Set original id. */
	tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));

	/* Set other data. */
	tsig_rdata_set_other_data(tmp_tsig, 0, NULL);

	dbg_tsig_verb("Message max length: %zu, message length: %zu\n",
	              msg_max_len, *msg_len);

	size_t tsig_wire_size = 0;
	uint16_t rr_count = 0;
	ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
	                         &tsig_wire_size, msg_max_len - *msg_len,
	                         &rr_count, NULL);
	if (ret != KNOT_EOK) {
		knot_rrset_free(&tmp_tsig, NULL);
		*digest_len = 0;
		return ret;
	}

	/* This should not happen, at least one rr has to be converted. */
	if (rr_count == 0) {
		knot_rrset_free(&tmp_tsig, NULL);
		return KNOT_EINVAL;
	}

	knot_rrset_free(&tmp_tsig, NULL);

	*msg_len += tsig_wire_size;
	uint16_t arcount = knot_wire_get_arcount(msg);
	knot_wire_set_arcount(msg, ++arcount);

	memcpy(digest, digest_tmp, digest_tmp_len);
	*digest_len = digest_tmp_len;

	return KNOT_EOK;
}
Beispiel #6
0
int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
                   size_t msg_max_len, const uint8_t *request_mac,
                   size_t request_mac_len,
                   uint8_t *digest, size_t *digest_len,
                   const knot_tsig_key_t *key, uint16_t tsig_rcode,
                   uint64_t request_time_signed)
{
	if (!msg || !msg_len || !key || digest == NULL || digest_len == NULL) {
		return KNOT_EINVAL;
	}

	knot_rrset_t *tmp_tsig =
		knot_rrset_new(key->name, KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY,
		               NULL);
	if (!tmp_tsig) {
		dbg_tsig("TSIG: tmp_tsig = NULL\n");
		return KNOT_ENOMEM;
	}

	/* Create rdata for TSIG RR. */
	uint16_t rdata_rcode = 0;
	if (tsig_rcode == KNOT_RCODE_BADTIME)
		rdata_rcode = tsig_rcode;
	tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
	                  knot_tsig_digest_length(key->algorithm), rdata_rcode);

	/* Distinguish BADTIME response. */
	if (tsig_rcode == KNOT_RCODE_BADTIME) {
		/* Set client's time signed into the time signed field. */
		tsig_rdata_set_time_signed(tmp_tsig, request_time_signed);

		/* Store current time into Other data. */
		uint8_t time_signed[6];
		time_t curr_time = time(NULL);

		uint64_t time64 = curr_time;
		knot_wire_write_u48(time_signed, time64);

		tsig_rdata_set_other_data(tmp_tsig, 6, time_signed);
	} else {
		tsig_rdata_store_current_time(tmp_tsig);

		/* Set other len. */
		tsig_rdata_set_other_data(tmp_tsig, 0, 0);
	}

	tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);

	/* Set original ID */
	tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));

	uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
	size_t digest_tmp_len = 0;

	int ret = KNOT_ERROR;
	ret = knot_tsig_create_sign_wire(msg, *msg_len, /*msg_max_len,*/
	                                     request_mac, request_mac_len,
	                                     digest_tmp, &digest_tmp_len,
					     tmp_tsig, key);
	if (ret != KNOT_EOK) {
		dbg_tsig("TSIG: could not create wire or sign wire: %s\n",
		         knot_strerror(ret));
		knot_rrset_free(&tmp_tsig, NULL);
		return ret;
	}

	/* Set the digest. */
	size_t tsig_wire_len = 0;
	dbg_tsig("TSIG: msg_len=%zu, msg_max_len=%zu, tsig_max_len=%zu\n",
		 *msg_len, msg_max_len, tsig_wire_len);
	uint16_t rr_count = 0;
	tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);

	/* Write RRSet to wire */
	ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
	                         &tsig_wire_len, msg_max_len - *msg_len,
	                         &rr_count, NULL);
	if (ret != KNOT_EOK) {
		dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
		*digest_len = 0;
		knot_rrset_free(&tmp_tsig, NULL);
		return ret;
	}

	knot_rrset_free(&tmp_tsig, NULL);

	dbg_tsig("TSIG: written TSIG RR (wire len %zu)\n", tsig_wire_len);
	*msg_len += tsig_wire_len;

	uint16_t arcount = knot_wire_get_arcount(msg);
	knot_wire_set_arcount(msg, ++arcount);

	// everything went ok, save the digest to the output parameter
	memcpy(digest, digest_tmp, digest_tmp_len);
	*digest_len = digest_tmp_len;

	return KNOT_EOK;
}