diff options
Diffstat (limited to 'dnscrypt/dnscrypt.c')
-rw-r--r-- | dnscrypt/dnscrypt.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c index a0db12077093..3545d3d9b43f 100644 --- a/dnscrypt/dnscrypt.c +++ b/dnscrypt/dnscrypt.c @@ -5,6 +5,7 @@ #ifdef HAVE_TIME_H #include <time.h> #endif +#include <inttypes.h> #include <sys/time.h> #include <sys/types.h> #include "sldns/sbuffer.h" @@ -588,18 +589,26 @@ dnsc_chroot_path(struct config_file *cfg, char *path) static int dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg) { - struct config_strlist *head; + struct config_strlist *head, *head2; size_t signed_cert_id; + size_t rotated_cert_id; char *nm; env->signed_certs_count = 0U; + env->rotated_certs_count = 0U; for (head = cfg->dnscrypt_provider_cert; head; head = head->next) { env->signed_certs_count++; } + for (head = cfg->dnscrypt_provider_cert_rotated; head; head = head->next) { + env->rotated_certs_count++; + } env->signed_certs = sodium_allocarray(env->signed_certs_count, sizeof *env->signed_certs); + env->rotated_certs = sodium_allocarray(env->rotated_certs_count, + sizeof env->signed_certs); signed_cert_id = 0U; + rotated_cert_id = 0U; for(head = cfg->dnscrypt_provider_cert; head; head = head->next, signed_cert_id++) { nm = dnsc_chroot_path(cfg, head->str); if(dnsc_read_from_file( @@ -608,6 +617,14 @@ dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg) sizeof(struct SignedCert)) != 0) { fatal_exit("dnsc_parse_certs: failed to load %s: %s", head->str, strerror(errno)); } + for(head2 = cfg->dnscrypt_provider_cert_rotated; head2; head2 = head2->next) { + if(strcmp(head->str, head2->str) == 0) { + *(env->rotated_certs + rotated_cert_id) = env->signed_certs + signed_cert_id; + rotated_cert_id++; + verbose(VERB_OPS, "Cert %s is rotated and will not be distributed via DNS", head->str); + break; + } + } verbose(VERB_OPS, "Loaded cert %s", head->str); } return signed_cert_id; @@ -692,27 +709,54 @@ dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg) // 2.dnscrypt-cert.example.com 86400 IN TXT "DNSC......" for(i=0; i<dnscenv->signed_certs_count; i++) { const char *ttl_class_type = " 86400 IN TXT \""; + int rotated_cert = 0; + uint32_t serial; + uint16_t rrlen; + char* rr; struct SignedCert *cert = dnscenv->signed_certs + i; - uint16_t rrlen = strlen(dnscenv->provider_name) + + // Check if the certificate is being rotated and should not be published + for(j=0; j<dnscenv->rotated_certs_count; j++){ + if(cert == dnscenv->rotated_certs[j]) { + rotated_cert = 1; + break; + } + } + memcpy(&serial, cert->serial, sizeof serial); + serial = htonl(serial); + if(rotated_cert) { + verbose(VERB_OPS, + "DNSCrypt: not adding cert with serial #%" + PRIu32 + " to local-data as it is rotated", + serial + ); + continue; + } + rrlen = strlen(dnscenv->provider_name) + strlen(ttl_class_type) + 4 * sizeof(struct SignedCert) + // worst case scenario 1 + // trailing double quote 1; - char *rr = malloc(rrlen); + rr = malloc(rrlen); if(!rr) { log_err("Could not allocate memory"); return -2; } snprintf(rr, rrlen - 1, "%s 86400 IN TXT \"", dnscenv->provider_name); for(j=0; j<sizeof(struct SignedCert); j++) { - int c = (int)*((const uint8_t *) cert + j); + int c = (int)*((const uint8_t *) cert + j); if (isprint(c) && c != '"' && c != '\\') { snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "%c", c); } else { snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\\%03d", c); } } - verbose(VERB_OPS, "DNSCrypt: adding local data to config: %s", rr); + verbose(VERB_OPS, + "DNSCrypt: adding cert with serial #%" + PRIu32 + " to local-data to config: %s", + serial, rr + ); snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\""); cfg_strlist_insert(&cfg->local_data, strdup(rr)); free(rr); @@ -826,6 +870,16 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg) return cert_id; } +static void +sodium_misuse_handler(void) +{ + fatal_exit( + "dnscrypt: libsodium could not be initialized, this typically" + " happens when no good source of entropy is found. If you run" + " unbound in a chroot, make sure /dev/random is available. See" + " https://www.unbound.net/documentation/unbound.conf.html"); +} + /** * ######################################################### @@ -889,6 +943,9 @@ struct dnsc_env * dnsc_create(void) { struct dnsc_env *env; +#ifdef SODIUM_MISUSE_HANDLER + sodium_set_misuse_handler(sodium_misuse_handler); +#endif if (sodium_init() == -1) { fatal_exit("dnsc_create: could not initialize libsodium."); } @@ -923,6 +980,7 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg) if(dnsc_load_local_data(env, cfg) <= 0) { fatal_exit("dnsc_apply_cfg: could not load local data"); } + lock_basic_lock(&env->shared_secrets_cache_lock); env->shared_secrets_cache = slabhash_create( cfg->dnscrypt_shared_secret_cache_slabs, HASH_DEFAULT_STARTARRAY, @@ -933,9 +991,11 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg) dnsc_shared_secrets_deldatafunc, NULL ); + lock_basic_unlock(&env->shared_secrets_cache_lock); if(!env->shared_secrets_cache){ fatal_exit("dnsc_apply_cfg: could not create shared secrets cache."); } + lock_basic_lock(&env->nonces_cache_lock); env->nonces_cache = slabhash_create( cfg->dnscrypt_nonce_cache_slabs, HASH_DEFAULT_STARTARRAY, @@ -946,6 +1006,7 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg) dnsc_nonces_deldatafunc, NULL ); + lock_basic_unlock(&env->nonces_cache_lock); return 0; } @@ -957,12 +1018,13 @@ dnsc_delete(struct dnsc_env *env) } verbose(VERB_OPS, "DNSCrypt: Freeing environment."); sodium_free(env->signed_certs); + sodium_free(env->rotated_certs); sodium_free(env->certs); sodium_free(env->keypairs); - slabhash_delete(env->shared_secrets_cache); - slabhash_delete(env->nonces_cache); lock_basic_destroy(&env->shared_secrets_cache_lock); lock_basic_destroy(&env->nonces_cache_lock); + slabhash_delete(env->shared_secrets_cache); + slabhash_delete(env->nonces_cache); free(env); } |