00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ink_config.h"
00023 #include "libts.h"
00024 #include "I_Layout.h"
00025 #include "P_Net.h"
00026 #include "ink_cap.h"
00027 #include "P_OCSPStapling.h"
00028
00029 #include <string>
00030 #include <openssl/err.h>
00031 #include <openssl/bio.h>
00032 #include <openssl/pem.h>
00033 #include <openssl/x509.h>
00034 #include <openssl/asn1.h>
00035 #include <openssl/rand.h>
00036 #include <unistd.h>
00037 #include <termios.h>
00038
00039 #if HAVE_OPENSSL_EVP_H
00040 #include <openssl/evp.h>
00041 #endif
00042
00043 #if HAVE_OPENSSL_HMAC_H
00044 #include <openssl/hmac.h>
00045 #endif
00046
00047 #if HAVE_OPENSSL_TS_H
00048 #include <openssl/ts.h>
00049 #endif
00050
00051 #if HAVE_OPENSSL_EC_H
00052 #include <openssl/ec.h>
00053 #endif
00054
00055
00056 #define SSL_IP_TAG "dest_ip"
00057 #define SSL_CERT_TAG "ssl_cert_name"
00058 #define SSL_PRIVATE_KEY_TAG "ssl_key_name"
00059 #define SSL_CA_TAG "ssl_ca_name"
00060 #define SSL_SESSION_TICKET_ENABLED "ssl_ticket_enabled"
00061 #define SSL_SESSION_TICKET_KEY_FILE_TAG "ticket_key_name"
00062 #define SSL_KEY_DIALOG "ssl_key_dialog"
00063 #define SSL_CERT_SEPARATE_DELIM ','
00064
00065
00066 #if (OPENSSL_VERSION_NUMBER < 0x00090400L)
00067 # error Traffic Server requires an OpenSSL library version 0.9.4 or greater
00068 #endif
00069
00070 #ifndef evp_md_func
00071 #ifdef OPENSSL_NO_SHA256
00072 #define evp_md_func EVP_sha1()
00073 #else
00074 #define evp_md_func EVP_sha256()
00075 #endif
00076 #endif
00077
00078 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) // openssl returns a const SSL_METHOD
00079 typedef const SSL_METHOD * ink_ssl_method_t;
00080 #else
00081 typedef SSL_METHOD * ink_ssl_method_t;
00082 #endif
00083
00084
00085 struct ssl_user_config
00086 {
00087 ssl_user_config () : session_ticket_enabled(1) {
00088 }
00089
00090 int session_ticket_enabled;
00091 ats_scoped_str addr;
00092 ats_scoped_str cert;
00093 ats_scoped_str first_cert;
00094 ats_scoped_str ca;
00095 ats_scoped_str key;
00096 ats_scoped_str ticket_key_filename;
00097 ats_scoped_str dialog;
00098 };
00099
00100
00101 #ifdef SSL_CTX_set_tlsext_ticket_key_cb
00102
00103 #define HAVE_OPENSSL_SESSION_TICKETS 1
00104
00105 static void session_ticket_free(void *, void *, CRYPTO_EX_DATA *, int, long, void *);
00106 static int ssl_callback_session_ticket(SSL *, unsigned char *, unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int);
00107 #endif
00108
00109 struct ssl_ticket_key_t
00110 {
00111 unsigned char key_name[16];
00112 unsigned char hmac_secret[16];
00113 unsigned char aes_key[16];
00114 };
00115
00116 static int ssl_session_ticket_index = -1;
00117 static pthread_mutex_t *mutex_buf = NULL;
00118 static bool open_ssl_initialized = false;
00119
00120 RecRawStatBlock *ssl_rsb = NULL;
00121 static InkHashTable *ssl_cipher_name_table = NULL;
00122
00123
00124
00125
00126
00127
00128 static unsigned long
00129 SSL_pthreads_thread_id()
00130 {
00131 return (unsigned long)pthread_self();
00132 }
00133
00134 static void
00135 SSL_locking_callback(int mode, int type, const char * , int )
00136 {
00137 ink_assert(type < CRYPTO_num_locks());
00138
00139 if (mode & CRYPTO_LOCK) {
00140 pthread_mutex_lock(&mutex_buf[type]);
00141 } else if (mode & CRYPTO_UNLOCK) {
00142 pthread_mutex_unlock(&mutex_buf[type]);
00143 } else {
00144 Debug("ssl", "invalid SSL locking mode 0x%x", mode);
00145 ink_assert(0);
00146 }
00147 }
00148
00149 static bool
00150 SSL_CTX_add_extra_chain_cert_file(SSL_CTX * ctx, const char * chainfile)
00151 {
00152 X509 *cert;
00153 scoped_BIO bio(BIO_new_file(chainfile, "r"));
00154
00155 for (;;) {
00156 cert = PEM_read_bio_X509_AUX(bio.get(), NULL, NULL, NULL);
00157
00158 if (!cert) {
00159
00160 break;
00161 }
00162
00163
00164 if (!SSL_CTX_add_extra_chain_cert(ctx, cert)) {
00165 X509_free(cert);
00166 return false;
00167 }
00168 }
00169
00170 return true;
00171 }
00172
00173 #if TS_USE_TLS_SNI
00174
00175 static int
00176 ssl_servername_callback(SSL * ssl, int * ad, void * arg)
00177 {
00178 SSL_CTX * ctx = NULL;
00179 SSLCertLookup * lookup = (SSLCertLookup *) arg;
00180 const char * servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
00181 SSLNetVConnection * netvc = (SSLNetVConnection *)SSL_get_app_data(ssl);
00182
00183 Debug("ssl", "ssl_servername_callback ssl=%p ad=%d lookup=%p server=%s handshake_complete=%d", ssl, *ad, lookup, servername,
00184 netvc->getSSLHandShakeComplete());
00185
00186
00187 if (SSLConfigParams::ssl_allow_client_renegotiation == false && netvc->getSSLHandShakeComplete()) {
00188 Debug("ssl", "ssl_servername_callback trying to renegotiate from the client");
00189 return SSL_TLSEXT_ERR_ALERT_FATAL;
00190 }
00191
00192
00193
00194
00195 if (likely(servername)) {
00196 ctx = lookup->findInfoInHash((char *)servername);
00197 }
00198
00199
00200 if (ctx == NULL) {
00201 IpEndpoint ip;
00202 int namelen = sizeof(ip);
00203
00204 safe_getsockname(netvc->get_socket(), &ip.sa, &namelen);
00205 ctx = lookup->findInfoInHash(ip);
00206 }
00207
00208 if (ctx != NULL) {
00209 SSL_set_SSL_CTX(ssl, ctx);
00210 }
00211
00212 ctx = SSL_get_SSL_CTX(ssl);
00213 Debug("ssl", "ssl_servername_callback found SSL context %p for requested name '%s'", ctx, servername);
00214
00215 if (ctx == NULL) {
00216 return SSL_TLSEXT_ERR_NOACK;
00217 }
00218
00219
00220
00221
00222 return SSL_TLSEXT_ERR_OK;
00223 }
00224
00225 #endif
00226
00227 static SSL_CTX *
00228 ssl_context_enable_sni(SSL_CTX * ctx, SSLCertLookup * lookup)
00229 {
00230 #if TS_USE_TLS_SNI
00231 if (ctx) {
00232 Debug("ssl", "setting SNI callbacks with for ctx %p", ctx);
00233 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback);
00234 SSL_CTX_set_tlsext_servername_arg(ctx, lookup);
00235 }
00236 #else
00237 (void)lookup;
00238 #endif
00239
00240 return ctx;
00241 }
00242
00243 static SSL_CTX *
00244 ssl_context_enable_ecdh(SSL_CTX * ctx)
00245 {
00246 #if TS_USE_TLS_ECKEY
00247
00248 #if defined(SSL_CTRL_SET_ECDH_AUTO)
00249 SSL_CTX_set_ecdh_auto(ctx, 1);
00250 #elif defined(HAVE_EC_KEY_NEW_BY_CURVE_NAME) && defined(NID_X9_62_prime256v1)
00251 EC_KEY * ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
00252
00253 if (ecdh) {
00254 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
00255 EC_KEY_free(ecdh);
00256 }
00257 #endif
00258 #endif
00259
00260 return ctx;
00261 }
00262
00263 static SSL_CTX *
00264 ssl_context_enable_tickets(SSL_CTX * ctx, const char * ticket_key_path)
00265 {
00266 #if HAVE_OPENSSL_SESSION_TICKETS
00267 ats_scoped_str ticket_key_data;
00268 int ticket_key_len;
00269 ssl_ticket_key_t * ticket_key = NULL;
00270
00271 ticket_key_data = readIntoBuffer(ticket_key_path, __func__, &ticket_key_len);
00272 if (!ticket_key_data) {
00273 Error("failed to read SSL session ticket key from %s", (const char *)ticket_key_path);
00274 goto fail;
00275 }
00276
00277 if (ticket_key_len < 48) {
00278 Error("SSL session ticket key from %s is too short (48 bytes are required)", (const char *)ticket_key_path);
00279 goto fail;
00280 }
00281
00282 ticket_key = new ssl_ticket_key_t();
00283 memcpy(ticket_key->key_name, (const char *)ticket_key_data, 16);
00284 memcpy(ticket_key->hmac_secret, (const char *)ticket_key_data + 16, 16);
00285 memcpy(ticket_key->aes_key, (const char *)ticket_key_data + 32, 16);
00286
00287
00288
00289
00290 if (SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_callback_session_ticket) == 0) {
00291 Error("failed to set session ticket callback");
00292 goto fail;
00293 }
00294
00295 if (SSL_CTX_set_ex_data(ctx, ssl_session_ticket_index, ticket_key) == 0) {
00296 Error ("failed to set session ticket data to ctx");
00297 goto fail;
00298 }
00299
00300 SSL_CTX_clear_options(ctx, SSL_OP_NO_TICKET);
00301 return ctx;
00302
00303 fail:
00304 delete ticket_key;
00305 return ctx;
00306
00307 #else
00308 (void)ticket_key_path;
00309 return ctx;
00310 #endif
00311 }
00312
00313 struct passphrase_cb_userdata
00314 {
00315 const SSLConfigParams * _configParams;
00316 const char * _serverDialog;
00317 const char * _serverCert;
00318 const char * _serverKey;
00319
00320 passphrase_cb_userdata(const SSLConfigParams *params,const char *dialog, const char *cert, const char *key) :
00321 _configParams(params), _serverDialog(dialog), _serverCert(cert), _serverKey(key) {}
00322 };
00323
00324
00325 struct ssl_termios : public termios
00326 {
00327 ssl_termios(int fd) {
00328 _fd = -1;
00329
00330 if (tcgetattr(fd, this) == 0) {
00331 _fd = fd;
00332 }
00333
00334 _initialAttr = *this;
00335 }
00336
00337 ~ssl_termios() {
00338 if (_fd != -1) {
00339 tcsetattr(_fd, 0, &_initialAttr);
00340 }
00341 }
00342
00343 bool ok() {
00344 return (_fd != -1);
00345 }
00346
00347 private:
00348 int _fd;
00349 struct termios _initialAttr;
00350 };
00351
00352 static int
00353 ssl_getpassword(const char* prompt, char* buffer, int size)
00354 {
00355 fprintf(stdout, "%s", prompt);
00356
00357
00358 ssl_termios tty_attr(STDIN_FILENO);
00359
00360 if (!tty_attr.ok()) {
00361 return -1;
00362 }
00363
00364 tty_attr.c_lflag &= ~ICANON;
00365 tty_attr.c_lflag &= ~ECHO;
00366 tty_attr.c_lflag &= ~ISIG;
00367
00368 if (tcsetattr(STDIN_FILENO, 0, &tty_attr) < 0) {
00369 return -1;
00370 }
00371
00372 int i = 0;
00373 int ch = 0;
00374 *buffer = 0;
00375 while ((ch = getchar()) != '\n' && ch != EOF) {
00376
00377 if (i >= size - 1) {
00378 return -1;
00379 }
00380
00381 buffer[i] = ch;
00382 buffer[++i] = 0;
00383 }
00384
00385 return i;
00386 }
00387
00388 static int
00389 ssl_private_key_passphrase_callback_exec(char *buf, int size, int rwflag, void *userdata)
00390 {
00391 if (0 == size) {
00392 return 0;
00393 }
00394
00395 *buf = 0;
00396 passphrase_cb_userdata *ud = static_cast<passphrase_cb_userdata *> (userdata);
00397
00398 Debug("ssl", "ssl_private_key_passphrase_callback_exec rwflag=%d serverDialog=%s", rwflag, ud->_serverDialog);
00399
00400
00401 if (0 == rwflag) {
00402
00403 FILE *f = popen(ud->_serverDialog, "r");
00404 if (f) {
00405 if (fgets(buf, size, f)) {
00406
00407 for (char *pass = buf; *pass; pass++) {
00408 if (*pass == '\n' || *pass == '\r') {
00409 *pass = 0;
00410 break;
00411 }
00412 }
00413 }
00414 pclose(f);
00415 } else {
00416 Error("could not open dialog '%s' - %s", ud->_serverDialog, strerror(errno));
00417 }
00418 }
00419 return strlen(buf);
00420 }
00421
00422 static int
00423 ssl_private_key_passphrase_callback_builtin(char *buf, int size, int rwflag, void *userdata)
00424 {
00425 if (0 == size) {
00426 return 0;
00427 }
00428
00429 *buf = 0;
00430 passphrase_cb_userdata *ud = static_cast<passphrase_cb_userdata *> (userdata);
00431
00432 Debug("ssl", "ssl_private_key_passphrase_callback rwflag=%d serverDialog=%s", rwflag, ud->_serverDialog);
00433
00434
00435 if (0 == rwflag) {
00436
00437 fprintf(stdout, "Some of your private key files are encrypted for security reasons.\n");
00438 fprintf(stdout, "In order to read them you have to provide the pass phrases.\n");
00439 fprintf(stdout, "ssl_cert_name=%s", ud->_serverCert);
00440 if (ud->_serverKey) {
00441 fprintf(stdout, " ssl_key_name=%s", ud->_serverKey);
00442 }
00443 fprintf(stdout, "\n");
00444
00445
00446 if (ssl_getpassword("Enter passphrase:", buf, size) <= 0) {
00447 *buf = 0;
00448 }
00449 fprintf(stdout, "\n");
00450 }
00451 return strlen(buf);
00452 }
00453
00454 static bool
00455 ssl_private_key_validate_exec(const char *cmdLine)
00456 {
00457 if (NULL == cmdLine) {
00458 errno = EINVAL;
00459 return false;
00460 }
00461
00462 bool bReturn = false;
00463 char *cmdLineCopy = ats_strdup(cmdLine);
00464 char *ptr = cmdLineCopy;
00465
00466 while(*ptr && !isspace(*ptr)) ++ptr;
00467 *ptr = 0;
00468 if (access(cmdLineCopy, X_OK) != -1) {
00469 bReturn = true;
00470 }
00471 ats_free(cmdLineCopy);
00472 return bReturn;
00473 }
00474
00475 static int
00476 SSLRecRawStatSyncCount(const char *name, RecDataT data_type, RecData *data, RecRawStatBlock *rsb, int id)
00477 {
00478
00479
00480 SSLCertificateConfig::scoped_config certLookup;
00481
00482 int64_t sessions = 0;
00483 int64_t hits = 0;
00484 int64_t misses = 0;
00485 int64_t timeouts = 0;
00486
00487 if (certLookup) {
00488 const unsigned ctxCount = certLookup->count();
00489 for (size_t i = 0; i < ctxCount; i++) {
00490 SSL_CTX * ctx = certLookup->get(i);
00491
00492 sessions += SSL_CTX_sess_accept_good(ctx);
00493 hits += SSL_CTX_sess_hits(ctx);
00494 misses += SSL_CTX_sess_misses(ctx);
00495 timeouts += SSL_CTX_sess_timeouts(ctx);
00496 }
00497 }
00498
00499 SSL_SET_COUNT_DYN_STAT(ssl_user_agent_sessions_stat, sessions);
00500 SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_hit_stat, hits);
00501 SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_miss_stat, misses);
00502 SSL_SET_COUNT_DYN_STAT(ssl_user_agent_session_timeout_stat, timeouts);
00503 return RecRawStatSyncCount(name, data_type, data, rsb, id);
00504 }
00505
00506 void
00507 SSLInitializeLibrary()
00508 {
00509 if (!open_ssl_initialized) {
00510 CRYPTO_set_mem_functions(ats_malloc, ats_realloc, ats_free);
00511
00512 SSL_load_error_strings();
00513 SSL_library_init();
00514
00515 mutex_buf = (pthread_mutex_t *) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
00516
00517 for (int i = 0; i < CRYPTO_num_locks(); i++) {
00518 pthread_mutex_init(&mutex_buf[i], NULL);
00519 }
00520
00521 CRYPTO_set_locking_callback(SSL_locking_callback);
00522 CRYPTO_set_id_callback(SSL_pthreads_thread_id);
00523 }
00524
00525 #ifdef SSL_CTX_set_tlsext_ticket_key_cb
00526 ssl_session_ticket_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, session_ticket_free);
00527 if (ssl_session_ticket_index == -1) {
00528 SSLError("failed to create session ticket index");
00529 }
00530 #endif
00531
00532 #ifdef HAVE_OPENSSL_OCSP_STAPLING
00533 ssl_stapling_ex_init();
00534 #endif
00535
00536 open_ssl_initialized = true;
00537 }
00538
00539 void
00540 SSLInitializeStatistics()
00541 {
00542 SSL_CTX * ctx;
00543 SSL * ssl;
00544 STACK_OF(SSL_CIPHER) * ciphers;
00545
00546
00547 ssl_rsb = RecAllocateRawStatBlock((int) Ssl_Stat_Count);
00548 ink_assert(ssl_rsb != NULL);
00549
00550
00551 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_other_errors",
00552 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_other_errors_stat,
00553 RecRawStatSyncSum);
00554 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_expired_cert",
00555 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_expired_cert_stat,
00556 RecRawStatSyncSum);
00557 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_revoked_cert",
00558 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_revoked_cert_stat,
00559 RecRawStatSyncSum);
00560 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_unknown_cert",
00561 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_unknown_cert_stat,
00562 RecRawStatSyncSum);
00563 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_cert_verify_failed",
00564 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_cert_verify_failed_stat,
00565 RecRawStatSyncSum);
00566 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_bad_cert",
00567 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_bad_cert_stat,
00568 RecRawStatSyncSum);
00569 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_decryption_failed",
00570 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_decryption_failed_stat,
00571 RecRawStatSyncSum);
00572 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_wrong_version",
00573 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_wrong_version_stat,
00574 RecRawStatSyncSum);
00575 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_unknown_ca",
00576 RECD_INT, RECP_PERSISTENT, (int) ssl_user_agent_unknown_ca_stat,
00577 RecRawStatSyncSum);
00578
00579
00580 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_sessions",
00581 RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_sessions_stat,
00582 SSLRecRawStatSyncCount);
00583 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_hit",
00584 RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_hit_stat,
00585 RecRawStatSyncCount);
00586 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_miss",
00587 RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_miss_stat,
00588 RecRawStatSyncCount);
00589 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.user_agent_session_timeout",
00590 RECD_INT, RECP_NON_PERSISTENT, (int) ssl_user_agent_session_timeout_stat,
00591 RecRawStatSyncCount);
00592
00593
00594 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_other_errors",
00595 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_other_errors_stat,
00596 RecRawStatSyncSum);
00597 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_expired_cert",
00598 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_expired_cert_stat,
00599 RecRawStatSyncSum);
00600 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_revoked_cert",
00601 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_revoked_cert_stat,
00602 RecRawStatSyncSum);
00603 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_unknown_cert",
00604 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_unknown_cert_stat,
00605 RecRawStatSyncSum);
00606 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_cert_verify_failed",
00607 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_cert_verify_failed_stat,
00608 RecRawStatSyncSum);
00609 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_bad_cert",
00610 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_bad_cert_stat,
00611 RecRawStatSyncSum);
00612 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_decryption_failed",
00613 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_decryption_failed_stat,
00614 RecRawStatSyncSum);
00615 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_wrong_version",
00616 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_wrong_version_stat,
00617 RecRawStatSyncSum);
00618 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_server_unknown_ca",
00619 RECD_INT, RECP_PERSISTENT, (int) ssl_origin_server_unknown_ca_stat,
00620 RecRawStatSyncSum);
00621
00622
00623 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_handshake_time",
00624 RECD_INT, RECP_PERSISTENT, (int) ssl_total_handshake_time_stat,
00625 RecRawStatSyncSum);
00626 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_success_handshake_count",
00627 RECD_INT, RECP_PERSISTENT, (int) ssl_total_success_handshake_count_stat,
00628 RecRawStatSyncCount);
00629
00630
00631 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_tickets_created",
00632 RECD_INT, RECP_PERSISTENT, (int) ssl_total_tickets_created_stat,
00633 RecRawStatSyncCount);
00634 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_tickets_verified",
00635 RECD_INT, RECP_PERSISTENT, (int) ssl_total_tickets_verified_stat,
00636 RecRawStatSyncCount);
00637 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_tickets_not_found",
00638 RECD_INT, RECP_PERSISTENT, (int) ssl_total_tickets_not_found_stat,
00639 RecRawStatSyncCount);
00640
00641 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_tickets_renewed",
00642 RECD_INT, RECP_PERSISTENT, (int) ssl_total_tickets_renewed_stat,
00643 RecRawStatSyncCount);
00644
00645
00646
00647 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_want_write",
00648 RECD_INT, RECP_PERSISTENT, (int) ssl_error_want_write,
00649 RecRawStatSyncCount);
00650 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_want_read",
00651 RECD_INT, RECP_PERSISTENT, (int) ssl_error_want_read,
00652 RecRawStatSyncCount);
00653 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_want_x509_lookup",
00654 RECD_INT, RECP_PERSISTENT, (int) ssl_error_want_x509_lookup,
00655 RecRawStatSyncCount);
00656 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_syscall",
00657 RECD_INT, RECP_PERSISTENT, (int) ssl_error_syscall,
00658 RecRawStatSyncCount);
00659 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_read_eos",
00660 RECD_INT, RECP_PERSISTENT, (int) ssl_error_read_eos,
00661 RecRawStatSyncCount);
00662 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_zero_return",
00663 RECD_INT, RECP_PERSISTENT, (int) ssl_error_zero_return,
00664 RecRawStatSyncCount);
00665 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_error_ssl",
00666 RECD_INT, RECP_PERSISTENT, (int) ssl_error_ssl,
00667 RecRawStatSyncCount);
00668 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.ssl_sni_name_set_failure",
00669 RECD_INT, RECP_PERSISTENT, (int) ssl_sni_name_set_failure,
00670 RecRawStatSyncCount);
00671
00672
00673
00674
00675
00676
00677
00678
00679 ssl_cipher_name_table = ink_hash_table_create(InkHashTableKeyType_Word);
00680
00681 ctx = SSLDefaultServerContext();
00682 ssl = SSL_new(ctx);
00683 ciphers = SSL_get_ciphers(ssl);
00684
00685 for (int index = 0; index < sk_SSL_CIPHER_num(ciphers); index++) {
00686 SSL_CIPHER * cipher = sk_SSL_CIPHER_value(ciphers, index);
00687 const char * cipherName = SSL_CIPHER_get_name(cipher);
00688 std::string statName = "proxy.process.ssl.cipher.user_agent." + std::string(cipherName);
00689
00690
00691 if ((ssl_cipher_stats_start + index) > ssl_cipher_stats_end) {
00692
00693 SSLError("too many ciphers to register metric '%s', increase SSL_Stats::ssl_cipher_stats_end",
00694 statName.c_str());
00695 continue;
00696 }
00697
00698
00699 if (!ink_hash_table_isbound(ssl_cipher_name_table, cipherName)) {
00700 ink_hash_table_insert(ssl_cipher_name_table, cipherName, (void *)(intptr_t) (ssl_cipher_stats_start + index));
00701
00702 RecRegisterRawStat(ssl_rsb, RECT_PROCESS, statName.c_str(),
00703 RECD_INT, RECP_NON_PERSISTENT, (int) ssl_cipher_stats_start + index,
00704 RecRawStatSyncSum);
00705 SSL_CLEAR_DYN_STAT((int) ssl_cipher_stats_start + index);
00706 Debug("ssl", "registering SSL cipher metric '%s'", statName.c_str());
00707 }
00708 }
00709
00710 SSL_free(ssl);
00711 SSL_CTX_free(ctx);
00712 }
00713
00714
00715 static bool
00716 increment_ssl_client_error(unsigned long err)
00717 {
00718
00719 if (ERR_LIB_SSL != ERR_GET_LIB(err)) {
00720 SSL_INCREMENT_DYN_STAT(ssl_user_agent_other_errors_stat);
00721 return false;
00722 }
00723
00724
00725
00726
00727 switch (ERR_GET_REASON(err)) {
00728 case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
00729 SSL_INCREMENT_DYN_STAT(ssl_user_agent_expired_cert_stat);
00730 break;
00731 case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
00732 SSL_INCREMENT_DYN_STAT(ssl_user_agent_revoked_cert_stat);
00733 break;
00734 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
00735 SSL_INCREMENT_DYN_STAT(ssl_user_agent_unknown_cert_stat);
00736 break;
00737 case SSL_R_CERTIFICATE_VERIFY_FAILED:
00738 SSL_INCREMENT_DYN_STAT(ssl_user_agent_cert_verify_failed_stat);
00739 break;
00740 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
00741 SSL_INCREMENT_DYN_STAT(ssl_user_agent_bad_cert_stat);
00742 break;
00743 case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
00744 SSL_INCREMENT_DYN_STAT(ssl_user_agent_decryption_failed_stat);
00745 break;
00746 case SSL_R_WRONG_VERSION_NUMBER:
00747 SSL_INCREMENT_DYN_STAT(ssl_user_agent_wrong_version_stat);
00748 break;
00749 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
00750 SSL_INCREMENT_DYN_STAT(ssl_user_agent_unknown_ca_stat);
00751 break;
00752 default:
00753 SSL_INCREMENT_DYN_STAT(ssl_user_agent_other_errors_stat);
00754 return false;
00755 }
00756
00757 return true;
00758 }
00759
00760
00761
00762 static bool
00763 increment_ssl_server_error(unsigned long err)
00764 {
00765
00766 if (ERR_LIB_SSL != ERR_GET_LIB(err)) {
00767 SSL_INCREMENT_DYN_STAT(ssl_origin_server_other_errors_stat);
00768 return false;
00769 }
00770
00771
00772
00773
00774 switch (ERR_GET_REASON(err)) {
00775 case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
00776 SSL_INCREMENT_DYN_STAT(ssl_origin_server_expired_cert_stat);
00777 break;
00778 case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
00779 SSL_INCREMENT_DYN_STAT(ssl_origin_server_revoked_cert_stat);
00780 break;
00781 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
00782 SSL_INCREMENT_DYN_STAT(ssl_origin_server_unknown_cert_stat);
00783 break;
00784 case SSL_R_CERTIFICATE_VERIFY_FAILED:
00785 SSL_INCREMENT_DYN_STAT(ssl_origin_server_cert_verify_failed_stat);
00786 break;
00787 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
00788 SSL_INCREMENT_DYN_STAT(ssl_origin_server_bad_cert_stat);
00789 break;
00790 case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
00791 SSL_INCREMENT_DYN_STAT(ssl_origin_server_decryption_failed_stat);
00792 break;
00793 case SSL_R_WRONG_VERSION_NUMBER:
00794 SSL_INCREMENT_DYN_STAT(ssl_origin_server_wrong_version_stat);
00795 break;
00796 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
00797 SSL_INCREMENT_DYN_STAT(ssl_origin_server_unknown_ca_stat);
00798 break;
00799 default:
00800 SSL_INCREMENT_DYN_STAT(ssl_origin_server_other_errors_stat);
00801 return false;
00802 }
00803
00804 return true;
00805 }
00806
00807 void
00808 SSLDiagnostic(const SrcLoc& loc, bool debug, SSLNetVConnection * vc, const char * fmt, ...)
00809 {
00810 unsigned long l;
00811 char buf[256];
00812 const char *file, *data;
00813 int line, flags;
00814 unsigned long es;
00815 va_list ap;
00816
00817 ip_text_buffer ip_buf;
00818 bool ip_buf_flag = false;
00819 if (vc) {
00820 ats_ip_ntop(vc->get_remote_addr(), ip_buf, sizeof(ip_buf));
00821 ip_buf_flag = true;
00822 }
00823
00824 es = CRYPTO_thread_id();
00825 while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
00826 if (debug) {
00827 if (unlikely(diags->on())) {
00828 diags->log("ssl", DL_Debug, loc.file, loc.func, loc.line,
00829 "SSL::%lu:%s:%s:%d%s%s%s%s", es, ERR_error_string(l, buf), file, line,
00830 (flags & ERR_TXT_STRING) ? ":" : "", (flags & ERR_TXT_STRING) ? data : "",
00831 ip_buf_flag? ": peer address is " : "", ip_buf);
00832 }
00833 } else {
00834 diags->error(DL_Error, loc.file, loc.func, loc.line,
00835 "SSL::%lu:%s:%s:%d%s%s%s%s", es, ERR_error_string(l, buf), file, line,
00836 (flags & ERR_TXT_STRING) ? ":" : "", (flags & ERR_TXT_STRING) ? data : "",
00837 ip_buf_flag? ": peer address is " : "", ip_buf);
00838 }
00839
00840
00841
00842 if (vc) {
00843
00844 if (vc->getSSLClientConnection()) {
00845 increment_ssl_server_error(l);
00846 } else {
00847 increment_ssl_client_error(l);
00848 }
00849 }
00850 }
00851
00852 va_start(ap, fmt);
00853 if (debug) {
00854 diags->log_va("ssl", DL_Debug, &loc, fmt, ap);
00855 } else {
00856 diags->error_va(DL_Error, loc.file, loc.func, loc.line, fmt, ap);
00857 }
00858 va_end(ap);
00859
00860 }
00861
00862 const char *
00863 SSLErrorName(int ssl_error)
00864 {
00865 static const char * names[] = {
00866 "SSL_ERROR_NONE",
00867 "SSL_ERROR_SSL",
00868 "SSL_ERROR_WANT_READ",
00869 "SSL_ERROR_WANT_WRITE",
00870 "SSL_ERROR_WANT_X509_LOOKUP",
00871 "SSL_ERROR_SYSCALL",
00872 "SSL_ERROR_ZERO_RETURN",
00873 "SSL_ERROR_WANT_CONNECT",
00874 "SSL_ERROR_WANT_ACCEPT"
00875 };
00876
00877 if (ssl_error < 0 || ssl_error >= (int)countof(names)) {
00878 return "unknown SSL error";
00879 }
00880
00881 return names[ssl_error];
00882 }
00883
00884 void
00885 SSLDebugBufferPrint(const char * tag, const char * buffer, unsigned buflen, const char * message)
00886 {
00887 if (is_debug_tag_set(tag)) {
00888 if (message != NULL) {
00889 fprintf(stdout, "%s\n", message);
00890 }
00891 for (unsigned ii = 0; ii < buflen; ii++) {
00892 putc(buffer[ii], stdout);
00893 }
00894 putc('\n', stdout);
00895 }
00896 }
00897
00898 SSL_CTX *
00899 SSLDefaultServerContext()
00900 {
00901 ink_ssl_method_t meth = NULL;
00902
00903 meth = SSLv23_server_method();
00904 return SSL_CTX_new(meth);
00905 }
00906
00907 static bool
00908 SSLPrivateKeyHandler(
00909 SSL_CTX * ctx,
00910 const SSLConfigParams * params,
00911 const ats_scoped_str& completeServerCertPath,
00912 const char * keyPath)
00913 {
00914 if (!keyPath) {
00915
00916 if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerCertPath, SSL_FILETYPE_PEM)) {
00917 SSLError("failed to load server private key from %s", (const char *) completeServerCertPath);
00918 return false;
00919 }
00920 } else if (params->serverKeyPathOnly != NULL) {
00921 ats_scoped_str completeServerKeyPath(Layout::get()->relative_to(params->serverKeyPathOnly, keyPath));
00922 if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerKeyPath, SSL_FILETYPE_PEM)) {
00923 SSLError("failed to load server private key from %s", (const char *) completeServerKeyPath);
00924 return false;
00925 }
00926 } else {
00927 SSLError("empty SSL private key path in records.config");
00928 }
00929
00930 if (!SSL_CTX_check_private_key(ctx)) {
00931 SSLError("server private key does not match the certificate public key");
00932 return false;
00933 }
00934
00935 return true;
00936 }
00937
00938 SSL_CTX *
00939 SSLInitServerContext(
00940 const SSLConfigParams * params,
00941 const ssl_user_config & sslMultCertSettings)
00942 {
00943 int session_id_context;
00944 int server_verify_client;
00945 ats_scoped_str completeServerCertPath;
00946 SSL_CTX * ctx = SSLDefaultServerContext();
00947
00948
00949 SSL_CTX_set_options(ctx, params->ssl_ctx_options);
00950
00951 switch (params->ssl_session_cache) {
00952 case SSLConfigParams::SSL_SESSION_CACHE_MODE_OFF:
00953 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF|SSL_SESS_CACHE_NO_INTERNAL);
00954 break;
00955 case SSLConfigParams::SSL_SESSION_CACHE_MODE_SERVER:
00956 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
00957 SSL_CTX_sess_set_cache_size(ctx, params->ssl_session_cache_size);
00958 if (params->ssl_session_cache_timeout) {
00959 SSL_CTX_set_timeout(ctx, params->ssl_session_cache_timeout);
00960 }
00961 break;
00962 }
00963
00964 #ifdef SSL_MODE_RELEASE_BUFFERS
00965 if (OPENSSL_VERSION_NUMBER > 0x1000107fL) {
00966 Debug("ssl", "enabling SSL_MODE_RELEASE_BUFFERS");
00967 SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
00968 }
00969 #endif
00970
00971 #ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG
00972 SSL_CTX_set_options(ctx, SSL_OP_SAFARI_ECDHE_ECDSA_BUG);
00973 #endif
00974
00975 SSL_CTX_set_quiet_shutdown(ctx, 1);
00976
00977
00978 passphrase_cb_userdata ud(params, sslMultCertSettings.dialog, sslMultCertSettings.first_cert, sslMultCertSettings.key);
00979
00980 if (sslMultCertSettings.dialog) {
00981 pem_password_cb * passwd_cb = NULL;
00982 if (strncmp(sslMultCertSettings.dialog, "exec:", 5) == 0) {
00983 ud._serverDialog = &sslMultCertSettings.dialog[5];
00984
00985 if (!ssl_private_key_validate_exec(ud._serverDialog)) {
00986 SSLError("failed to access '%s' pass phrase program: %s", (const char *) ud._serverDialog, strerror(errno));
00987 goto fail;
00988 }
00989 passwd_cb = ssl_private_key_passphrase_callback_exec;
00990 } else if (strcmp(sslMultCertSettings.dialog, "builtin") == 0) {
00991 passwd_cb = ssl_private_key_passphrase_callback_builtin;
00992 } else {
00993 SSLError("unknown " SSL_KEY_DIALOG " configuration value '%s'", (const char *)sslMultCertSettings.dialog);
00994 goto fail;
00995 }
00996 SSL_CTX_set_default_passwd_cb(ctx, passwd_cb);
00997 SSL_CTX_set_default_passwd_cb_userdata(ctx, &ud);
00998 }
00999
01000 if (!params->serverCertChainFilename && !sslMultCertSettings.ca && sslMultCertSettings.cert) {
01001 SimpleTokenizer cert_tok((const char *)sslMultCertSettings.cert, SSL_CERT_SEPARATE_DELIM);
01002 SimpleTokenizer key_tok((sslMultCertSettings.key ? (const char *)sslMultCertSettings.key : ""), SSL_CERT_SEPARATE_DELIM);
01003
01004 if (sslMultCertSettings.key && cert_tok.getNumTokensRemaining() != key_tok.getNumTokensRemaining()) {
01005 Error("the number of certificates in ssl_cert_name and ssl_key_name doesn't match");
01006 goto fail;
01007 }
01008
01009 for (const char * certname = cert_tok.getNext(); certname; certname = cert_tok.getNext()) {
01010 completeServerCertPath = Layout::relative_to(params->serverCertPathOnly, certname);
01011 if (SSL_CTX_use_certificate_chain_file(ctx, completeServerCertPath) < 0) {
01012 SSLError("failed to load certificate chain from %s", (const char *)completeServerCertPath);
01013 goto fail;
01014 }
01015
01016 const char * keyPath = key_tok.getNext();
01017 if (!SSLPrivateKeyHandler(ctx, params, completeServerCertPath, keyPath)) {
01018 goto fail;
01019 }
01020 }
01021 } else if (sslMultCertSettings.first_cert) {
01022 completeServerCertPath = Layout::relative_to(params->serverCertPathOnly, sslMultCertSettings.first_cert);
01023 if (!SSL_CTX_use_certificate_chain_file(ctx, completeServerCertPath)) {
01024 SSLError("failed to load certificate from %s", (const char *) completeServerCertPath);
01025 goto fail;
01026 }
01027
01028
01029 if (params->serverCertChainFilename) {
01030 ats_scoped_str completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, params->serverCertChainFilename));
01031 if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) {
01032 SSLError("failed to load global certificate chain from %s", (const char *) completeServerCertChainPath);
01033 goto fail;
01034 }
01035 }
01036
01037
01038 if (sslMultCertSettings.ca) {
01039 ats_scoped_str completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, sslMultCertSettings.ca));
01040 if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) {
01041 SSLError("failed to load certificate chain from %s", (const char *) completeServerCertChainPath);
01042 goto fail;
01043 }
01044 }
01045
01046 if (!SSLPrivateKeyHandler(ctx, params, completeServerCertPath, sslMultCertSettings.key)) {
01047 goto fail;
01048 }
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 if (!sslMultCertSettings.ca && params->serverCACertPath != NULL) {
01064 if ((!SSL_CTX_load_verify_locations(ctx, params->serverCACertFilename, params->serverCACertPath)) ||
01065 (!SSL_CTX_set_default_verify_paths(ctx))) {
01066 SSLError("invalid CA Certificate file or CA Certificate path");
01067 goto fail;
01068 }
01069 }
01070
01071 if (params->clientCertLevel != 0) {
01072
01073 if (params->serverCACertFilename != NULL && params->serverCACertPath != NULL) {
01074 if ((!SSL_CTX_load_verify_locations(ctx, params->serverCACertFilename, params->serverCACertPath)) ||
01075 (!SSL_CTX_set_default_verify_paths(ctx))) {
01076 SSLError("CA Certificate file or CA Certificate path invalid");
01077 goto fail;
01078 }
01079 }
01080
01081 if (params->clientCertLevel == 2) {
01082 server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
01083 } else if (params->clientCertLevel == 1) {
01084 server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
01085 } else {
01086
01087 server_verify_client = SSL_VERIFY_NONE;
01088 Error("illegal client certification level %d in records.config", server_verify_client);
01089 }
01090
01091
01092
01093 session_id_context = 1;
01094 SSL_CTX_set_session_id_context(ctx, (const unsigned char *) &session_id_context, sizeof(session_id_context));
01095
01096 SSL_CTX_set_verify(ctx, server_verify_client, NULL);
01097 SSL_CTX_set_verify_depth(ctx, params->verify_depth);
01098
01099 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(params->serverCACertFilename));
01100 }
01101
01102 if (params->cipherSuite != NULL) {
01103 if (!SSL_CTX_set_cipher_list(ctx, params->cipherSuite)) {
01104 SSLError("invalid cipher suite in records.config");
01105 goto fail;
01106 }
01107 }
01108 #define SSL_CLEAR_PW_REFERENCES(UD,CTX) { \
01109 memset(static_cast<void *>(&UD),0,sizeof(UD));\
01110 SSL_CTX_set_default_passwd_cb(CTX, NULL);\
01111 SSL_CTX_set_default_passwd_cb_userdata(CTX, NULL);\
01112 }
01113 SSL_CLEAR_PW_REFERENCES(ud,ctx)
01114 return ssl_context_enable_ecdh(ctx);
01115
01116 fail:
01117 SSL_CLEAR_PW_REFERENCES(ud,ctx)
01118 SSL_CTX_free(ctx);
01119
01120 return NULL;
01121 }
01122
01123 SSL_CTX *
01124 SSLInitClientContext(const SSLConfigParams * params)
01125 {
01126 ink_ssl_method_t meth = NULL;
01127 SSL_CTX * client_ctx = NULL;
01128 char * clientKeyPtr = NULL;
01129
01130
01131
01132
01133
01134 meth = SSLv23_client_method();
01135 client_ctx = SSL_CTX_new(meth);
01136
01137
01138 SSL_CTX_set_options(client_ctx, params->ssl_ctx_options);
01139 if (!client_ctx) {
01140 SSLError("cannot create new client context");
01141 return NULL;
01142 }
01143
01144 if (params->ssl_client_ctx_protocols) {
01145 SSL_CTX_set_options(client_ctx, params->ssl_client_ctx_protocols);
01146 }
01147 if (params->client_cipherSuite != NULL) {
01148 if (!SSL_CTX_set_cipher_list(client_ctx, params->client_cipherSuite)) {
01149 SSLError("invalid client cipher suite in records.config");
01150 goto fail;
01151 }
01152 }
01153
01154
01155
01156 clientKeyPtr = params->clientKeyPath;
01157 if (clientKeyPtr == NULL) {
01158 clientKeyPtr = params->clientCertPath;
01159 }
01160
01161 if (params->clientCertPath != 0) {
01162 if (!SSL_CTX_use_certificate_chain_file(client_ctx, params->clientCertPath)) {
01163 SSLError("failed to load client certificate from %s", params->clientCertPath);
01164 goto fail;
01165 }
01166
01167 if (!SSL_CTX_use_PrivateKey_file(client_ctx, clientKeyPtr, SSL_FILETYPE_PEM)) {
01168 SSLError("failed to load client private key file from %s", clientKeyPtr);
01169 goto fail;
01170 }
01171
01172 if (!SSL_CTX_check_private_key(client_ctx)) {
01173 SSLError("client private key (%s) does not match the certificate public key (%s)",
01174 clientKeyPtr, params->clientCertPath);
01175 goto fail;
01176 }
01177 }
01178
01179 if (params->clientVerify) {
01180 int client_verify_server;
01181
01182 client_verify_server = params->clientVerify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
01183 SSL_CTX_set_verify(client_ctx, client_verify_server, NULL);
01184 SSL_CTX_set_verify_depth(client_ctx, params->client_verify_depth);
01185
01186 if (params->clientCACertFilename != NULL && params->clientCACertPath != NULL) {
01187 if (!SSL_CTX_load_verify_locations(client_ctx, params->clientCACertFilename, params->clientCACertPath)) {
01188 SSLError("invalid client CA Certificate file (%s) or CA Certificate path (%s)",
01189 params->clientCACertFilename, params->clientCACertPath);
01190 goto fail;
01191 }
01192 }
01193
01194 if (!SSL_CTX_set_default_verify_paths(client_ctx)) {
01195 SSLError("failed to set the default verify paths");
01196 goto fail;
01197 }
01198 }
01199
01200 if (SSLConfigParams::init_ssl_ctx_cb) {
01201 SSLConfigParams::init_ssl_ctx_cb(client_ctx, false);
01202 }
01203
01204 return client_ctx;
01205
01206 fail:
01207 SSL_CTX_free(client_ctx);
01208 return NULL;
01209 }
01210
01211 static char *
01212 asn1_strdup(ASN1_STRING * s)
01213 {
01214
01215 ink_assert(ASN1_STRING_type(s) == V_ASN1_IA5STRING ||
01216 ASN1_STRING_type(s) == V_ASN1_UTF8STRING ||
01217 ASN1_STRING_type(s) == V_ASN1_PRINTABLESTRING ||
01218 ASN1_STRING_type(s) == V_ASN1_T61STRING);
01219
01220 return ats_strndup((const char *)ASN1_STRING_data(s), ASN1_STRING_length(s));
01221 }
01222
01223
01224
01225
01226 static void
01227 ssl_index_certificate(SSLCertLookup * lookup, SSL_CTX * ctx, const char * certfile)
01228 {
01229 X509_NAME * subject = NULL;
01230 X509 * cert;
01231 scoped_BIO bio(BIO_new_file(certfile, "r"));
01232
01233 cert = PEM_read_bio_X509_AUX(bio.get(), NULL, NULL, NULL);
01234 if (NULL == cert) {
01235 return;
01236 }
01237
01238
01239 subject = X509_get_subject_name(cert);
01240 if (subject) {
01241 int pos = -1;
01242 for (;;) {
01243 pos = X509_NAME_get_index_by_NID(subject, NID_commonName, pos);
01244 if (pos == -1) {
01245 break;
01246 }
01247
01248 X509_NAME_ENTRY * e = X509_NAME_get_entry(subject, pos);
01249 ASN1_STRING * cn = X509_NAME_ENTRY_get_data(e);
01250 ats_scoped_str name(asn1_strdup(cn));
01251
01252 Debug("ssl", "mapping '%s' to certificate %s", (const char *) name, certfile);
01253 lookup->insert(ctx, name);
01254 }
01255 }
01256
01257 #if HAVE_OPENSSL_TS_H
01258
01259 GENERAL_NAMES * names = (GENERAL_NAMES *) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
01260 if (names) {
01261 unsigned count = sk_GENERAL_NAME_num(names);
01262 for (unsigned i = 0; i < count; ++i) {
01263 GENERAL_NAME * name;
01264
01265 name = sk_GENERAL_NAME_value(names, i);
01266 if (name->type == GEN_DNS) {
01267 ats_scoped_str dns(asn1_strdup(name->d.dNSName));
01268 Debug("ssl", "mapping '%s' to certificate %s", (const char *) dns, certfile);
01269 lookup->insert(ctx, dns);
01270 }
01271 }
01272
01273 GENERAL_NAMES_free(names);
01274 }
01275 #endif // HAVE_OPENSSL_TS_H
01276 X509_free(cert);
01277 }
01278
01279
01280
01281
01282 static void
01283 ssl_callback_info(const SSL *ssl, int where, int ret)
01284 {
01285 Debug("ssl", "ssl_callback_info ssl: %p where: %d ret: %d", ssl, where, ret);
01286 SSLNetVConnection * netvc = (SSLNetVConnection *)SSL_get_app_data(ssl);
01287
01288 if ((where & SSL_CB_ACCEPT_LOOP) && netvc->getSSLHandShakeComplete() == true &&
01289 SSLConfigParams::ssl_allow_client_renegotiation == false) {
01290 int state = SSL_get_state(ssl);
01291
01292 if (state == SSL3_ST_SR_CLNT_HELLO_A || state == SSL23_ST_SR_CLNT_HELLO_A) {
01293 netvc->setSSLClientRenegotiationAbort(true);
01294 Debug("ssl", "ssl_callback_info trying to renegotiate from the client");
01295 }
01296 }
01297 if (where & SSL_CB_HANDSHAKE_DONE) {
01298
01299 const SSL_CIPHER * cipher = SSL_get_current_cipher(ssl);
01300 if (cipher) {
01301 const char * cipherName = SSL_CIPHER_get_name(cipher);
01302
01303 InkHashTableValue data;
01304 if (ink_hash_table_lookup(ssl_cipher_name_table, cipherName, &data)) {
01305 SSL_INCREMENT_DYN_STAT((intptr_t)data);
01306 }
01307 }
01308 }
01309 }
01310
01311 static bool
01312 ssl_store_ssl_context(
01313 const SSLConfigParams * params,
01314 SSLCertLookup * lookup,
01315 const ssl_user_config & sslMultCertSettings)
01316 {
01317 SSL_CTX * ctx;
01318 ats_scoped_str certpath;
01319 ats_scoped_str session_key_path;
01320
01321 ctx = ssl_context_enable_sni(SSLInitServerContext(params, sslMultCertSettings), lookup);
01322 if (!ctx) {
01323 return false;
01324 }
01325
01326 SSL_CTX_set_info_callback(ctx, ssl_callback_info);
01327
01328 #if TS_USE_TLS_NPN
01329 SSL_CTX_set_next_protos_advertised_cb(ctx, SSLNetVConnection::advertise_next_protocol, NULL);
01330 #endif
01331
01332 #if TS_USE_TLS_ALPN
01333 SSL_CTX_set_alpn_select_cb(ctx, SSLNetVConnection::select_next_protocol, NULL);
01334 #endif
01335
01336 certpath = Layout::relative_to(params->serverCertPathOnly, sslMultCertSettings.first_cert);
01337
01338
01339 if (sslMultCertSettings.addr) {
01340 if (strcmp(sslMultCertSettings.addr, "*") == 0) {
01341 lookup->ssl_default = ctx;
01342 lookup->insert(ctx, sslMultCertSettings.addr);
01343 } else {
01344 IpEndpoint ep;
01345
01346 if (ats_ip_pton(sslMultCertSettings.addr, &ep) == 0) {
01347 Debug("ssl", "mapping '%s' to certificate %s", (const char *)sslMultCertSettings.addr, (const char *)certpath);
01348 lookup->insert(ctx, ep);
01349 } else {
01350 Error("'%s' is not a valid IPv4 or IPv6 address", (const char *)sslMultCertSettings.addr);
01351 }
01352 }
01353 }
01354
01355 #if defined(SSL_OP_NO_TICKET)
01356
01357 if (sslMultCertSettings.session_ticket_enabled == 0) {
01358 SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
01359 Debug("ssl", "ssl session ticket is disabled");
01360 }
01361 #endif
01362
01363
01364 if (sslMultCertSettings.session_ticket_enabled != 0 && sslMultCertSettings.ticket_key_filename) {
01365 ats_scoped_str ticket_key_path(Layout::relative_to(params->serverCertPathOnly, sslMultCertSettings.ticket_key_filename));
01366 ssl_context_enable_tickets(ctx, ticket_key_path);
01367 }
01368
01369 #ifdef HAVE_OPENSSL_OCSP_STAPLING
01370 if (SSLConfigParams::ssl_ocsp_enabled) {
01371 Debug("ssl", "ssl ocsp stapling is enabled");
01372 SSL_CTX_set_tlsext_status_cb(ctx, ssl_callback_ocsp_stapling);
01373 if (!ssl_stapling_init_cert(ctx, (const char *)certpath)) {
01374 Error("fail to configure SSL_CTX for OCSP Stapling info");
01375 }
01376 } else {
01377 Debug("ssl", "ssl ocsp stapling is disabled");
01378 }
01379 #else
01380 if (SSLConfigParams::ssl_ocsp_enabled) {
01381 Error("fail to enable ssl ocsp stapling, this openssl version does not support it");
01382 }
01383 #endif
01384
01385
01386
01387
01388 Debug("ssl", "importing SNI names from %s", (const char *)certpath);
01389 ssl_index_certificate(lookup, ctx, certpath);
01390
01391 if (SSLConfigParams::init_ssl_ctx_cb) {
01392 SSLConfigParams::init_ssl_ctx_cb(ctx, true);
01393 }
01394
01395 return true;
01396 }
01397
01398 static bool
01399 ssl_extract_certificate(
01400 const matcher_line * line_info,
01401 ssl_user_config & sslMultCertSettings)
01402
01403 {
01404 for (int i = 0; i < MATCHER_MAX_TOKENS; ++i) {
01405 const char * label;
01406 const char * value;
01407
01408 label = line_info->line[0][i];
01409 value = line_info->line[1][i];
01410
01411 if (label == NULL) {
01412 continue;
01413 }
01414
01415 if (strcasecmp(label, SSL_IP_TAG) == 0) {
01416 sslMultCertSettings.addr = ats_strdup(value);
01417 }
01418
01419 if (strcasecmp(label, SSL_CERT_TAG) == 0) {
01420 sslMultCertSettings.cert = ats_strdup(value);
01421 }
01422
01423 if (strcasecmp(label, SSL_CA_TAG) == 0) {
01424 sslMultCertSettings.ca = ats_strdup(value);
01425 }
01426
01427 if (strcasecmp(label, SSL_PRIVATE_KEY_TAG) == 0) {
01428 sslMultCertSettings.key = ats_strdup(value);
01429 }
01430
01431 if (strcasecmp(label, SSL_SESSION_TICKET_ENABLED) == 0) {
01432 sslMultCertSettings.session_ticket_enabled = atoi(value);
01433 }
01434
01435 if (strcasecmp(label, SSL_SESSION_TICKET_KEY_FILE_TAG) == 0) {
01436 sslMultCertSettings.ticket_key_filename = ats_strdup(value);
01437 }
01438
01439 if (strcasecmp(label, SSL_KEY_DIALOG) == 0) {
01440 sslMultCertSettings.dialog = ats_strdup(value);
01441 }
01442 }
01443 if (!sslMultCertSettings.cert) {
01444 Error("missing %s tag", SSL_CERT_TAG);
01445 return false;
01446 }
01447
01448 SimpleTokenizer cert_tok(sslMultCertSettings.cert, SSL_CERT_SEPARATE_DELIM);
01449 const char * first_cert = cert_tok.getNext();
01450 if (first_cert) {
01451 sslMultCertSettings.first_cert = ats_strdup(first_cert);
01452 }
01453
01454 return true;
01455 }
01456
01457 bool
01458 SSLParseCertificateConfiguration(
01459 const SSLConfigParams * params,
01460 SSLCertLookup * lookup)
01461 {
01462 char * tok_state = NULL;
01463 char * line = NULL;
01464 ats_scoped_str file_buf;
01465 unsigned line_num = 0;
01466 matcher_line line_info;
01467
01468 const matcher_tags sslCertTags = {
01469 NULL, NULL, NULL, NULL, NULL, NULL, false
01470 };
01471
01472 Note("loading SSL certificate configuration from %s", params->configFilePath);
01473
01474 if (params->configFilePath) {
01475 file_buf = readIntoBuffer(params->configFilePath, __func__, NULL);
01476 }
01477
01478 if (!file_buf) {
01479 Error("failed to read SSL certificate configuration from %s", params->configFilePath);
01480 return false;
01481 }
01482
01483
01484 uint32_t elevate_setting = 0;
01485 REC_ReadConfigInteger(elevate_setting, "proxy.config.ssl.cert.load_elevated");
01486 ElevateAccess elevate_access(elevate_setting != 0);
01487
01488 line = tokLine(file_buf, &tok_state);
01489 while (line != NULL) {
01490
01491 line_num++;
01492
01493
01494 while (*line && isspace(*line)) {
01495 line++;
01496 }
01497
01498 if (*line != '\0' && *line != '#') {
01499 ssl_user_config sslMultiCertSettings;
01500 const char * errPtr;
01501
01502 errPtr = parseConfigLine(line, &line_info, &sslCertTags);
01503
01504 if (errPtr != NULL) {
01505 RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s: discarding %s entry at line %d: %s",
01506 __func__, params->configFilePath, line_num, errPtr);
01507 } else {
01508 if (ssl_extract_certificate(&line_info, sslMultiCertSettings)) {
01509 if (!ssl_store_ssl_context(params, lookup, sslMultiCertSettings)) {
01510 Error("failed to load SSL certificate specification from %s line %u",
01511 params->configFilePath, line_num);
01512 }
01513 } else {
01514 RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s: discarding invalid %s entry at line %u",
01515 __func__, params->configFilePath, line_num);
01516 }
01517 }
01518
01519 }
01520
01521 line = tokLine(NULL, &tok_state);
01522 }
01523
01524
01525
01526
01527 if (lookup->ssl_default == NULL) {
01528 ssl_user_config sslMultiCertSettings;
01529 sslMultiCertSettings.addr = ats_strdup("*");
01530 ssl_store_ssl_context(params, lookup, sslMultiCertSettings);
01531 }
01532
01533 return true;
01534 }
01535
01536 #if HAVE_OPENSSL_SESSION_TICKETS
01537
01538 static void
01539 session_ticket_free(void * , void * ptr, CRYPTO_EX_DATA * ,
01540 int , long , void * )
01541 {
01542 ssl_ticket_key_t * key = (ssl_ticket_key_t *)ptr;
01543 delete key;
01544 }
01545
01546
01547
01548
01549
01550
01551 static int
01552 ssl_callback_session_ticket(
01553 SSL * ssl,
01554 unsigned char * keyname,
01555 unsigned char * iv,
01556 EVP_CIPHER_CTX * cipher_ctx,
01557 HMAC_CTX * hctx,
01558 int enc)
01559 {
01560 ssl_ticket_key_t* ssl_ticket_key = (ssl_ticket_key_t*) SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl), ssl_session_ticket_index);
01561
01562 if (NULL == ssl_ticket_key) {
01563 Error("ssl ticket key is null.");
01564 return -1;
01565 }
01566
01567 if (enc == 1) {
01568 memcpy(keyname, ssl_ticket_key->key_name, 16);
01569 RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH);
01570 EVP_EncryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, ssl_ticket_key->aes_key, iv);
01571 HMAC_Init_ex(hctx, ssl_ticket_key->hmac_secret, 16, evp_md_func, NULL);
01572
01573 Debug("ssl", "create ticket for a new session.");
01574 SSL_INCREMENT_DYN_STAT(ssl_total_tickets_created_stat);
01575 return 0;
01576 } else if (enc == 0) {
01577 if (memcmp(keyname, ssl_ticket_key->key_name, 16)) {
01578 Debug("ssl", "keyname is not consistent.");
01579 SSL_INCREMENT_DYN_STAT(ssl_total_tickets_not_found_stat);
01580 return 0;
01581 }
01582
01583 EVP_DecryptInit_ex(cipher_ctx, EVP_aes_128_cbc(), NULL, ssl_ticket_key->aes_key, iv);
01584 HMAC_Init_ex(hctx, ssl_ticket_key->hmac_secret, 16, evp_md_func, NULL);
01585
01586 Debug("ssl", "verify the ticket for an existing session.");
01587 SSL_INCREMENT_DYN_STAT(ssl_total_tickets_verified_stat);
01588 return 1;
01589 }
01590
01591 return -1;
01592 }
01593 #endif
01594
01595 void
01596 SSLReleaseContext(SSL_CTX * ctx)
01597 {
01598 SSL_CTX_free(ctx);
01599 }