diff options
Diffstat (limited to 'util/net_help.c')
| -rw-r--r-- | util/net_help.c | 168 |
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; +} |
