From 784a363e5969972c108be9a8817ca8cbcd687f4e Mon Sep 17 00:00:00 2001 From: Karel Slany Date: Tue, 10 May 2016 15:26:50 +0200 Subject: [PATCH] Obtaining server IP address when generating query. --- daemon/worker.c | 22 ++++++++++++ lib/cookies/control.c | 80 +++++++++++++++++++++++++++++++++++++++---- lib/cookies/control.h | 21 +++++++++--- lib/resolve.c | 6 +--- 4 files changed, 113 insertions(+), 16 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 1ab3d5d76..a7ef6df77 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -25,6 +25,7 @@ #include #endif #include +#include "lib/cookies/control.h" #include "lib/utils.h" #include "lib/layer.h" #include "daemon/worker.h" @@ -645,6 +646,25 @@ static void subreq_lead(struct qr_task *task) } } +/** UpdateDNS cookie data in */ +static bool subreq_update_cookies(struct qr_task *task) +{ + assert(task); + if (!kr_cookies_control.enabled || !task->pktbuf->opt_rr) { + fprintf(stderr, "XXX [%s %s %d]: packet has no edns\n", __FILE__, __func__, __LINE__); + return true; + } + + fprintf(stderr, "XXX [%s %s %d]: packet has edns\n", __FILE__, __func__, __LINE__); + + struct sockaddr_in6 *choice = &((struct sockaddr_in6 *)task->addrlist)[task->addrlist_turn]; + + kr_pkt_put_cookie(&kr_cookies_control, choice, task->pktbuf); + + /*TODO */ + return true; +} + static bool subreq_enqueue(struct qr_task *task) { assert(task); @@ -712,6 +732,8 @@ static int qr_task_step(struct qr_task *task, const struct sockaddr *packet_sour /* Start fast retransmit with UDP, otherwise connect. */ int ret = 0; if (sock_type == SOCK_DGRAM) { + /* Update DNS cookies data. */ + subreq_update_cookies(task); /* If there is already outgoing query, enqueue to it. */ if (subreq_enqueue(task)) { return kr_ok(); /* Will be notified when outgoing query finishes. */ diff --git a/lib/cookies/control.c b/lib/cookies/control.c index 1873cb175..582b9c58c 100644 --- a/lib/cookies/control.c +++ b/lib/cookies/control.c @@ -14,15 +14,29 @@ along with this program. If not, see . */ +#include +#include #include #include #include #include #include "lib/cookies/control.h" +#include "lib/layer.h" +#include "lib/utils.h" -struct cookies_control cookies_control = { - .enabled = true +#define DEBUG_MSG(qry, fmt...) QRDEBUG(qry, "cookies_control", fmt) + +static uint8_t cc[KNOT_OPT_COOKIE_CLNT] = { 1, 2, 3, 4, 5, 6, 7, 8}; + +static struct secret_quantity client = { + .size = KNOT_OPT_COOKIE_CLNT, + .secret = cc +}; + +struct cookies_control kr_cookies_control = { + .enabled = true, + .client = &client }; static int opt_rr_add_cookies(knot_rrset_t *opt_rr, @@ -54,15 +68,67 @@ static int opt_rr_add_cookies(knot_rrset_t *opt_rr, return KNOT_EOK; } -int kr_pkt_add_cookie(knot_pkt_t *pkt) +int prepare_client_cookie(uint8_t cc[KNOT_OPT_COOKIE_CLNT], + const void *srvr_addr, + const struct secret_quantity *csq) +{ + assert(cc); + assert(srvr_addr); + assert(csq); + + assert(csq->size >= KNOT_OPT_COOKIE_CLNT); + + /* According to the draft (section A.1) the recommended sequence is + * client IP address | server IP address , client secret. */ + + int addr_family = ((struct sockaddr *) srvr_addr)->sa_family; + if (addr_family == AF_INET) { + srvr_addr = &((struct sockaddr_in *) srvr_addr)->sin_addr; + } else if (addr_family == AF_INET6) { + srvr_addr = &((struct sockaddr_in6 *) srvr_addr)->sin6_addr; + } else { + assert(0); + return kr_error(EINVAL); + } + + WITH_DEBUG { + char ns_str[INET6_ADDRSTRLEN]; + inet_ntop(addr_family, srvr_addr, ns_str, sizeof(ns_str)); + DEBUG_MSG(NULL, "adding server address '%s' into client cookie\n", ns_str); + } + + memcpy(cc, csq->secret, KNOT_OPT_COOKIE_CLNT); +} + +int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr, + knot_pkt_t *pkt) { + assert(cntrl); assert(pkt); - assert(pkt->opt_rr); + + uint8_t cc[KNOT_OPT_COOKIE_CLNT]; + + if (!pkt->opt_rr) { + return kr_ok(); + } + + if (!cntrl->client) { + return kr_error(EINVAL); + } + + int ret = prepare_client_cookie(cc, sockaddr, cntrl->client); + + /* Reclaim reserved size. */ + ret = knot_pkt_reclaim(pkt, knot_edns_wire_size(pkt->opt_rr)); + if (ret != KNOT_EOK) { + return ret; + } /* TODO -- generate cleitn cookie from client address, server address * and secret quentity. */ - static uint8_t cc[KNOT_OPT_COOKIE_CLNT] = { 1, 2, 3, 4, 5, 6, 7, 8}; + ret = opt_rr_add_cookies(pkt->opt_rr, cc, NULL, 0, &pkt->mm); - int ret = opt_rr_add_cookies(pkt->opt_rr, cc, NULL, 0, &pkt->mm); - return ret; + /* Write to packet. */ + assert(pkt->current == KNOT_ADDITIONAL); + return knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE); } diff --git a/lib/cookies/control.h b/lib/cookies/control.h index 179195c6c..f204ee728 100644 --- a/lib/cookies/control.h +++ b/lib/cookies/control.h @@ -19,20 +19,33 @@ #include #include +#include "lib/defines.h" + #define KR_COOKIE_PLD_MAX 44 /* Define in libknot. */ +/** Holds secret quantity. */ +struct secret_quantity { + size_t size; /*!< Secret quantity size. */ + const uint8_t *secret; +}; + /** DNSSEC cookies controlling structure. */ struct cookies_control { bool enabled; /*!< Enabled/disables DNS cookies functionality. */ - /* Cache. */ + struct secret_quantity *client; /*!< Client secret quantity. */ + /* TODO -- Cache. */ }; /** Global cookies control. */ -extern struct cookies_control cookies_control; +KR_EXPORT +extern struct cookies_control kr_cookies_control; /** * Insert a DNS cookie into the packet. * @note The packet must already contain ENDS section. - * @param pkt Packet. + * @param cntrl Cookie control structure. + * @param pkt Packet. */ -int kr_pkt_add_cookie(knot_pkt_t *pkt); +KR_EXPORT +int kr_pkt_put_cookie(struct cookies_control *cntrl, void *sockaddr, + knot_pkt_t *pkt); diff --git a/lib/resolve.c b/lib/resolve.c index 243b3d336..189a5fe82 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -268,7 +268,7 @@ static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request { pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm); size_t wire_size = knot_edns_wire_size(pkt->opt_rr); - if (cookies_control.enabled) { + if (kr_cookies_control.enabled) { wire_size += KR_COOKIE_PLD_MAX; } return knot_pkt_reserve(pkt, wire_size); @@ -361,10 +361,6 @@ static int query_finalize(struct kr_request *request, struct kr_query *qry, knot knot_edns_set_do(pkt->opt_rr); knot_wire_set_cd(pkt->wire); } - /* Insert cookies. */ - if (cookies_control.enabled) { - ret = kr_pkt_add_cookie(pkt); - } ret = edns_put(pkt); } } -- 2.47.3