// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/tools/flip_server/spdy_ssl.h" #include "base/logging.h" #include "openssl/err.h" #include "openssl/ssl.h" namespace net { #define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0" #define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH" int ssl_set_npn_callback(SSL *s, const unsigned char **data, unsigned int *len, void *arg) { VLOG(1) << "SSL NPN callback: advertising protocols."; *data = (const unsigned char *) NEXT_PROTO_STRING; *len = strlen(NEXT_PROTO_STRING); return SSL_TLSEXT_ERR_OK; } void InitSSL(SSLState* state, std::string ssl_cert_name, std::string ssl_key_name, bool use_npn, int session_expiration_time, bool disable_ssl_compression) { SSL_library_init(); PrintSslError(); SSL_load_error_strings(); PrintSslError(); state->ssl_method = SSLv23_method(); // TODO(joth): Remove const_cast when the openssl 1.0.0 upgrade is complete. // (See http://codereview.chromium.org/9254031). state->ssl_ctx = SSL_CTX_new(const_cast(state->ssl_method)); if (!state->ssl_ctx) { PrintSslError(); LOG(FATAL) << "Unable to create SSL context"; } // Disable SSLv2 support. SSL_CTX_set_options(state->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE); if (SSL_CTX_use_certificate_chain_file(state->ssl_ctx, ssl_cert_name.c_str()) <= 0) { PrintSslError(); LOG(FATAL) << "Unable to use cert.pem as SSL cert."; } if (SSL_CTX_use_PrivateKey_file(state->ssl_ctx, ssl_key_name.c_str(), SSL_FILETYPE_PEM) <= 0) { PrintSslError(); LOG(FATAL) << "Unable to use key.pem as SSL key."; } if (!SSL_CTX_check_private_key(state->ssl_ctx)) { PrintSslError(); LOG(FATAL) << "The cert.pem and key.pem files don't match"; } if (use_npn) { SSL_CTX_set_next_protos_advertised_cb(state->ssl_ctx, ssl_set_npn_callback, NULL); } VLOG(1) << "SSL CTX default cipher list: " << SSL_CIPHER_LIST; SSL_CTX_set_cipher_list(state->ssl_ctx, SSL_CIPHER_LIST); VLOG(1) << "SSL CTX session expiry: " << session_expiration_time << " seconds"; SSL_CTX_set_timeout(state->ssl_ctx, session_expiration_time); #ifdef SSL_MODE_RELEASE_BUFFERS VLOG(1) << "SSL CTX: Setting Release Buffers mode."; SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif // Proper methods to disable compression don't exist until 0.9.9+. For now // we must manipulate the stack of compression methods directly. if (disable_ssl_compression) { STACK_OF(SSL_COMP) *ssl_comp_methods = SSL_COMP_get_compression_methods(); int num_methods = sk_SSL_COMP_num(ssl_comp_methods); int i; for (i = 0; i < num_methods; i++) { static_cast(sk_SSL_COMP_delete(ssl_comp_methods, i)); } } } SSL* CreateSSLContext(SSL_CTX* ssl_ctx) { SSL* ssl = SSL_new(ssl_ctx); SSL_set_accept_state(ssl); PrintSslError(); return ssl; } void PrintSslError() { char buf[128]; // this buffer must be at least 120 chars long. int error_num = ERR_get_error(); while (error_num != 0) { ERR_error_string_n(error_num, buf, sizeof(buf)); LOG(ERROR) << buf; error_num = ERR_get_error(); } } } // namespace net