]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Generating FORMERR and BADCOOKIE response codes when processing cookies.
authorKarel Slany <karel.slany@nic.cz>
Wed, 15 Jun 2016 15:26:26 +0000 (17:26 +0200)
committerOndřej Surý <ondrej@sury.org>
Thu, 11 Aug 2016 12:06:45 +0000 (14:06 +0200)
lib/layer/cookiemonster.c

index bf05abfe549ebeaafe7dbb1f696b861d278d3542..a8732f3d3dee8ac3d8170e68bc23f472d400e3b5 100644 (file)
@@ -370,6 +370,18 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt)
        return ctx->state;
 }
 
+static int knot_pkt_set_ext_rcode(knot_pkt_t *pkt, uint16_t whole_rcode)
+{
+       assert(pkt && knot_pkt_has_edns(pkt));
+
+       uint8_t rcode = whole_rcode & 0x0f;
+       uint8_t ext_rcode = whole_rcode >> 4;
+       knot_wire_set_rcode(pkt->wire, rcode);
+       knot_edns_set_ext_rcode(pkt->opt_rr, ext_rcode);
+
+       return kr_ok();
+}
+
 static int check_request(knot_layer_t *ctx, void *module_param)
 {
        if (!kr_glob_cookie_ctx.srvr.enabled) {
@@ -401,15 +413,32 @@ static int check_request(knot_layer_t *ctx, void *module_param)
                                             &req_cc, &req_cc_len,
                                             &req_sc, &req_sc_len);
        if (ret != KNOT_EOK) {
-               /* TODO -- Generate BADCOOKIE response. */
+               /* Generate FORMERR response because malformed DNS cookie. */
                DEBUG_MSG(NULL, "%s\n", "got malformed DNS cookie in request");
-               return ctx->state;
+               knot_wire_set_rcode(req->answer->wire, KNOT_RCODE_FORMERR);
+               return KNOT_STATE_FAIL | KNOT_STATE_DONE;
        }
        assert(req_cc_len == KNOT_OPT_COOKIE_CLNT);
 
+       bool ignore_badcookie = true; /* TODO -- Occasionally ignore? */
+
        if (!req_sc) {
-               /* TODO -- BADCOOKIE? Occasionally ignore? */
-               DEBUG_MSG(NULL, "%s\n", "no server DNS cookie in request");
+               /* TODO -- Silently discard? */
+               if (!ignore_badcookie) {
+                       /* Generate BADCOOKIE response. */
+                       DEBUG_MSG(NULL, "%s\n",
+                                 "missing server DNS cookie in request");
+                       if (!knot_pkt_has_edns(req->answer)) {
+                               DEBUG_MSG(NULL, "%s\n",
+                                         "missing EDNS section in prepared answer");
+                               return KNOT_STATE_FAIL;
+                       }
+                       knot_pkt_set_ext_rcode(req->answer,
+                                              KNOT_RCODE_BADCOOKIE);
+                       return KNOT_STATE_FAIL | KNOT_STATE_DONE;
+               }
+               DEBUG_MSG(NULL, "%s\n",
+                         "ignoring missing server DNS cookie in request");
                return ctx->state;
        }
 
@@ -419,9 +448,8 @@ static int check_request(knot_layer_t *ctx, void *module_param)
 
        if (!req->qsource.addr ||
            !srvr_cntrl->current.ssec || !srvr_cntrl->current.salg) {
-               /* TODO -- SERVFAIL? */
                DEBUG_MSG(NULL, "%s\n", "no server DNS cookie context data");
-               return ctx->state;
+               return KNOT_STATE_FAIL;
        }
 
        struct kr_srvr_cookie_check_ctx check_ctx = {
@@ -442,8 +470,22 @@ static int check_request(knot_layer_t *ctx, void *module_param)
                                           srvr_cntrl->recent.salg);
        }
        if (ret != kr_ok()) {
-               /* TODO -- BADCOOKIE? Occasionally ignore? */
-               DEBUG_MSG(NULL, "%s\n", "invalid server DNS cookie data");
+               /* TODO -- Silently discard? */
+               if (!ignore_badcookie) {
+                       /* Generate BADCOOKIE response. */
+                       DEBUG_MSG(NULL, "%s\n",
+                                 "invalid server DNS cookie in request");
+                       if (!knot_pkt_has_edns(req->answer)) {
+                               DEBUG_MSG(NULL, "%s\n",
+                                         "missing EDNS section in prepared answer");
+                               return KNOT_STATE_FAIL;
+                       }
+                       knot_pkt_set_ext_rcode(req->answer,
+                                              KNOT_RCODE_BADCOOKIE);
+                       return KNOT_STATE_FAIL | KNOT_STATE_DONE;
+               }
+               DEBUG_MSG(NULL, "%s\n",
+                         "ignoring invalid server DNS cookie in request");
                return ctx->state;
        }
 
@@ -452,6 +494,30 @@ static int check_request(knot_layer_t *ctx, void *module_param)
        return ctx->state;
 }
 
+static int process_response(knot_layer_t *ctx)
+{
+       if (!kr_glob_cookie_ctx.srvr.enabled) {
+               return ctx->state;
+       }
+
+       struct kr_request *req = ctx->data;
+       const knot_rrset_t *req_opt_rr = req->qsource.opt;
+
+       if (!req_opt_rr) {
+               return ctx->state;
+       }
+
+       uint8_t *req_cookie_opt = knot_edns_get_option(req_opt_rr,
+                                                      KNOT_EDNS_OPTION_COOKIE);
+       if (!req_cookie_opt) {
+               return ctx->state;
+       }
+
+       /* TODO -- Add server cookie into answer. */
+
+       return ctx->state;
+}
+
 /** Module implementation. */
 
 KR_EXPORT
@@ -459,6 +525,7 @@ const knot_layer_api_t *cookiemonster_layer(struct kr_module *module)
 {
        static knot_layer_api_t _layer = {
                .begin = &check_request,
+               .finish = &process_response,
                .consume = &check_response
        };
        /* Store module reference */