Add SSLConfig object to IceServer.

This is a rollforward of https://webrtc-review.googlesource.com/c/src/+/96020,
with the addition of setting the old tlsCertPolicy, tlsAlpnProtocols and
tlsEllipticCurves in the RTCIceServer initializer, for backwards compatibility.

Bug: webrtc:9662
Change-Id: I28706ed4ff5abe3f7f913f105779f0e5412aeac5
Reviewed-on: https://webrtc-review.googlesource.com/98762
Commit-Queue: Diogo Real <diogor@google.com>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24696}
This commit is contained in:
Diogo Real
2018-09-11 16:00:22 -07:00
committed by Commit Bot
parent e0c8b230e7
commit 4f085434b9
31 changed files with 1093 additions and 183 deletions

View File

@ -112,6 +112,7 @@
#include "rtc_base/rtccertificate.h" #include "rtc_base/rtccertificate.h"
#include "rtc_base/rtccertificategenerator.h" #include "rtc_base/rtccertificategenerator.h"
#include "rtc_base/socketaddress.h" #include "rtc_base/socketaddress.h"
#include "rtc_base/ssladapter.h"
#include "rtc_base/sslcertificate.h" #include "rtc_base/sslcertificate.h"
#include "rtc_base/sslstreamadapter.h" #include "rtc_base/sslstreamadapter.h"
@ -187,6 +188,7 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
kIceConnectionMax, kIceConnectionMax,
}; };
// Deprecated. TODO(diogor, webrtc:9673): Remove from API.
// TLS certificate policy. // TLS certificate policy.
enum TlsCertPolicy { enum TlsCertPolicy {
// For TLS based protocols, ensure the connection is secure by not // For TLS based protocols, ensure the connection is secure by not
@ -211,23 +213,29 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
std::vector<std::string> urls; std::vector<std::string> urls;
std::string username; std::string username;
std::string password; std::string password;
// Deprecated. rtc::SSLConfig should be used instead.
TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure; TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure;
// If the URIs in |urls| only contain IP addresses, this field can be used // If the URIs in |urls| only contain IP addresses, this field can be used
// to indicate the hostname, which may be necessary for TLS (using the SNI // to indicate the hostname, which may be necessary for TLS (using the SNI
// extension). If |urls| itself contains the hostname, this isn't // extension). If |urls| itself contains the hostname, this isn't
// necessary. // necessary.
std::string hostname; std::string hostname;
// Deprecated. rtc::SSLConfig should be used instead.
// List of protocols to be used in the TLS ALPN extension. // List of protocols to be used in the TLS ALPN extension.
std::vector<std::string> tls_alpn_protocols; std::vector<std::string> tls_alpn_protocols;
// Deprecated. rtc::SSLConfig should be used instead.
// List of elliptic curves to be used in the TLS elliptic curves extension. // List of elliptic curves to be used in the TLS elliptic curves extension.
std::vector<std::string> tls_elliptic_curves; std::vector<std::string> tls_elliptic_curves;
// SSL configuration options for any SSL/TLS connections to this IceServer.
rtc::SSLConfig ssl_config;
bool operator==(const IceServer& o) const { bool operator==(const IceServer& o) const {
return uri == o.uri && urls == o.urls && username == o.username && return uri == o.uri && urls == o.urls && username == o.username &&
password == o.password && tls_cert_policy == o.tls_cert_policy && password == o.password && tls_cert_policy == o.tls_cert_policy &&
hostname == o.hostname && hostname == o.hostname &&
tls_alpn_protocols == o.tls_alpn_protocols && tls_alpn_protocols == o.tls_alpn_protocols &&
tls_elliptic_curves == o.tls_elliptic_curves; tls_elliptic_curves == o.tls_elliptic_curves &&
ssl_config == o.ssl_config;
} }
bool operator!=(const IceServer& o) const { return !(*this == o); } bool operator!=(const IceServer& o) const { return !(*this == o); }
}; };

View File

@ -157,12 +157,7 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
return NULL; return NULL;
} }
if (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE) { ssl_adapter->SetSSLConfig(tcp_options.ssl_config);
ssl_adapter->SetIgnoreBadCert(true);
}
ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols);
ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves);
ssl_adapter->SetCertVerifier(tcp_options.tls_cert_verifier); ssl_adapter->SetCertVerifier(tcp_options.tls_cert_verifier);
socket = ssl_adapter; socket = ssl_adapter;

View File

@ -14,8 +14,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/types/optional.h"
#include "rtc_base/constructormagic.h" #include "rtc_base/constructormagic.h"
#include "rtc_base/proxyinfo.h" #include "rtc_base/proxyinfo.h"
#include "rtc_base/ssladapter.h"
#include "rtc_base/sslcertificate.h" #include "rtc_base/sslcertificate.h"
namespace rtc { namespace rtc {
@ -26,11 +28,12 @@ struct PacketSocketTcpOptions {
~PacketSocketTcpOptions(); ~PacketSocketTcpOptions();
int opts = 0; int opts = 0;
std::vector<std::string> tls_alpn_protocols;
std::vector<std::string> tls_elliptic_curves;
// An optional custom SSL certificate verifier that an API user can provide to // An optional custom SSL certificate verifier that an API user can provide to
// inject their own certificate verification logic. // inject their own certificate verification logic.
SSLCertificateVerifier* tls_cert_verifier = nullptr; SSLCertificateVerifier* tls_cert_verifier = nullptr;
// SSL configuration options.
rtc::SSLConfig ssl_config;
}; };
class AsyncPacketSocket; class AsyncPacketSocket;

View File

@ -537,8 +537,7 @@ class PortTest : public testing::Test, public sigslot::has_slots<> {
return TurnPort::Create( return TurnPort::Create(
&main_, socket_factory, MakeNetwork(addr), 0, 0, username_, password_, &main_, socket_factory, MakeNetwork(addr), 0, 0, username_, password_,
ProtocolAddress(server_addr, int_proto), kRelayCredentials, 0, ProtocolAddress(server_addr, int_proto), kRelayCredentials, 0,
std::string(), std::vector<std::string>(), std::vector<std::string>(), std::string(), nullptr, rtc::SSLConfig(), nullptr);
nullptr, nullptr);
} }
RelayPort* CreateGturnPort(const SocketAddress& addr, RelayPort* CreateGturnPort(const SocketAddress& addr,
ProtocolType int_proto, ProtocolType int_proto,

View File

@ -20,6 +20,7 @@
#include "p2p/base/portinterface.h" #include "p2p/base/portinterface.h"
#include "rtc_base/helpers.h" #include "rtc_base/helpers.h"
#include "rtc_base/proxyinfo.h" #include "rtc_base/proxyinfo.h"
#include "rtc_base/ssladapter.h"
#include "rtc_base/sslcertificate.h" #include "rtc_base/sslcertificate.h"
#include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
@ -118,17 +119,6 @@ enum : uint32_t {
CF_ALL = 0x7, CF_ALL = 0x7,
}; };
// TLS certificate policy.
enum class TlsCertPolicy {
// For TLS based protocols, ensure the connection is secure by not
// circumventing certificate validation.
TLS_CERT_POLICY_SECURE,
// For TLS based protocols, disregard security completely by skipping
// certificate validation. This is insecure and should never be used unless
// security is irrelevant in that particular context.
TLS_CERT_POLICY_INSECURE_NO_CHECK,
};
// TODO(deadbeef): Rename to TurnCredentials (and username to ufrag). // TODO(deadbeef): Rename to TurnCredentials (and username to ufrag).
struct RelayCredentials { struct RelayCredentials {
RelayCredentials() {} RelayCredentials() {}
@ -144,6 +134,17 @@ struct RelayCredentials {
std::string password; std::string password;
}; };
// TLS certificate policy.
enum class TlsCertPolicy {
// For TLS based protocols, ensure the connection is secure by not
// circumventing certificate validation.
TLS_CERT_POLICY_SECURE,
// For TLS based protocols, disregard security completely by skipping
// certificate validation. This is insecure and should never be used unless
// security is irrelevant in that particular context.
TLS_CERT_POLICY_INSECURE_NO_CHECK,
};
typedef std::vector<ProtocolAddress> PortList; typedef std::vector<ProtocolAddress> PortList;
// TODO(deadbeef): Rename to TurnServerConfig. // TODO(deadbeef): Rename to TurnServerConfig.
struct RelayServerConfig { struct RelayServerConfig {
@ -180,6 +181,7 @@ struct RelayServerConfig {
TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE; TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE;
std::vector<std::string> tls_alpn_protocols; std::vector<std::string> tls_alpn_protocols;
std::vector<std::string> tls_elliptic_curves; std::vector<std::string> tls_elliptic_curves;
rtc::SSLConfig ssl_config;
rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr; rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr;
}; };

View File

@ -110,7 +110,12 @@ class TestTurnServer : public TurnAuthInterface {
adapter->SetRole(rtc::SSL_SERVER); adapter->SetRole(rtc::SSL_SERVER);
adapter->SetIdentity( adapter->SetIdentity(
rtc::SSLIdentity::Generate(common_name, rtc::KeyParams())); rtc::SSLIdentity::Generate(common_name, rtc::KeyParams()));
adapter->SetIgnoreBadCert(ignore_bad_cert); rtc::SSLConfig ssl_config;
if (ignore_bad_cert) {
ssl_config.tls_cert_policy =
rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
}
adapter->SetSSLConfig(ssl_config);
socket = adapter; socket = adapter;
} }
socket->Bind(int_addr); socket->Bind(int_addr);

View File

@ -244,8 +244,47 @@ TurnPort::TurnPort(rtc::Thread* thread,
username, username,
password), password),
server_address_(server_address), server_address_(server_address),
tls_alpn_protocols_(tls_alpn_protocols), tls_cert_verifier_(tls_cert_verifier),
tls_elliptic_curves_(tls_elliptic_curves), credentials_(credentials),
socket_(NULL),
resolver_(NULL),
error_(0),
request_manager_(thread),
next_channel_number_(TURN_CHANNEL_NUMBER_START),
state_(STATE_CONNECTING),
server_priority_(server_priority),
allocate_mismatch_retries_(0),
turn_customizer_(customizer) {
ssl_config_.tls_alpn_protocols = tls_alpn_protocols;
ssl_config_.tls_elliptic_curves = tls_elliptic_curves;
request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
request_manager_.set_origin(origin);
}
TurnPort::TurnPort(rtc::Thread* thread,
rtc::PacketSocketFactory* factory,
rtc::Network* network,
uint16_t min_port,
uint16_t max_port,
const std::string& username,
const std::string& password,
const ProtocolAddress& server_address,
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
webrtc::TurnCustomizer* customizer,
const rtc::SSLConfig& ssl_config,
rtc::SSLCertificateVerifier* tls_cert_verifier)
: Port(thread,
RELAY_PORT_TYPE,
factory,
network,
min_port,
max_port,
username,
password),
server_address_(server_address),
ssl_config_(ssl_config),
tls_cert_verifier_(tls_cert_verifier), tls_cert_verifier_(tls_cert_verifier),
credentials_(credentials), credentials_(credentials),
socket_(NULL), socket_(NULL),
@ -289,20 +328,20 @@ ProtocolType TurnPort::GetProtocol() const {
return server_address_.proto; return server_address_.proto;
} }
TlsCertPolicy TurnPort::GetTlsCertPolicy() const {
return tls_cert_policy_;
}
void TurnPort::SetTlsCertPolicy(TlsCertPolicy tls_cert_policy) { void TurnPort::SetTlsCertPolicy(TlsCertPolicy tls_cert_policy) {
tls_cert_policy_ = tls_cert_policy; switch (tls_cert_policy) {
case TlsCertPolicy::TLS_CERT_POLICY_SECURE:
ssl_config_.tls_cert_policy = rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE;
break;
case TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK:
ssl_config_.tls_cert_policy =
rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
break;
}
} }
std::vector<std::string> TurnPort::GetTlsAlpnProtocols() const { const rtc::SSLConfig& TurnPort::GetSslConfig() const {
return tls_alpn_protocols_; return ssl_config_;
}
std::vector<std::string> TurnPort::GetTlsEllipticCurves() const {
return tls_elliptic_curves_;
} }
void TurnPort::PrepareAddress() { void TurnPort::PrepareAddress() {
@ -362,8 +401,8 @@ bool TurnPort::CreateTurnClientSocket() {
// Apply server address TLS and insecure bits to options. // Apply server address TLS and insecure bits to options.
if (server_address_.proto == PROTO_TLS) { if (server_address_.proto == PROTO_TLS) {
if (tls_cert_policy_ == if (ssl_config_.tls_cert_policy ==
TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK) { rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK) {
opts |= rtc::PacketSocketFactory::OPT_TLS_INSECURE; opts |= rtc::PacketSocketFactory::OPT_TLS_INSECURE;
} else { } else {
opts |= rtc::PacketSocketFactory::OPT_TLS; opts |= rtc::PacketSocketFactory::OPT_TLS;
@ -372,9 +411,8 @@ bool TurnPort::CreateTurnClientSocket() {
rtc::PacketSocketTcpOptions tcp_options; rtc::PacketSocketTcpOptions tcp_options;
tcp_options.opts = opts; tcp_options.opts = opts;
tcp_options.tls_alpn_protocols = tls_alpn_protocols_;
tcp_options.tls_elliptic_curves = tls_elliptic_curves_;
tcp_options.tls_cert_verifier = tls_cert_verifier_; tcp_options.tls_cert_verifier = tls_cert_verifier_;
tcp_options.ssl_config = ssl_config_;
socket_ = socket_factory()->CreateClientTcpSocket( socket_ = socket_factory()->CreateClientTcpSocket(
rtc::SocketAddress(Network()->GetBestIP(), 0), server_address_.address, rtc::SocketAddress(Network()->GetBestIP(), 0), server_address_.address,
proxy(), user_agent(), tcp_options); proxy(), user_agent(), tcp_options);

View File

@ -22,6 +22,7 @@
#include "p2p/client/basicportallocator.h" #include "p2p/client/basicportallocator.h"
#include "rtc_base/asyncinvoker.h" #include "rtc_base/asyncinvoker.h"
#include "rtc_base/asyncpacketsocket.h" #include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/ssladapter.h"
#include "rtc_base/sslcertificate.h" #include "rtc_base/sslcertificate.h"
namespace rtc { namespace rtc {
@ -66,6 +67,7 @@ class TurnPort : public Port {
customizer); customizer);
} }
// Deprecated. TODO(diogor, webrtc:9673): Remove this constructor.
// Create a TURN port that will use a new socket, bound to |network| and // Create a TURN port that will use a new socket, bound to |network| and
// using a port in the range between |min_port| and |max_port|. // using a port in the range between |min_port| and |max_port|.
static TurnPort* Create( static TurnPort* Create(
@ -84,10 +86,34 @@ class TurnPort : public Port {
const std::vector<std::string>& tls_elliptic_curves, const std::vector<std::string>& tls_elliptic_curves,
webrtc::TurnCustomizer* customizer, webrtc::TurnCustomizer* customizer,
rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr) { rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr) {
rtc::SSLConfig ssl_config;
ssl_config.tls_alpn_protocols = tls_alpn_protocols;
ssl_config.tls_elliptic_curves = tls_elliptic_curves;
return new TurnPort(thread, factory, network, min_port, max_port, username, return new TurnPort(thread, factory, network, min_port, max_port, username,
password, server_address, credentials, server_priority, password, server_address, credentials, server_priority,
origin, tls_alpn_protocols, tls_elliptic_curves, origin, customizer, ssl_config, tls_cert_verifier);
customizer, tls_cert_verifier); }
// Create a TURN port that will use a new socket, bound to |network| and
// using a port in the range between |min_port| and |max_port|.
static TurnPort* Create(
rtc::Thread* thread,
rtc::PacketSocketFactory* factory,
rtc::Network* network,
uint16_t min_port,
uint16_t max_port,
const std::string& username, // ice username.
const std::string& password, // ice password.
const ProtocolAddress& server_address,
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
webrtc::TurnCustomizer* customizer,
const rtc::SSLConfig& ssl_config,
rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr) {
return new TurnPort(thread, factory, network, min_port, max_port, username,
password, server_address, credentials, server_priority,
origin, customizer, ssl_config, tls_cert_verifier);
} }
~TurnPort() override; ~TurnPort() override;
@ -104,11 +130,11 @@ class TurnPort : public Port {
ProtocolType GetProtocol() const override; ProtocolType GetProtocol() const override;
virtual TlsCertPolicy GetTlsCertPolicy() const; // Deprecated. SSLConfig should be used instead.
// TODO(diogor, webrtc:9673): Remove this.
virtual void SetTlsCertPolicy(TlsCertPolicy tls_cert_policy); virtual void SetTlsCertPolicy(TlsCertPolicy tls_cert_policy);
virtual std::vector<std::string> GetTlsAlpnProtocols() const; virtual const rtc::SSLConfig& GetSslConfig() const;
virtual std::vector<std::string> GetTlsEllipticCurves() const;
// Release a TURN allocation by sending a refresh with lifetime 0. // Release a TURN allocation by sending a refresh with lifetime 0.
// Sets state to STATE_RECEIVEONLY. // Sets state to STATE_RECEIVEONLY.
@ -220,6 +246,21 @@ class TurnPort : public Port {
webrtc::TurnCustomizer* customizer, webrtc::TurnCustomizer* customizer,
rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr); rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr);
TurnPort(rtc::Thread* thread,
rtc::PacketSocketFactory* factory,
rtc::Network* network,
uint16_t min_port,
uint16_t max_port,
const std::string& username,
const std::string& password,
const ProtocolAddress& server_address,
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
webrtc::TurnCustomizer* customizer,
const rtc::SSLConfig& ssl_config,
rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr);
// NOTE: This method needs to be accessible for StacPort // NOTE: This method needs to be accessible for StacPort
// return true if entry was created (i.e channel_number consumed). // return true if entry was created (i.e channel_number consumed).
bool CreateOrRefreshEntry(const rtc::SocketAddress& addr, bool CreateOrRefreshEntry(const rtc::SocketAddress& addr,
@ -304,9 +345,7 @@ class TurnPort : public Port {
size_t size, bool payload); size_t size, bool payload);
ProtocolAddress server_address_; ProtocolAddress server_address_;
TlsCertPolicy tls_cert_policy_ = TlsCertPolicy::TLS_CERT_POLICY_SECURE; rtc::SSLConfig ssl_config_;
std::vector<std::string> tls_alpn_protocols_;
std::vector<std::string> tls_elliptic_curves_;
rtc::SSLCertificateVerifier* tls_cert_verifier_; rtc::SSLCertificateVerifier* tls_cert_verifier_;
RelayCredentials credentials_; RelayCredentials credentials_;
AttemptedServerSet attempted_server_addresses_; AttemptedServerSet attempted_server_addresses_;

View File

@ -270,21 +270,16 @@ class TurnPortTest : public testing::Test,
const ProtocolAddress& server_address, const ProtocolAddress& server_address,
const std::string& origin) { const std::string& origin) {
RelayCredentials credentials(username, password); RelayCredentials credentials(username, password);
turn_port_.reset(TurnPort::Create( rtc::SSLConfig ssl_config;
&main_, &socket_factory_, network, 0, 0, kIceUfrag1, kIcePwd1, ssl_config.tls_cert_policy =
server_address, credentials, 0, origin, std::vector<std::string>(), rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
std::vector<std::string>(), turn_customizer_.get())); turn_port_.reset(TurnPort::Create(&main_, &socket_factory_, network, 0, 0,
kIceUfrag1, kIcePwd1, server_address,
credentials, 0, origin,
turn_customizer_.get(), ssl_config));
// This TURN port will be the controlling. // This TURN port will be the controlling.
turn_port_->SetIceRole(ICEROLE_CONTROLLING); turn_port_->SetIceRole(ICEROLE_CONTROLLING);
ConnectSignals(); ConnectSignals();
if (server_address.proto == cricket::PROTO_TLS) {
// The test TURN server has a self-signed certificate so will not pass
// the normal client validation. Instruct the client to ignore certificate
// errors for testing only.
turn_port_->SetTlsCertPolicy(
TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK);
}
} }
void CreateSharedTurnPort(const std::string& username, void CreateSharedTurnPort(const std::string& username,

View File

@ -26,20 +26,29 @@ std::unique_ptr<Port> TurnPortFactory::Create(
args.username, args.password, *args.server_address, args.username, args.password, *args.server_address,
args.config->credentials, args.config->priority, args.origin, args.config->credentials, args.config->priority, args.origin,
args.turn_customizer); args.turn_customizer);
port->SetTlsCertPolicy(args.config->tls_cert_policy);
return std::unique_ptr<Port>(port); return std::unique_ptr<Port>(port);
} }
std::unique_ptr<Port> TurnPortFactory::Create(const CreateRelayPortArgs& args, std::unique_ptr<Port> TurnPortFactory::Create(const CreateRelayPortArgs& args,
int min_port, int min_port,
int max_port) { int max_port) {
rtc::SSLConfig ssl_config = args.config->ssl_config;
if (!args.config->tls_alpn_protocols.empty()) {
ssl_config.tls_alpn_protocols = args.config->tls_alpn_protocols;
}
if (!args.config->tls_elliptic_curves.empty()) {
ssl_config.tls_elliptic_curves = args.config->tls_elliptic_curves;
}
if (args.config->tls_cert_policy ==
TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK) {
ssl_config.tls_cert_policy =
rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
}
TurnPort* port = TurnPort::Create( TurnPort* port = TurnPort::Create(
args.network_thread, args.socket_factory, args.network, min_port, args.network_thread, args.socket_factory, args.network, min_port,
max_port, args.username, args.password, *args.server_address, max_port, args.username, args.password, *args.server_address,
args.config->credentials, args.config->priority, args.origin, args.config->credentials, args.config->priority, args.origin,
args.config->tls_alpn_protocols, args.config->tls_elliptic_curves, args.turn_customizer, ssl_config, args.config->tls_cert_verifier);
args.turn_customizer, args.config->tls_cert_verifier);
port->SetTlsCertPolicy(args.config->tls_cert_policy);
return std::unique_ptr<Port>(port); return std::unique_ptr<Port>(port);
} }

View File

@ -14,6 +14,7 @@
#include <string> #include <string>
#include "rtc_base/arraysize.h" #include "rtc_base/arraysize.h"
#include "rtc_base/ssladapter.h"
namespace webrtc { namespace webrtc {
@ -254,13 +255,22 @@ static RTCErrorType ParseIceServerUrl(
} }
cricket::RelayServerConfig config = cricket::RelayServerConfig( cricket::RelayServerConfig config = cricket::RelayServerConfig(
socket_address, username, server.password, turn_transport_type); socket_address, username, server.password, turn_transport_type);
config.ssl_config = server.ssl_config;
if (server.tls_cert_policy == if (server.tls_cert_policy ==
PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck) { PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck) {
config.tls_cert_policy = config.ssl_config.tls_cert_policy =
cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK; rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
}
if (!server.ssl_config.tls_alpn_protocols.has_value() &&
!server.tls_alpn_protocols.empty()) {
config.ssl_config.tls_alpn_protocols = server.tls_alpn_protocols;
}
if (!server.ssl_config.tls_elliptic_curves.has_value() &&
!server.tls_elliptic_curves.empty()) {
config.ssl_config.tls_elliptic_curves = server.tls_elliptic_curves;
} }
config.tls_alpn_protocols = server.tls_alpn_protocols;
config.tls_elliptic_curves = server.tls_elliptic_curves;
turn_servers->push_back(config); turn_servers->push_back(config);
break; break;

View File

@ -86,16 +86,16 @@ TEST_F(IceServerParsingTest, ParseStunPrefixes) {
EXPECT_EQ(0U, stun_servers_.size()); EXPECT_EQ(0U, stun_servers_.size());
EXPECT_EQ(1U, turn_servers_.size()); EXPECT_EQ(1U, turn_servers_.size());
EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto); EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
EXPECT_TRUE(turn_servers_[0].tls_cert_policy == EXPECT_TRUE(turn_servers_[0].ssl_config.tls_cert_policy ==
cricket::TlsCertPolicy::TLS_CERT_POLICY_SECURE); rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE);
EXPECT_TRUE(ParseUrl( EXPECT_TRUE(ParseUrl(
"turns:hostname", "username", "password", "turns:hostname", "username", "password",
PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicyInsecureNoCheck)); PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicyInsecureNoCheck));
EXPECT_EQ(0U, stun_servers_.size()); EXPECT_EQ(0U, stun_servers_.size());
EXPECT_EQ(1U, turn_servers_.size()); EXPECT_EQ(1U, turn_servers_.size());
EXPECT_TRUE(turn_servers_[0].tls_cert_policy == EXPECT_TRUE(turn_servers_[0].ssl_config.tls_cert_policy ==
cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK); rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK);
EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto); EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
// invalid prefixes // invalid prefixes

View File

@ -209,7 +209,6 @@ OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket,
ssl_(nullptr), ssl_(nullptr),
ssl_ctx_(nullptr), ssl_ctx_(nullptr),
ssl_mode_(SSL_MODE_TLS), ssl_mode_(SSL_MODE_TLS),
ignore_bad_cert_(false),
custom_cert_verifier_status_(false) { custom_cert_verifier_status_(false) {
// If a factory is used, take a reference on the factory's SSL_CTX. // If a factory is used, take a reference on the factory's SSL_CTX.
// Otherwise, we'll create our own later. // Otherwise, we'll create our own later.
@ -226,16 +225,8 @@ OpenSSLAdapter::~OpenSSLAdapter() {
Cleanup(); Cleanup();
} }
void OpenSSLAdapter::SetIgnoreBadCert(bool ignore) { void OpenSSLAdapter::SetSSLConfig(const SSLConfig& ssl_config) {
ignore_bad_cert_ = ignore; ssl_config_ = ssl_config;
}
void OpenSSLAdapter::SetAlpnProtocols(const std::vector<std::string>& protos) {
alpn_protocols_ = protos;
}
void OpenSSLAdapter::SetEllipticCurves(const std::vector<std::string>& curves) {
elliptic_curves_ = curves;
} }
void OpenSSLAdapter::SetMode(SSLMode mode) { void OpenSSLAdapter::SetMode(SSLMode mode) {
@ -269,7 +260,7 @@ AsyncSocket* OpenSSLAdapter::Accept(SocketAddress* paddr) {
SSLAdapter* adapter = SSLAdapter::Create(socket); SSLAdapter* adapter = SSLAdapter::Create(socket);
adapter->SetIdentity(identity_->GetReference()); adapter->SetIdentity(identity_->GetReference());
adapter->SetRole(rtc::SSL_SERVER); adapter->SetRole(rtc::SSL_SERVER);
adapter->SetIgnoreBadCert(ignore_bad_cert_); adapter->SetSSLConfig(ssl_config_);
adapter->StartSSL("", false); adapter->StartSSL("", false);
return adapter; return adapter;
} }
@ -367,13 +358,28 @@ int OpenSSLAdapter::BeginSSL() {
} }
#ifdef OPENSSL_IS_BORINGSSL #ifdef OPENSSL_IS_BORINGSSL
// Set a couple common TLS extensions; even though we don't use them yet. // Potentially set a couple common TLS extensions; even though we don't use
// them yet.
if (ssl_config_.enable_ocsp_stapling) {
SSL_enable_ocsp_stapling(ssl_); SSL_enable_ocsp_stapling(ssl_);
}
if (ssl_config_.enable_signed_cert_timestamp) {
SSL_enable_signed_cert_timestamps(ssl_); SSL_enable_signed_cert_timestamps(ssl_);
}
SSL_CTX_set_grease_enabled(ssl_ctx_, ssl_config_.enable_grease);
#endif #endif
if (!alpn_protocols_.empty()) { if (ssl_config_.max_ssl_version.has_value()) {
std::string tls_alpn_string = TransformAlpnProtocols(alpn_protocols_); SSL_set_max_proto_version(ssl_, ssl_config_.max_ssl_version.value());
}
if (ssl_config_.enable_tls_channel_id) {
SSL_enable_tls_channel_id(ssl_);
}
if (ssl_config_.tls_alpn_protocols.has_value()) {
std::string tls_alpn_string =
TransformAlpnProtocols(ssl_config_.tls_alpn_protocols.value());
if (!tls_alpn_string.empty()) { if (!tls_alpn_string.empty()) {
SSL_set_alpn_protos( SSL_set_alpn_protos(
ssl_, reinterpret_cast<const unsigned char*>(tls_alpn_string.data()), ssl_, reinterpret_cast<const unsigned char*>(tls_alpn_string.data()),
@ -381,8 +387,9 @@ int OpenSSLAdapter::BeginSSL() {
} }
} }
if (!elliptic_curves_.empty()) { if (ssl_config_.tls_elliptic_curves.has_value()) {
SSL_set1_curves_list(ssl_, rtc::join(elliptic_curves_, ':').c_str()); SSL_set1_curves_list(
ssl_, rtc::join(ssl_config_.tls_elliptic_curves.value(), ':').c_str());
} }
// Now that the initial config is done, transfer ownership of |bio| to the // Now that the initial config is done, transfer ownership of |bio| to the
@ -794,10 +801,10 @@ bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const std::string& host) {
openssl::VerifyPeerCertMatchesHost(ssl, host) && openssl::VerifyPeerCertMatchesHost(ssl, host) &&
(SSL_get_verify_result(ssl) == X509_V_OK || custom_cert_verifier_status_); (SSL_get_verify_result(ssl) == X509_V_OK || custom_cert_verifier_status_);
if (!is_valid_cert_name && ignore_bad_cert_) { if (!is_valid_cert_name && ShouldIgnoreBadCert()) {
RTC_DLOG(LS_WARNING) << "Other TLS post connection checks failed. " RTC_DLOG(LS_WARNING) << "Other TLS post connection checks failed. "
"ignore_bad_cert_ set to true. Overriding name " "TLS cert policy set to ignore bad certs. "
"verification failure!"; "Overriding name verification failure!";
is_valid_cert_name = true; is_valid_cert_name = true;
} }
return is_valid_cert_name; return is_valid_cert_name;
@ -870,7 +877,7 @@ int OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
} }
// Should only be used for debugging and development. // Should only be used for debugging and development.
if (!ok && stream->ignore_bad_cert_) { if (!ok && stream->ShouldIgnoreBadCert()) {
RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
ok = 1; ok = 1;
} }
@ -941,6 +948,11 @@ SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
return ctx; return ctx;
} }
bool OpenSSLAdapter::ShouldIgnoreBadCert() {
return ssl_config_.tls_cert_policy ==
TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
}
std::string TransformAlpnProtocols( std::string TransformAlpnProtocols(
const std::vector<std::string>& alpn_protocols) { const std::vector<std::string>& alpn_protocols) {
// Transforms the alpn_protocols list to the format expected by // Transforms the alpn_protocols list to the format expected by

View File

@ -45,9 +45,7 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler {
SSLCertificateVerifier* ssl_cert_verifier = nullptr); SSLCertificateVerifier* ssl_cert_verifier = nullptr);
~OpenSSLAdapter() override; ~OpenSSLAdapter() override;
void SetIgnoreBadCert(bool ignore) override; void SetSSLConfig(const SSLConfig& ssl_config) override;
void SetAlpnProtocols(const std::vector<std::string>& protos) override;
void SetEllipticCurves(const std::vector<std::string>& curves) override;
void SetMode(SSLMode mode) override; void SetMode(SSLMode mode) override;
void SetCertVerifier(SSLCertificateVerifier* ssl_cert_verifier) override; void SetCertVerifier(SSLCertificateVerifier* ssl_cert_verifier) override;
void SetIdentity(SSLIdentity* identity) override; void SetIdentity(SSLIdentity* identity) override;
@ -95,6 +93,9 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler {
void Error(const char* context, int err, bool signal = true); void Error(const char* context, int err, bool signal = true);
void Cleanup(); void Cleanup();
// If true, the server certificate need not match the configured hostname.
bool ShouldIgnoreBadCert();
// Return value and arguments have the same meanings as for Send; |error| is // Return value and arguments have the same meanings as for Send; |error| is
// an output parameter filled with the result of SSL_get_error. // an output parameter filled with the result of SSL_get_error.
int DoSslWrite(const void* pv, size_t cb, int* error); int DoSslWrite(const void* pv, size_t cb, int* error);
@ -138,12 +139,8 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler {
std::string ssl_host_name_; std::string ssl_host_name_;
// Set the adapter to DTLS or TLS mode before creating the context. // Set the adapter to DTLS or TLS mode before creating the context.
SSLMode ssl_mode_; SSLMode ssl_mode_;
// If true, the server certificate need not match the configured hostname. // SSL configuration for this session.
bool ignore_bad_cert_; SSLConfig ssl_config_;
// List of protocols to be used in the TLS ALPN extension.
std::vector<std::string> alpn_protocols_;
// List of elliptic curves to be used in the TLS elliptic curves extension.
std::vector<std::string> elliptic_curves_;
// Holds the result of the call to run of the ssl_cert_verify_->Verify() // Holds the result of the call to run of the ssl_cert_verify_->Verify()
bool custom_cert_verifier_status_; bool custom_cert_verifier_status_;
}; };

View File

@ -16,6 +16,12 @@
namespace rtc { namespace rtc {
SSLConfig::SSLConfig() = default;
SSLConfig::SSLConfig(const SSLConfig&) = default;
SSLConfig::~SSLConfig() = default;
///////////////////////////////////////////////////////////////////////////////
SSLAdapterFactory* SSLAdapterFactory::Create() { SSLAdapterFactory* SSLAdapterFactory::Create() {
return new OpenSSLAdapterFactory(); return new OpenSSLAdapterFactory();
} }

View File

@ -22,6 +22,57 @@ namespace rtc {
class SSLAdapter; class SSLAdapter;
// TLS certificate policy.
enum class TlsCertPolicy {
// For TLS based protocols, ensure the connection is secure by not
// circumventing certificate validation.
TLS_CERT_POLICY_SECURE,
// For TLS based protocols, disregard security completely by skipping
// certificate validation. This is insecure and should never be used unless
// security is irrelevant in that particular context.
// Do not set to this value in production code.
// TODO(juberti): Remove the opportunistic encryption mechanism in
// BasicPacketSocketFactory that uses this value.
TLS_CERT_POLICY_INSECURE_NO_CHECK,
};
// SSL configuration options.
struct SSLConfig final {
SSLConfig();
SSLConfig(const SSLConfig&);
~SSLConfig();
bool operator==(const SSLConfig& o) const {
return enable_ocsp_stapling == o.enable_ocsp_stapling &&
enable_signed_cert_timestamp == o.enable_signed_cert_timestamp &&
enable_tls_channel_id == o.enable_tls_channel_id &&
enable_grease == o.enable_grease &&
max_ssl_version == o.max_ssl_version &&
tls_alpn_protocols == o.tls_alpn_protocols &&
tls_elliptic_curves == o.tls_elliptic_curves;
}
bool operator!=(const SSLConfig& o) const { return !(*this == o); }
// If true, enables the (unused) OCSP stapling TLS extension.
bool enable_ocsp_stapling = true;
// If true, enables the (unused) signed certificate timestamp TLS extension.
bool enable_signed_cert_timestamp = true;
// If true, enables the (unused) channel ID TLS extension.
bool enable_tls_channel_id = false;
// If true, enables the (unused) GREASE TLS extension.
bool enable_grease = false;
// Indicates how to process incoming certificates.
TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE;
// If set, indicates the highest supported SSL version.
absl::optional<int> max_ssl_version;
// If set, indicates the list of protocols to be used in the TLS ALPN
// extension.
absl::optional<std::vector<std::string>> tls_alpn_protocols;
// If set, indicates the list of curves to be used in the TLS elliptic curves
// extension.
absl::optional<std::vector<std::string>> tls_elliptic_curves;
};
// Class for creating SSL adapters with shared state, e.g., a session cache, // Class for creating SSL adapters with shared state, e.g., a session cache,
// which allows clients to resume SSL sessions to previously-contacted hosts. // which allows clients to resume SSL sessions to previously-contacted hosts.
// Clients should create the factory using Create(), set up the factory as // Clients should create the factory using Create(), set up the factory as
@ -52,14 +103,8 @@ class SSLAdapter : public AsyncSocketAdapter {
public: public:
explicit SSLAdapter(AsyncSocket* socket) : AsyncSocketAdapter(socket) {} explicit SSLAdapter(AsyncSocket* socket) : AsyncSocketAdapter(socket) {}
// Methods that control server certificate verification, used in unit tests. // Sets the SSL configuration for this session.
// Do not call these methods in production code. virtual void SetSSLConfig(const SSLConfig& ssl_config) = 0;
// TODO(juberti): Remove the opportunistic encryption mechanism in
// BasicPacketSocketFactory that uses this function.
virtual void SetIgnoreBadCert(bool ignore) = 0;
virtual void SetAlpnProtocols(const std::vector<std::string>& protos) = 0;
virtual void SetEllipticCurves(const std::vector<std::string>& curves) = 0;
// Do DTLS or TLS (default is TLS, if unspecified) // Do DTLS or TLS (default is TLS, if unspecified)
virtual void SetMode(SSLMode mode) = 0; virtual void SetMode(SSLMode mode) = 0;

View File

@ -67,7 +67,9 @@ class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
// Ignore any certificate errors for the purpose of testing. // Ignore any certificate errors for the purpose of testing.
// Note: We do this only because we don't have a real certificate. // Note: We do this only because we don't have a real certificate.
// NEVER USE THIS IN PRODUCTION CODE! // NEVER USE THIS IN PRODUCTION CODE!
ssl_adapter_->SetIgnoreBadCert(true); ssl_config_.tls_cert_policy =
rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
ssl_adapter_->SetSSLConfig(ssl_config_);
ssl_adapter_->SignalReadEvent.connect( ssl_adapter_->SignalReadEvent.connect(
this, &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent); this, &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent);
@ -75,22 +77,52 @@ class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
this, &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent); this, &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent);
} }
void SetIgnoreBadCert(bool ignore_bad_cert) { void SetTlsCertPolicy(rtc::TlsCertPolicy tls_cert_policy) {
ssl_adapter_->SetIgnoreBadCert(ignore_bad_cert); ssl_config_.tls_cert_policy = tls_cert_policy;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetEnableOcspStapling(bool enable_ocsp_stapling) {
ssl_config_.enable_ocsp_stapling = enable_ocsp_stapling;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetEnableSignedCertTimestamp(bool enable_signed_cert_timestamp) {
ssl_config_.enable_signed_cert_timestamp = enable_signed_cert_timestamp;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetEnableTlsChannelId(bool enable_tls_channel_id) {
ssl_config_.enable_tls_channel_id = enable_tls_channel_id;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetEnableGrease(bool enable_grease) {
ssl_config_.enable_grease = enable_grease;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetMaxSslVersion(const absl::optional<int>& max_ssl_version) {
ssl_config_.max_ssl_version = max_ssl_version;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetAlpnProtocols(
const absl::optional<std::vector<std::string>>& tls_alpn_protocols) {
ssl_config_.tls_alpn_protocols = tls_alpn_protocols;
ssl_adapter_->SetSSLConfig(ssl_config_);
}
void SetEllipticCurves(
const absl::optional<std::vector<std::string>>& tls_elliptic_curves) {
ssl_config_.tls_elliptic_curves = tls_elliptic_curves;
ssl_adapter_->SetSSLConfig(ssl_config_);
} }
void SetCertVerifier(rtc::SSLCertificateVerifier* ssl_cert_verifier) { void SetCertVerifier(rtc::SSLCertificateVerifier* ssl_cert_verifier) {
ssl_adapter_->SetCertVerifier(ssl_cert_verifier); ssl_adapter_->SetCertVerifier(ssl_cert_verifier);
} }
void SetAlpnProtocols(const std::vector<std::string>& protos) {
ssl_adapter_->SetAlpnProtocols(protos);
}
void SetEllipticCurves(const std::vector<std::string>& curves) {
ssl_adapter_->SetEllipticCurves(curves);
}
rtc::SocketAddress GetAddress() const { rtc::SocketAddress GetAddress() const {
return ssl_adapter_->GetLocalAddress(); return ssl_adapter_->GetLocalAddress();
} }
@ -154,6 +186,8 @@ class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
std::unique_ptr<rtc::SSLAdapter> ssl_adapter_; std::unique_ptr<rtc::SSLAdapter> ssl_adapter_;
rtc::SSLConfig ssl_config_;
std::string data_; std::string data_;
}; };
@ -305,29 +339,51 @@ class SSLAdapterTestBase : public testing::Test, public sigslot::has_slots<> {
void SetHandshakeWait(int wait) { handshake_wait_ = wait; } void SetHandshakeWait(int wait) { handshake_wait_ = wait; }
void SetIgnoreBadCert(bool ignore_bad_cert) { void SetTlsCertPolicy(rtc::TlsCertPolicy tls_cert_policy) {
client_->SetIgnoreBadCert(ignore_bad_cert); client_->SetTlsCertPolicy(tls_cert_policy);
}
void SetEnableOcspStapling(bool enable_ocsp_stapling) {
client_->SetEnableOcspStapling(enable_ocsp_stapling);
}
void SetEnableSignedCertTimestamp(bool enable_signed_cert_timestamp) {
client_->SetEnableSignedCertTimestamp(enable_signed_cert_timestamp);
}
void SetEnableTlsChannelId(bool enable_tls_channel_id) {
client_->SetEnableTlsChannelId(enable_tls_channel_id);
}
void SetEnableGrease(bool enable_grease) {
client_->SetEnableGrease(enable_grease);
}
void SetMaxSslVersion(const absl::optional<int>& max_ssl_version) {
client_->SetMaxSslVersion(max_ssl_version);
}
void SetAlpnProtocols(
const absl::optional<std::vector<std::string>>& tls_alpn_protocols) {
client_->SetAlpnProtocols(tls_alpn_protocols);
}
void SetEllipticCurves(
const absl::optional<std::vector<std::string>>& tls_elliptic_curves) {
client_->SetEllipticCurves(tls_elliptic_curves);
} }
void SetCertVerifier(rtc::SSLCertificateVerifier* ssl_cert_verifier) { void SetCertVerifier(rtc::SSLCertificateVerifier* ssl_cert_verifier) {
client_->SetCertVerifier(ssl_cert_verifier); client_->SetCertVerifier(ssl_cert_verifier);
} }
void SetAlpnProtocols(const std::vector<std::string>& protos) {
client_->SetAlpnProtocols(protos);
}
void SetEllipticCurves(const std::vector<std::string>& curves) {
client_->SetEllipticCurves(curves);
}
void SetMockCertVerifier(bool return_value) { void SetMockCertVerifier(bool return_value) {
auto mock_verifier = absl::make_unique<MockCertVerifier>(); auto mock_verifier = absl::make_unique<MockCertVerifier>();
EXPECT_CALL(*mock_verifier, Verify(_)).WillRepeatedly(Return(return_value)); EXPECT_CALL(*mock_verifier, Verify(_)).WillRepeatedly(Return(return_value));
cert_verifier_ = cert_verifier_ =
std::unique_ptr<rtc::SSLCertificateVerifier>(std::move(mock_verifier)); std::unique_ptr<rtc::SSLCertificateVerifier>(std::move(mock_verifier));
SetIgnoreBadCert(false); SetTlsCertPolicy(rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE);
SetCertVerifier(cert_verifier_.get()); SetCertVerifier(cert_verifier_.get());
} }
@ -525,6 +581,76 @@ TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransferCustomCertVerifier) {
TestTransfer("Hello, world!"); TestTransfer("Hello, world!");
} }
// Test transfer with OCSP stapling enabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestOcspStaplingEnabled) {
SetEnableOcspStapling(true);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with OCSP stapling disabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestOcspStaplingDisabled) {
SetEnableOcspStapling(false);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// test transfer with signed cert timestamp enabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestSignedCertTimestampEnabled) {
SetEnableSignedCertTimestamp(true);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with signed cert timestamp disabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestSignedCertTimestampDisabled) {
SetEnableSignedCertTimestamp(false);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with TLS channel ID enabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSChannelIdEnabled) {
SetEnableTlsChannelId(true);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with TLS channel ID disabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSChannelIdDisabled) {
SetEnableTlsChannelId(false);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with GREASE enabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestGreaseEnabled) {
SetEnableGrease(true);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with GREASE disabled
TEST_F(SSLAdapterTestTLS_ECDSA, TestGreaseDisabled) {
SetEnableGrease(false);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with TLS1_3.
TEST_F(SSLAdapterTestTLS_ECDSA, TestMaxSSLVersionTLS1_3) {
SetMaxSslVersion(0x0304 /* TLS1_3 */);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer with TLS1_2.
TEST_F(SSLAdapterTestTLS_ECDSA, TestMaxSSLVersionTLS1_2) {
SetMaxSslVersion(0x0303 /* TLS1_2 */);
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Test transfer using ALPN with protos as h2 and http/1.1 // Test transfer using ALPN with protos as h2 and http/1.1
TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSALPN) { TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSALPN) {
std::vector<std::string> alpn_protos{"h2", "http/1.1"}; std::vector<std::string> alpn_protos{"h2", "http/1.1"};

View File

@ -870,6 +870,9 @@ if (is_ios || is_mac) {
"objc/api/peerconnection/RTCRtpTransceiver.mm", "objc/api/peerconnection/RTCRtpTransceiver.mm",
"objc/api/peerconnection/RTCSSLAdapter.h", "objc/api/peerconnection/RTCSSLAdapter.h",
"objc/api/peerconnection/RTCSSLAdapter.mm", "objc/api/peerconnection/RTCSSLAdapter.mm",
"objc/api/peerconnection/RTCSSLConfig+Native.h",
"objc/api/peerconnection/RTCSSLConfig.h",
"objc/api/peerconnection/RTCSSLConfig.mm",
"objc/api/peerconnection/RTCSessionDescription+Private.h", "objc/api/peerconnection/RTCSessionDescription+Private.h",
"objc/api/peerconnection/RTCSessionDescription.h", "objc/api/peerconnection/RTCSessionDescription.h",
"objc/api/peerconnection/RTCSessionDescription.mm", "objc/api/peerconnection/RTCSessionDescription.mm",
@ -985,6 +988,7 @@ if (is_ios || is_mac) {
"objc/Framework/Headers/WebRTC/RTCRtpSender.h", "objc/Framework/Headers/WebRTC/RTCRtpSender.h",
"objc/Framework/Headers/WebRTC/RTCRtpTransceiver.h", "objc/Framework/Headers/WebRTC/RTCRtpTransceiver.h",
"objc/Framework/Headers/WebRTC/RTCSSLAdapter.h", "objc/Framework/Headers/WebRTC/RTCSSLAdapter.h",
"objc/Framework/Headers/WebRTC/RTCSSLConfig.h",
"objc/Framework/Headers/WebRTC/RTCSessionDescription.h", "objc/Framework/Headers/WebRTC/RTCSessionDescription.h",
"objc/Framework/Headers/WebRTC/RTCTracing.h", "objc/Framework/Headers/WebRTC/RTCTracing.h",
"objc/Framework/Headers/WebRTC/RTCVideoCapturer.h", "objc/Framework/Headers/WebRTC/RTCVideoCapturer.h",

View File

@ -306,6 +306,7 @@ if (is_android) {
"api/org/webrtc/RtpSender.java", "api/org/webrtc/RtpSender.java",
"api/org/webrtc/RtpTransceiver.java", "api/org/webrtc/RtpTransceiver.java",
"api/org/webrtc/SSLCertificateVerifier.java", "api/org/webrtc/SSLCertificateVerifier.java",
"api/org/webrtc/SslConfig.java",
"api/org/webrtc/SdpObserver.java", "api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java", "api/org/webrtc/SessionDescription.java",
"api/org/webrtc/StatsObserver.java", "api/org/webrtc/StatsObserver.java",
@ -648,6 +649,8 @@ if (is_android) {
"src/jni/pc/sessiondescription.h", "src/jni/pc/sessiondescription.h",
"src/jni/pc/sslcertificateverifierwrapper.cc", "src/jni/pc/sslcertificateverifierwrapper.cc",
"src/jni/pc/sslcertificateverifierwrapper.h", "src/jni/pc/sslcertificateverifierwrapper.h",
"src/jni/pc/sslconfig.cc",
"src/jni/pc/sslconfig.h",
"src/jni/pc/statsobserver.cc", "src/jni/pc/statsobserver.cc",
"src/jni/pc/statsobserver.h", "src/jni/pc/statsobserver.h",
"src/jni/pc/turncustomizer.cc", "src/jni/pc/turncustomizer.cc",
@ -1193,6 +1196,7 @@ if (is_android) {
"api/org/webrtc/SSLCertificateVerifier.java", "api/org/webrtc/SSLCertificateVerifier.java",
"api/org/webrtc/SdpObserver.java", "api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java", "api/org/webrtc/SessionDescription.java",
"api/org/webrtc/SslConfig.java",
"api/org/webrtc/StatsObserver.java", "api/org/webrtc/StatsObserver.java",
"api/org/webrtc/StatsReport.java", "api/org/webrtc/StatsReport.java",
"api/org/webrtc/TurnCustomizer.java", "api/org/webrtc/TurnCustomizer.java",

View File

@ -50,6 +50,7 @@ public class PeerConnection {
} }
} }
// TODO(diogor, webrtc:9673): Remove TlsCertPolicy. It's deprecated, in favor of SslConfig.
/** Tracks PeerConnectionInterface::TlsCertPolicy */ /** Tracks PeerConnectionInterface::TlsCertPolicy */
public enum TlsCertPolicy { public enum TlsCertPolicy {
TLS_CERT_POLICY_SECURE, TLS_CERT_POLICY_SECURE,
@ -126,7 +127,9 @@ public class PeerConnection {
public final List<String> urls; public final List<String> urls;
public final String username; public final String username;
public final String password; public final String password;
public final TlsCertPolicy tlsCertPolicy; // TODO(diogor, webrtc:9673): Remove tlsCertPolicy from this API.
// This field will be ignored if tlsCertPolicy is also set in SslConfig.
@Deprecated public final TlsCertPolicy tlsCertPolicy;
// If the URIs in |urls| only contain IP addresses, this field can be used // If the URIs in |urls| only contain IP addresses, this field can be used
// to indicate the hostname, which may be necessary for TLS (using the SNI // to indicate the hostname, which may be necessary for TLS (using the SNI
@ -134,12 +137,18 @@ public class PeerConnection {
// necessary. // necessary.
public final String hostname; public final String hostname;
// TODO(diogor, webrtc:9673): Remove tlsAlpnProtocols from this API.
// List of protocols to be used in the TLS ALPN extension. // List of protocols to be used in the TLS ALPN extension.
public final List<String> tlsAlpnProtocols; @Deprecated public final List<String> tlsAlpnProtocols;
// TODO(diogor, webrtc:9673): Remove tlsEllipticCurves from this API.
// List of elliptic curves to be used in the TLS elliptic curves extension. // List of elliptic curves to be used in the TLS elliptic curves extension.
// Only curve names supported by OpenSSL should be used (eg. "P-256","X25519"). // Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
public final List<String> tlsEllipticCurves; // This field will be ignored if tlsEllipticCurves is also set in SslConfig.
@Deprecated public final List<String> tlsEllipticCurves;
// SSL configuration options for any SSL/TLS connections to this IceServer.
public final SslConfig sslConfig;
/** Convenience constructor for STUN servers. */ /** Convenience constructor for STUN servers. */
@Deprecated @Deprecated
@ -161,12 +170,12 @@ public class PeerConnection {
public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy, public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy,
String hostname) { String hostname) {
this(uri, Collections.singletonList(uri), username, password, tlsCertPolicy, hostname, null, this(uri, Collections.singletonList(uri), username, password, tlsCertPolicy, hostname, null,
null); null, SslConfig.builder().createSslConfig());
} }
private IceServer(String uri, List<String> urls, String username, String password, private IceServer(String uri, List<String> urls, String username, String password,
TlsCertPolicy tlsCertPolicy, String hostname, List<String> tlsAlpnProtocols, TlsCertPolicy tlsCertPolicy, String hostname, List<String> tlsAlpnProtocols,
List<String> tlsEllipticCurves) { List<String> tlsEllipticCurves, SslConfig sslConfig) {
if (uri == null || urls == null || urls.isEmpty()) { if (uri == null || urls == null || urls.isEmpty()) {
throw new IllegalArgumentException("uri == null || urls == null || urls.isEmpty()"); throw new IllegalArgumentException("uri == null || urls == null || urls.isEmpty()");
} }
@ -192,12 +201,13 @@ public class PeerConnection {
this.hostname = hostname; this.hostname = hostname;
this.tlsAlpnProtocols = tlsAlpnProtocols; this.tlsAlpnProtocols = tlsAlpnProtocols;
this.tlsEllipticCurves = tlsEllipticCurves; this.tlsEllipticCurves = tlsEllipticCurves;
this.sslConfig = sslConfig;
} }
@Override @Override
public String toString() { public String toString() {
return urls + " [" + username + ":" + password + "] [" + tlsCertPolicy + "] [" + hostname return urls + " [" + username + ":" + password + "] [" + tlsCertPolicy + "] [" + hostname
+ "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "]"; + "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "] [" + sslConfig + "]";
} }
public static Builder builder(String uri) { public static Builder builder(String uri) {
@ -216,6 +226,7 @@ public class PeerConnection {
private String hostname = ""; private String hostname = "";
private List<String> tlsAlpnProtocols; private List<String> tlsAlpnProtocols;
private List<String> tlsEllipticCurves; private List<String> tlsEllipticCurves;
private SslConfig sslConfig = SslConfig.builder().createSslConfig();
private Builder(List<String> urls) { private Builder(List<String> urls) {
if (urls == null || urls.isEmpty()) { if (urls == null || urls.isEmpty()) {
@ -234,6 +245,7 @@ public class PeerConnection {
return this; return this;
} }
@Deprecated
public Builder setTlsCertPolicy(TlsCertPolicy tlsCertPolicy) { public Builder setTlsCertPolicy(TlsCertPolicy tlsCertPolicy) {
this.tlsCertPolicy = tlsCertPolicy; this.tlsCertPolicy = tlsCertPolicy;
return this; return this;
@ -244,19 +256,26 @@ public class PeerConnection {
return this; return this;
} }
@Deprecated
public Builder setTlsAlpnProtocols(List<String> tlsAlpnProtocols) { public Builder setTlsAlpnProtocols(List<String> tlsAlpnProtocols) {
this.tlsAlpnProtocols = tlsAlpnProtocols; this.tlsAlpnProtocols = tlsAlpnProtocols;
return this; return this;
} }
@Deprecated
public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) { public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) {
this.tlsEllipticCurves = tlsEllipticCurves; this.tlsEllipticCurves = tlsEllipticCurves;
return this; return this;
} }
public Builder setSslConfig(SslConfig sslConfig) {
this.sslConfig = sslConfig;
return this;
}
public IceServer createIceServer() { public IceServer createIceServer() {
return new IceServer(urls.get(0), urls, username, password, tlsCertPolicy, hostname, return new IceServer(urls.get(0), urls, username, password, tlsCertPolicy, hostname,
tlsAlpnProtocols, tlsEllipticCurves); tlsAlpnProtocols, tlsEllipticCurves, sslConfig);
} }
} }
@ -298,6 +317,11 @@ public class PeerConnection {
List<String> getTlsEllipticCurves() { List<String> getTlsEllipticCurves() {
return tlsEllipticCurves; return tlsEllipticCurves;
} }
@CalledByNative("IceServer")
SslConfig getSslConfig() {
return sslConfig;
}
} }
/** Java version of PeerConnectionInterface.IceTransportsType */ /** Java version of PeerConnectionInterface.IceTransportsType */

View File

@ -0,0 +1,204 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
/**
* Java version of rtc::SSLConfig.
*
* Contains the configuration of any SSL/TLS connections that are initiated by
* our client.
*/
public class SslConfig {
/** Tracks rtc::TlsCertPolicy */
public enum TlsCertPolicy {
TLS_CERT_POLICY_SECURE,
TLS_CERT_POLICY_INSECURE_NO_CHECK,
}
/** Indicates whether to enable OCSP stapling in TLS. */
public final boolean enableOcspStapling;
/** Indicates whether to enable the signed certificate timestamp extension in TLS. */
public final boolean enableSignedCertTimestamp;
/** Indicates whether to enable the TLS Channel ID extension. */
public final boolean enableTlsChannelId;
/** Indicates whether to enable the TLS GREASE extension. */
public final boolean enableGrease;
/** Indicates how to process TURN server certificates */
public final TlsCertPolicy tlsCertPolicy;
/**
* Highest supported SSL version, as defined in the supported_versions TLS extension.
* If null, the default OpenSSL/BoringSSL max version will be used.
*/
@Nullable public final Integer maxSslVersion;
/**
* List of protocols to be used in the TLS ALPN extension.
* If null, the default list of OpenSSL/BoringSSL ALPN protocols will be used.
*/
@Nullable public final List<String> tlsAlpnProtocols;
/**
* List of elliptic curves to be used in the TLS elliptic curves extension.
* Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
* If null, the default list of OpenSSL/BoringSSL curves will be used.
*/
@Nullable public final List<String> tlsEllipticCurves;
private SslConfig(boolean enableOcspStapling, boolean enableSignedCertTimestamp,
boolean enableTlsChannelId, boolean enableGrease, TlsCertPolicy tlsCertPolicy,
Integer maxSslVersion, List<String> tlsAlpnProtocols, List<String> tlsEllipticCurves) {
this.enableOcspStapling = enableOcspStapling;
this.enableSignedCertTimestamp = enableSignedCertTimestamp;
this.enableTlsChannelId = enableTlsChannelId;
this.enableGrease = enableGrease;
this.tlsCertPolicy = tlsCertPolicy;
this.maxSslVersion = maxSslVersion;
if (tlsAlpnProtocols != null) {
this.tlsAlpnProtocols = Collections.unmodifiableList(tlsAlpnProtocols);
} else {
this.tlsAlpnProtocols = null;
}
if (tlsEllipticCurves != null) {
this.tlsEllipticCurves = Collections.unmodifiableList(tlsEllipticCurves);
} else {
this.tlsEllipticCurves = null;
}
}
@Override
public String toString() {
return "[enableOcspStapling=" + enableOcspStapling + "] [enableSignedCertTimestamp="
+ enableSignedCertTimestamp + "] [enableTlsChannelId=" + enableTlsChannelId
+ "] [enableGrease=" + enableGrease + "] [tlsCertPolicy=" + tlsCertPolicy
+ "] [maxSslVersion=" + maxSslVersion + "] [tlsAlpnProtocols=" + tlsAlpnProtocols
+ "] [tlsEllipticCurves=" + tlsEllipticCurves + "]";
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private boolean enableOcspStapling;
private boolean enableSignedCertTimestamp;
private boolean enableTlsChannelId;
private boolean enableGrease;
private TlsCertPolicy tlsCertPolicy;
@Nullable private Integer maxSslVersion;
@Nullable private List<String> tlsAlpnProtocols;
@Nullable private List<String> tlsEllipticCurves;
private Builder() {
this.enableOcspStapling = true;
this.enableSignedCertTimestamp = true;
this.enableTlsChannelId = false;
this.enableGrease = false;
this.tlsCertPolicy = TlsCertPolicy.TLS_CERT_POLICY_SECURE;
this.maxSslVersion = null;
this.tlsAlpnProtocols = null;
this.tlsEllipticCurves = null;
}
public Builder setEnableOcspStapling(boolean enableOcspStapling) {
this.enableOcspStapling = enableOcspStapling;
return this;
}
public Builder setEnableSignedCertTimestamp(boolean enableSignedCertTimestamp) {
this.enableSignedCertTimestamp = enableSignedCertTimestamp;
return this;
}
public Builder setEnableTlsChannelId(boolean enableTlsChannelId) {
this.enableTlsChannelId = enableTlsChannelId;
return this;
}
public Builder setEnableGrease(boolean enableGrease) {
this.enableGrease = enableGrease;
return this;
}
public Builder setTlsCertPolicy(TlsCertPolicy tlsCertPolicy) {
this.tlsCertPolicy = tlsCertPolicy;
return this;
}
public Builder setMaxSslVersion(int maxSslVersion) {
this.maxSslVersion = maxSslVersion;
return this;
}
public Builder setTlsAlpnProtocols(List<String> tlsAlpnProtocols) {
this.tlsAlpnProtocols = tlsAlpnProtocols;
return this;
}
public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) {
this.tlsEllipticCurves = tlsEllipticCurves;
return this;
}
public SslConfig createSslConfig() {
return new SslConfig(enableOcspStapling, enableSignedCertTimestamp, enableTlsChannelId,
enableGrease, tlsCertPolicy, maxSslVersion, tlsAlpnProtocols, tlsEllipticCurves);
}
}
@CalledByNative
boolean getEnableOcspStapling() {
return enableOcspStapling;
}
@CalledByNative
boolean getEnableSignedCertTimestamp() {
return enableSignedCertTimestamp;
}
@CalledByNative
boolean getEnableTlsChannelId() {
return enableTlsChannelId;
}
@CalledByNative
boolean getEnableGrease() {
return enableGrease;
}
@CalledByNative
TlsCertPolicy getTlsCertPolicy() {
return tlsCertPolicy;
}
@Nullable
@CalledByNative
Integer getMaxSslVersion() {
return maxSslVersion;
}
@Nullable
@CalledByNative
List<String> getTlsAlpnProtocols() {
return tlsAlpnProtocols;
}
@Nullable
@CalledByNative
List<String> getTlsEllipticCurves() {
return tlsEllipticCurves;
}
}

View File

@ -51,6 +51,7 @@
#include "sdk/android/src/jni/pc/rtpsender.h" #include "sdk/android/src/jni/pc/rtpsender.h"
#include "sdk/android/src/jni/pc/sdpobserver.h" #include "sdk/android/src/jni/pc/sdpobserver.h"
#include "sdk/android/src/jni/pc/sessiondescription.h" #include "sdk/android/src/jni/pc/sessiondescription.h"
#include "sdk/android/src/jni/pc/sslconfig.h"
#include "sdk/android/src/jni/pc/statsobserver.h" #include "sdk/android/src/jni/pc/statsobserver.h"
#include "sdk/android/src/jni/pc/turncustomizer.h" #include "sdk/android/src/jni/pc/turncustomizer.h"
@ -87,6 +88,8 @@ PeerConnectionInterface::IceServers JavaToNativeIceServers(
Java_IceServer_getTlsAlpnProtocols(jni, j_ice_server); Java_IceServer_getTlsAlpnProtocols(jni, j_ice_server);
ScopedJavaLocalRef<jobject> tls_elliptic_curves = ScopedJavaLocalRef<jobject> tls_elliptic_curves =
Java_IceServer_getTlsEllipticCurves(jni, j_ice_server); Java_IceServer_getTlsEllipticCurves(jni, j_ice_server);
ScopedJavaLocalRef<jobject> ssl_config =
Java_IceServer_getSslConfig(jni, j_ice_server);
PeerConnectionInterface::IceServer server; PeerConnectionInterface::IceServer server;
server.urls = JavaListToNativeVector<std::string, jstring>( server.urls = JavaListToNativeVector<std::string, jstring>(
jni, urls, &JavaToNativeString); jni, urls, &JavaToNativeString);
@ -98,6 +101,7 @@ PeerConnectionInterface::IceServers JavaToNativeIceServers(
jni, tls_alpn_protocols, &JavaToNativeString); jni, tls_alpn_protocols, &JavaToNativeString);
server.tls_elliptic_curves = JavaListToNativeVector<std::string, jstring>( server.tls_elliptic_curves = JavaListToNativeVector<std::string, jstring>(
jni, tls_elliptic_curves, &JavaToNativeString); jni, tls_elliptic_curves, &JavaToNativeString);
server.ssl_config = JavaToNativeSslConfig(jni, ssl_config);
ice_servers.push_back(server); ice_servers.push_back(server);
} }
return ice_servers; return ice_servers;

View File

@ -0,0 +1,78 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sdk/android/src/jni/pc/sslconfig.h"
#include <string>
#include "rtc_base/ssladapter.h"
#include "sdk/android/generated_peerconnection_jni/jni/SslConfig_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
rtc::TlsCertPolicy JavaToNativeRtcTlsCertPolicy(
JNIEnv* jni,
const JavaRef<jobject>& j_ssl_config_tls_cert_policy) {
std::string enum_name = GetJavaEnumName(jni, j_ssl_config_tls_cert_policy);
if (enum_name == "TLS_CERT_POLICY_SECURE")
return rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE;
if (enum_name == "TLS_CERT_POLICY_INSECURE_NO_CHECK")
return rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
RTC_NOTREACHED();
return rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE;
}
rtc::SSLConfig JavaToNativeSslConfig(JNIEnv* jni,
const JavaRef<jobject>& j_ssl_config) {
rtc::SSLConfig ssl_config;
ssl_config.enable_ocsp_stapling =
Java_SslConfig_getEnableOcspStapling(jni, j_ssl_config);
ssl_config.enable_signed_cert_timestamp =
Java_SslConfig_getEnableSignedCertTimestamp(jni, j_ssl_config);
ssl_config.enable_tls_channel_id =
Java_SslConfig_getEnableTlsChannelId(jni, j_ssl_config);
ssl_config.enable_grease = Java_SslConfig_getEnableGrease(jni, j_ssl_config);
ScopedJavaLocalRef<jobject> j_ssl_config_max_ssl_version =
Java_SslConfig_getMaxSslVersion(jni, j_ssl_config);
ssl_config.max_ssl_version =
JavaToNativeOptionalInt(jni, j_ssl_config_max_ssl_version);
ScopedJavaLocalRef<jobject> j_ssl_config_tls_cert_policy =
Java_SslConfig_getTlsCertPolicy(jni, j_ssl_config);
ssl_config.tls_cert_policy =
JavaToNativeRtcTlsCertPolicy(jni, j_ssl_config_tls_cert_policy);
ScopedJavaLocalRef<jobject> j_ssl_config_tls_alpn_protocols =
Java_SslConfig_getTlsAlpnProtocols(jni, j_ssl_config);
if (!IsNull(jni, j_ssl_config_tls_alpn_protocols)) {
ssl_config.tls_alpn_protocols =
JavaListToNativeVector<std::string, jstring>(
jni, j_ssl_config_tls_alpn_protocols, &JavaToNativeString);
}
ScopedJavaLocalRef<jobject> j_ssl_config_tls_elliptic_curves =
Java_SslConfig_getTlsEllipticCurves(jni, j_ssl_config);
if (!IsNull(jni, j_ssl_config_tls_elliptic_curves)) {
ssl_config.tls_elliptic_curves =
JavaListToNativeVector<std::string, jstring>(
jni, j_ssl_config_tls_elliptic_curves, &JavaToNativeString);
}
return ssl_config;
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,30 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_ANDROID_SRC_JNI_PC_SSLCONFIG_H_
#define SDK_ANDROID_SRC_JNI_PC_SSLCONFIG_H_
#include "api/peerconnectioninterface.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"
namespace webrtc {
namespace jni {
rtc::TlsCertPolicy JavaToNativeRtcTlsCertPolicy(
JNIEnv* jni,
const JavaRef<jobject>& j_ssl_config_tls_cert_policy);
rtc::SSLConfig JavaToNativeSslConfig(JNIEnv* env,
const JavaRef<jobject>& j_ssl_config);
} // namespace jni
} // namespace webrtc
#endif // SDK_ANDROID_SRC_JNI_PC_SSLCONFIG_H_

View File

@ -0,0 +1,11 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "api/peerconnection/RTCSSLConfig.h"

View File

@ -11,11 +11,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "RTCMacros.h" #import "RTCMacros.h"
#import "RTCSSLConfig.h"
typedef NS_ENUM(NSUInteger, RTCTlsCertPolicy) {
RTCTlsCertPolicySecure,
RTCTlsCertPolicyInsecureNoCheck
};
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -32,7 +28,8 @@ RTC_EXPORT
@property(nonatomic, readonly, nullable) NSString *credential; @property(nonatomic, readonly, nullable) NSString *credential;
/** /**
* TLS certificate policy to use if this RTCIceServer object is a TURN server. Deprecated. TODO(diogor, webrtc:9673): Remove from API.
TLS certificate policy to use if this RTCIceServer object is a TURN server.
*/ */
@property(nonatomic, readonly) RTCTlsCertPolicy tlsCertPolicy; @property(nonatomic, readonly) RTCTlsCertPolicy tlsCertPolicy;
@ -43,15 +40,24 @@ RTC_EXPORT
*/ */
@property(nonatomic, readonly, nullable) NSString *hostname; @property(nonatomic, readonly, nullable) NSString *hostname;
/** List of protocols to be used in the TLS ALPN extension. */ /**
Deprecated. TODO(diogor, webrtc:9673): Remove from API.
List of protocols to be used in the TLS ALPN extension.
This field will be ignored if also set in RTCSSLConfig.
*/
@property(nonatomic, readonly) NSArray<NSString *> *tlsAlpnProtocols; @property(nonatomic, readonly) NSArray<NSString *> *tlsAlpnProtocols;
/** /**
Deprecated. TODO(diogor, webrtc:9673): Remove from API.
List elliptic curves to be used in the TLS elliptic curves extension. List elliptic curves to be used in the TLS elliptic curves extension.
Only curve names supported by OpenSSL should be used (eg. "P-256","X25519"). Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
This field will be ignored if also set in RTCSSLConfig.
*/ */
@property(nonatomic, readonly) NSArray<NSString *> *tlsEllipticCurves; @property(nonatomic, readonly) NSArray<NSString *> *tlsEllipticCurves;
/** SSL configuration options for any SSL/TLS connections to this IceServer. */
@property(nonatomic, readonly) RTCSSLConfig *sslConfig;
- (nonnull instancetype)init NS_UNAVAILABLE; - (nonnull instancetype)init NS_UNAVAILABLE;
/** Convenience initializer for a server with no authentication (e.g. STUN). */ /** Convenience initializer for a server with no authentication (e.g. STUN). */
@ -106,8 +112,17 @@ RTC_EXPORT
tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy
hostname:(nullable NSString *)hostname hostname:(nullable NSString *)hostname
tlsAlpnProtocols:(nullable NSArray<NSString *> *)tlsAlpnProtocols tlsAlpnProtocols:(nullable NSArray<NSString *> *)tlsAlpnProtocols
tlsEllipticCurves:(nullable NSArray<NSString *> *)tlsEllipticCurves tlsEllipticCurves:(nullable NSArray<NSString *> *)tlsEllipticCurves;
NS_DESIGNATED_INITIALIZER;
/**
* Initialize an RTCIceServer with its associated URLs, optional
* username, optional credential, hostname and SSL config.
*/
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
username:(nullable NSString *)username
credential:(nullable NSString *)credential
hostname:(nullable NSString *)hostname
sslConfig:(RTCSSLConfig *)sslConfig NS_DESIGNATED_INITIALIZER;
@end @end

View File

@ -9,6 +9,7 @@
*/ */
#import "RTCIceServer+Private.h" #import "RTCIceServer+Private.h"
#import "RTCSSLConfig+Native.h"
#import "helpers/NSString+StdString.h" #import "helpers/NSString+StdString.h"
@ -21,6 +22,7 @@
@synthesize hostname = _hostname; @synthesize hostname = _hostname;
@synthesize tlsAlpnProtocols = _tlsAlpnProtocols; @synthesize tlsAlpnProtocols = _tlsAlpnProtocols;
@synthesize tlsEllipticCurves = _tlsEllipticCurves; @synthesize tlsEllipticCurves = _tlsEllipticCurves;
@synthesize sslConfig = _sslConfig;
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings { - (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings {
return [self initWithURLStrings:urlStrings return [self initWithURLStrings:urlStrings
@ -83,28 +85,50 @@
hostname:(NSString *)hostname hostname:(NSString *)hostname
tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols
tlsEllipticCurves:(NSArray<NSString *> *)tlsEllipticCurves { tlsEllipticCurves:(NSArray<NSString *> *)tlsEllipticCurves {
RTCSSLConfig *sslConfig = [[RTCSSLConfig alloc] init];
sslConfig.tlsCertPolicy = tlsCertPolicy;
sslConfig.tlsALPNProtocols = [[NSArray alloc] initWithArray:tlsAlpnProtocols copyItems:YES];
sslConfig.tlsEllipticCurves = [[NSArray alloc] initWithArray:tlsEllipticCurves copyItems:YES];
return [self initWithURLStrings:urlStrings
username:username
credential:credential
hostname:hostname
sslConfig:sslConfig];
}
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
username:(NSString *)username
credential:(NSString *)credential
hostname:(NSString *)hostname
sslConfig:(RTCSSLConfig *)sslConfig {
NSParameterAssert(urlStrings.count); NSParameterAssert(urlStrings.count);
if (self = [super init]) { if (self = [super init]) {
_urlStrings = [[NSArray alloc] initWithArray:urlStrings copyItems:YES]; _urlStrings = [[NSArray alloc] initWithArray:urlStrings copyItems:YES];
_username = [username copy]; _username = [username copy];
_credential = [credential copy]; _credential = [credential copy];
_tlsCertPolicy = tlsCertPolicy;
_hostname = [hostname copy]; _hostname = [hostname copy];
_tlsAlpnProtocols = [[NSArray alloc] initWithArray:tlsAlpnProtocols copyItems:YES]; _sslConfig = sslConfig;
_tlsEllipticCurves = [[NSArray alloc] initWithArray:tlsEllipticCurves copyItems:YES];
// TODO(diogor, webrtc:9673): Remove these duplicate assignments.
_tlsCertPolicy = sslConfig.tlsCertPolicy;
if (sslConfig.tlsALPNProtocols) {
_tlsAlpnProtocols = [[NSArray alloc] initWithArray:sslConfig.tlsALPNProtocols copyItems:YES];
}
if (sslConfig.tlsEllipticCurves) {
_tlsEllipticCurves =
[[NSArray alloc] initWithArray:sslConfig.tlsEllipticCurves copyItems:YES];
}
} }
return self; return self;
} }
- (NSString *)description { - (NSString *)description {
return [NSString stringWithFormat:@"RTCIceServer:\n%@\n%@\n%@\n%@\n%@\n%@\n%@", return [NSString stringWithFormat:@"RTCIceServer:\n%@\n%@\n%@\n%@\n%@",
_urlStrings, _urlStrings,
_username, _username,
_credential, _credential,
[self stringForTlsCertPolicy:_tlsCertPolicy],
_hostname, _hostname,
_tlsAlpnProtocols, _sslConfig];
_tlsEllipticCurves];
} }
#pragma mark - Private #pragma mark - Private
@ -149,6 +173,8 @@
webrtc::PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck; webrtc::PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck;
break; break;
} }
iceServer.ssl_config = [_sslConfig nativeConfig];
return iceServer; return iceServer;
} }
@ -162,34 +188,38 @@
NSString *username = [NSString stringForStdString:nativeServer.username]; NSString *username = [NSString stringForStdString:nativeServer.username];
NSString *credential = [NSString stringForStdString:nativeServer.password]; NSString *credential = [NSString stringForStdString:nativeServer.password];
NSString *hostname = [NSString stringForStdString:nativeServer.hostname]; NSString *hostname = [NSString stringForStdString:nativeServer.hostname];
NSMutableArray *tlsAlpnProtocols = RTCSSLConfig *sslConfig = [[RTCSSLConfig alloc] initWithNativeConfig:nativeServer.ssl_config];
if (!nativeServer.ssl_config.tls_alpn_protocols.has_value() &&
!nativeServer.tls_alpn_protocols.empty()) {
NSMutableArray *tlsALPNProtocols =
[NSMutableArray arrayWithCapacity:nativeServer.tls_alpn_protocols.size()]; [NSMutableArray arrayWithCapacity:nativeServer.tls_alpn_protocols.size()];
for (auto const &proto : nativeServer.tls_alpn_protocols) { for (auto const &proto : nativeServer.tls_alpn_protocols) {
[tlsAlpnProtocols addObject:[NSString stringForStdString:proto]]; [tlsALPNProtocols addObject:[NSString stringForStdString:proto]];
} }
sslConfig.tlsALPNProtocols = tlsALPNProtocols;
}
if (!nativeServer.ssl_config.tls_elliptic_curves.has_value() &&
!nativeServer.tls_elliptic_curves.empty()) {
NSMutableArray *tlsEllipticCurves = NSMutableArray *tlsEllipticCurves =
[NSMutableArray arrayWithCapacity:nativeServer.tls_elliptic_curves.size()]; [NSMutableArray arrayWithCapacity:nativeServer.tls_elliptic_curves.size()];
for (auto const &curve : nativeServer.tls_elliptic_curves) { for (auto const &curve : nativeServer.tls_elliptic_curves) {
[tlsEllipticCurves addObject:[NSString stringForStdString:curve]]; [tlsEllipticCurves addObject:[NSString stringForStdString:curve]];
} }
RTCTlsCertPolicy tlsCertPolicy; sslConfig.tlsEllipticCurves = tlsEllipticCurves;
}
switch (nativeServer.tls_cert_policy) { if (nativeServer.tls_cert_policy ==
case webrtc::PeerConnectionInterface::kTlsCertPolicySecure: webrtc::PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck) {
tlsCertPolicy = RTCTlsCertPolicySecure; sslConfig.tlsCertPolicy = RTCTlsCertPolicyInsecureNoCheck;
break;
case webrtc::PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck:
tlsCertPolicy = RTCTlsCertPolicyInsecureNoCheck;
break;
} }
self = [self initWithURLStrings:urls self = [self initWithURLStrings:urls
username:username username:username
credential:credential credential:credential
tlsCertPolicy:tlsCertPolicy
hostname:hostname hostname:hostname
tlsAlpnProtocols:tlsAlpnProtocols sslConfig:sslConfig];
tlsEllipticCurves:tlsEllipticCurves];
return self; return self;
} }

View File

@ -0,0 +1,27 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "RTCSSLConfig.h"
#include "api/peerconnectioninterface.h"
#include "rtc_base/ssladapter.h"
NS_ASSUME_NONNULL_BEGIN
@interface RTCSSLConfig (Native)
- (rtc::SSLConfig)nativeConfig;
/** Initialize an RTCSSLConfig from a native SSLConfig. */
- (instancetype)initWithNativeConfig:(const rtc::SSLConfig &)config;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,56 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import <Foundation/Foundation.h>
#import <WebRTC/RTCMacros.h>
typedef NS_ENUM(NSUInteger, RTCTlsCertPolicy) {
RTCTlsCertPolicySecure,
RTCTlsCertPolicyInsecureNoCheck
};
NS_ASSUME_NONNULL_BEGIN
RTC_EXPORT
@interface RTCSSLConfig : NSObject
/** Indicates whether to enable OCSP stapling in TLS. */
@property(nonatomic) BOOL enableOCSPStapling;
/** Indicates whether to enable the signed certificate timestamp extension in TLS. */
@property(nonatomic) BOOL enableSignedCertTimestamp;
/** Indicates whether to enable the TLS Channel ID extension. */
@property(nonatomic) BOOL enableTlsChannelId;
/** Indicates whether to enable the TLS GREASE extension. */
@property(nonatomic) BOOL enableGrease;
/** Indicates how to process TURN server certificates */
@property(nonatomic) RTCTlsCertPolicy tlsCertPolicy;
/** Highest supported SSL version, as defined in the supported_versions TLS extension. */
@property(nonatomic, nullable) NSNumber *maxSSLVersion;
/** List of protocols to be used in the TLS ALPN extension. */
@property(nonatomic, copy, nullable) NSArray<NSString *> *tlsALPNProtocols;
/**
List of elliptic curves to be used in the TLS elliptic curves extension.
Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
*/
@property(nonatomic, copy, nullable) NSArray<NSString *> *tlsEllipticCurves;
- (instancetype)init;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,134 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "RTCSSLConfig+Native.h"
#import "helpers/NSString+StdString.h"
@implementation RTCSSLConfig
@synthesize enableOCSPStapling = _enableOCSPStapling;
@synthesize enableSignedCertTimestamp = _enableSignedCertTimestamp;
@synthesize enableTlsChannelId = _enableTlsChannelId;
@synthesize enableGrease = _enableGrease;
@synthesize tlsCertPolicy = _tlsCertPolicy;
@synthesize maxSSLVersion = _maxSSLVersion;
@synthesize tlsALPNProtocols = _tlsALPNProtocols;
@synthesize tlsEllipticCurves = _tlsEllipticCurves;
- (instancetype)init {
// Copy defaults
rtc::SSLConfig config;
return [self initWithNativeConfig:config];
}
- (instancetype)initWithNativeConfig:(const rtc::SSLConfig &)config {
if (self = [super init]) {
_enableOCSPStapling = config.enable_ocsp_stapling;
_enableSignedCertTimestamp = config.enable_signed_cert_timestamp;
_enableTlsChannelId = config.enable_tls_channel_id;
_enableGrease = config.enable_grease;
switch (config.tls_cert_policy) {
case rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE:
_tlsCertPolicy = RTCTlsCertPolicySecure;
break;
case rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK:
_tlsCertPolicy = RTCTlsCertPolicyInsecureNoCheck;
break;
}
if (config.max_ssl_version) {
_maxSSLVersion = [NSNumber numberWithInt:*config.max_ssl_version];
}
if (config.tls_alpn_protocols) {
NSMutableArray *tlsALPNProtocols =
[NSMutableArray arrayWithCapacity:config.tls_alpn_protocols.value().size()];
for (auto const &proto : config.tls_alpn_protocols.value()) {
[tlsALPNProtocols addObject:[NSString stringForStdString:proto]];
}
_tlsALPNProtocols = tlsALPNProtocols;
}
if (config.tls_elliptic_curves) {
NSMutableArray *tlsEllipticCurves =
[NSMutableArray arrayWithCapacity:config.tls_elliptic_curves.value().size()];
for (auto const &curve : config.tls_elliptic_curves.value()) {
[tlsEllipticCurves addObject:[NSString stringForStdString:curve]];
}
_tlsEllipticCurves = tlsEllipticCurves;
}
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"RTCSSLConfig:\n%d\n%d\n%d\n%d\n%@\n%@\n%@\n%@",
_enableOCSPStapling,
_enableSignedCertTimestamp,
_enableTlsChannelId,
_enableGrease,
[self stringForTlsCertPolicy:_tlsCertPolicy],
_maxSSLVersion,
_tlsALPNProtocols,
_tlsEllipticCurves];
}
#pragma mark - Private
- (NSString *)stringForTlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy {
switch (tlsCertPolicy) {
case RTCTlsCertPolicySecure:
return @"RTCTlsCertPolicySecure";
case RTCTlsCertPolicyInsecureNoCheck:
return @"RTCTlsCertPolicyInsecureNoCheck";
}
}
- (rtc::SSLConfig)nativeConfig {
__block rtc::SSLConfig sslConfig;
sslConfig.enable_ocsp_stapling = _enableOCSPStapling;
sslConfig.enable_signed_cert_timestamp = _enableSignedCertTimestamp;
sslConfig.enable_tls_channel_id = _enableTlsChannelId;
sslConfig.enable_grease = _enableGrease;
switch (_tlsCertPolicy) {
case RTCTlsCertPolicySecure:
sslConfig.tls_cert_policy = rtc::TlsCertPolicy::TLS_CERT_POLICY_SECURE;
break;
case RTCTlsCertPolicyInsecureNoCheck:
sslConfig.tls_cert_policy = rtc::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
break;
}
if (_maxSSLVersion != nil) {
sslConfig.max_ssl_version = absl::optional<int>(_maxSSLVersion.intValue);
}
if (_tlsALPNProtocols != nil) {
__block std::vector<std::string> alpn_protocols;
[_tlsALPNProtocols enumerateObjectsUsingBlock:^(NSString *proto, NSUInteger idx, BOOL *stop) {
alpn_protocols.push_back(proto.stdString);
}];
sslConfig.tls_alpn_protocols = absl::optional<std::vector<std::string>>(alpn_protocols);
}
if (_tlsEllipticCurves != nil) {
__block std::vector<std::string> elliptic_curves;
[_tlsEllipticCurves enumerateObjectsUsingBlock:^(NSString *curve, NSUInteger idx, BOOL *stop) {
elliptic_curves.push_back(curve.stdString);
}];
sslConfig.tls_elliptic_curves = absl::optional<std::vector<std::string>>(elliptic_curves);
}
return sslConfig;
}
@end

View File

@ -89,7 +89,7 @@
EXPECT_EQ("username", iceStruct.username); EXPECT_EQ("username", iceStruct.username);
EXPECT_EQ("credential", iceStruct.password); EXPECT_EQ("credential", iceStruct.password);
EXPECT_EQ("hostname", iceStruct.hostname); EXPECT_EQ("hostname", iceStruct.hostname);
EXPECT_EQ(2u, iceStruct.tls_alpn_protocols.size()); EXPECT_EQ(2u, iceStruct.ssl_config.tls_alpn_protocols.value().size());
} }
- (void)testTlsEllipticCurves { - (void)testTlsEllipticCurves {
@ -106,8 +106,8 @@
EXPECT_EQ("username", iceStruct.username); EXPECT_EQ("username", iceStruct.username);
EXPECT_EQ("credential", iceStruct.password); EXPECT_EQ("credential", iceStruct.password);
EXPECT_EQ("hostname", iceStruct.hostname); EXPECT_EQ("hostname", iceStruct.hostname);
EXPECT_EQ(2u, iceStruct.tls_alpn_protocols.size()); EXPECT_EQ(2u, iceStruct.ssl_config.tls_alpn_protocols.value().size());
EXPECT_EQ(2u, iceStruct.tls_elliptic_curves.size()); EXPECT_EQ(2u, iceStruct.ssl_config.tls_elliptic_curves.value().size());
} }
- (void)testInitFromNativeServer { - (void)testInitFromNativeServer {
@ -129,8 +129,8 @@
EXPECT_EQ("username", [NSString stdStringForString:iceServer.username]); EXPECT_EQ("username", [NSString stdStringForString:iceServer.username]);
EXPECT_EQ("password", [NSString stdStringForString:iceServer.credential]); EXPECT_EQ("password", [NSString stdStringForString:iceServer.credential]);
EXPECT_EQ("hostname", [NSString stdStringForString:iceServer.hostname]); EXPECT_EQ("hostname", [NSString stdStringForString:iceServer.hostname]);
EXPECT_EQ(2u, iceServer.tlsAlpnProtocols.count); EXPECT_EQ(2u, iceServer.sslConfig.tlsALPNProtocols.count);
EXPECT_EQ(2u, iceServer.tlsEllipticCurves.count); EXPECT_EQ(2u, iceServer.sslConfig.tlsEllipticCurves.count);
} }
@end @end