static void cert_query_cb(void *arg, int status, int timeouts, unsigned char *abuf, int alen) { Bincert *bincert = NULL; ProxyContext *proxy_context = arg; struct ares_txt_reply *txt_out; struct ares_txt_reply *txt_out_current; (void) timeouts; DNSCRYPT_PROXY_CERTS_UPDATE_RECEIVED(); if (status != ARES_SUCCESS || ares_parse_txt_reply(abuf, alen, &txt_out) != ARES_SUCCESS) { logger_noformat(proxy_context, LOG_ERR, "Unable to retrieve server certificates"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION(); return; } txt_out_current = txt_out; while (txt_out_current != NULL) { cert_open_bincert(proxy_context, (const SignedBincert *) txt_out_current->txt, txt_out_current->length, &bincert); txt_out_current = txt_out_current->next; } ares_free_data(txt_out); if (bincert == NULL) { logger_noformat(proxy_context, LOG_ERR, "No useable certificates found"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_NOCERTS(); return; } COMPILER_ASSERT(sizeof proxy_context->resolver_publickey == sizeof bincert->server_publickey); memcpy(proxy_context->resolver_publickey, bincert->server_publickey, sizeof proxy_context->resolver_publickey); COMPILER_ASSERT(sizeof proxy_context->dnscrypt_magic_query == sizeof bincert->magic_query); memcpy(proxy_context->dnscrypt_magic_query, bincert->magic_query, sizeof proxy_context->dnscrypt_magic_query); cert_print_server_key(proxy_context); dnscrypt_client_init_magic_query(&proxy_context->dnscrypt_client, bincert->magic_query); memset(bincert, 0, sizeof *bincert); free(bincert); dnscrypt_client_init_nmkey(&proxy_context->dnscrypt_client, proxy_context->resolver_publickey); dnscrypt_proxy_start_listeners(proxy_context); proxy_context->cert_updater.query_retry_step = 0U; cert_reschedule_query_after_success(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_DONE((unsigned char *) proxy_context->resolver_publickey); }
static void cert_query_cb(int result, char type, int count, int ttl, void * const txt_records_, void * const arg) { Bincert *bincert = NULL; ProxyContext *proxy_context = arg; const struct txt_record *txt_records = txt_records_; int i = 0; (void) type; (void) ttl; DNSCRYPT_PROXY_CERTS_UPDATE_RECEIVED(); evdns_base_free(proxy_context->cert_updater.evdns_base, 0); proxy_context->cert_updater.evdns_base = NULL; if (result != DNS_ERR_NONE) { logger_noformat(proxy_context, LOG_ERR, "Unable to retrieve server certificates"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION(); return; } assert(count >= 0); while (i < count) { cert_open_bincert(proxy_context, (const SignedBincert *) txt_records[i].txt, txt_records[i].len, &bincert); i++; } if (bincert == NULL) { logger_noformat(proxy_context, LOG_ERR, "No useable certificates found"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_NOCERTS(); if (proxy_context->test_only) { exit(DNSCRYPT_EXIT_CERT_NOCERTS); } return; } if (proxy_context->test_only != 0) { const uint32_t now_u32 = (uint32_t) time(NULL); uint32_t ts_end; memcpy(&ts_end, bincert->ts_end, sizeof ts_end); ts_end = htonl(ts_end); if (ts_end < (uint32_t) proxy_context->test_cert_margin || now_u32 > ts_end - (uint32_t) proxy_context->test_cert_margin) { logger_noformat(proxy_context, LOG_WARNING, "The certificate is not valid for the given safety margin"); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_NOCERTS(); exit(DNSCRYPT_EXIT_CERT_MARGIN); } } COMPILER_ASSERT(sizeof proxy_context->resolver_publickey == sizeof bincert->server_publickey); memcpy(proxy_context->resolver_publickey, bincert->server_publickey, sizeof proxy_context->resolver_publickey); COMPILER_ASSERT(sizeof proxy_context->dnscrypt_magic_query == sizeof bincert->magic_query); memcpy(proxy_context->dnscrypt_magic_query, bincert->magic_query, sizeof proxy_context->dnscrypt_magic_query); cert_print_bincert_info(proxy_context, bincert); cert_print_server_key(proxy_context); dnscrypt_client_init_magic_query(&proxy_context->dnscrypt_client, bincert->magic_query); memset(bincert, 0, sizeof *bincert); free(bincert); if (proxy_context->test_only) { DNSCRYPT_PROXY_CERTS_UPDATE_DONE((unsigned char *) proxy_context->resolver_publickey); exit(0); } dnscrypt_client_init_nmkey(&proxy_context->dnscrypt_client, proxy_context->resolver_publickey); dnscrypt_proxy_start_listeners(proxy_context); proxy_context->cert_updater.query_retry_step = 0U; cert_reschedule_query_after_success(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_DONE((unsigned char *) proxy_context->resolver_publickey); }