1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_ssl.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "openssl/err.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "openssl/ssl.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint ssl_set_npn_callback(SSL *s,
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         const unsigned char **data,
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         unsigned int *len,
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         void *arg) {
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) <<  "SSL NPN callback: advertising protocols.";
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  *data = (const unsigned char *) NEXT_PROTO_STRING;
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  *len = strlen(NEXT_PROTO_STRING);
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return SSL_TLSEXT_ERR_OK;
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid InitSSL(SSLState* state,
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen             std::string ssl_cert_name,
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen             std::string ssl_key_name,
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen             bool use_npn,
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen             int session_expiration_time,
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen             bool disable_ssl_compression) {
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_library_init();
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PrintSslError();
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_load_error_strings();
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PrintSslError();
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  state->ssl_method = SSLv23_method();
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  state->ssl_ctx = SSL_CTX_new(state->ssl_method);
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!state->ssl_ctx) {
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(FATAL) << "Unable to create SSL context";
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Disable SSLv2 support.
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_CTX_set_options(state->ssl_ctx,
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE);
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (SSL_CTX_use_certificate_chain_file(state->ssl_ctx,
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                         ssl_cert_name.c_str()) <= 0) {
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(FATAL) << "Unable to use cert.pem as SSL cert.";
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (SSL_CTX_use_PrivateKey_file(state->ssl_ctx,
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                  ssl_key_name.c_str(),
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                  SSL_FILETYPE_PEM) <= 0) {
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(FATAL) << "Unable to use key.pem as SSL key.";
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!SSL_CTX_check_private_key(state->ssl_ctx)) {
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(FATAL) << "The cert.pem and key.pem files don't match";
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (use_npn) {
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSL_CTX_set_next_protos_advertised_cb(state->ssl_ctx,
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          ssl_set_npn_callback, NULL);
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << "SSL CTX default cipher list: " << SSL_CIPHER_LIST;
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_CTX_set_cipher_list(state->ssl_ctx, SSL_CIPHER_LIST);
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << "SSL CTX session expiry: " << session_expiration_time
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << " seconds";
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_CTX_set_timeout(state->ssl_ctx, session_expiration_time);
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifdef SSL_MODE_RELEASE_BUFFERS
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << "SSL CTX: Setting Release Buffers mode.";
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Proper methods to disable compression don't exist until 0.9.9+. For now
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // we must manipulate the stack of compression methods directly.
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (disable_ssl_compression) {
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    STACK_OF(SSL_COMP) *ssl_comp_methods = SSL_COMP_get_compression_methods();
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int num_methods = sk_SSL_COMP_num(ssl_comp_methods);
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int i;
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    for (i = 0; i < num_methods; i++) {
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<void>(sk_SSL_COMP_delete(ssl_comp_methods, i));
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
90dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSSL* CreateSSLContext(SSL_CTX* ssl_ctx) {
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL* ssl = SSL_new(ssl_ctx);
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSL_set_accept_state(ssl);
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PrintSslError();
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ssl;
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PrintSslError() {
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char buf[128];  // this buffer must be at least 120 chars long.
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int error_num = ERR_get_error();
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while (error_num != 0) {
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ERR_error_string_n(error_num, buf, sizeof(buf));
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(ERROR) << buf;
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    error_num = ERR_get_error();
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109