From: Ivana Krumlová Date: Fri, 12 Jul 2019 13:16:52 +0000 (+0200) Subject: WIP padding module X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fpadding-flag;p=thirdparty%2Fknot-resolver.git WIP padding module - in .begin sets PADDING_REQUIRED flag for tls requests - function add_padding is moved from resolve.c but .answer_finalize is too early and .finish too late to aply it --- diff --git a/lib/resolve.c b/lib/resolve.c index 3dbb2d2de..2d87dbc19 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -427,15 +427,6 @@ static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request wire_size += KR_COOKIE_OPT_MAX_LEN; } #endif /* defined(ENABLE_COOKIES) */ - if (req->options.PADDING_REQUIRED) { - if (req->ctx->tls_padding == -1) - /* FIXME: we do not know how to reserve space for the - * default padding policy, since we can't predict what - * it will select. So i'm just guessing :/ */ - wire_size += KNOT_EDNS_OPTION_HDRLEN + 512; - if (req->ctx->tls_padding >= 2) - wire_size += KNOT_EDNS_OPTION_HDRLEN + req->ctx->tls_padding; - } return knot_pkt_reserve(pkt, wire_size); } @@ -519,42 +510,6 @@ static int write_extra_ranked_records(const ranked_rr_array_t *arr, uint16_t reo return err; } -/** @internal Add an EDNS padding RR into the answer if requested and required. */ -static int answer_padding_maybe(struct kr_request *request) -{ - if (!request || !request->answer || !request->ctx) { - assert(false); - return kr_error(EINVAL); - } - if (!request->options.PADDING_REQUIRED) return kr_ok(); - - int32_t padding = request->ctx->tls_padding; - knot_pkt_t *answer = request->answer; - knot_rrset_t *opt_rr = answer->opt_rr; - int32_t pad_bytes = -1; - - if (padding == -1) { /* use the default padding policy from libknot */ - pad_bytes = knot_pkt_default_padding_size(answer, opt_rr); - } - if (padding >= 2) { - int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (answer->size + knot_rrset_size(opt_rr)); - pad_bytes = MIN(knot_edns_alignment_size(answer->size, knot_rrset_size(opt_rr), padding), - max_pad_bytes); - } - - if (pad_bytes >= 0) { - uint8_t zeros[MAX(1, pad_bytes)]; - memset(zeros, 0, sizeof(zeros)); - int r = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_PADDING, - pad_bytes, zeros, &answer->mm); - if (r != KNOT_EOK) { - knot_rrset_clear(opt_rr, &answer->mm); - return kr_error(r); - } - } - return kr_ok(); -} - static int answer_fail(struct kr_request *request) { knot_pkt_t *answer = request->answer; @@ -565,7 +520,6 @@ static int answer_fail(struct kr_request *request) if (ret == 0 && answer->opt_rr) { /* OPT in SERVFAIL response is still useful for cookies/additional info. */ knot_pkt_begin(answer, KNOT_ADDITIONAL); - answer_padding_maybe(request); /* Ignore failed padding in SERVFAIL answer. */ ret = edns_put(answer, false); } return ret; @@ -630,9 +584,6 @@ static int answer_finalize(struct kr_request *request, int state) } /* Write EDNS information */ if (answer->opt_rr) { - if (answer_padding_maybe(request) != kr_ok()) { - return answer_fail(request); - } knot_pkt_begin(answer, KNOT_ADDITIONAL); int ret = knot_pkt_put(answer, KNOT_COMPR_HINT_NONE, answer->opt_rr, KNOT_PF_FREE); @@ -712,7 +663,6 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk request->ctx = ctx; request->answer = answer; request->options = ctx->options; - request->options.PADDING_REQUIRED = true; //WIP: this sets the flag for every request request->state = KR_STATE_CONSUME; request->current_query = NULL; array_init(request->additional); diff --git a/modules/meson.build b/modules/meson.build index 3ae4b56de..1c509b246 100644 --- a/modules/meson.build +++ b/modules/meson.build @@ -46,6 +46,7 @@ subdir('experimental_dot_auth') subdir('hints') subdir('http') subdir('nsid') +subdir('padding') subdir('policy') subdir('stats') subdir('view') diff --git a/modules/padding/meson.build b/modules/padding/meson.build new file mode 100644 index 000000000..55f1191bd --- /dev/null +++ b/modules/padding/meson.build @@ -0,0 +1,23 @@ +# C module: padding + +padding_src = files([ + 'padding.c', +]) +c_src_lint += padding_src + +integr_tests += [ + ['padding', join_paths(meson.current_source_dir(), 'test.integr')], +] + + +padding_mod = shared_module( + 'padding', + padding_src, + dependencies: [ + luajit_inc, + ], + include_directories: mod_inc_dir, + name_prefix: '', + install: true, + install_dir: modules_dir, +) diff --git a/modules/padding/padding.c b/modules/padding/padding.c new file mode 100644 index 000000000..c4fecaa7f --- /dev/null +++ b/modules/padding/padding.c @@ -0,0 +1,113 @@ +/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. + + 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 . + */ + +/** + * @file padding.c + * @brief TODO + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "lib/layer/iterate.h" +#include "lib/rplan.h" +#include "lib/module.h" +#include "lib/layer.h" +#include "lib/resolve.h" + +/** @internal Compatibility wrapper for Lua < 5.2 */ +#if LUA_VERSION_NUM < 502 +#define lua_rawlen(L, obj) lua_objlen((L), (obj)) +#endif + +static int set_for_tls(kr_layer_t *ctx) +{ + struct kr_request *req = ctx->req; + if (req->qsource.flags.tls) { + req->options.PADDING_REQUIRED = true; + } + return ctx->state; +} + +static int add_padding(kr_layer_t *ctx) { + struct kr_request *request = ctx->req; + + if (!request || !request->answer || !request->ctx) { + assert(false); + return kr_error(EINVAL); + } + if (!request->options.PADDING_REQUIRED) return kr_ok(); + + int32_t padding = request->ctx->tls_padding; + knot_pkt_t *answer = request->answer; + knot_rrset_t *opt_rr = answer->opt_rr; + int32_t pad_bytes = -1; + + if (padding == -1) { /* use the default padding policy from libknot */ + pad_bytes = knot_pkt_default_padding_size(answer, opt_rr); + } + if (padding >= 2) { + int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (answer->size + knot_rrset_size(opt_rr)); + pad_bytes = MIN(knot_edns_alignment_size(answer->size, knot_rrset_size(opt_rr), padding), + max_pad_bytes); + } + + if (pad_bytes >= 0) { + uint8_t zeros[MAX(1, pad_bytes)]; + memset(zeros, 0, sizeof(zeros)); + int r = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_PADDING, + pad_bytes, zeros, &answer->mm); + if (r != KNOT_EOK) { + knot_rrset_clear(opt_rr, &answer->mm); + return kr_error(r); + } + } + return kr_ok(); +} + +KR_EXPORT +int padding_init(struct kr_module *module) +{ + static kr_layer_api_t layer = { + .begin = &set_for_tls, + .answer_finalize = &add_padding, + //.finish = &add_padding, + }; + /* Store module reference */ + layer.data = module; + module->layer = &layer; + + static const struct kr_prop props[] = { + { NULL, NULL, NULL } + }; + module->props = props; + return kr_ok(); +} + +KR_EXPORT +int padding_deinit(struct kr_module *module) +{ + return kr_ok(); +} + +KR_MODULE_EXPORT(padding) + +#undef VERBOSE_MSG