summaryrefslogtreecommitdiff
path: root/chromium/net/tools/flip_server/spdy_ssl.cc
blob: 1f18a0b30fff624edcc35f6b02acb06aafa45a25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 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 {

// Each element consists of <the length of the string><string> .
#define NEXT_PROTO_STRING \
  "\x08spdy/4a2" \
  "\x06spdy/3" \
  "\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<SSL_METHOD*>(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<void>(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