summaryrefslogtreecommitdiff
path: root/util/net_help.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/net_help.c')
-rw-r--r--util/net_help.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/util/net_help.c b/util/net_help.c
index 91368c847597..1a4fa8a58e6f 100644
--- a/util/net_help.c
+++ b/util/net_help.c
@@ -43,11 +43,14 @@
#include "util/data/dname.h"
#include "util/module.h"
#include "util/regional.h"
+#include "util/config_file.h"
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"
#include <fcntl.h>
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
#endif
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
@@ -67,6 +70,15 @@ int MINIMAL_RESPONSES = 0;
/** rrset order roundrobin: default is no */
int RRSET_ROUNDROBIN = 0;
+/** log tag queries with name instead of 'info' for filtering */
+int LOG_TAG_QUERYREPLY = 0;
+
+static struct tls_session_ticket_key {
+ unsigned char *key_name;
+ unsigned char *aes_key;
+ unsigned char *hmac_key;
+} *ticket_keys;
+
/* returns true is string addr is an ip6 specced address */
int
str_is_ip6(const char* str)
@@ -361,6 +373,37 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
log_info("%s %s %s %s", str, buf, ts, cs);
}
+void
+log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
+{
+ char buf[LDNS_MAX_DOMAINLEN+1];
+ char t[12], c[12];
+ const char *ts, *cs;
+ dname_str(name, buf);
+ if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
+ else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
+ else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
+ else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
+ else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
+ else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
+ else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
+ ts = sldns_rr_descript(type)->_name;
+ else {
+ snprintf(t, sizeof(t), "TYPE%d", (int)type);
+ ts = t;
+ }
+ if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
+ sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
+ cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
+ else {
+ snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
+ cs = c;
+ }
+ if(LOG_TAG_QUERYREPLY)
+ log_query("%s %s %s %s", str, buf, ts, cs);
+ else log_info("%s %s %s %s", str, buf, ts, cs);
+}
+
void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
struct sockaddr_storage* addr, socklen_t addrlen)
{
@@ -1056,3 +1099,128 @@ void ub_openssl_lock_delete(void)
#endif /* OPENSSL_THREADS */
}
+int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys) {
+#ifdef HAVE_SSL
+ size_t s = 1;
+ struct config_strlist* p;
+ struct tls_session_ticket_key *keys;
+ for(p = tls_session_ticket_keys; p; p = p->next) {
+ s++;
+ }
+ keys = calloc(s, sizeof(struct tls_session_ticket_key));
+ memset(keys, 0, s*sizeof(*keys));
+ ticket_keys = keys;
+
+ for(p = tls_session_ticket_keys; p; p = p->next) {
+ size_t n;
+ unsigned char *data = (unsigned char *)malloc(80);
+ FILE *f = fopen(p->str, "r");
+ if(!f) {
+ log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
+ free(data);
+ return 0;
+ }
+ n = fread(data, 1, 80, f);
+ fclose(f);
+
+ if(n != 80) {
+ log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
+ free(data);
+ return 0;
+ }
+ verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
+
+ keys->key_name = data;
+ keys->aes_key = data + 16;
+ keys->hmac_key = data + 48;
+ keys++;
+ }
+ /* terminate array with NULL key name entry */
+ keys->key_name = NULL;
+ if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
+ log_err("no support for TLS session ticket");
+ return 0;
+ }
+ return 1;
+#else
+ (void)sslctx;
+ (void)tls_session_ticket_keys;
+ return 0;
+#endif
+
+}
+
+int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name, unsigned char* iv, void *evp_sctx, void *hmac_ctx, int enc)
+{
+#ifdef HAVE_SSL
+ const EVP_MD *digest;
+ const EVP_CIPHER *cipher;
+ int evp_cipher_length;
+ digest = EVP_sha256();
+ cipher = EVP_aes_256_cbc();
+ evp_cipher_length = EVP_CIPHER_iv_length(cipher);
+ if( enc == 1 ) {
+ /* encrypt */
+ verbose(VERB_CLIENT, "start session encrypt");
+ memcpy(key_name, ticket_keys->key_name, 16);
+ if (RAND_bytes(iv, evp_cipher_length) != 1) {
+ verbose(VERB_CLIENT, "RAND_bytes failed");
+ return -1;
+ }
+ if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
+ verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
+ return -1;
+ }
+ if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
+ verbose(VERB_CLIENT, "HMAC_Init_ex failed");
+ return -1;
+ }
+ return 1;
+ } else if (enc == 0) {
+ /* decrypt */
+ struct tls_session_ticket_key *key;
+ verbose(VERB_CLIENT, "start session decrypt");
+ for(key = ticket_keys; key->key_name != NULL; key++) {
+ if (!memcmp(key_name, key->key_name, 16)) {
+ verbose(VERB_CLIENT, "Found session_key");
+ break;
+ }
+ }
+ if(key->key_name == NULL) {
+ verbose(VERB_CLIENT, "Not found session_key");
+ return 0;
+ }
+
+ if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
+ verbose(VERB_CLIENT, "HMAC_Init_ex failed");
+ return -1;
+ }
+ if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
+ log_err("EVP_DecryptInit_ex failed");
+ return -1;
+ }
+
+ return (key == ticket_keys) ? 1 : 2;
+ }
+ return -1;
+#else
+ (void)key_name;
+ (void)iv;
+ (void)evp_sctx;
+ (void)hmac_ctx;
+ (void)enc;
+ return 0;
+#endif
+}
+
+void
+listen_sslctx_delete_ticket_keys(void)
+{
+ struct tls_session_ticket_key *key;
+ if(!ticket_keys) return;
+ for(key = ticket_keys; key->key_name != NULL; key++) {
+ free(key->key_name);
+ }
+ free(ticket_keys);
+ ticket_keys = NULL;
+}