Changeset a335d729973892ef579ddf315445c22f17037ef4

Show
Ignore:
Timestamp:
05/17/11 04:30:53 (8 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1305606653 -0400
git-parent:

[f0c199b52ceaa27bd6d903d16f0729ddb5541867]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1305606653 -0400
Message:

caching of SSL_CTXs we create. The creation (particularly ingestion of a full CA chain) can be quite expensive

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/eventer/eventer_SSL_fd_opset.c

    r7bfafa3 ra335d72  
    4646#define EVENTER_SSL_DATANAME "eventer_ssl" 
    4747 
     48#define SSL_CTX_KEYLEN (PATH_MAX * 4 + 5) 
     49typedef struct { 
     50  char *key; 
     51  SSL_CTX *internal_ssl_ctx; 
     52  time_t creation_time; 
     53  noit_atomic32_t refcnt; 
     54} ssl_ctx_cache_node; 
     55 
     56static noit_hash_table ssl_ctx_cache; 
     57static pthread_mutex_t ssl_ctx_cache_lock; 
     58static int ssl_ctx_cache_expiry = 3600; 
     59 
    4860struct eventer_ssl_ctx_t { 
    49   SSL_CTX *ssl_ctx
     61  ssl_ctx_cache_node *ssl_ctx_cn
    5062  SSL     *ssl; 
    5163  char    *issuer; 
     
    5971  unsigned renegotiated:1; 
    6072}; 
     73 
     74#define ssl_ctx ssl_ctx_cn->internal_ssl_ctx 
    6175 
    6276/* Static function prototypes */ 
     
    232246 * Helpers to create and destroy our context. 
    233247 */ 
     248static void 
     249ssl_ctx_cache_node_free(ssl_ctx_cache_node *node) { 
     250  if(!node) return; 
     251  if(noit_atomic_dec32(&node->refcnt) == 0) { 
     252    SSL_CTX_free(node->internal_ssl_ctx); 
     253    free(node->key); 
     254    free(node); 
     255  } 
     256} 
     257 
    234258void 
    235259eventer_ssl_ctx_free(eventer_ssl_ctx_t *ctx) { 
    236260  if(ctx->ssl) SSL_free(ctx->ssl); 
    237   if(ctx->ssl_ctx) SSL_CTX_free(ctx->ssl_ctx); 
     261  if(ctx->ssl_ctx_cn) ssl_ctx_cache_node_free(ctx->ssl_ctx_cn); 
    238262  if(ctx->issuer) free(ctx->issuer); 
    239263  if(ctx->subject) free(ctx->subject); 
     
    257281} 
    258282 
     283static void 
     284ssl_ctx_key_write(char *b, int blen, eventer_ssl_orientation_t type, 
     285                  const char *certificate, const char *key, 
     286                  const char *ca, const char *ciphers) { 
     287  snprintf(b, blen, "%c:%s:%s:%s:%s", 
     288           (type == SSL_SERVER) ? 'S' : 'C', 
     289           certificate ? certificate : "", key ? key : "", 
     290           ca ? ca : "", ciphers ? ciphers : ""); 
     291} 
     292 
     293static void 
     294ssl_ctx_cache_remove(const char *key) { 
     295  pthread_mutex_lock(&ssl_ctx_cache_lock); 
     296  noit_hash_delete(&ssl_ctx_cache, key, strlen(key), 
     297                   NULL, (void (*)(void *))ssl_ctx_cache_node_free); 
     298  pthread_mutex_unlock(&ssl_ctx_cache_lock); 
     299} 
     300 
     301static ssl_ctx_cache_node * 
     302ssl_ctx_cache_get(const char *key) { 
     303  void *vnode; 
     304  ssl_ctx_cache_node *node = NULL; 
     305  pthread_mutex_lock(&ssl_ctx_cache_lock); 
     306  if(noit_hash_retrieve(&ssl_ctx_cache, key, strlen(key), &vnode)) { 
     307    node = vnode; 
     308    noit_atomic_inc32(&node->refcnt); 
     309  } 
     310  pthread_mutex_unlock(&ssl_ctx_cache_lock); 
     311  return node; 
     312} 
     313 
     314static ssl_ctx_cache_node * 
     315ssl_ctx_cache_set(ssl_ctx_cache_node *node) { 
     316  void *vnode; 
     317  pthread_mutex_lock(&ssl_ctx_cache_lock); 
     318  if(noit_hash_retrieve(&ssl_ctx_cache, node->key, strlen(node->key), 
     319                        &vnode)) { 
     320    ssl_ctx_cache_node_free(node); 
     321    node = vnode; 
     322  } 
     323  else { 
     324    noit_hash_store(&ssl_ctx_cache, node->key, strlen(node->key), node); 
     325  } 
     326  noit_atomic_inc32(&node->refcnt); 
     327  pthread_mutex_unlock(&ssl_ctx_cache_lock); 
     328  return node; 
     329} 
     330 
    259331eventer_ssl_ctx_t * 
    260332eventer_ssl_ctx_new(eventer_ssl_orientation_t type, 
    261333                    const char *certificate, const char *key, 
    262334                    const char *ca, const char *ciphers) { 
     335  char ssl_ctx_key[SSL_CTX_KEYLEN]; 
    263336  eventer_ssl_ctx_t *ctx; 
     337  time_t now; 
    264338  ctx = calloc(1, sizeof(*ctx)); 
    265339  if(!ctx) return NULL; 
    266   /* 
    267    * First step is to setup the SSL context.  This is long-lived in SSL-land 
    268    * however, that would require us caching it.  Maybe we'll do that? 
    269    */ 
    270   ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? 
    271                              SSLv23_server_method() : SSLv23_client_method()); 
    272   if(!ctx->ssl_ctx) return NULL; 
    273   if (type == SSL_SERVER) 
    274     SSL_CTX_set_session_id_context(ctx->ssl_ctx, 
    275             (unsigned char *)EVENTER_SSL_DATANAME, 
    276             sizeof(EVENTER_SSL_DATANAME)-1); 
    277   SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_ALL); 
    278   if(certificate && 
    279      SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1) 
    280     goto bail; 
    281   if(key && 
    282      SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key, 
    283                                     SSL_FILETYPE_PEM) != 1) 
    284     goto bail; 
    285   if(ca) { 
    286     STACK_OF(X509_NAME) *cert_stack; 
    287     if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) || 
    288        (cert_stack = SSL_load_client_CA_file(ca)) == NULL) 
     340 
     341  now = time(NULL); 
     342  ssl_ctx_key_write(ssl_ctx_key, sizeof(ssl_ctx_key), 
     343                    type, certificate, key, ca, ciphers); 
     344  ctx->ssl_ctx_cn = ssl_ctx_cache_get(ssl_ctx_key); 
     345  if(ctx->ssl_ctx_cn) { 
     346    if(now - ctx->ssl_ctx_cn->creation_time > ssl_ctx_cache_expiry) { 
     347      noit_atomic_dec32(&ctx->ssl_ctx_cn->refcnt); 
     348      ssl_ctx_cache_remove(ssl_ctx_key); 
     349      ctx->ssl_ctx_cn = NULL; 
     350    } 
     351  } 
     352 
     353  if(!ctx->ssl_ctx_cn) { 
     354    ctx->ssl_ctx_cn = calloc(1, sizeof(*ctx->ssl_ctx_cn)); 
     355    ctx->ssl_ctx_cn->key = strdup(ssl_ctx_key); 
     356    ctx->ssl_ctx_cn->refcnt = 1; 
     357    ctx->ssl_ctx_cn->creation_time = now; 
     358    ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ? 
     359                               SSLv23_server_method() : SSLv23_client_method()); 
     360    if(!ctx->ssl_ctx) return NULL; 
     361    if (type == SSL_SERVER) 
     362      SSL_CTX_set_session_id_context(ctx->ssl_ctx, 
     363              (unsigned char *)EVENTER_SSL_DATANAME, 
     364              sizeof(EVENTER_SSL_DATANAME)-1); 
     365    SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_ALL); 
     366    if(certificate && 
     367       SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1) 
    289368      goto bail; 
    290     SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack); 
    291   } 
    292   SSL_CTX_set_tmp_rsa_callback(ctx->ssl_ctx, tmp_rsa_cb); 
    293   SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT"); 
    294   SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb); 
    295   SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2); 
     369    if(key && 
     370       SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key, 
     371                                      SSL_FILETYPE_PEM) != 1) 
     372      goto bail; 
     373    if(ca) { 
     374      STACK_OF(X509_NAME) *cert_stack; 
     375      if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) || 
     376         (cert_stack = SSL_load_client_CA_file(ca)) == NULL) 
     377        goto bail; 
     378      SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack); 
     379    } 
     380    SSL_CTX_set_tmp_rsa_callback(ctx->ssl_ctx, tmp_rsa_cb); 
     381    SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT"); 
     382    SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb); 
     383    SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2); 
     384    ssl_ctx_cache_set(ctx->ssl_ctx_cn); 
     385  } 
    296386 
    297387  ctx->ssl = SSL_new(ctx->ssl_ctx); 
     
    542632  else pthread_mutex_unlock(&lock->lock); 
    543633} 
     634void eventer_ssl_set_ssl_ctx_cache_expiry(int timeout) { 
     635  ssl_ctx_cache_expiry = timeout; 
     636} 
    544637void eventer_ssl_init() { 
    545638  int i, numlocks; 
  • src/eventer/eventer_SSL_fd_opset.h

    rc35ae3a ra335d72  
    9595  eventer_ssl_verify_cert(eventer_ssl_ctx_t *ctx, int ok, 
    9696                          X509_STORE_CTX *x509ctx, void *closure); 
     97API_EXPORT(void) 
     98  eventer_ssl_set_ssl_ctx_cache_expiry(int timeout); 
    9799 
    98100/* These are all helper functions to expose information 
  • src/eventer/eventer_impl.c

    rf0c199b ra335d72  
    110110    return 0; 
    111111  } 
     112  else if(!strcasecmp(key, "ssl_ctx_cache_expiry")) { 
     113    eventer_ssl_set_ssl_ctx_cache_expiry(atoi(value)); 
     114    return 0; 
     115  } 
    112116  noitL(noit_error, "Warning: unknown eventer config '%s'\n", key); 
    113117  return 0;