~ubuntu-branches/ubuntu/wily/trafficserver/wily

« back to all changes in this revision

Viewing changes to iocore/net/SSLNetProcessor.cc

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2012-12-17 22:28:16 UTC
  • mfrom: (5.1.8 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20121217222816-7xwjsx5k76zkb63d
Tags: 3.2.0-1ubuntu1
* Revert FreeBSD strerror_r() fixes that give errors with glibc 2.16.
* Apply patch from Konstantinos Margaritis to define barriers on ARM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  @section license License
 
4
 
 
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
 
12
 
 
13
      http://www.apache.org/licenses/LICENSE-2.0
 
14
 
 
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.
 
20
 */
 
21
 
 
22
#include "ink_config.h"
 
23
 
 
24
#include "P_Net.h"
 
25
#include "I_Layout.h"
 
26
#include "I_RecHttp.h"
 
27
 
 
28
#include <openssl/engine.h>
 
29
 
 
30
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) // openssl returns a const SSL_METHOD
 
31
typedef const SSL_METHOD * ink_ssl_method_t;
 
32
#else
 
33
typedef SSL_METHOD * ink_ssl_method_t;
 
34
#endif
 
35
 
 
36
//
 
37
// Global Data
 
38
//
 
39
 
 
40
SSLNetProcessor ssl_NetProcessor;
 
41
NetProcessor & sslNetProcessor = ssl_NetProcessor;
 
42
 
 
43
EventType SSLNetProcessor::ET_SSL;
 
44
 
 
45
void sslLockingCallback(int mode, int type, const char *file, int line);
 
46
unsigned long SSL_pthreads_thread_id();
 
47
 
 
48
bool SSLNetProcessor::open_ssl_initialized = false;
 
49
 
 
50
static int
 
51
SSL_CTX_add_extra_chain_cert_file(SSL_CTX * ctx, const char *file)
 
52
{
 
53
  BIO *in;
 
54
  int ret = 0;
 
55
  X509 *x = NULL;
 
56
 
 
57
  in = BIO_new(BIO_s_file_internal());
 
58
  if (in == NULL) {
 
59
    SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
 
60
    goto end;
 
61
  }
 
62
 
 
63
  if (BIO_read_filename(in, file) <= 0) {
 
64
    SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
 
65
    goto end;
 
66
  }
 
67
 
 
68
  // j = ERR_R_PEM_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);
 
71
    if (!ret) {
 
72
        X509_free(x);
 
73
        BIO_free(in);
 
74
        return -1;
 
75
     }
 
76
    }
 
77
/*  x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
 
78
  if (x == NULL) {
 
79
    SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j);
 
80
    goto end;
 
81
  }
 
82
 
 
83
  ret = SSL_CTX_add_extra_chain_cert(ctx, x);*/
 
84
end:
 
85
  //  if (x != NULL) X509_free(x);
 
86
  if (in != NULL)
 
87
    BIO_free(in);
 
88
  return (ret);
 
89
}
 
90
 
 
91
void
 
92
SSLNetProcessor::cleanup(void)
 
93
{
 
94
  if (sslMutexArray) {
 
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();
 
99
    }
 
100
    OPENSSL_free(sslMutexArray);
 
101
    sslMutexArray = NULL;
 
102
  }
 
103
 
 
104
  if (client_ctx)
 
105
    SSL_CTX_free(client_ctx);
 
106
  client_ctx = NULL;
 
107
}
 
108
 
 
109
void
 
110
SSLNetProcessor::initSSLLocks(void)
 
111
{
 
112
 
 
113
  sslMutexArray = (ProxyMutex **) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(ProxyMutex *));
 
114
 
 
115
  for (int i = 0; i < CRYPTO_num_locks(); i++) {
 
116
    sslMutexArray[i] = new_ProxyMutex();
 
117
  }
 
118
  CRYPTO_set_locking_callback((void (*)(int, int, const char *, int)) sslLockingCallback);
 
119
  CRYPTO_set_id_callback(SSL_pthreads_thread_id);
 
120
}
 
121
 
 
122
int
 
123
SSLNetProcessor::reconfigure(void)
 
124
{
 
125
  int err = 0;
 
126
 
 
127
  cleanup();
 
128
 
 
129
  if (!open_ssl_initialized) {
 
130
    open_ssl_initialized = true;
 
131
    SSL_load_error_strings();
 
132
    SSL_library_init();
 
133
    initSSLLocks();
 
134
  }
 
135
 
 
136
  SslConfigParams *param = sslTerminationConfig.acquire();
 
137
  ink_assert(param);
 
138
 
 
139
  if (HttpProxyPort::hasSSL()) {
 
140
    // Only init server stuff if SSL is enabled in the config file
 
141
    sslCertLookup.init(param);
 
142
  }
 
143
 
 
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.
 
147
  if (err == 0) {
 
148
    err = initSSLClient(param);
 
149
    if (err != 0)
 
150
      logSSLError("Can't initialize the SSL client, HTTPS in remap rules will not function");
 
151
  }
 
152
 
 
153
  sslTerminationConfig.release(param);
 
154
  return (err);
 
155
}
 
156
 
 
157
void
 
158
sslLockingCallback(int mode, int type, const char *file, int line)
 
159
{
 
160
  NOWARN_UNUSED(file);
 
161
  (void) 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());
 
166
  else
 
167
    ink_debug_assert(0);
 
168
}
 
169
 
 
170
unsigned long
 
171
SSL_pthreads_thread_id()
 
172
{
 
173
  EThread *eth = this_ethread();
 
174
  return (unsigned long) (eth->id);
 
175
}
 
176
 
 
177
void
 
178
SSLNetProcessor::logSSLError(const char *errStr, int critical)
 
179
{
 
180
  unsigned long l;
 
181
  char buf[256];
 
182
  const char *file, *data;
 
183
  int line, flags;
 
184
  unsigned long es;
 
185
 
 
186
  if (!critical) {
 
187
    if (errStr) {
 
188
      Debug("ssl_error", "SSL ERROR: %s.", errStr);
 
189
    } else {
 
190
      Debug("ssl_error", "SSL ERROR.");
 
191
    }
 
192
  } else {
 
193
    if (errStr) {
 
194
      Error("SSL ERROR: %s.", errStr);
 
195
    } else {
 
196
      Error("SSL ERROR.");
 
197
    }
 
198
  }
 
199
 
 
200
  es = CRYPTO_thread_id();
 
201
  while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
 
202
    if (!critical) {
 
203
      Debug("ssl_error", "SSL::%lu:%s:%s:%d:%s", es,
 
204
            ERR_error_string(l, buf), file, line, (flags & ERR_TXT_STRING) ? data : "");
 
205
    } else {
 
206
      Error("SSL::%lu:%s:%s:%d:%s", es, ERR_error_string(l, buf), file, line, (flags & ERR_TXT_STRING) ? data : "");
 
207
    }
 
208
  }
 
209
}
 
210
 
 
211
int
 
212
SSLNetProcessor::initSSLServerCTX(SSL_CTX * lCtx, const SslConfigParams * param,
 
213
    const char *serverCertPtr, const char *serverCaCertPtr,
 
214
    const char *serverKeyPtr)
 
215
{
 
216
  int session_id_context;
 
217
  int server_verify_client;
 
218
  char *completeServerCertPath;
 
219
 
 
220
  // disable selected protocols
 
221
  SSL_CTX_set_options(lCtx, param->ssl_ctx_options);
 
222
 
 
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);
 
226
    break;
 
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);
 
230
    break;
 
231
  }
 
232
 
 
233
  //might want to make configurable at some point.
 
234
  int verify_depth = param->verify_depth;
 
235
  SSL_CTX_set_quiet_shutdown(lCtx, 1);
 
236
 
 
237
  completeServerCertPath = Layout::relative_to (param->getServerCertPathOnly(), serverCertPtr);
 
238
 
 
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);
 
242
    return -2;
 
243
  }
 
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);
 
249
      return -2;
 
250
    }
 
251
    ats_free(completeServerCaCertPath);
 
252
  }
 
253
 
 
254
  if (serverKeyPtr == NULL)   // assume private key is contained in cert obtained from multicert file.
 
255
  {
 
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);
 
259
      return -3;
 
260
    }
 
261
  } else {
 
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);
 
267
        return -3;
 
268
      }
 
269
      ats_free(completeServerKeyPath);
 
270
    } else {
 
271
      logSSLError("Empty ssl private key path in records.config.");
 
272
    }
 
273
 
 
274
  }
 
275
  ats_free(completeServerCertPath);
 
276
 
 
277
  if (!SSL_CTX_check_private_key(lCtx)) {
 
278
    logSSLError("Server private key does not match the certificate public key");
 
279
    return -4;
 
280
  }
 
281
 
 
282
  if (param->clientCertLevel != 0) {
 
283
 
 
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");
 
288
        return -5;
 
289
      }
 
290
    }
 
291
 
 
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;
 
296
    } else {
 
297
      // disable client cert support
 
298
      server_verify_client = SSL_VERIFY_NONE;
 
299
      Error("Illegal Client Certification Level in records.config\n");
 
300
    }
 
301
 
 
302
    session_id_context = 1;
 
303
 
 
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);
 
307
 
 
308
    SSL_CTX_set_client_CA_list(lCtx, SSL_load_client_CA_file(param->CACertFilename));
 
309
  }
 
310
 
 
311
  if (param->cipherSuite != NULL) {
 
312
    if (!SSL_CTX_set_cipher_list(lCtx, param->cipherSuite)) {
 
313
      logSSLError("Invalid Cipher Suite in records.config");
 
314
      return -6;
 
315
    }
 
316
  }
 
317
 
 
318
#if TS_USE_TLS_NPN
 
319
  SSL_CTX_set_next_protos_advertised_cb(lCtx,
 
320
      SSLNetVConnection::advertise_next_protocol, this);
 
321
#endif /* TS_USE_TLS_NPN */
 
322
 
 
323
  return 0;
 
324
 
 
325
}
 
326
 
 
327
int
 
328
SSLNetProcessor::initSSLClient(const SslConfigParams * param)
 
329
{
 
330
  ink_ssl_method_t meth = NULL;
 
331
  int client_verify_server;
 
332
  char *clientKeyPtr = NULL;
 
333
 
 
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.
 
337
 
 
338
  client_verify_server = param->clientVerify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
 
339
  meth = SSLv23_client_method();
 
340
  client_ctx = SSL_CTX_new(meth);
 
341
 
 
342
  // disable selected protocols
 
343
  SSL_CTX_set_options(client_ctx, param->ssl_ctx_options);
 
344
  int verify_depth = param->client_verify_depth;
 
345
  if (!client_ctx) {
 
346
    logSSLError("Cannot create new client contex.");
 
347
    return (-1);
 
348
  }
 
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;
 
354
 
 
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);
 
358
      return (-2);
 
359
    }
 
360
 
 
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);
 
363
      return (-3);
 
364
    }
 
365
 
 
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);
 
368
      return (-4);
 
369
    }
 
370
  }
 
371
 
 
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);
 
375
    // ???
 
376
 
 
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);
 
382
        return (-5);
 
383
      }
 
384
    }
 
385
  }
 
386
  return (0);
 
387
}
 
388
 
 
389
int
 
390
SSLNetProcessor::start(int number_of_ssl_threads)
 
391
{
 
392
  sslTerminationConfig.startup();
 
393
  int err = reconfigure();
 
394
 
 
395
  if (err != 0) {
 
396
    return -1;
 
397
  }
 
398
 
 
399
  if (number_of_ssl_threads < 1)
 
400
    return -1;
 
401
 
 
402
  SSLNetProcessor::ET_SSL = eventProcessor.spawn_event_threads(number_of_ssl_threads, "ET_SSL");
 
403
  if (err == 0) {
 
404
    err = UnixNetProcessor::start();
 
405
  }
 
406
 
 
407
  return err;
 
408
}
 
409
 
 
410
NetAccept *
 
411
SSLNetProcessor::createNetAccept()
 
412
{
 
413
  return ((NetAccept *) NEW(new SSLNetAccept));
 
414
}
 
415
 
 
416
// Virtual function allows etype to be upgraded to ET_SSL for SSLNetProcessor.  Does
 
417
// nothing for NetProcessor
 
418
void
 
419
SSLNetProcessor::upgradeEtype(EventType & etype)
 
420
{
 
421
  if (etype == ET_NET) {
 
422
    etype = ET_SSL;
 
423
  }
 
424
}
 
425
 
 
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.
 
431
UnixNetVConnection *
 
432
SSLNetProcessor::allocateThread(EThread *t)
 
433
{
 
434
  return ((UnixNetVConnection *) THREAD_ALLOC(sslNetVCAllocator, t));
 
435
}
 
436
 
 
437
void
 
438
SSLNetProcessor::freeThread(UnixNetVConnection *vc, EThread *t)
 
439
{
 
440
  ink_assert(!vc->from_accept_thread);
 
441
  THREAD_FREE((SSLNetVConnection *) vc, sslNetVCAllocator, t);
 
442
}
 
443
 
 
444
SSLNetProcessor::SSLNetProcessor()
 
445
  : client_ctx(NULL), sslMutexArray(NULL)
 
446
{
 
447
}
 
448
 
 
449
SSLNetProcessor::~SSLNetProcessor()
 
450
{
 
451
  cleanup();
 
452
}