net.tls_padding() can now take a boolean in addition to a numeric
value. true means "use sensible default padding policy", false means
"never pad".
In the struct kr_context, we change tls_padding from a uint32_t to an
int32_t so that we can explicitly represent the default value (-1).
This should be a safe ABI/API change, since no one had ever set a
padding > 4096 anyway.
This depends on libknot having adopted the changes from
2dd9f406e333a1cedfa2380ffad57913cecf8efb which is first included in
2.4.3. In the event that knot-resolver is compiled against an older
version of libknot, it just uses a baked-in default of 468 as before.
See https://gitlab.labs.nic.cz/knot/resolver/merge_requests/249 for
further discussion.
.. function:: net.tls_padding([padding])
- Get/set EDNS(0) padding. If set to value >= 2 it will pad the answers
- to nearest *padding* boundary, e.g. if set to `64`, the answer will
- have size of multiplies of 64 (64, 128, 192, ...). Setting padding to
- value < 2 will disable it.
+ Get/set EDNS(0) padding of answers to queries that arrive over TLS
+ transport. If set to `true` (the default), it will use a sensible
+ default padding scheme, as implemented by libknot if available at
+ compile time. If set to a numeric value >= 2 it will pad the
+ answers to nearest *padding* boundary, e.g. if set to `64`, the
+ answer will have size of a multiple of 64 (64, 128, 192, ...). If
+ set to `false` (or a number < 2), it will disable padding entirely.
.. function:: net.outgoing_v4([string address])
/* Only return current padding. */
if (lua_gettop(L) == 0) {
- if (engine->resolver.tls_padding == 0) {
- return -1;
+ if (engine->resolver.tls_padding < 0) {
+ lua_pushboolean(L, true);
+ return 1;
+ } else if (engine->resolver.tls_padding == 0) {
+ lua_pushboolean(L, false);
+ return 1;
}
lua_pushinteger(L, engine->resolver.tls_padding);
return 1;
}
- if ((lua_gettop(L) != 1) || !lua_isnumber(L, 1)) {
- lua_pushstring(L, "net.tls_padding takes one numeric parameter: (\"padding\")");
+ if ((lua_gettop(L) != 1)) {
+ lua_pushstring(L, "net.tls_padding takes one parameter: (\"padding\")");
lua_error(L);
}
- int padding = lua_tointeger(L, 1);
- if ((padding < 0) || (padding > MAX_TLS_PADDING)) {
- lua_pushstring(L, "net.tls_padding parameter has to be a number between <0, " xstr(MAX_TLS_PADDING) ">");
+ if (lua_isboolean(L, 1)) {
+ bool x = lua_toboolean(L, 1);
+ if (x) {
+ engine->resolver.tls_padding = -1;
+ } else {
+ engine->resolver.tls_padding = 0;
+ }
+ } else if (lua_isnumber(L, 1)) {
+ int padding = lua_tointeger(L, 1);
+ if ((padding < 0) || (padding > MAX_TLS_PADDING)) {
+ lua_pushstring(L, "net.tls_padding parameter has to be true, false, or a number between <0, " xstr(MAX_TLS_PADDING) ">");
+ lua_error(L);
+ }
+ engine->resolver.tls_padding = padding;
+ } else {
+ lua_pushstring(L, "net.tls_padding parameter has to be true, false, or a number between <0, " xstr(MAX_TLS_PADDING) ">");
lua_error(L);
}
- engine->resolver.tls_padding = padding;
lua_pushboolean(L, true);
return 1;
}
return kr_error(ENOMEM);
}
knot_edns_init(engine->resolver.opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
- /* Set default TLS padding */
- engine->resolver.tls_padding = KR_DEFAULT_TLS_PADDING;
+ /* Use default TLS padding */
+ engine->resolver.tls_padding = -1;
/* Set default root hints */
kr_zonecut_init(&engine->resolver.root_hints, (const uint8_t *)"", engine->pool);
kr_zonecut_set_sbelt(&engine->resolver, &engine->resolver.root_hints);
wire_size += KR_COOKIE_OPT_MAX_LEN;
}
#endif /* defined(ENABLE_COOKIES) */
- if (req->has_tls && req->ctx->tls_padding >= 2) {
- wire_size += KNOT_EDNS_OPTION_HDRLEN + req->ctx->tls_padding;
+ if (req->has_tls) {
+ 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);
}
assert(false);
return kr_error(EINVAL);
}
- uint16_t padding = request->ctx->tls_padding;
+ int32_t padding = request->ctx->tls_padding;
knot_pkt_t *answer = request->answer;
knot_rrset_t *opt_rr = answer->opt_rr;
-
- if (padding < 2) {
- return kr_ok();
+ int32_t pad_bytes = -1;
+
+ if (padding == -1) { /* use the default padding policy from libknot */
+#if KNOT_VERSION_HEX < ((2 << 16) | (4 << 8) | 3)
+ /* no knot_edns_default_padding_size available in libknot */
+ padding = KR_DEFAULT_TLS_PADDING;
+#else
+ pad_bytes = knot_edns_default_padding_size(answer, opt_rr);
+#endif
}
- int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (answer->size + knot_rrset_size(opt_rr));
-
- int32_t pad_bytes = MIN(knot_edns_alignment_size(answer->size, knot_rrset_size(opt_rr), padding),
+ 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)];
* module because of better access. */
struct kr_cookie_ctx cookie_ctx;
kr_cookie_lru_t *cache_cookie;
- uint32_t tls_padding; /**< See net.tls_padding in ../daemon/README.rst */
+ int32_t tls_padding; /**< See net.tls_padding in ../daemon/README.rst -- -1 is "true" (default policy), 0 is "false" (no padding) */
knot_mm_t *pool;
};