15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/spdy_ssl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "openssl/err.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "openssl/ssl.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Each element consists of <the length of the string><string> .
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define NEXT_PROTO_STRING \
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  "\x08spdy/4a2" \
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  "\x06spdy/3" \
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  "\x06spdy/2" \
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  "\x08http/1.1" \
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  "\x08http/1.0"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int ssl_set_npn_callback(SSL* s,
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         const unsigned char** data,
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         unsigned int* len,
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         void* arg) {
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "SSL NPN callback: advertising protocols.";
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  *data = (const unsigned char*)NEXT_PROTO_STRING;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *len = strlen(NEXT_PROTO_STRING);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SSL_TLSEXT_ERR_OK;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitSSL(SSLState* state,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             std::string ssl_cert_name,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             std::string ssl_key_name,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             bool use_npn,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             int session_expiration_time,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             bool disable_ssl_compression) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_library_init();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSslError();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_load_error_strings();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSslError();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->ssl_method = SSLv23_method();
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->ssl_ctx = SSL_CTX_new(state->ssl_method);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!state->ssl_ctx) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintSslError();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Unable to create SSL context";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disable SSLv2 support.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX_set_options(state->ssl_ctx,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SSL_CTX_use_certificate_chain_file(state->ssl_ctx,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ssl_cert_name.c_str()) <= 0) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintSslError();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Unable to use cert.pem as SSL cert.";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (SSL_CTX_use_PrivateKey_file(
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          state->ssl_ctx, ssl_key_name.c_str(), SSL_FILETYPE_PEM) <= 0) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintSslError();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Unable to use key.pem as SSL key.";
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SSL_CTX_check_private_key(state->ssl_ctx)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintSslError();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "The cert.pem and key.pem files don't match";
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_npn) {
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SSL_CTX_set_next_protos_advertised_cb(
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        state->ssl_ctx, ssl_set_npn_callback, NULL);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "SSL CTX default cipher list: " << SSL_CIPHER_LIST;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX_set_cipher_list(state->ssl_ctx, SSL_CIPHER_LIST);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "SSL CTX session expiry: " << session_expiration_time
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " seconds";
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX_set_timeout(state->ssl_ctx, session_expiration_time);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SSL_MODE_RELEASE_BUFFERS
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "SSL CTX: Setting Release Buffers mode.";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if !defined(OPENSSL_IS_BORINGSSL)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Proper methods to disable compression don't exist until 0.9.9+. For now
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we must manipulate the stack of compression methods directly.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disable_ssl_compression) {
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    STACK_OF(SSL_COMP)* ssl_comp_methods = SSL_COMP_get_compression_methods();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_methods = sk_SSL_COMP_num(ssl_comp_methods);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_methods; i++) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<void>(sk_SSL_COMP_delete(ssl_comp_methods, i));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSL* CreateSSLContext(SSL_CTX* ssl_ctx) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL* ssl = SSL_new(ssl_ctx);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_set_accept_state(ssl);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintSslError();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ssl;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintSslError() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[128];  // this buffer must be at least 120 chars long.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error_num = ERR_get_error();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (error_num != 0) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ERR_error_string_n(error_num, buf, sizeof(buf));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << buf;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_num = ERR_get_error();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
115