diff --git a/src/context.c b/src/context.c index ba51d90c..c52f770b 100644 --- a/src/context.c +++ b/src/context.c @@ -693,9 +693,10 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) upstream->finished_dnsreqs = dnsreq->finished_next; _getdns_context_cancel_request(dnsreq); } + if (upstream->tls_session != NULL) + SSL_SESSION_free(upstream->tls_session); + if (upstream->tls_obj != NULL) { - if (upstream->tls_session != NULL) - SSL_SESSION_free(upstream->tls_session); SSL_shutdown(upstream->tls_obj); SSL_free(upstream->tls_obj); } diff --git a/src/request-internal.c b/src/request-internal.c index a74fe8f0..1bd5475e 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -110,6 +110,9 @@ network_req_cleanup(getdns_network_req *net_req) if (net_req->response && (net_req->response < net_req->wire_data || net_req->response > net_req->wire_data+ net_req->wire_data_sz)) GETDNS_FREE(net_req->owner->my_mf, net_req->response); + if (net_req->debug_tls_peer_cert.size && + net_req->debug_tls_peer_cert.data) + OPENSSL_free(net_req->debug_tls_peer_cert.data); } static uint8_t * @@ -182,6 +185,8 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->write_queue_tail = NULL; /* Some fields to record info for return_call_reporting */ net_req->debug_tls_auth_status = GETDNS_AUTH_NONE; + net_req->debug_tls_peer_cert.size = 0; + net_req->debug_tls_peer_cert.data = NULL; net_req->debug_udp = 0; /* Scheduling, touch only via _getdns_netreq_change_state! diff --git a/src/stub.c b/src/stub.c index 29112cc3..d23fb61f 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1618,6 +1618,7 @@ upstream_write_cb(void *userarg) getdns_upstream *upstream = (getdns_upstream *)userarg; getdns_network_req *netreq = upstream->write_queue; int q; + X509 *cert; if (!netreq) { GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); @@ -1672,6 +1673,15 @@ upstream_write_cb(void *userarg) return; default: + if (netreq->owner->return_call_reporting && + netreq->upstream->tls_obj && + (cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) { + assert(netreq->debug_tls_peer_cert.data == NULL); + + netreq->debug_tls_peer_cert.size = i2d_X509( + cert, &netreq->debug_tls_peer_cert.data); + X509_free(cert); + } /* Need this because auth status is reset on connection close */ netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state; upstream->queries_sent++; diff --git a/src/types-internal.h b/src/types-internal.h index 57286bed..5e1961ac 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -240,6 +240,7 @@ typedef struct getdns_network_req uint64_t debug_start_time; uint64_t debug_end_time; getdns_auth_state_t debug_tls_auth_status; + getdns_bindata debug_tls_peer_cert; size_t debug_udp; /* When more space is needed for the wire_data response than is diff --git a/src/util-internal.c b/src/util-internal.c index 48242eb1..33c31745 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -904,6 +904,15 @@ _getdns_create_call_reporting_dict( getdns_dict_destroy(netreq_debug); return NULL; } + if (getdns_dict_set_bindata(netreq_debug, "tls_peer_cert", + &netreq->debug_tls_peer_cert)) { + + getdns_dict_destroy(netreq_debug); + return NULL; + } + netreq->debug_tls_peer_cert.size = 0; + OPENSSL_free(netreq->debug_tls_peer_cert.data); + netreq->debug_tls_peer_cert.data = NULL; return netreq_debug; }