diff --git a/daemon/worker.c b/daemon/worker.c index a5dd9bc02..b4e50b345 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1550,6 +1550,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, return 0; } query_error(c->buffer, LDNS_RCODE_FORMERR, 0); + sldns_buffer_copy(c->dnscrypt_buffer, c->buffer); return 1; } dname_str(qinfo.qname, buf); @@ -1568,6 +1569,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, query_error(c->buffer, LDNS_RCODE_SERVFAIL, qinfo.qname_len); worker->stats.num_query_dnscrypt_cleartext++; + sldns_buffer_copy(c->dnscrypt_buffer, c->buffer); return 1; } worker->stats.num_query_dnscrypt_cert++; @@ -1828,7 +1830,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error, server_stats_insquery(&worker->stats, c, qinfo.qtype, qinfo.qclass, &edns, repinfo); if(c->type != comm_udp) +#ifdef USE_DNSCRYPT + edns.udp_size = (c->dnscrypt && repinfo->is_dnscrypted) + ? sldns_buffer_capacity(c->buffer) - DNSCRYPT_REPLY_HEADER_SIZE + : 65535; +#else edns.udp_size = 65535; /* max size for TCP replies */ +#endif if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo, &edns, repinfo, c->buffer)) { regional_free_all(worker->scratchpad); @@ -2112,7 +2120,7 @@ send_reply_rc: } } #ifdef USE_DNSCRYPT - if(!dnsc_handle_uncurved_request(repinfo)) { + if(!dnsc_handle_uncurved_request(repinfo, c->buffer)) { return 0; } #endif diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c index 173484cdf..08f9dcb8c 100644 --- a/dnscrypt/dnscrypt.c +++ b/dnscrypt/dnscrypt.c @@ -474,10 +474,18 @@ dnscrypt_server_curve(const dnsccert *cert, uint8_t *const buf = sldns_buffer_begin(buffer); size_t len = sldns_buffer_limit(buffer); + if(len + DNSCRYPT_REPLY_HEADER_SIZE > sldns_buffer_capacity(buffer)) + return -1; + sldns_buffer_clear(buffer); + if(udp){ if (max_len > max_reply_size) max_len = max_reply_size; } + if(max_len > sldns_buffer_capacity(buffer)) + max_len = sldns_buffer_capacity(buffer); + if(max_len > 65535) + max_len = 65535; memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES); @@ -520,6 +528,7 @@ dnscrypt_server_curve(const dnsccert *cert, DNSCRYPT_MAGIC_HEADER_LEN, nonce, crypto_box_NONCEBYTES); + sldns_buffer_flip(buffer); sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE); return 0; } @@ -912,12 +921,13 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv, } int -dnsc_handle_uncurved_request(struct comm_reply *repinfo) +dnsc_handle_uncurved_request(struct comm_reply *repinfo, + struct sldns_buffer* buffer) { if(!repinfo->c->dnscrypt) { return 1; } - sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer); + sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer); if(!repinfo->is_dnscrypted) { return 1; } diff --git a/dnscrypt/dnscrypt.h b/dnscrypt/dnscrypt.h index b0da9b732..998237d48 100644 --- a/dnscrypt/dnscrypt.h +++ b/dnscrypt/dnscrypt.h @@ -128,7 +128,8 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv, * \return 0 in case of failure. */ -int dnsc_handle_uncurved_request(struct comm_reply *repinfo); +int dnsc_handle_uncurved_request(struct comm_reply *repinfo, + struct sldns_buffer* buffer); /** * Computes the size of the shared secret cache entry. diff --git a/util/netevent.c b/util/netevent.c index a86e22518..c5287e6c9 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -6685,7 +6685,9 @@ comm_point_send_reply(struct comm_reply *repinfo) log_assert(repinfo && repinfo->c); #ifdef USE_DNSCRYPT buffer = repinfo->c->dnscrypt_buffer; - if(!dnsc_handle_uncurved_request(repinfo)) { + if(!dnsc_handle_uncurved_request(repinfo, + repinfo->c->tcp_req_info? + repinfo->c->tcp_req_info->spool_buffer:repinfo->c->buffer)) { return; } #else