More fixes, statistic counter at end of struct for backwards compatibility, man page, free at exit, indent.

git-svn-id: file:///svn/unbound/trunk@5062 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2019-01-23 10:19:04 +00:00
parent ed8b859e31
commit d3f397c686
6 changed files with 72 additions and 39 deletions

View file

@ -749,6 +749,7 @@ daemon_delete(struct daemon* daemon)
free(daemon->pidfile);
free(daemon->env);
#ifdef HAVE_SSL
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
#endif

View file

@ -538,6 +538,10 @@ other servers.
Number of queries that were made using TLS towards the unbound server.
These are also counted in num.query.tcp, because TLS uses TCP.
.TP
.I num.query.tls.resume
Number of TLS session resumptions, these are queries over TLS towards
the unbound server where the client negotiated a TLS session resumption key.
.TP
.I num.query.ipv6
Number of queries that were made using IPv6 towards the unbound server.
.TP

View file

@ -504,6 +504,16 @@ List portnumbers as tls\-additional\-port, and when interfaces are defined,
eg. with the @port suffix, as this port number, they provide dns over TLS
service. Can list multiple, each on a new statement.
.TP
.B tls-session-ticket-keys: \fI<file>
If not "", lists files with 80 bytes of random contents that are used to
perform TLS session resumption for clients using the unbound server.
These files contain the secret key for the TLS session tickets.
First key use to encrypt and decrypt TLS session tickets.
Other keys use to decrypt only. With this you can roll over to new keys,
by generating a new first file and allowing decrypt of the old file by
listing it after the first file for some time, after the wait clients are not
using the old key any more and the old key can be removed.
.TP
.B tls\-ciphers: \fI<string with cipher list>
Set the list of ciphers to allow when serving TLS. Use "" for defaults,
and that is the default.

View file

@ -682,8 +682,6 @@ struct ub_server_stats {
long long qtcp_outgoing;
/** number of queries over (DNS over) TLS */
long long qtls;
/** number of TLS connection resume */
long long qtls_resume;
/** number of queries over IPv6 */
long long qipv6;
/** number of queries with QR bit */
@ -774,6 +772,8 @@ struct ub_server_stats {
long long num_query_subnet_cache;
/** number of bytes in the stream wait buffers */
long long mem_stream_wait;
/** number of TLS connection resume */
long long qtls_resume;
};
/**

View file

@ -74,9 +74,9 @@ int RRSET_ROUNDROBIN = 0;
int LOG_TAG_QUERYREPLY = 0;
static struct tls_session_ticket_key {
unsigned char *key_name;
unsigned char *aes_key;
unsigned char *hmac_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 */
@ -1108,7 +1108,7 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
s++;
}
keys = calloc(s, sizeof(struct tls_session_ticket_key));
memset(keys, 0, sizeof(*keys));
memset(keys, 0, s*sizeof(*keys));
ticket_keys = keys;
for(p = tls_session_ticket_keys; p; p = p->next) {
@ -1133,50 +1133,51 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
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) {
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;
}
return 1;
#else
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)
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_chiper_length;
const EVP_MD *digest;
const EVP_CIPHER *cipher;
int evp_cipher_length;
digest = EVP_sha256();
cipher = EVP_aes_256_cbc();
evp_chiper_length = EVP_CIPHER_iv_length(cipher);
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_chiper_length) != 1) {
if (RAND_bytes(iv, evp_cipher_length) != 1) {
verbose(VERB_CLIENT, "RAND_bytes failed");
return -1;
return -1;
}
if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) {
verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
return -1;
return -1;
}
if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 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) {
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)) {
if (!memcmp(key_name, key->key_name, 16)) {
verbose(VERB_CLIENT, "Found session_key");
break;
}
@ -1186,20 +1187,31 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
return 0;
}
if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
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) {
return -1;
}
if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) {
log_err("EVP_DecryptInit_ex failed");
return -1;
}
return -1;
}
return (key == ticket_keys) ? 1 : 2;
}
return -1;
return -1;
#else
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;
}

View file

@ -444,18 +444,24 @@ void ub_openssl_lock_delete(void);
* @param tls_session_ticket_keys: TLS ticket secret filenames
* @return false on failure (alloc failure).
*/
int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_session_ticket_keys);
int listen_sslctx_setup_ticket_keys(void* sslctx,
struct config_strlist* tls_session_ticket_keys);
/**
* callback TLS session ticket encrypt and decrypt
* For use with SSL_CTX_set_tlsext_ticket_key_cb
* @param s: the SSL_CTX to use (from connect_sslctx_create())
* @param key_name: secret name
* @param iv:
* @param evp_ctx:
* @param hmac_ctx:
* @param key_name: secret name, 16 bytes
* @param iv: up to EVP_MAX_IV_LENGTH.
* @param evp_ctx: the evp cipher context, function sets this.
* @param hmac_ctx: the hmax context, function sets this.
* @param enc: 1 is encrypt, 0 is decrypt
* @return false on failure (alloc failure).
* @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
* (the ticket is decrypt only). and <0 for failures.
*/
int tls_session_ticket_key_cb(void *s, unsigned char* key_name,unsigned char* iv, void *evp_ctx, void *hmac_ctx, int enc);
/** Free memory used for TLS session ticket keys */
void listen_sslctx_delete_ticket_keys(void);
#endif /* NET_HELP_H */