Return-Path: X-Original-To: apmail-httpd-cvs-archive@www.apache.org Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 039A17FB1 for ; Wed, 9 Nov 2011 23:38:00 +0000 (UTC) Received: (qmail 38972 invoked by uid 500); 9 Nov 2011 23:37:59 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 38923 invoked by uid 500); 9 Nov 2011 23:37:59 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 38916 invoked by uid 99); 9 Nov 2011 23:37:59 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 Nov 2011 23:37:59 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_FRT_SLUT X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 Nov 2011 23:37:58 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 0C35C238897A; Wed, 9 Nov 2011 23:37:38 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1200040 - in /httpd/httpd/trunk: CHANGES modules/ssl/mod_ssl.c modules/ssl/ssl_engine_config.c modules/ssl/ssl_engine_init.c modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_private.h Date: Wed, 09 Nov 2011 23:37:37 -0000 To: cvs@httpd.apache.org From: pquerna@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111109233738.0C35C238897A@eris.apache.org> Author: pquerna Date: Wed Nov 9 23:37:37 2011 New Revision: 1200040 URL: http://svn.apache.org/viewvc?rev=1200040&view=rev Log: Add support for RFC 5077 TLS Session tickets. This adds two new directives: * SSLTicketKeyFile: To store the private information for the encryption of the ticket. * SSLTicketKeyDefault To set the default, otherwise the first listed token is used. This enables key rotation across servers. Modified: httpd/httpd/trunk/CHANGES httpd/httpd/trunk/modules/ssl/mod_ssl.c httpd/httpd/trunk/modules/ssl/ssl_engine_config.c httpd/httpd/trunk/modules/ssl/ssl_engine_init.c httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c httpd/httpd/trunk/modules/ssl/ssl_private.h Modified: httpd/httpd/trunk/CHANGES URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/CHANGES [utf-8] (original) +++ httpd/httpd/trunk/CHANGES [utf-8] Wed Nov 9 23:37:37 2011 @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.3.16 + *) mod_ssl: Add support for RFC 5077 TLS Session tickets. + [Paul Querna] + *) mod_usertrack: Use random value instead of remote IP address. [Stefan Fritsch] Modified: httpd/httpd/trunk/modules/ssl/mod_ssl.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/mod_ssl.c?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/mod_ssl.c (original) +++ httpd/httpd/trunk/modules/ssl/mod_ssl.c Wed Nov 9 23:37:37 2011 @@ -79,6 +79,14 @@ static const command_rec ssl_config_cmds SSL_CMD_SRV(FIPS, FLAG, "Enable FIPS-140 mode " "(`on', `off')") +#ifdef HAVE_TLSEXT_TICKETS + SSL_CMD_SRV(TicketKeyFile, TAKE2, + "Key file to use for encrypting and decrypting the client ticket (RFC 5077) " + "(keyname '/path/to/file')") + SSL_CMD_SRV(TicketKeyDefault, TAKE1, + "Set the key name used by default for new sessions " + "(keyname)") +#endif SSL_CMD_ALL(CipherSuite, TAKE1, "Colon-delimited list of permitted SSL Ciphers " "('XXX:...:XXX' - see manual)") Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_config.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_config.c?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_engine_config.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_engine_config.c Wed Nov 9 23:37:37 2011 @@ -200,6 +200,12 @@ static SSLSrvConfigRec *ssl_config_serve sc->fips = UNSET; #endif +#ifdef HAVE_TLSEXT_TICKETS + sc->default_ticket_name = NULL; + sc->default_ticket = NULL; + sc->tickets = apr_array_make(p, 4, sizeof(modssl_ticket_t*)); +#endif + modssl_ctx_init_proxy(sc, p); modssl_ctx_init_server(sc, p); @@ -304,6 +310,11 @@ void *ssl_config_server_merge(apr_pool_t cfgMerge(mc, NULL); cfgMerge(enabled, SSL_ENABLED_UNSET); +#ifdef HAVE_TLSEXT_TICKETS + cfgMergeString(default_ticket_name); + apr_array_cat(mrg->tickets, base->tickets); + apr_array_cat(mrg->tickets, add->tickets); +#endif cfgMergeBool(proxy_enabled); cfgMergeInt(session_cache_timeout); cfgMergeBool(cipher_server_pref); @@ -584,6 +595,62 @@ const char *ssl_cmd_SSLEngine(cmd_parms return "Argument must be On, Off, or Optional"; } +const char *ssl_cmd_SSLTicketKeyDefault(cmd_parms *cmd, void *dcfg, const char *name) +{ +#ifdef HAVE_TLSEXT_TICKETS + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->default_ticket_name = name; + + return NULL; +#else + return "TLS Ticket keys are not supported."; +#endif +} + +const char *ssl_cmd_SSLTicketKeyFile(cmd_parms *cmd, void *dcfg, const char *name, const char *path) +{ +#ifdef HAVE_TLSEXT_TICKETS + apr_status_t rv; + apr_file_t *fp; + apr_size_t len; + char buf[TLSEXT_TICKET_KEYLEN]; + modssl_ticket_t* ticket = NULL; + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + rv = apr_file_open(&fp, path, APR_READ|APR_BINARY, + APR_OS_DEFAULT, cmd->temp_pool); + + if (rv != APR_SUCCESS) { + return apr_psprintf(cmd->pool, + "Failed to open %s: (%d) %pm", + path, rv, &rv); + } + + rv = apr_file_read_full(fp, &buf[0], TLSEXT_TICKET_KEYLEN, &len); + + if (rv != APR_SUCCESS) { + return apr_psprintf(cmd->pool, + "Failed to read at least 48 bytes from %s: (%d) %pm", + path, rv, &rv); + } + + ticket = apr_palloc(cmd->pool, sizeof(modssl_ticket_t)); + + ticket->conf_name = name; + + memcpy(ticket->key_name, buf, 16); + memcpy(ticket->hmac_secret, buf + 16, 16); + memcpy(ticket->aes_key, buf + 32, 16); + + APR_ARRAY_PUSH(sc->tickets, modssl_ticket_t*) = ticket; + + return NULL; +#else + return "TLS Ticket keys are not supported."; +#endif +} + const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag) { #ifdef HAVE_FIPS Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_init.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_init.c?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_engine_init.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_engine_init.c Wed Nov 9 23:37:37 2011 @@ -1143,6 +1143,43 @@ static void ssl_init_server_certs(server #endif ssl_die(); } + +#ifdef HAVE_TLSEXT_TICKETS + if (mctx->sc->tickets->nelts > 0) { + + if (mctx->sc->default_ticket_name != NULL) { + int i; + modssl_ticket_t* ticket = NULL; + mctx->sc->default_ticket = NULL; + + for (i = 0; i < mctx->sc->tickets->nelts; i++) { + ticket = APR_ARRAY_IDX(mctx->sc->tickets, i, modssl_ticket_t*); + if (strcmp(ticket->conf_name, mctx->sc->default_ticket_name) == 0) { + mctx->sc->default_ticket = ticket; + } + } + + if (mctx->sc->default_ticket == NULL) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, + "Misconfigured TLS Tickets. Couldn't find key named '%s'", + mctx->sc->default_ticket_name); + ssl_die(); + } + } + else { + mctx->sc->default_ticket = APR_ARRAY_IDX(mctx->sc->tickets, 0, modssl_ticket_t*); + } + + if (!SSL_CTX_set_tlsext_ticket_key_cb(mctx->ssl_ctx, ssl_callback_tlsext_tickets)) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, + "Unable to initialize TLS session ticket extension " + "(incompatible OpenSSL version?)"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); + ssl_die(); + } + } +#endif + } static void ssl_init_proxy_certs(server_rec *s, Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c Wed Nov 9 23:37:37 2011 @@ -2067,3 +2067,94 @@ static int ssl_find_vhost(void *serverna return 0; } #endif + +#ifdef HAVE_TLSEXT_TICKETS + +#ifndef tlsext_tick_md +#ifdef OPENSSL_NO_SHA256 +#define tlsext_tick_md EVP_sha1 +#else +#define tlsext_tick_md EVP_sha256 +#endif +#endif + +int ssl_callback_tlsext_tickets(SSL *ssl, + char *keyname, + char *iv, + EVP_CIPHER_CTX *cipher_ctx, + HMAC_CTX *hctx, + int mode) +{ + conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl); + server_rec *s = mySrvFromConn(conn); + SSLSrvConfigRec *sc = mySrvConfig(s); + + if (mode == 1) { + modssl_ticket_t* ticket = sc->default_ticket; + + /* Setting up the stuff for encrypting: + * - keyname contains at least 16 bytes we can write to. + * - iv contains at least EVP_MAX_IV_LENGTH (16) bytes we can write to. + * - hctx is already allocated, we just need to set the + * secret key via HMAC_Init_ex. + * - cipher_ctx is also allocated, and we need to configure + * the cipher and private key. + */ + + if (ticket == NULL) { + /* this should not happen, we always set the default + * ticket. + */ + return -1; + } + + memcpy(keyname, ticket->key_name, 16); + + RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH); + + memcpy(iv, iv, EVP_MAX_IV_LENGTH); + + EVP_EncryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, + ticket->aes_key, iv); + + HMAC_Init_ex(hctx, ticket->hmac_secret, 16, tlsext_tick_md(), NULL); + + return 0; + } + else if (mode == 0) { + /* Setup contextes for decryption, based on the keyname input */ + int i; + modssl_ticket_t* ticket = NULL; + + for (i = 0; i < sc->tickets->nelts; i++) { + modssl_ticket_t* itticket = APR_ARRAY_IDX(sc->tickets, i, modssl_ticket_t*); + if (memcmp(keyname, itticket->key_name, 16) == 0) { + ticket = itticket; + break; + } + } + + if (ticket == NULL) { + /* Ticket key not found, but no error */ + return 0; + } + + EVP_DecryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, ticket->aes_key, iv); + + HMAC_Init_ex(hctx, ticket->hmac_secret, 16, tlsext_tick_md(), NULL); + + if (ticket != sc->default_ticket) { + /* Ticket key found, we did our stuff, but didn't use the default, + * re-issue a ticket with the default ticket */ + return 2; + } + else { + return 1; + } + } + + /* TODO: log invalid use */ + return -1; +} + +#endif Modified: httpd/httpd/trunk/modules/ssl/ssl_private.h URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_private.h?rev=1200040&r1=1200039&r2=1200040&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_private.h (original) +++ httpd/httpd/trunk/modules/ssl/ssl_private.h Wed Nov 9 23:37:37 2011 @@ -157,6 +157,12 @@ #endif #endif +#ifndef OPENSSL_NO_TLSEXT +#ifdef SSL_CTX_set_tlsext_ticket_key_cb +#define HAVE_TLSEXT_TICKETS +#endif +#endif + /* mod_ssl headers */ #include "ssl_util_ssl.h" @@ -557,6 +563,21 @@ typedef struct { ssl_verify_t verify_mode; } modssl_auth_ctx_t; + +#ifdef HAVE_TLSEXT_TICKETS + +/* 48 bytes: 16 for keyname, 16 for HMAC secret, 16 for AES private key */ +#define TLSEXT_TICKET_KEYLEN (48) + +typedef struct { + /* Human readable name, used in the configuration */ + const char *conf_name; + char key_name[16]; + char hmac_secret[16]; + char aes_key[16]; +} modssl_ticket_t; +#endif + typedef struct SSLSrvConfigRec SSLSrvConfigRec; typedef struct { @@ -625,6 +646,11 @@ struct SSLSrvConfigRec { #ifdef HAVE_FIPS BOOL fips; #endif +#ifdef HAVE_TLSEXT_TICKETS + const char *default_ticket_name; + modssl_ticket_t* default_ticket; + apr_array_header_t* tickets; +#endif }; /** @@ -716,6 +742,8 @@ const char *ssl_cmd_SSLOCSPResponderTime const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLTicketKeyDefault(cmd_parms *cmd, void *dcfg, const char *name); +const char *ssl_cmd_SSLTicketKeyFile(cmd_parms *cmd, void *dcfg, const char *name, const char *path); /** module initialization */ int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); @@ -757,6 +785,15 @@ void ssl_callback_Info(const SSL int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); #endif +#ifdef HAVE_TLSEXT_TICKETS +int ssl_callback_tlsext_tickets(SSL *ssl, + char *keyname, + char *iv, + EVP_CIPHER_CTX *cipher_ctx, + HMAC_CTX *hctx, + int mode); +#endif + /** Session Cache Support */ void ssl_scache_init(server_rec *, apr_pool_t *); void ssl_scache_status_register(apr_pool_t *p);