コード例 #1
0
ファイル: query.c プロジェクト: nice-redbull/knot
int knot_query_add_rrset_authority(knot_packet_t *query,
				   const knot_rrset_t *rrset)
{
	if (query == NULL || rrset == NULL) {
		return KNOT_EINVAL;
	}

	if (query->ns_rrsets == query->max_ns_rrsets) {
		size_t oldsize = query->max_ns_rrsets * sizeof(knot_rrset_t *);
		++query->max_ns_rrsets;
		size_t newsize = query->max_ns_rrsets * sizeof(knot_rrset_t *);
		const knot_rrset_t ** na = malloc(newsize);
		if (na == 0) {
			query->max_ns_rrsets = 0;
			return KNOT_ENOMEM;
		} else {
			memcpy(na, query->authority, oldsize);
			free(query->authority);
			query->authority = na;
		}
	}

	/* Append to packet. */
	query->authority[query->ns_rrsets] = rrset;

	/* Write to wire. */
	uint8_t *startp = query->wireformat + query->size;
	uint8_t *endp = query->wireformat + query->max_size;

	assert(endp - startp > query->opt_rr.size + query->tsig_size);
	// reserve space for OPT RR
	/*! \todo Why here??? */
	endp -= query->opt_rr.size;
	/* Reserve space for TSIG RR */
	endp -= query->tsig_size;

	size_t written = 0;
	uint16_t rr_count = 0;
	int ret = knot_rrset_to_wire(rrset, startp, &written, query->max_size,
	                             &rr_count, NULL);
	if (ret != KNOT_EOK) {
		return ret;
	}
	query->size += written;
	++query->ns_rrsets;
	++query->header.nscount;

	return KNOT_EOK;
}
コード例 #2
0
ファイル: sig0.c プロジェクト: jkadlec/knot-dns-zoneapi
_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;
}
コード例 #3
0
ファイル: tsig-op.c プロジェクト: dnstap/knot
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;
}
コード例 #4
0
ファイル: signature.c プロジェクト: Karm/knot-resolver
/*!
 * \brief Add covered RRs to signing context.
 *
 * Requires all DNAMEs in canonical form and all RRs ordered canonically.
 *
 * \param ctx      Signing context.
 * \param covered  Covered RRs.
 *
 * \return Error code, KNOT_EOK if successful.
 */
static int sign_ctx_add_records(dnssec_sign_ctx_t *ctx, const knot_rrset_t *covered,
                                uint32_t orig_ttl, int trim_labels)
{
	// huge block of rrsets can be optionally created
	static uint8_t wire_buffer[KNOT_WIRE_MAX_PKTSIZE];
	int written = knot_rrset_to_wire(covered, wire_buffer, sizeof(wire_buffer), NULL);
	if (written < 0) {
		return written;
	}

	/* Set original ttl. */
	int ret = adjust_wire_ttl(wire_buffer, written, orig_ttl);
	if (ret != 0) {
		return ret;
	}

	/* RFC4035 5.3.2
	 * Remove leftmost labels and replace them with '*.'.
	 */
	uint8_t *beginp = wire_buffer;
	if (trim_labels > 0) {
		for (int i = 0; i < trim_labels; ++i) {
			assert(beginp[0]);
			beginp = (uint8_t *) knot_wire_next_label(beginp, NULL);
		}
		*(--beginp) = '*';
		*(--beginp) = 1;
	}

	dnssec_binary_t wire_binary = {
		.size = written - (beginp - wire_buffer),
		.data = beginp
	};
	return dnssec_sign_add(ctx, &wire_binary);
}

/*!
 * \brief Add all data covered by signature into signing context.
 *
 * RFC 4034: The signature covers RRSIG RDATA field (excluding the signature)
 * and all matching RR records, which are ordered canonically.
 *
 * Requires all DNAMEs in canonical form and all RRs ordered canonically.
 *
 * \param ctx          Signing context.
 * \param rrsig_rdata  RRSIG RDATA with populated fields except signature.
 * \param covered      Covered RRs.
 *
 * \return Error code, KNOT_EOK if successful.
 */
/* TODO -- Taken from knot/src/knot/dnssec/rrset-sign.c. Re-write for better fit needed. */
static int sign_ctx_add_data(dnssec_sign_ctx_t *ctx, const uint8_t *rrsig_rdata,
                             const knot_rrset_t *covered, uint32_t orig_ttl, int trim_labels)
{
	int result = sign_ctx_add_self(ctx, rrsig_rdata);
	if (result != KNOT_EOK) {
		return result;
	}

	return sign_ctx_add_records(ctx, covered, orig_ttl, trim_labels);
}
コード例 #5
0
ファイル: tsig-op.c プロジェクト: dnstap/knot
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;
}
コード例 #6
0
ファイル: tsig-op.c プロジェクト: dnstap/knot
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;
}
コード例 #7
0
ファイル: response.c プロジェクト: nice-redbull/knot
	//short size = knot_response_rrset_size(rrset, &resp->compression);

dbg_response_exec(
	char *name = knot_dname_to_str(rrset->owner);
	dbg_response_verb("\nAdding RRSet with owner %s and type %u: \n",
	                  name, rrset->type);
	free(name);
);
	uint8_t *pos = resp->wireformat + resp->size;
	size_t size = max_size;
	compression_param_t param;
	param.compressed_dnames = resp->compression;
	param.wire_pos = resp->size;
	param.wire = resp->wireformat;
	uint16_t rr_count = 0;
	int ret = knot_rrset_to_wire(rrset, pos, &size, max_size,
	                             &rr_count, &param);

	if (ret != KNOT_EOK) {
		dbg_response("Failed to convert RRSet to wire. (%s).\n,",
		             knot_strerror(ret));
	}

	if (rr_count > 0) {
		rrsets[(*rrset_count)++] = rrset;
		resp->size += size;
		dbg_response_verb("RRset added, size: %zu, RRs: %d, total "
		                  "size of response: %zu\n\n", size, rr_count,
		                  resp->size);
	} else if (tc) {
		dbg_response_verb("Setting TC bit.\n");
		knot_wire_flags_set_tc(&resp->header.flags1);
コード例 #8
0
ファイル: pkt.c プロジェクト: gitter-badger/knot
_public_
int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr,
                 uint16_t flags)
{
	if (pkt == NULL || rr == NULL) {
		return KNOT_EINVAL;
	}

	/* Reserve memory for RR descriptors. */
	int ret = pkt_rr_array_alloc(pkt, pkt->rrset_count + 1);
	if (ret != KNOT_EOK) {
		return ret;
	}

	knot_rrinfo_t *rrinfo = &pkt->rr_info[pkt->rrset_count];
	memset(rrinfo, 0, sizeof(knot_rrinfo_t));
	rrinfo->pos = pkt->size;
	rrinfo->flags = flags;
	rrinfo->compress_ptr[0] = compr_hint;
	memcpy(pkt->rr + pkt->rrset_count, rr, sizeof(knot_rrset_t));

	/* Check for double insertion. */
	if ((flags & KNOT_PF_CHECKDUP) &&
	    pkt_contains(pkt, rr)) {
		return KNOT_EOK; /*! \todo return rather a number of added RRs */
	}

	uint8_t *pos = pkt->wire + pkt->size;
	size_t maxlen = pkt_remaining(pkt);

	/* Create compression context. */
	knot_compr_t compr;
	compr.wire = pkt->wire;
	compr.rrinfo = rrinfo;
	compr.suffix.pos = KNOT_WIRE_HEADER_SIZE;
	compr.suffix.labels = knot_dname_labels(compr.wire + compr.suffix.pos,
	                                        compr.wire);

	/* Write RRSet to wireformat. */
	ret = knot_rrset_to_wire(rr, pos, maxlen, &compr);
	if (ret < 0) {
		/* Truncate packet if required. */
		if (ret == KNOT_ESPACE && !(flags & KNOT_PF_NOTRUNC)) {
				knot_wire_set_tc(pkt->wire);
		}
		return ret;
	}

	size_t len = ret;
	uint16_t rr_added = rr->rrs.rr_count;

	/* Keep reference to special types. */
	if (rr->type == KNOT_RRTYPE_OPT) {
		pkt->opt_rr = &pkt->rr[pkt->rrset_count];
	}

	if (rr_added > 0) {
		pkt->rrset_count += 1;
		pkt->sections[pkt->current].count += 1;
		pkt->size += len;
		pkt_rr_wirecount_add(pkt, pkt->current, rr_added);
	}

	return KNOT_EOK;
}