return ret;
}
-int kr_answer_write_cookie(const struct knot_sc_private *srvr_data,
- const uint8_t *cc, uint16_t cc_len,
+int kr_answer_write_cookie(struct knot_sc_input *sc_input,
const struct kr_nonce_input *nonce,
- const struct knot_sc_alg *alg,
- knot_pkt_t *pkt)
+ const struct knot_sc_alg *alg, knot_pkt_t *pkt)
{
- if (!srvr_data || !srvr_data->clnt_sockaddr ||
- !srvr_data->secret_data|| !srvr_data->secret_len) {
+ if (!sc_input || !sc_input->cc || sc_input->cc_len == 0) {
return kr_error(EINVAL);
}
- if (!cc || cc_len == 0 || !nonce) {
+ if (!sc_input->srvr_data || !sc_input->srvr_data->clnt_sockaddr ||
+ !sc_input->srvr_data->secret_data ||
+ !sc_input->srvr_data->secret_len) {
+ return kr_error(EINVAL);
+ }
+
+ if (!nonce) {
return kr_error(EINVAL);
}
return kr_error(EINVAL);
}
- if (!pkt && !pkt->opt_rr) {
+ if (!pkt || !pkt->opt_rr) {
return kr_error(EINVAL);
}
uint16_t hash_len = alg->hash_size;
/*
- * Space for cookie is reserved inside the EDNS OPT RR inside
+ * Space for cookie is reserved inside the EDNS OPT RR of
* the answer packet.
*/
uint8_t *cookie = NULL;
- uint16_t cookie_len = knot_edns_opt_cookie_data_len(cc_len,
+ uint16_t cookie_len = knot_edns_opt_cookie_data_len(sc_input->cc_len,
nonce_len + hash_len);
if (cookie_len == 0) {
return kr_error(EINVAL);
if (ret != KNOT_EOK) {
return kr_error(ENOMEM);
}
+ assert(cookie != NULL);
/*
* Function knot_edns_opt_cookie_data_len() returns the sum of its
* parameters or zero. Anyway, let's check again.
*/
- if (cookie_len < (cc_len + nonce_len + hash_len)) {
+ if (cookie_len < (sc_input->cc_len + nonce_len + hash_len)) {
return kr_error(EINVAL);
}
- struct knot_sc_input input = {
- .cc = cookie,
- .cc_len = cc_len,
- .srvr_data = srvr_data
- };
- memcpy(cookie, cc, cc_len);
+ /* Copy client cookie data portion. */
+ memcpy(cookie, sc_input->cc, sc_input->cc_len);
if (nonce_len) {
- kr_nonce_write_wire(cookie + cc_len, nonce_len, nonce);
+ /* Write nonce data portion. */
+ kr_nonce_write_wire(cookie + sc_input->cc_len, nonce_len,
+ nonce);
/* Adjust input for written nonce value. */
- input.nonce = cookie + cc_len;
- input.nonce_len = nonce_len;
+ sc_input->nonce = cookie + sc_input->cc_len;
+ sc_input->nonce_len = nonce_len;
}
- hash_len = alg->hash_func(&input, cookie + cc_len + nonce_len, hash_len);
- if (hash_len == 0) {
- return kr_error(EINVAL);
- }
+ hash_len = alg->hash_func(sc_input,
+ cookie + sc_input->cc_len + nonce_len,
+ hash_len);
+ /* Zero nonce values. */
+ sc_input->nonce = NULL;
+ sc_input->nonce_len = 0;
- return kr_ok();
+ return (hash_len != 0) ? kr_ok() : kr_error(EINVAL);
}
int kr_pkt_set_ext_rcode(knot_pkt_t *pkt, uint16_t whole_rcode)
/**
* @brief Inserts a cookie option into the OPT RR. It does not write any
* wire data.
- * @param srvr_data server knowledge
- * @param cc client cookie
- * @param cc_len client cookie length
- * @param nonce nonce value
+ * @note The content of @a sc_input is modified. Any pre-set nonce value is
+ * ignored. After retuning its nonce value will be null.
+ * @param sc_input data needed to compute server cookie, nonce is ignored
+ * @param nonce nonce value that is actually used
* @param alg hash algorithm
* @param pkt DNS response packet
*/
KR_EXPORT
-int kr_answer_write_cookie(const struct knot_sc_private *srvr_data,
- const uint8_t *cc, uint16_t cc_len,
+int kr_answer_write_cookie(struct knot_sc_input *sc_input,
const struct kr_nonce_input *nonce,
- const struct knot_sc_alg *alg,
- knot_pkt_t *pkt);
+ const struct knot_sc_alg *alg, knot_pkt_t *pkt);
/**
* @brief Set RCODE and extended RCODE.
}
if (!srvr_sett->enabled) {
- /* TODO -- IS there a way how to determine whether the original
- * request came via TCP? */
if (knot_pkt_has_edns(answer)) {
/* Delete any cookies. */
knot_edns_remove_options(answer->opt_rr,
return ctx->state;
}
+ /*
+ * TODO -- Would it be of any benefit to know whether the request came
+ * via TCP?
+ */
+
uint8_t *req_cookie_opt = req_cookie_option(req);
if (!req_cookie_opt) {
return ctx->state; /* Don't do anything without cookies. */
.secret_len = srvr_sett->current.secr->size
};
+ struct knot_sc_input sc_input = {
+ .cc = cookies.cc,
+ .cc_len = cookies.cc_len,
+ /* Don't set nonce here. */
+ .srvr_data = &srvr_data
+ };
+
struct kr_nonce_input nonce = {
.rand = kr_rand_uint(UINT32_MAX),
.time = req->current_query->timestamp.tv_sec
answer_add_cookies:
/* Add server cookie into response. */
- ret = kr_answer_write_cookie(&srvr_data, cookies.cc, cookies.cc_len,
- &nonce, current_sc_alg, answer);
+ ret = kr_answer_write_cookie(&sc_input, &nonce, current_sc_alg, answer);
if (ret != kr_ok()) {
return_state = KNOT_STATE_FAIL;
}