You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@trafficserver.apache.org by James Peach <jp...@apache.org> on 2016/10/18 02:54:11 UTC

Re: [trafficserver] branch master updated: TS-4858: fix memory leak problem of global_default_keyblock

> On Oct 17, 2016, at 3:53 PM, shinrich@apache.org wrote:
> 
> This is an automated email from the ASF dual-hosted git repository.
> 
> shinrich pushed a commit to branch master
> in repository https://git-dual.apache.org/repos/asf/trafficserver.git
> 
> The following commit(s) were added to refs/heads/master by this push:
>       new  34b5535   TS-4858: fix memory leak problem of global_default_keyblock
> 34b5535 is described below
> 
> commit 34b55356d1cfb38744bb4b4c080fc758e96c6381
> Author: Persia Aziz <pe...@yahoo-inc.com>
> AuthorDate: Tue Sep 20 14:40:28 2016 -0500
> 
>    TS-4858: fix memory leak problem of global_default_keyblock
> ---
> iocore/net/P_SSLCertLookup.h |  4 +--
> iocore/net/P_SSLConfig.h     |  6 +++-
> iocore/net/SSLCertLookup.cc  | 70 ++++++++++++++++++++++++++++++++++++++++
> iocore/net/SSLConfig.cc      | 23 ++++++++++++--
> iocore/net/SSLUtils.cc       | 76 +++-----------------------------------------
> proxy/InkAPI.cc              |  1 -
> 6 files changed, 103 insertions(+), 77 deletions(-)
> 
> diff --git a/iocore/net/P_SSLCertLookup.h b/iocore/net/P_SSLCertLookup.h
> index b408626..97c11ff 100644
> --- a/iocore/net/P_SSLCertLookup.h
> +++ b/iocore/net/P_SSLCertLookup.h
> @@ -40,7 +40,6 @@ struct ssl_ticket_key_block {
>   unsigned num_keys;
>   ssl_ticket_key_t keys[];
> };
> -
> /** A certificate context.
> 
>     This holds data about a certificate and how it is used by the SSL logic. Current this is mainly
> @@ -110,5 +109,6 @@ struct SSLCertLookup : public ConfigInfo {
> 
> void ticket_block_free(void *ptr);
> ssl_ticket_key_block *ticket_block_alloc(unsigned count);
> -
> +ssl_ticket_key_block *ticket_block_create(char *ticket_key_data, int ticket_key_len);
> +ssl_ticket_key_block *ssl_create_ticket_keyblock(const char *ticket_key_path);

As noted in the original review, this should be called ticket_block_read() to be consistent with the other APIs above.

> #endif /* __P_SSLCERTLOOKUP_H__ */
> diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h
> index 35fdff1..6adc2b5 100644
> --- a/iocore/net/P_SSLConfig.h
> +++ b/iocore/net/P_SSLConfig.h
> @@ -34,9 +34,11 @@
> #include "ProxyConfig.h"
> #include "SSLSessionCache.h"
> #include "ts/ink_inet.h"
> +#include <openssl/rand.h>
> +#include "P_SSLCertLookup.h"
> 
> struct SSLCertLookup;
> -
> +struct ssl_ticket_key_block;
> /////////////////////////////////////////////////////////////
> //
> // struct SSLConfigParams
> @@ -67,6 +69,8 @@ struct SSLConfigParams : public ConfigInfo {
>   char *dhparamsFile;
>   char *cipherSuite;
>   char *client_cipherSuite;
> +  char *ticket_key_filename;
> +  ssl_ticket_key_block *default_global_keyblock;
>   int configExitOnLoadError;
>   int clientCertLevel;
>   int verify_depth;
> diff --git a/iocore/net/SSLCertLookup.cc b/iocore/net/SSLCertLookup.cc
> index b9d7381..972071d 100644
> --- a/iocore/net/SSLCertLookup.cc
> +++ b/iocore/net/SSLCertLookup.cc
> @@ -28,10 +28,18 @@
> #include "P_SSLConfig.h"
> #include "I_EventSystem.h"
> #include "ts/I_Layout.h"
> +#include "ts/MatcherUtils.h"
> #include "ts/Regex.h"
> #include "ts/Trie.h"
> #include "ts/TestBox.h"
> 
> +// Check if the ticket_key callback #define is available, and if so, enable session tickets.
> +#ifdef SSL_CTX_set_tlsext_ticket_key_cb
> +
> +#define HAVE_OPENSSL_SESSION_TICKETS 1
> +
> +#endif /* SSL_CTX_set_tlsext_ticket_key_cb */
> +
> struct SSLAddressLookupKey {
>   explicit SSLAddressLookupKey(const IpEndpoint &ip) : sep(0)
>   {
> @@ -160,7 +168,69 @@ ticket_block_alloc(unsigned count)
> 
>   return ptr;
> }
> +ssl_ticket_key_block *
> +ticket_block_create(char *ticket_key_data, int ticket_key_len)
> +{
> +  ssl_ticket_key_block *keyblock = NULL;
> +  unsigned num_ticket_keys       = ticket_key_len / sizeof(ssl_ticket_key_t);
> +  if (num_ticket_keys == 0) {
> +    Error("SSL session ticket key is too short (>= 48 bytes are required)");
> +    goto fail;
> +  }
> +
> +  keyblock = ticket_block_alloc(num_ticket_keys);
> 
> +  // Slurp all the keys in the ticket key file. We will encrypt with the first key, and decrypt
> +  // with any key (for rotation purposes).
> +  for (unsigned i = 0; i < num_ticket_keys; ++i) {
> +    const char *data = (const char *)ticket_key_data + (i * sizeof(ssl_ticket_key_t));
> +
> +    memcpy(keyblock->keys[i].key_name, data, sizeof(keyblock->keys[i].key_name));
> +    memcpy(keyblock->keys[i].hmac_secret, data + sizeof(keyblock->keys[i].key_name), sizeof(keyblock->keys[i].hmac_secret));
> +    memcpy(keyblock->keys[i].aes_key, data + sizeof(keyblock->keys[i].key_name) + sizeof(keyblock->keys[i].hmac_secret),
> +           sizeof(keyblock->keys[i].aes_key));
> +  }
> +
> +  return keyblock;
> +
> +fail:
> +  ticket_block_free(keyblock);
> +  return NULL;
> +}
> +
> +ssl_ticket_key_block *
> +ssl_create_ticket_keyblock(const char *ticket_key_path)
> +{
> +#if HAVE_OPENSSL_SESSION_TICKETS
> +  ats_scoped_str ticket_key_data;
> +  int ticket_key_len;
> +  ssl_ticket_key_block *keyblock = NULL;
> +
> +  if (ticket_key_path != NULL) {
> +    ticket_key_data = readIntoBuffer(ticket_key_path, __func__, &ticket_key_len);
> +    if (!ticket_key_data) {
> +      Error("failed to read SSL session ticket key from %s", (const char *)ticket_key_path);
> +      goto fail;
> +    }
> +    keyblock = ticket_block_create(ticket_key_data, ticket_key_len);
> +  } else {
> +    // Generate a random ticket key
> +    ssl_ticket_key_t key;
> +    RAND_bytes(reinterpret_cast<unsigned char *>(&key), sizeof(key));
> +    keyblock = ticket_block_create(reinterpret_cast<char *>(&key), sizeof(key));
> +  }
> +
> +  return keyblock;
> +
> +fail:
> +  ticket_block_free(keyblock);
> +  return NULL;
> +
> +#else  /* !HAVE_OPENSSL_SESSION_TICKETS */
> +  (void)ticket_key_path;
> +  return NULL;
> +#endif /* HAVE_OPENSSL_SESSION_TICKETS */
> +}

Please leave a newline between functions.

> void
> SSLCertContext::release()
> {
> diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc
> index 13b6921..f52a1b0 100644
> --- a/iocore/net/SSLConfig.cc
> +++ b/iocore/net/SSLConfig.cc
> @@ -64,12 +64,19 @@ char *SSLConfigParams::ssl_wire_trace_server_name = NULL;
> 
> static ConfigUpdateHandler<SSLCertificateConfig> *sslCertUpdate;
> 
> +// Check if the ticket_key callback #define is available, and if so, enable session tickets.
> +#ifdef SSL_CTX_set_tlsext_ticket_key_cb
> +
> +#define HAVE_OPENSSL_SESSION_TICKETS 1
> +
> +#endif /* SSL_CTX_set_tlsext_ticket_key_cb */
> +
> SSLConfigParams::SSLConfigParams()
> {
>   serverCertPathOnly = serverCertChainFilename = configFilePath = serverCACertFilename = serverCACertPath = clientCertPath =
>     clientKeyPath = clientCACertFilename = clientCACertPath = cipherSuite = client_cipherSuite = dhparamsFile = serverKeyPathOnly =
> -      NULL;
> -
> +      ticket_key_filename                                                                                     = NULL;
> +  default_global_keyblock                                                                                     = NULL;
>   clientCertLevel = client_verify_depth = verify_depth = clientVerify = 0;
> 
>   ssl_ctx_options               = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
> @@ -105,6 +112,8 @@ SSLConfigParams::cleanup()
>   ats_free_null(client_cipherSuite);
>   ats_free_null(dhparamsFile);
>   ats_free_null(ssl_wire_trace_ip);
> +  ats_free_null(ticket_key_filename);
> +  ticket_block_free(default_global_keyblock);
> 
>   clientCertLevel = client_verify_depth = verify_depth = clientVerify = 0;
> }
> @@ -243,6 +252,16 @@ SSLConfigParams::initialize()
>   ats_free(ssl_server_ca_cert_filename);
>   ats_free(CACertRelativePath);
> 
> +#if HAVE_OPENSSL_SESSION_TICKETS
> +  REC_ReadConfigStringAlloc(ticket_key_filename, "proxy.config.ssl.server.ticket_key.filename");
> +  if (this->ticket_key_filename != NULL) {
> +    ats_scoped_str ticket_key_path(Layout::relative_to(this->serverCertPathOnly, this->ticket_key_filename));
> +    default_global_keyblock = ssl_create_ticket_keyblock(ticket_key_path);
> +  } else {
> +    default_global_keyblock = ssl_create_ticket_keyblock(NULL);
> +  }
> +#endif
> +
>   // SSL session cache configurations
>   REC_ReadConfigInteger(ssl_session_cache, "proxy.config.ssl.session_cache");
>   REC_ReadConfigInteger(ssl_session_cache_size, "proxy.config.ssl.session_cache.size");
> diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
> index ef44181..ce96222 100644
> --- a/iocore/net/SSLUtils.cc
> +++ b/iocore/net/SSLUtils.cc
> @@ -133,8 +133,7 @@ static int ssl_callback_session_ticket(SSL *, unsigned char *, unsigned char *,
> #endif /* SSL_CTX_set_tlsext_ticket_key_cb */
> 
> #if HAVE_OPENSSL_SESSION_TICKETS
> -static int ssl_session_ticket_index                  = -1;
> -static ssl_ticket_key_block *global_default_keyblock = NULL;
> +static int ssl_session_ticket_index = -1;
> #endif
> 
> static int ssl_vc_index = -1;
> @@ -562,70 +561,15 @@ ssl_context_enable_ecdh(SSL_CTX *ctx)
> }
> 
> static ssl_ticket_key_block *
> -ssl_create_ticket_keyblock(const char *ticket_key_path)
> +ssl_context_enable_tickets(SSL_CTX *ctx, const char *ticket_key_path)
> {
> #if HAVE_OPENSSL_SESSION_TICKETS
> -  ats_scoped_str ticket_key_data;
> -  int ticket_key_len;
> -  unsigned num_ticket_keys;
>   ssl_ticket_key_block *keyblock = NULL;
> -
> -  if (ticket_key_path != NULL) {
> -    ticket_key_data = readIntoBuffer(ticket_key_path, __func__, &ticket_key_len);
> -    if (!ticket_key_data) {
> -      Error("failed to read SSL session ticket key from %s", (const char *)ticket_key_path);
> -      goto fail;
> -    }
> -  } else {
> -    // Generate a random ticket key
> -    ticket_key_len  = 48;
> -    ticket_key_data = (char *)ats_malloc(ticket_key_len);
> -    char *tmp_ptr   = ticket_key_data;
> -    RAND_bytes(reinterpret_cast<unsigned char *>(tmp_ptr), ticket_key_len);
> -  }
> -
> -  num_ticket_keys = ticket_key_len / sizeof(ssl_ticket_key_t);
> -  if (num_ticket_keys == 0) {
> -    Error("SSL session ticket key from %s is too short (>= 48 bytes are required)", (const char *)ticket_key_path);
> -    goto fail;
> -  }
> -
> +  keyblock                       = ssl_create_ticket_keyblock(ticket_key_path);
>   // Increase the stats.
>   if (ssl_rsb != NULL) { // ssl_rsb is not initialized during the first run.
>     SSL_INCREMENT_DYN_STAT(ssl_total_ticket_keys_renewed_stat);
>   }
> -
> -  keyblock = ticket_block_alloc(num_ticket_keys);
> -
> -  // Slurp all the keys in the ticket key file. We will encrypt with the first key, and decrypt
> -  // with any key (for rotation purposes).
> -  for (unsigned i = 0; i < num_ticket_keys; ++i) {
> -    const char *data = (const char *)ticket_key_data + (i * sizeof(ssl_ticket_key_t));
> -
> -    memcpy(keyblock->keys[i].key_name, data, sizeof(keyblock->keys[i].key_name));
> -    memcpy(keyblock->keys[i].hmac_secret, data + sizeof(keyblock->keys[i].key_name), sizeof(keyblock->keys[i].hmac_secret));
> -    memcpy(keyblock->keys[i].aes_key, data + sizeof(keyblock->keys[i].key_name) + sizeof(keyblock->keys[i].hmac_secret),
> -           sizeof(keyblock->keys[i].aes_key));
> -  }
> -
> -  return keyblock;
> -
> -fail:
> -  ticket_block_free(keyblock);
> -  return NULL;
> -
> -#else  /* !HAVE_OPENSSL_SESSION_TICKETS */
> -  (void)ticket_key_path;
> -  return NULL;
> -#endif /* HAVE_OPENSSL_SESSION_TICKETS */
> -}
> -
> -static ssl_ticket_key_block *
> -ssl_context_enable_tickets(SSL_CTX *ctx, const char *ticket_key_path)
> -{
> -#if HAVE_OPENSSL_SESSION_TICKETS
> -  ssl_ticket_key_block *keyblock = NULL;
> -  keyblock                       = ssl_create_ticket_keyblock(ticket_key_path);
>   // Setting the callback can only fail if OpenSSL does not recognize the
>   // SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB constant. we set the callback first
>   // so that we don't leave a ticket_key pointer attached if it fails.
> @@ -2054,22 +1998,11 @@ SSLParseCertificateConfiguration(const SSLConfigParams *params, SSLCertLookup *l
>   char *tok_state = NULL;
>   char *line      = NULL;
>   ats_scoped_str file_buf;
> -  ats_scoped_str ticket_key_filename;
>   unsigned line_num = 0;
>   matcher_line line_info;
> 
>   const matcher_tags sslCertTags = {NULL, NULL, NULL, NULL, NULL, NULL, false};
> 
> -  // Load the global ticket key for later use.
> -  REC_ReadConfigStringAlloc(ticket_key_filename, "proxy.config.ssl.server.ticket_key.filename");
> -
> -  if (ticket_key_filename != NULL) {
> -    ats_scoped_str ticket_key_path(Layout::relative_to(params->serverCertPathOnly, ticket_key_filename));
> -    global_default_keyblock = ssl_create_ticket_keyblock(ticket_key_path);
> -  } else {
> -    global_default_keyblock = ssl_create_ticket_keyblock(NULL);
> -  }
> -
>   Note("loading SSL certificate configuration from %s", params->configFilePath);
> 
>   if (params->configFilePath) {
> @@ -2153,6 +2086,7 @@ ssl_callback_session_ticket(SSL *ssl, unsigned char *keyname, unsigned char *iv,
>                             int enc)
> {
>   SSLCertificateConfig::scoped_config lookup;
> +  SSLConfig::scoped_config params;
>   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
> 
>   // Get the IP address to look up the keyblock
> @@ -2163,7 +2097,7 @@ ssl_callback_session_ticket(SSL *ssl, unsigned char *keyname, unsigned char *iv,
>   ssl_ticket_key_block *keyblock = NULL;
>   if (cc == NULL || cc->keyblock == NULL) {
>     // Try the default
> -    keyblock = global_default_keyblock;
> +    keyblock = params->default_global_keyblock;
>   } else {
>     keyblock = cc->keyblock;
>   }
> diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
> index 52f8c00..2c92c42 100644
> --- a/proxy/InkAPI.cc
> +++ b/proxy/InkAPI.cc
> @@ -5440,7 +5440,6 @@ TSHttpSsnIncomingAddrGet(TSHttpSsn ssnp)
>   if (vc == NULL) {
>     return 0;
>   }
> -
>   return vc->get_local_addr();
> }
> sockaddr const *
> 
> -- 
> To stop receiving notification emails like this one, please contact
> ['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].