Commit 8de47b5e authored by Karel Slaný's avatar Karel Slaný

Added DNS cookie algorithm interface into libknot.

parent b46546d9
......@@ -101,6 +101,8 @@ nobase_libknot_la_HEADERS = \
libknot/codes.h \
libknot/consts.h \
libknot/control/control.h \
libknot/cookies/client.h \
libknot/cookies/server.h \
libknot/descriptor.h \
libknot/dname.h \
libknot/errcode.h \
......@@ -142,6 +144,8 @@ libknot_la_SOURCES = \
libknot/binary.c \
libknot/codes.c \
libknot/control/control.c \
libknot/cookies/client.c \
libknot/cookies/server.c \
libknot/descriptor.c \
libknot/dname.c \
libknot/error.c \
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "libknot/attribute.h"
#include "libknot/cookies/client.h"
#include "libknot/errcode.h"
#include "libknot/rrtype/opt_cookie.h"
_public_
int knot_sockaddr_bytes(const void *sockaddr,
const uint8_t **addr, size_t *len)
{
if (!sockaddr || !addr || !len) {
return KNOT_EINVAL;
}
int addr_family = ((struct sockaddr *) sockaddr)->sa_family;
switch (addr_family) {
case AF_INET:
*addr = (uint8_t *) &((struct sockaddr_in *) sockaddr)->sin_addr;
*len = 4;
break;
case AF_INET6:
*addr = (uint8_t *) &((struct sockaddr_in6 *) sockaddr)->sin6_addr;
*len = 16;
break;
default:
*addr = NULL;
*len = 0;
addr_family = AF_UNSPEC;
return KNOT_EINVAL;
break;
}
return KNOT_EOK;
}
_public_
int knot_ccookie_check(const uint8_t *cc, uint16_t cc_len,
const struct knot_ccookie_input *input,
const struct knot_cc_alg *cc_alg)
{
if (!cc || !cc_len || !input ||
!cc_alg || !cc_alg->cc_size || cc_alg->gen_func) {
return KNOT_EINVAL;
}
if (cc_alg->cc_size > KNOT_OPT_COOKIE_CLNT) {
return KNOT_ESPACE;
}
uint8_t generated_cc[KNOT_OPT_COOKIE_CLNT] = { 0, };
uint16_t generated_cc_len = KNOT_OPT_COOKIE_CLNT;
int ret = cc_alg->gen_func(input, generated_cc, &generated_cc_len);
if (ret != KNOT_EOK) {
return ret;
}
if (generated_cc_len != cc_len) {
return KNOT_EINVAL;
}
ret = memcmp(cc, generated_cc, generated_cc_len);
if (ret != 0) {
return KNOT_EINVAL;
}
return KNOT_EOK;
}
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Functions for manipulating client cookie values.
*
* \addtogroup libknot
* @{
*/
#pragma once
/*!
* \brief Input data needed to compute the client cookie value.
*/
struct knot_ccookie_input {
const void *clnt_sockaddr; /*!< Client (local) socket address. */
const void *srvr_sockaddr; /*!< Server (remote) socket address. */
const uint8_t *secret_data; /*!< Client secret data. */
size_t secret_len; /*!< Secret data length. */
};
/*!
* \brief Client cookie generator function type.
*
* \param input Data which to generate the cookie from.
* \param cc_out Buffer to write the resulting client cookie data into.
* \param cc_len On input set to cookie buffer size.
* On successful return contains size of client cookie.
*
* \retval KNOT_EOK
* \retval KNOT_ESPACE
* \retval KNOT_EINVAL
*/
typedef int (knot_cc_gen_t)(const struct knot_ccookie_input *input,
uint8_t *cc_out, uint16_t *cc_len);
/*!
* \brief Holds description of the client cookie algorithm.
*/
struct knot_cc_alg {
const uint16_t cc_size; /*!< Cookie size the algorithm operates with. */
knot_cc_gen_t *gen_func; /*!< Cookie generator function. */
};
/*!
* \brief Get pointer to IP address and the size of the address.
*
* \param sockaddr Socket address.
* \param addr Pointer to address to be set.
* \param len Address length to be set.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
int knot_sockaddr_bytes(const void *sockaddr,
const uint8_t **addr, size_t *len);
/*!
* \brief Check whether client cookie \a cc was generated from given \a input.
*
* \param cc Client cookie that should be checked.
* \param cc_len Client cookie size.
* \param input Client cookie input algorithm parameters.
* \param cc_alg Client cookie algorithm.
*
* \retval KNOT_EOK
* \retval KNOT_ESPACE
* \retval KNOT_EINVAL
*/
int knot_ccookie_check(const uint8_t *cc, uint16_t cc_len,
const struct knot_ccookie_input *input,
const struct knot_cc_alg *cc_alg);
/*! @} */
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "libknot/attribute.h"
#include "libknot/cookies/server.h"
#include "libknot/errcode.h"
#include "libknot/rrtype/opt_cookie.h"
_public_
int knot_scookie_check(const struct knot_dns_cookies *cookies,
const struct knot_scookie_check_ctx *check_ctx,
const struct knot_sc_alg *sc_alg)
{
if (!cookies || !check_ctx || !sc_alg) {
return KNOT_EINVAL;
}
if (!cookies->cc || !cookies->cc_len ||
!cookies->sc || !cookies->sc_len) {
return KNOT_EINVAL;
}
if (!check_ctx->clnt_sockaddr ||
!check_ctx->secret_data || !check_ctx->secret_len) {
return KNOT_EINVAL;
}
if (!sc_alg->sc_size || !sc_alg->parse_func || !sc_alg->gen_func) {
return KNOT_EINVAL;
}
if (sc_alg->sc_size > KNOT_OPT_COOKIE_SRVR_MAX) {
return KNOT_ESPACE;
}
if (cookies->sc_len != sc_alg->sc_size) {
/* Cookie size does to match. */
return KNOT_EINVAL;
}
struct knot_scookie_inbound inbound = { 0, };
/* Obtain data from received server cookie. */
int ret = sc_alg->parse_func(cookies->sc, cookies->sc_len, &inbound);
if (ret != KNOT_EOK) {
return ret;
}
uint8_t generated_sc[KNOT_OPT_COOKIE_SRVR_MAX] = { 0, };
uint16_t generated_sc_len = KNOT_OPT_COOKIE_SRVR_MAX;
struct knot_scookie_input sc_input = {
.cc = cookies->cc,
.cc_len = cookies->cc_len,
.nonce = inbound.nonce,
.time = inbound.time,
.srvr_data = check_ctx
};
/* Generate a new server cookie. */
ret = sc_alg->gen_func(&sc_input, generated_sc, &generated_sc_len);
if (ret != KNOT_EOK) {
return ret;
}
ret = memcmp(cookies->sc, generated_sc, generated_sc_len);
if (ret != 0) {
return KNOT_EINVAL;
}
return KNOT_EOK;
}
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Functions for manipulating server cookie values.
*
* \addtogroup libknot
* @{
*/
#pragma once
/*!
* \brief Convenience structure holding both, server and client, cookies.
*/
struct knot_dns_cookies {
const uint8_t *cc; /*!< Client cookie. */
uint16_t cc_len; /*!< Client cookie size. */
const uint8_t *sc; /*!< Server cookie. */
uint16_t sc_len; /*!< Server cookie size. */
};
/*!
* \brief Inbound server cookie checking context.
*
* Additional data needed to check the inbound server cookie.
*/
struct knot_scookie_check_ctx {
const void *clnt_sockaddr; /*!< Client (remote) socket address. */
const uint8_t *secret_data; /*!< Server secret data. */
size_t secret_len; /*!< Secret data length. */
};
/*!
* \brief Inbound server cookie content structure.
*/
struct knot_scookie_inbound {
uint32_t nonce; /*!< Some value. */
uint32_t time; /*!< Time stamp. */
const uint8_t *hash_data; /*!< Hash data. */
uint16_t hash_len; /*!< Hash data length. */
};
/*!
* \brief Input data needed to compute the client cookie value.
*/
struct knot_scookie_input {
const uint8_t *cc; /*!< Client cookie. */
uint16_t cc_len; /*!< Client cookie size. */
uint32_t nonce; /*!< Some generated value. */
uint32_t time; /*!< Time stamp. */
const struct knot_scookie_check_ctx *srvr_data; /*!< Private data known to the server. */
};
/*!
* \brief Server cookie parser function type.
*
* \param sc Server cookie data.
* \param data_len Server cookie data length.
* \param inbound Inbound cookie structure to be set.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
typedef int (knot_sc_parse_t)(const uint8_t *sc, uint16_t sc_len,
struct knot_scookie_inbound *inbound);
/*!
* \brief Server cookie generator function type.
*
* \param input Data which to generate the cookie from.
* \param sc_out Buffer to write the resulting client cookie data into.
* \param sc_len On input set to cookie buffer size.
* On successful return contains size of server cookie.
*
* \retval KNOT_EOK
* \retval KNOT_ESPACE
* \retval KNOT_EINVAL
*/
typedef int (knot_sc_gen_t)(const struct knot_scookie_input *input,
uint8_t *sc_out, uint16_t *sc_len);
/*!
* \brief Holds description of the server cookie algorithm.
*/
struct knot_sc_alg {
const uint16_t sc_size; /*!< Cookie size the algorithm operates with. */
knot_sc_parse_t *parse_func; /*!< Cookie parser function. */
knot_sc_gen_t *gen_func; /*!< Cookie generator function. */
};
/*!
* \brief Check whether supplied client and server cookies match.
*
* \param cookies Cookie data.
* \param check_ctx Data known to the server needed for cookie validation.
* \param sc_alg Server cookie algorithm.
*
* \retval KNOT_EOK
* \retval KNOT_ESPACE
* \retval KNOT_EINVAL
*/
int knot_scookie_check(const struct knot_dns_cookies *cookies,
const struct knot_scookie_check_ctx *check_ctx,
const struct knot_sc_alg *sc_alg);
/*! @} */
......@@ -14,7 +14,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
......@@ -29,8 +28,6 @@ int knot_edns_opt_cookie_write(const uint8_t *cc, uint16_t cc_len,
const uint8_t *sc, uint16_t sc_len,
uint8_t *data, uint16_t *data_len)
{
assert(cc != NULL);
if ((cc == NULL && cc_len > 0) || (sc == NULL && sc_len > 0)) {
return KNOT_EINVAL;
}
......@@ -71,6 +68,10 @@ int knot_edns_opt_cookie_parse(const uint8_t *data, uint16_t data_len,
return KNOT_EINVAL;
}
if (!cookie_len_ok(data_len)) {
return KNOT_EMALF;
}
if (cc != NULL && cc_len != NULL) {
*cc_len = KNOT_OPT_COOKIE_CLNT;
*cc = data;
......
......@@ -16,7 +16,7 @@
/*!
* \file
*
* \brief Functions for manipulating the EDNS OPT pseudo-RR.
* \brief Functions for manipulating the EDNS Cookie OPT pseudo-RR.
*
* \addtogroup libknot
* @{
......@@ -97,8 +97,9 @@ int knot_edns_opt_cookie_write(const uint8_t *cc, uint16_t cc_len,
* \param sc Server cookie.
* \param sc_len Server cookie size.
*
* \return KNOT_EOK
* \return KNOT_EINVAL
* \retval KNOT_EOK
* \retval KNOT_EINVAL
* \retval KNOT_EMALF
*/
int knot_edns_opt_cookie_parse(const uint8_t *data, uint16_t data_len,
const uint8_t **cc, uint16_t *cc_len,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment