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