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