3
@section license License
5
Licensed to the Apache Software Foundation (ASF) under one
6
or more contributor license agreements. See the NOTICE file
7
distributed with this work for additional information
8
regarding copyright ownership. The ASF licenses this file
9
to you under the Apache License, Version 2.0 (the
10
"License"); you may not use this file except in compliance
11
with the License. You may obtain a copy of the License at
13
http://www.apache.org/licenses/LICENSE-2.0
15
Unless required by applicable law or agreed to in writing, software
16
distributed under the License is distributed on an "AS IS" BASIS,
17
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
See the License for the specific language governing permissions and
19
limitations under the License.
22
#include "ink_config.h"
26
#include "I_RecHttp.h"
28
#include <openssl/engine.h>
30
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) // openssl returns a const SSL_METHOD
31
typedef const SSL_METHOD * ink_ssl_method_t;
33
typedef SSL_METHOD * ink_ssl_method_t;
40
SSLNetProcessor ssl_NetProcessor;
41
NetProcessor & sslNetProcessor = ssl_NetProcessor;
43
EventType SSLNetProcessor::ET_SSL;
45
void sslLockingCallback(int mode, int type, const char *file, int line);
46
unsigned long SSL_pthreads_thread_id();
48
bool SSLNetProcessor::open_ssl_initialized = false;
51
SSL_CTX_add_extra_chain_cert_file(SSL_CTX * ctx, const char *file)
57
in = BIO_new(BIO_s_file_internal());
59
SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
63
if (BIO_read_filename(in, file) <= 0) {
64
SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
69
while ((x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) != NULL) {
70
ret = SSL_CTX_add_extra_chain_cert(ctx, x);
77
/* x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
79
SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j);
83
ret = SSL_CTX_add_extra_chain_cert(ctx, x);*/
85
// if (x != NULL) X509_free(x);
92
SSLNetProcessor::cleanup(void)
95
CRYPTO_set_locking_callback(NULL);
96
CRYPTO_set_id_callback(NULL);
97
for (int i = 0; i < CRYPTO_num_locks(); i++) {
98
sslMutexArray[i]->free();
100
OPENSSL_free(sslMutexArray);
101
sslMutexArray = NULL;
105
SSL_CTX_free(client_ctx);
110
SSLNetProcessor::initSSLLocks(void)
113
sslMutexArray = (ProxyMutex **) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(ProxyMutex *));
115
for (int i = 0; i < CRYPTO_num_locks(); i++) {
116
sslMutexArray[i] = new_ProxyMutex();
118
CRYPTO_set_locking_callback((void (*)(int, int, const char *, int)) sslLockingCallback);
119
CRYPTO_set_id_callback(SSL_pthreads_thread_id);
123
SSLNetProcessor::reconfigure(void)
129
if (!open_ssl_initialized) {
130
open_ssl_initialized = true;
131
SSL_load_error_strings();
136
SslConfigParams *param = sslTerminationConfig.acquire();
139
if (HttpProxyPort::hasSSL()) {
140
// Only init server stuff if SSL is enabled in the config file
141
sslCertLookup.init(param);
144
// Enable client regardless of config file setttings as remap file
145
// can cause HTTP layer to connect using SSL. But only if SSL
146
// initialization hasn't failed already.
148
err = initSSLClient(param);
150
logSSLError("Can't initialize the SSL client, HTTPS in remap rules will not function");
153
sslTerminationConfig.release(param);
158
sslLockingCallback(int mode, int type, const char *file, int line)
162
if (mode & CRYPTO_LOCK) {
163
MUTEX_TAKE_LOCK(ssl_NetProcessor.sslMutexArray[type], this_ethread());
164
} else if (mode & CRYPTO_UNLOCK)
165
MUTEX_UNTAKE_LOCK(ssl_NetProcessor.sslMutexArray[type], this_ethread());
171
SSL_pthreads_thread_id()
173
EThread *eth = this_ethread();
174
return (unsigned long) (eth->id);
178
SSLNetProcessor::logSSLError(const char *errStr, int critical)
182
const char *file, *data;
188
Debug("ssl_error", "SSL ERROR: %s.", errStr);
190
Debug("ssl_error", "SSL ERROR.");
194
Error("SSL ERROR: %s.", errStr);
200
es = CRYPTO_thread_id();
201
while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
203
Debug("ssl_error", "SSL::%lu:%s:%s:%d:%s", es,
204
ERR_error_string(l, buf), file, line, (flags & ERR_TXT_STRING) ? data : "");
206
Error("SSL::%lu:%s:%s:%d:%s", es, ERR_error_string(l, buf), file, line, (flags & ERR_TXT_STRING) ? data : "");
212
SSLNetProcessor::initSSLServerCTX(SSL_CTX * lCtx, const SslConfigParams * param,
213
const char *serverCertPtr, const char *serverCaCertPtr,
214
const char *serverKeyPtr)
216
int session_id_context;
217
int server_verify_client;
218
char *completeServerCertPath;
220
// disable selected protocols
221
SSL_CTX_set_options(lCtx, param->ssl_ctx_options);
223
switch (param->ssl_session_cache) {
224
case SslConfigParams::SSL_SESSION_CACHE_MODE_OFF:
225
SSL_CTX_set_session_cache_mode(lCtx, SSL_SESS_CACHE_OFF|SSL_SESS_CACHE_NO_INTERNAL);
227
case SslConfigParams::SSL_SESSION_CACHE_MODE_SERVER:
228
SSL_CTX_set_session_cache_mode(lCtx, SSL_SESS_CACHE_SERVER);
229
SSL_CTX_sess_set_cache_size(lCtx, param->ssl_session_cache_size);
233
//might want to make configurable at some point.
234
int verify_depth = param->verify_depth;
235
SSL_CTX_set_quiet_shutdown(lCtx, 1);
237
completeServerCertPath = Layout::relative_to (param->getServerCertPathOnly(), serverCertPtr);
239
if (SSL_CTX_use_certificate_file(lCtx, completeServerCertPath, SSL_FILETYPE_PEM) <= 0) {
240
Error ("SSL ERROR: Cannot use server certificate file: %s", completeServerCertPath);
241
ats_free(completeServerCertPath);
244
if (serverCaCertPtr) {
245
char *completeServerCaCertPath = Layout::relative_to (param->getServerCACertPathOnly(), serverCaCertPtr);
246
if (SSL_CTX_add_extra_chain_cert_file(lCtx, completeServerCaCertPath) <= 0) {
247
Error ("SSL ERROR: Cannot use server certificate chain file: %s", completeServerCaCertPath);
248
ats_free(completeServerCaCertPath);
251
ats_free(completeServerCaCertPath);
254
if (serverKeyPtr == NULL) // assume private key is contained in cert obtained from multicert file.
256
if (SSL_CTX_use_PrivateKey_file(lCtx, completeServerCertPath, SSL_FILETYPE_PEM) <= 0) {
257
Error("SSL ERROR: Cannot use server private key file: %s", completeServerCertPath);
258
ats_free(completeServerCertPath);
262
if (param->getServerKeyPathOnly() != NULL) {
263
char *completeServerKeyPath = Layout::get()->relative_to(param->getServerKeyPathOnly(), serverKeyPtr);
264
if (SSL_CTX_use_PrivateKey_file(lCtx, completeServerKeyPath, SSL_FILETYPE_PEM) <= 0) {
265
Error("SSL ERROR: Cannot use server private key file: %s", completeServerKeyPath);
266
ats_free(completeServerKeyPath);
269
ats_free(completeServerKeyPath);
271
logSSLError("Empty ssl private key path in records.config.");
275
ats_free(completeServerCertPath);
277
if (!SSL_CTX_check_private_key(lCtx)) {
278
logSSLError("Server private key does not match the certificate public key");
282
if (param->clientCertLevel != 0) {
284
if (param->CACertFilename != NULL && param->CACertPath != NULL) {
285
if ((!SSL_CTX_load_verify_locations(lCtx, param->CACertFilename, param->CACertPath)) ||
286
(!SSL_CTX_set_default_verify_paths(lCtx))) {
287
logSSLError("CA Certificate file or CA Certificate path invalid");
292
if (param->clientCertLevel == 2) {
293
server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
294
} else if (param->clientCertLevel == 1) {
295
server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
297
// disable client cert support
298
server_verify_client = SSL_VERIFY_NONE;
299
Error("Illegal Client Certification Level in records.config\n");
302
session_id_context = 1;
304
SSL_CTX_set_verify(lCtx, server_verify_client, NULL);
305
SSL_CTX_set_verify_depth(lCtx, verify_depth);
306
SSL_CTX_set_session_id_context(lCtx, (const unsigned char *) &session_id_context, sizeof session_id_context);
308
SSL_CTX_set_client_CA_list(lCtx, SSL_load_client_CA_file(param->CACertFilename));
311
if (param->cipherSuite != NULL) {
312
if (!SSL_CTX_set_cipher_list(lCtx, param->cipherSuite)) {
313
logSSLError("Invalid Cipher Suite in records.config");
319
SSL_CTX_set_next_protos_advertised_cb(lCtx,
320
SSLNetVConnection::advertise_next_protocol, this);
321
#endif /* TS_USE_TLS_NPN */
328
SSLNetProcessor::initSSLClient(const SslConfigParams * param)
330
ink_ssl_method_t meth = NULL;
331
int client_verify_server;
332
char *clientKeyPtr = NULL;
334
// Note that we do not call RAND_seed() explicitly here, we depend on OpenSSL
335
// to do the seeding of the PRNG for us. This is the case for all platforms that
336
// has /dev/urandom for example.
338
client_verify_server = param->clientVerify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
339
meth = SSLv23_client_method();
340
client_ctx = SSL_CTX_new(meth);
342
// disable selected protocols
343
SSL_CTX_set_options(client_ctx, param->ssl_ctx_options);
344
int verify_depth = param->client_verify_depth;
346
logSSLError("Cannot create new client contex.");
349
// if no path is given for the client private key,
350
// assume it is contained in the client certificate file.
351
clientKeyPtr = param->clientKeyPath;
352
if (clientKeyPtr == NULL)
353
clientKeyPtr = param->clientCertPath;
355
if (param->clientCertPath != 0) {
356
if (SSL_CTX_use_certificate_file(client_ctx, param->clientCertPath, SSL_FILETYPE_PEM) <= 0) {
357
Error ("SSL Error: Cannot use client certificate file: %s", param->clientCertPath);
361
if (SSL_CTX_use_PrivateKey_file(client_ctx, clientKeyPtr, SSL_FILETYPE_PEM) <= 0) {
362
Error ("SSL ERROR: Cannot use client private key file: %s", clientKeyPtr);
366
if (!SSL_CTX_check_private_key(client_ctx)) {
367
Error("SSL ERROR: Client private key (%s) does not match the certificate public key (%s)", clientKeyPtr, param->clientCertPath);
372
if (param->clientVerify) {
373
SSL_CTX_set_verify(client_ctx, client_verify_server, NULL);
374
/*???*/ SSL_CTX_set_verify_depth(client_ctx, verify_depth);
377
if (param->clientCACertFilename != NULL && param->clientCACertPath != NULL) {
378
if ((!SSL_CTX_load_verify_locations(client_ctx, param->clientCACertFilename,
379
param->clientCACertPath)) ||
380
(!SSL_CTX_set_default_verify_paths(client_ctx))) {
381
Error("SSL ERROR: Client CA Certificate file (%s) or CA Certificate path (%s) invalid", param->clientCACertFilename, param->clientCACertPath);
390
SSLNetProcessor::start(int number_of_ssl_threads)
392
sslTerminationConfig.startup();
393
int err = reconfigure();
399
if (number_of_ssl_threads < 1)
402
SSLNetProcessor::ET_SSL = eventProcessor.spawn_event_threads(number_of_ssl_threads, "ET_SSL");
404
err = UnixNetProcessor::start();
411
SSLNetProcessor::createNetAccept()
413
return ((NetAccept *) NEW(new SSLNetAccept));
416
// Virtual function allows etype to be upgraded to ET_SSL for SSLNetProcessor. Does
417
// nothing for NetProcessor
419
SSLNetProcessor::upgradeEtype(EventType & etype)
421
if (etype == ET_NET) {
426
// Functions all THREAD_FREE and THREAD_ALLOC to be performed
427
// for both SSL and regular NetVConnection transparent to
428
// netProcessor connect functions. Yes it looks goofy to
429
// have them in both places, but it saves a bunch of
430
// connect code from being duplicated.
432
SSLNetProcessor::allocateThread(EThread *t)
434
return ((UnixNetVConnection *) THREAD_ALLOC(sslNetVCAllocator, t));
438
SSLNetProcessor::freeThread(UnixNetVConnection *vc, EThread *t)
440
ink_assert(!vc->from_accept_thread);
441
THREAD_FREE((SSLNetVConnection *) vc, sslNetVCAllocator, t);
444
SSLNetProcessor::SSLNetProcessor()
445
: client_ctx(NULL), sslMutexArray(NULL)
449
SSLNetProcessor::~SSLNetProcessor()