aboutsummaryrefslogtreecommitdiff
path: root/dnscrypt/dnscrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'dnscrypt/dnscrypt.c')
-rw-r--r--dnscrypt/dnscrypt.c76
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);
}