3 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if HAVE_OPENSSL_SSL_H
30 #include "talk/base/openssladapter.h"
36 // Must be included first before openssl headers.
37 #include "talk/base/win32.h" // NOLINT
39 #include <openssl/bio.h>
40 #include <openssl/crypto.h>
41 #include <openssl/err.h>
42 #include <openssl/opensslv.h>
43 #include <openssl/rand.h>
44 #include <openssl/x509v3.h>
48 #endif // HAVE_CONFIG_H
50 #include "talk/base/common.h"
51 #include "talk/base/logging.h"
52 #include "talk/base/openssl.h"
53 #include "talk/base/sslroots.h"
54 #include "talk/base/stringutils.h"
56 // TODO: Use a nicer abstraction for mutex.
59 #define MUTEX_TYPE HANDLE
60 #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
61 #define MUTEX_CLEANUP(x) CloseHandle(x)
62 #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
63 #define MUTEX_UNLOCK(x) ReleaseMutex(x)
64 #define THREAD_ID GetCurrentThreadId()
66 #define MUTEX_TYPE pthread_mutex_t
67 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
68 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
69 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
70 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
71 #define THREAD_ID pthread_self()
73 #error You must define mutex operations appropriate for your platform!
76 struct CRYPTO_dynlock_value {
80 //////////////////////////////////////////////////////////////////////
82 //////////////////////////////////////////////////////////////////////
84 static int socket_write(BIO* h, const char* buf, int num);
85 static int socket_read(BIO* h, char* buf, int size);
86 static int socket_puts(BIO* h, const char* str);
87 static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
88 static int socket_new(BIO* h);
89 static int socket_free(BIO* data);
91 static BIO_METHOD methods_socket = {
104 BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
106 BIO* BIO_new_socket(talk_base::AsyncSocket* socket) {
107 BIO* ret = BIO_new(BIO_s_socket2());
115 static int socket_new(BIO* b) {
118 b->num = 0; // 1 means socket closed
123 static int socket_free(BIO* b) {
129 static int socket_read(BIO* b, char* out, int outl) {
132 talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
133 BIO_clear_retry_flags(b);
134 int result = socket->Recv(out, outl);
137 } else if (result == 0) {
139 } else if (socket->IsBlocking()) {
140 BIO_set_retry_read(b);
145 static int socket_write(BIO* b, const char* in, int inl) {
148 talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
149 BIO_clear_retry_flags(b);
150 int result = socket->Send(in, inl);
153 } else if (socket->IsBlocking()) {
154 BIO_set_retry_write(b);
159 static int socket_puts(BIO* b, const char* str) {
160 return socket_write(b, str, strlen(str));
163 static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
172 case BIO_CTRL_WPENDING:
173 case BIO_CTRL_PENDING:
182 /////////////////////////////////////////////////////////////////////////////
184 /////////////////////////////////////////////////////////////////////////////
186 namespace talk_base {
188 // This array will store all of the mutexes available to OpenSSL.
189 static MUTEX_TYPE* mutex_buf = NULL;
191 static void locking_function(int mode, int n, const char * file, int line) {
192 if (mode & CRYPTO_LOCK) {
193 MUTEX_LOCK(mutex_buf[n]);
195 MUTEX_UNLOCK(mutex_buf[n]);
199 static unsigned long id_function() { // NOLINT
200 // Use old-style C cast because THREAD_ID's type varies with the platform,
201 // in some cases requiring static_cast, and in others requiring
203 return (unsigned long)THREAD_ID; // NOLINT
206 static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
207 CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
210 MUTEX_SETUP(value->mutex);
214 static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
215 const char* file, int line) {
216 if (mode & CRYPTO_LOCK) {
217 MUTEX_LOCK(l->mutex);
219 MUTEX_UNLOCK(l->mutex);
223 static void dyn_destroy_function(CRYPTO_dynlock_value* l,
224 const char* file, int line) {
225 MUTEX_CLEANUP(l->mutex);
229 VerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL;
231 bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
232 if (!InitializeSSLThread() || !SSL_library_init())
234 #if !defined(ADDRESS_SANITIZER) || !defined(OSX)
235 // Loading the error strings crashes mac_asan. Omit this debugging aid there.
236 SSL_load_error_strings();
238 ERR_load_BIO_strings();
239 OpenSSL_add_all_algorithms();
241 custom_verify_callback_ = callback;
245 bool OpenSSLAdapter::InitializeSSLThread() {
246 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
249 for (int i = 0; i < CRYPTO_num_locks(); ++i)
250 MUTEX_SETUP(mutex_buf[i]);
252 // we need to cast our id_function to return an unsigned long -- pthread_t is
254 CRYPTO_set_id_callback(id_function);
255 CRYPTO_set_locking_callback(locking_function);
256 CRYPTO_set_dynlock_create_callback(dyn_create_function);
257 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
258 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
262 bool OpenSSLAdapter::CleanupSSL() {
265 CRYPTO_set_id_callback(NULL);
266 CRYPTO_set_locking_callback(NULL);
267 CRYPTO_set_dynlock_create_callback(NULL);
268 CRYPTO_set_dynlock_lock_callback(NULL);
269 CRYPTO_set_dynlock_destroy_callback(NULL);
270 for (int i = 0; i < CRYPTO_num_locks(); ++i)
271 MUTEX_CLEANUP(mutex_buf[i]);
277 OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
278 : SSLAdapter(socket),
280 ssl_read_needs_write_(false),
281 ssl_write_needs_read_(false),
283 ssl_(NULL), ssl_ctx_(NULL),
284 custom_verification_succeeded_(false) {
287 OpenSSLAdapter::~OpenSSLAdapter() {
292 OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
293 if (state_ != SSL_NONE)
296 ssl_host_name_ = hostname;
297 restartable_ = restartable;
299 if (socket_->GetState() != Socket::CS_CONNECTED) {
304 state_ = SSL_CONNECTING;
305 if (int err = BeginSSL()) {
306 Error("BeginSSL", err, false);
314 OpenSSLAdapter::BeginSSL() {
315 LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
316 ASSERT(state_ == SSL_CONNECTING);
321 // First set up the context
323 ssl_ctx_ = SetupSSLContext();
330 bio = BIO_new_socket(static_cast<AsyncSocketAdapter*>(socket_));
336 ssl_ = SSL_new(ssl_ctx_);
342 SSL_set_app_data(ssl_, this);
344 SSL_set_bio(ssl_, bio, bio);
345 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
346 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
348 // the SSL object owns the bio now
367 OpenSSLAdapter::ContinueSSL() {
368 ASSERT(state_ == SSL_CONNECTING);
370 int code = SSL_connect(ssl_);
371 switch (SSL_get_error(ssl_, code)) {
373 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
374 LOG(LS_ERROR) << "TLS post connection check failed";
375 // make sure we close the socket
377 // The connect failed so return -1 to shut down the socket
381 state_ = SSL_CONNECTED;
382 AsyncSocketAdapter::OnConnectEvent(this);
383 #if 0 // TODO: worry about this
384 // Don't let ourselves go away during the callbacks
385 PRefPtr<OpenSSLAdapter> lock(this);
386 LOG(LS_INFO) << " -- onStreamReadable";
387 AsyncSocketAdapter::OnReadEvent(this);
388 LOG(LS_INFO) << " -- onStreamWriteable";
389 AsyncSocketAdapter::OnWriteEvent(this);
393 case SSL_ERROR_WANT_READ:
394 case SSL_ERROR_WANT_WRITE:
397 case SSL_ERROR_ZERO_RETURN:
399 LOG(LS_WARNING) << "ContinueSSL -- error " << code;
400 return (code != 0) ? code : -1;
407 OpenSSLAdapter::Error(const char* context, int err, bool signal) {
408 LOG(LS_WARNING) << "OpenSSLAdapter::Error("
409 << context << ", " << err << ")";
413 AsyncSocketAdapter::OnCloseEvent(this, err);
417 OpenSSLAdapter::Cleanup() {
418 LOG(LS_INFO) << "Cleanup";
421 ssl_read_needs_write_ = false;
422 ssl_write_needs_read_ = false;
423 custom_verification_succeeded_ = false;
431 SSL_CTX_free(ssl_ctx_);
437 // AsyncSocket Implementation
441 OpenSSLAdapter::Send(const void* pv, size_t cb) {
442 //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
446 return AsyncSocketAdapter::Send(pv, cb);
450 SetError(EWOULDBLOCK);
461 // OpenSSL will return an error if we try to write zero bytes
465 ssl_write_needs_read_ = false;
467 int code = SSL_write(ssl_, pv, cb);
468 switch (SSL_get_error(ssl_, code)) {
470 //LOG(LS_INFO) << " -- success";
472 case SSL_ERROR_WANT_READ:
473 //LOG(LS_INFO) << " -- error want read";
474 ssl_write_needs_read_ = true;
475 SetError(EWOULDBLOCK);
477 case SSL_ERROR_WANT_WRITE:
478 //LOG(LS_INFO) << " -- error want write";
479 SetError(EWOULDBLOCK);
481 case SSL_ERROR_ZERO_RETURN:
482 //LOG(LS_INFO) << " -- remote side closed";
483 SetError(EWOULDBLOCK);
484 // do we need to signal closure?
487 //LOG(LS_INFO) << " -- error " << code;
488 Error("SSL_write", (code ? code : -1), false);
496 OpenSSLAdapter::Recv(void* pv, size_t cb) {
497 //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
501 return AsyncSocketAdapter::Recv(pv, cb);
505 SetError(EWOULDBLOCK);
516 // Don't trust OpenSSL with zero byte reads
520 ssl_read_needs_write_ = false;
522 int code = SSL_read(ssl_, pv, cb);
523 switch (SSL_get_error(ssl_, code)) {
525 //LOG(LS_INFO) << " -- success";
527 case SSL_ERROR_WANT_READ:
528 //LOG(LS_INFO) << " -- error want read";
529 SetError(EWOULDBLOCK);
531 case SSL_ERROR_WANT_WRITE:
532 //LOG(LS_INFO) << " -- error want write";
533 ssl_read_needs_write_ = true;
534 SetError(EWOULDBLOCK);
536 case SSL_ERROR_ZERO_RETURN:
537 //LOG(LS_INFO) << " -- remote side closed";
538 SetError(EWOULDBLOCK);
539 // do we need to signal closure?
542 //LOG(LS_INFO) << " -- error " << code;
543 Error("SSL_read", (code ? code : -1), false);
551 OpenSSLAdapter::Close() {
553 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
554 return AsyncSocketAdapter::Close();
558 OpenSSLAdapter::GetState() const {
560 // return CS_CONNECTED;
561 ConnState state = socket_->GetState();
562 if ((state == CS_CONNECTED)
563 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
564 state = CS_CONNECTING;
569 OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
570 LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
571 if (state_ != SSL_WAIT) {
572 ASSERT(state_ == SSL_NONE);
573 AsyncSocketAdapter::OnConnectEvent(socket);
577 state_ = SSL_CONNECTING;
578 if (int err = BeginSSL()) {
579 AsyncSocketAdapter::OnCloseEvent(socket, err);
584 OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
585 //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
587 if (state_ == SSL_NONE) {
588 AsyncSocketAdapter::OnReadEvent(socket);
592 if (state_ == SSL_CONNECTING) {
593 if (int err = ContinueSSL()) {
594 Error("ContinueSSL", err);
599 if (state_ != SSL_CONNECTED)
602 // Don't let ourselves go away during the callbacks
603 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
604 if (ssl_write_needs_read_) {
605 //LOG(LS_INFO) << " -- onStreamWriteable";
606 AsyncSocketAdapter::OnWriteEvent(socket);
609 //LOG(LS_INFO) << " -- onStreamReadable";
610 AsyncSocketAdapter::OnReadEvent(socket);
614 OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
615 //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
617 if (state_ == SSL_NONE) {
618 AsyncSocketAdapter::OnWriteEvent(socket);
622 if (state_ == SSL_CONNECTING) {
623 if (int err = ContinueSSL()) {
624 Error("ContinueSSL", err);
629 if (state_ != SSL_CONNECTED)
632 // Don't let ourselves go away during the callbacks
633 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
635 if (ssl_read_needs_write_) {
636 //LOG(LS_INFO) << " -- onStreamReadable";
637 AsyncSocketAdapter::OnReadEvent(socket);
640 //LOG(LS_INFO) << " -- onStreamWriteable";
641 AsyncSocketAdapter::OnWriteEvent(socket);
645 OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
646 LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
647 AsyncSocketAdapter::OnCloseEvent(socket, err);
650 // This code is taken from the "Network Security with OpenSSL"
651 // sample in chapter 5
653 bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
654 bool ignore_bad_cert) {
658 // Checking the return from SSL_get_peer_certificate here is not strictly
659 // necessary. With our setup, it is not possible for it to return
660 // NULL. However, it is good form to check the return.
661 X509* certificate = SSL_get_peer_certificate(ssl);
665 // Logging certificates is extremely verbose. So it is disabled by default.
666 #ifdef LOG_CERTIFICATES
668 LOG(LS_INFO) << "Certificate from server:";
669 BIO* mem = BIO_new(BIO_s_mem());
670 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
671 BIO_write(mem, "\0", 1);
673 BIO_get_mem_data(mem, &buffer);
674 LOG(LS_INFO) << buffer;
677 char* cipher_description =
678 SSL_CIPHER_description(SSL_get_current_cipher(ssl), NULL, 128);
679 LOG(LS_INFO) << "Cipher: " << cipher_description;
680 OPENSSL_free(cipher_description);
685 int extension_count = X509_get_ext_count(certificate);
686 for (int i = 0; i < extension_count; ++i) {
687 X509_EXTENSION* extension = X509_get_ext(certificate, i);
688 int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
690 if (extension_nid == NID_subject_alt_name) {
691 const X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
695 void* ext_str = NULL;
697 // We assign this to a local variable, instead of passing the address
698 // directly to ASN1_item_d2i.
699 // See http://readlist.com/lists/openssl.org/openssl-users/0/4761.html.
700 unsigned char* ext_value_data = extension->value->data;
702 const unsigned char **ext_value_data_ptr =
703 (const_cast<const unsigned char **>(&ext_value_data));
706 ext_str = ASN1_item_d2i(NULL, ext_value_data_ptr,
707 extension->value->length,
708 ASN1_ITEM_ptr(meth->it));
710 ext_str = meth->d2i(NULL, ext_value_data_ptr, extension->value->length);
713 STACK_OF(CONF_VALUE)* value = meth->i2v(meth, ext_str, NULL);
714 for (int j = 0; j < sk_CONF_VALUE_num(value); ++j) {
715 CONF_VALUE* nval = sk_CONF_VALUE_value(value, j);
716 // The value for nval can contain wildcards
717 if (!strcmp(nval->name, "DNS") && string_match(host, nval->value)) {
722 sk_CONF_VALUE_pop_free(value, X509V3_conf_free);
726 ASN1_item_free(reinterpret_cast<ASN1_VALUE*>(ext_str),
727 ASN1_ITEM_ptr(meth->it));
729 meth->ext_free(ext_str);
738 X509_name_st* subject;
740 && ((subject = X509_get_subject_name(certificate)) != NULL)
741 && (X509_NAME_get_text_by_NID(subject, NID_commonName,
742 data, sizeof(data)) > 0)) {
743 data[sizeof(data)-1] = 0;
744 if (_stricmp(data, host) == 0)
748 X509_free(certificate);
750 // This should only ever be turned on for debugging and development.
751 if (!ok && ignore_bad_cert) {
752 LOG(LS_WARNING) << "TLS certificate check FAILED. "
753 << "Allowing connection anyway.";
760 bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
761 bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
764 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
765 custom_verification_succeeded_);
768 if (!ok && ignore_bad_cert()) {
769 LOG(LS_INFO) << "Other TLS post connection checks failed.";
778 // We only use this for tracing and so it is only needed in debug mode
781 OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
782 const char* str = "undefined";
783 int w = where & ~SSL_ST_MASK;
784 if (w & SSL_ST_CONNECT) {
786 } else if (w & SSL_ST_ACCEPT) {
789 if (where & SSL_CB_LOOP) {
790 LOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
791 } else if (where & SSL_CB_ALERT) {
792 str = (where & SSL_CB_READ) ? "read" : "write";
793 LOG(LS_INFO) << "SSL3 alert " << str
794 << ":" << SSL_alert_type_string_long(ret)
795 << ":" << SSL_alert_desc_string_long(ret);
796 } else if (where & SSL_CB_EXIT) {
798 LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
799 } else if (ret < 0) {
800 LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
808 OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
812 X509* cert = X509_STORE_CTX_get_current_cert(store);
813 int depth = X509_STORE_CTX_get_error_depth(store);
814 int err = X509_STORE_CTX_get_error(store);
816 LOG(LS_INFO) << "Error with certificate at depth: " << depth;
817 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
818 LOG(LS_INFO) << " issuer = " << data;
819 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
820 LOG(LS_INFO) << " subject = " << data;
821 LOG(LS_INFO) << " err = " << err
822 << ":" << X509_verify_cert_error_string(err);
826 // Get our stream pointer from the store
827 SSL* ssl = reinterpret_cast<SSL*>(
828 X509_STORE_CTX_get_ex_data(store,
829 SSL_get_ex_data_X509_STORE_CTX_idx()));
831 OpenSSLAdapter* stream =
832 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
834 if (!ok && custom_verify_callback_) {
836 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
837 if (custom_verify_callback_(cert)) {
838 stream->custom_verification_succeeded_ = true;
839 LOG(LS_INFO) << "validated certificate using custom callback";
844 // Should only be used for debugging and development.
845 if (!ok && stream->ignore_bad_cert()) {
846 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
853 bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
854 // Add the root cert that we care about to the SSL context
855 int count_of_added_certs = 0;
856 for (int i = 0; i < ARRAY_SIZE(kSSLCertCertificateList); i++) {
857 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
858 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
859 X509* cert = d2i_X509(NULL, &cert_buffer, cert_buffer_len);
861 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
862 if (return_value == 0) {
863 LOG(LS_WARNING) << "Unable to add certificate.";
865 count_of_added_certs++;
870 return count_of_added_certs > 0;
874 OpenSSLAdapter::SetupSSLContext() {
875 SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
877 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
878 LOG(LS_WARNING) << "SSL_CTX creation failed: "
879 << '"' << ERR_reason_error_string(error) << "\" "
880 << "(error=" << error << ')';
883 if (!ConfigureTrustedRootCertificates(ctx)) {
889 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
892 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
893 SSL_CTX_set_verify_depth(ctx, 4);
894 SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
899 } // namespace talk_base
901 #endif // HAVE_OPENSSL_SSL_H