--- a/media/mtransport/transportlayerdtls.cpp
+++ b/media/mtransport/transportlayerdtls.cpp
@@ -10,17 +10,19 @@
#include <algorithm>
#include <queue>
#include <sstream>
#include "dtlsidentity.h"
#include "keyhi.h"
#include "logging.h"
+#include "mozilla/Move.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsIEventTarget.h"
#include "nsNetCID.h"
#include "nsServiceManagerUtils.h"
#include "ssl.h"
#include "sslerr.h"
@@ -484,174 +486,175 @@ bool TransportLayerDtls::Setup() {
"Can't start DTLS without specifying a verification mode");
return false;
}
if (transport_layer_identity == PR_INVALID_IO_LAYER) {
transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter");
}
- ScopedPRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity,
+ UniquePRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity,
&TransportLayerMethods));
MOZ_ASSERT(pr_fd != nullptr);
if (!pr_fd)
return false;
pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get());
- ScopedPRFileDesc ssl_fd(DTLS_ImportFD(nullptr, pr_fd));
+ UniquePRFileDesc ssl_fd(DTLS_ImportFD(nullptr, pr_fd.get()));
MOZ_ASSERT(ssl_fd != nullptr); // This should never happen
if (!ssl_fd) {
return false;
}
- pr_fd.forget(); // ownership transfered to ssl_fd;
+ Unused << pr_fd.release(); // ownership transfered to ssl_fd;
if (role_ == CLIENT) {
MOZ_MTLOG(ML_INFO, "Setting up DTLS as client");
- rv = SSL_GetClientAuthDataHook(ssl_fd, GetClientAuthDataHook,
+ rv = SSL_GetClientAuthDataHook(ssl_fd.get(), GetClientAuthDataHook,
this);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
return false;
}
} else {
MOZ_MTLOG(ML_INFO, "Setting up DTLS as server");
// Server side
- rv = SSL_ConfigSecureServer(ssl_fd, identity_->cert(),
+ rv = SSL_ConfigSecureServer(ssl_fd.get(), identity_->cert(),
identity_->privkey(),
identity_->auth_type());
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
return false;
}
// Insist on a certificate from the client
- rv = SSL_OptionSet(ssl_fd, SSL_REQUEST_CERTIFICATE, PR_TRUE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_REQUEST_CERTIFICATE, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't request certificate");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_REQUIRE_CERTIFICATE, PR_TRUE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_REQUIRE_CERTIFICATE, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't require certificate");
return false;
}
}
// Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS
// 1.0 for stream modes.
SSLVersionRange version_range = {
SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2
};
- rv = SSL_VersionRangeSet(ssl_fd, &version_range);
+ rv = SSL_VersionRangeSet(ssl_fd.get(), &version_range);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable session tickets");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_NO_CACHE, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable session caching");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_DEFLATE, PR_FALSE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_DEFLATE, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable deflate");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_RENEGOTIATION,
+ SSL_RENEGOTIATE_NEVER);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable renegotiation");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_FALSE_START, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable false start");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_NO_LOCKS, PR_TRUE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_NO_LOCKS, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable locks");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable ECDHE key reuse");
return false;
}
if (!SetupCipherSuites(ssl_fd)) {
return false;
}
- rv = SSL_NamedGroupConfig(ssl_fd, NamedGroupPreferences,
+ rv = SSL_NamedGroupConfig(ssl_fd.get(), NamedGroupPreferences,
mozilla::ArrayLength(NamedGroupPreferences));
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set named groups");
return false;
}
// Certificate validation
- rv = SSL_AuthCertificateHook(ssl_fd, AuthCertificateHook,
+ rv = SSL_AuthCertificateHook(ssl_fd.get(), AuthCertificateHook,
reinterpret_cast<void *>(this));
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set certificate validation hook");
return false;
}
if (!SetupAlpn(ssl_fd)) {
return false;
}
// Now start the handshake
- rv = SSL_ResetHandshake(ssl_fd, role_ == SERVER ? PR_TRUE : PR_FALSE);
+ rv = SSL_ResetHandshake(ssl_fd.get(), role_ == SERVER ? PR_TRUE : PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't reset handshake");
return false;
}
- ssl_fd_ = ssl_fd.forget();
+ ssl_fd_ = Move(ssl_fd);
// Finally, get ready to receive data
downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange);
downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived);
if (downward_->state() == TS_OPEN) {
TL_SET_STATE(TS_CONNECTING);
Handshake();
}
return true;
}
-bool TransportLayerDtls::SetupAlpn(PRFileDesc* ssl_fd) const {
+bool TransportLayerDtls::SetupAlpn(UniquePRFileDesc& ssl_fd) const {
if (alpn_allowed_.empty()) {
return true;
}
- SECStatus rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_NPN, PR_FALSE);
+ SECStatus rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_NPN, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't disable NPN");
return false;
}
- rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_ALPN, PR_TRUE);
+ rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_ALPN, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't enable ALPN");
return false;
}
unsigned char buf[MAX_ALPN_LENGTH];
size_t offset = 0;
for (auto tag = alpn_allowed_.begin();
@@ -659,17 +662,17 @@ bool TransportLayerDtls::SetupAlpn(PRFil
if ((offset + 1 + tag->length()) >= sizeof(buf)) {
MOZ_MTLOG(ML_ERROR, "ALPN too long");
return false;
}
buf[offset++] = tag->length();
memcpy(buf + offset, tag->c_str(), tag->length());
offset += tag->length();
}
- rv = SSL_SetNextProtoNego(ssl_fd, buf, offset);
+ rv = SSL_SetNextProtoNego(ssl_fd.get(), buf, offset);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set ALPN string");
return false;
}
return true;
}
// Ciphers we need to enable. These are on by default in standard firefox
@@ -736,52 +739,52 @@ static const uint32_t DisabledCiphers[]
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDH_ECDSA_WITH_NULL_SHA,
TLS_ECDH_RSA_WITH_NULL_SHA,
TLS_RSA_WITH_NULL_SHA,
TLS_RSA_WITH_NULL_SHA256,
TLS_RSA_WITH_NULL_MD5,
};
-bool TransportLayerDtls::SetupCipherSuites(PRFileDesc* ssl_fd) const {
+bool TransportLayerDtls::SetupCipherSuites(UniquePRFileDesc& ssl_fd) const {
SECStatus rv;
// Set the SRTP ciphers
if (!srtp_ciphers_.empty()) {
// Note: std::vector is guaranteed to contiguous
- rv = SSL_SetSRTPCiphers(ssl_fd, &srtp_ciphers_[0], srtp_ciphers_.size());
-
+ rv = SSL_SetSRTPCiphers(ssl_fd.get(), &srtp_ciphers_[0],
+ srtp_ciphers_.size());
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, "Couldn't set SRTP cipher suite");
return false;
}
}
for (const auto& cipher : EnabledCiphers) {
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Enabling: " << cipher);
- rv = SSL_CipherPrefSet(ssl_fd, cipher, PR_TRUE);
+ rv = SSL_CipherPrefSet(ssl_fd.get(), cipher, PR_TRUE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO <<
"Unable to enable suite: " << cipher);
return false;
}
}
for (const auto& cipher : DisabledCiphers) {
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Disabling: " << cipher);
PRBool enabled = false;
- rv = SSL_CipherPrefGet(ssl_fd, cipher, &enabled);
+ rv = SSL_CipherPrefGet(ssl_fd.get(), cipher, &enabled);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
"Unable to check if suite is enabled: " << cipher);
return false;
}
if (enabled) {
- rv = SSL_CipherPrefSet(ssl_fd, cipher, PR_FALSE);
+ rv = SSL_CipherPrefSet(ssl_fd.get(), cipher, PR_FALSE);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
"Unable to disable suite: " << cipher);
return false;
}
}
}
@@ -793,17 +796,17 @@ nsresult TransportLayerDtls::GetCipherSu
if (!cipherSuite) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "GetCipherSuite passed a nullptr");
return NS_ERROR_NULL_POINTER;
}
if (state_ != TS_OPEN) {
return NS_ERROR_NOT_AVAILABLE;
}
SSLChannelInfo info;
- SECStatus rv = SSL_GetChannelInfo(ssl_fd_, &info, sizeof(info));
+ SECStatus rv = SSL_GetChannelInfo(ssl_fd_.get(), &info, sizeof(info));
if (rv != SECSuccess) {
MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "GetCipherSuite can't get channel info");
return NS_ERROR_FAILURE;
}
*cipherSuite = info.cipherSuite;
return NS_OK;
}
@@ -854,17 +857,17 @@ void TransportLayerDtls::StateChange(Tra
break;
}
}
void TransportLayerDtls::Handshake() {
// Clear the retransmit timer
timer_->Cancel();
- SECStatus rv = SSL_ForceHandshake(ssl_fd_);
+ SECStatus rv = SSL_ForceHandshake(ssl_fd_.get());
if (rv == SECSuccess) {
MOZ_MTLOG(ML_NOTICE,
LAYER_INFO << "****** SSL handshake completed ******");
if (!cert_ok_) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Certificate check never occurred");
TL_SET_STATE(TS_ERROR);
return;
@@ -885,17 +888,17 @@ void TransportLayerDtls::Handshake() {
case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Malformed DTLS message; ignoring");
// If this were TLS (and not DTLS), this would be fatal, but
// here we're required to ignore bad messages, so fall through
MOZ_FALLTHROUGH;
case PR_WOULD_BLOCK_ERROR:
MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Handshake would have blocked");
PRIntervalTime timeout;
- rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout);
+ rv = DTLS_GetHandshakeTimeout(ssl_fd_.get(), &timeout);
if (rv == SECSuccess) {
uint32_t timeout_ms = PR_IntervalToMilliseconds(timeout);
MOZ_MTLOG(ML_DEBUG,
LAYER_INFO << "Setting DTLS timeout to " << timeout_ms);
timer_->SetTarget(target_);
timer_->InitWithFuncCallback(TimerCallback,
this, timeout_ms,
@@ -918,17 +921,17 @@ void TransportLayerDtls::Handshake() {
bool TransportLayerDtls::CheckAlpn() {
if (alpn_allowed_.empty()) {
return true;
}
SSLNextProtoState alpnState;
char chosenAlpn[MAX_ALPN_LENGTH];
unsigned int chosenAlpnLen;
- SECStatus rv = SSL_GetNextProto(ssl_fd_, &alpnState,
+ SECStatus rv = SSL_GetNextProto(ssl_fd_.get(), &alpnState,
reinterpret_cast<unsigned char*>(chosenAlpn),
&chosenAlpnLen, sizeof(chosenAlpn));
if (rv != SECSuccess) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "ALPN error");
return false;
}
switch (alpnState) {
case SSL_NEXT_PROTO_SELECTED:
@@ -993,17 +996,17 @@ void TransportLayerDtls::PacketReceived(
// Now try a recv if we're open, since there might be data left
if (state_ == TS_OPEN) {
// nICEr uses a 9216 bytes buffer to allow support for jumbo frames
unsigned char buf[9216];
int32_t rv;
// One packet might contain several DTLS packets
do {
- rv = PR_Recv(ssl_fd_, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
+ rv = PR_Recv(ssl_fd_.get(), buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
if (rv > 0) {
// We have data
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS");
SignalPacketReceived(this, buf, rv);
} else if (rv == 0) {
TL_SET_STATE(TS_CLOSED);
} else {
int32_t err = PR_GetError();
@@ -1024,17 +1027,17 @@ TransportResult TransportLayerDtls::Send
size_t len) {
CheckThread();
if (state_ != TS_OPEN) {
MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Can't call SendPacket() in state "
<< state_);
return TE_ERROR;
}
- int32_t rv = PR_Send(ssl_fd_, data, len, 0, PR_INTERVAL_NO_WAIT);
+ int32_t rv = PR_Send(ssl_fd_.get(), data, len, 0, PR_INTERVAL_NO_WAIT);
if (rv > 0) {
// We have data
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << rv << " bytes to SSL Layer");
return rv;
}
if (rv == 0) {
@@ -1094,17 +1097,17 @@ nsresult TransportLayerDtls::SetSrtpCiph
return NS_OK;
}
nsresult TransportLayerDtls::GetSrtpCipher(uint16_t *cipher) const {
CheckThread();
if (state_ != TS_OPEN) {
return NS_ERROR_NOT_AVAILABLE;
}
- SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, cipher);
+ SECStatus rv = SSL_GetSRTPCipher(ssl_fd_.get(), cipher);
if (rv != SECSuccess) {
MOZ_MTLOG(ML_DEBUG, "No SRTP cipher negotiated");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
@@ -1113,17 +1116,17 @@ nsresult TransportLayerDtls::ExportKeyin
const std::string& context,
unsigned char *out,
unsigned int outlen) {
CheckThread();
if (state_ != TS_OPEN) {
MOZ_ASSERT(false, "Transport must be open for ExportKeyingMaterial");
return NS_ERROR_NOT_AVAILABLE;
}
- SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_,
+ SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_.get(),
label.c_str(),
label.size(),
use_context,
reinterpret_cast<const unsigned char *>(
context.c_str()),
context.size(),
out,
outlen);
@@ -1140,26 +1143,25 @@ SECStatus TransportLayerDtls::AuthCertif
PRBool checksig,
PRBool isServer) {
TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg);
stream->CheckThread();
return stream->AuthCertificateHook(fd, checksig, isServer);
}
SECStatus
-TransportLayerDtls::CheckDigest(const RefPtr<VerificationDigest>&
- digest,
- CERTCertificate *peer_cert) {
+TransportLayerDtls::CheckDigest(const RefPtr<VerificationDigest>& digest,
+ UniqueCERTCertificate& peer_cert) {
unsigned char computed_digest[kMaxDigestLength];
size_t computed_digest_len;
MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Checking digest, algorithm="
<< digest->algorithm_);
nsresult res =
- DtlsIdentity::ComputeFingerprint(peer_cert,
+ DtlsIdentity::ComputeFingerprint(peer_cert.get(),
digest->algorithm_,
computed_digest,
sizeof(computed_digest),
&computed_digest_len);
if (NS_FAILED(res)) {
MOZ_MTLOG(ML_ERROR, "Could not compute peer fingerprint for digest " <<
digest->algorithm_);
// Go to end
@@ -1184,19 +1186,17 @@ TransportLayerDtls::CheckDigest(const Re
return SECSuccess;
}
SECStatus TransportLayerDtls::AuthCertificateHook(PRFileDesc *fd,
PRBool checksig,
PRBool isServer) {
CheckThread();
- ScopedCERTCertificate peer_cert;
- peer_cert = SSL_PeerCertificate(fd);
-
+ UniqueCERTCertificate peer_cert(SSL_PeerCertificate(fd));
// We are not set up to take this being called multiple
// times. Change this if we ever add renegotiation.
MOZ_ASSERT(!auth_hook_called_);
if (auth_hook_called_) {
PR_SetError(PR_UNKNOWN_ERROR, 0);
return SECFailure;
}
@@ -1207,17 +1207,17 @@ SECStatus TransportLayerDtls::AuthCertif
switch (verification_mode_) {
case VERIFY_UNSET:
// Break out to error exit
PR_SetError(PR_UNKNOWN_ERROR, 0);
break;
case VERIFY_ALLOW_ALL:
- peer_cert_ = peer_cert.forget();
+ peer_cert_ = Move(peer_cert);
cert_ok_ = true;
return SECSuccess;
case VERIFY_DIGEST:
{
MOZ_ASSERT(digests_.size() != 0);
// Check all the provided digests
@@ -1225,17 +1225,17 @@ SECStatus TransportLayerDtls::AuthCertif
SECStatus rv = SECFailure;
for (size_t i = 0; i < digests_.size(); i++) {
RefPtr<VerificationDigest> digest = digests_[i];
rv = CheckDigest(digest, peer_cert);
// Matches a digest, we are good to go
if (rv == SECSuccess) {
cert_ok_ = true;
- peer_cert = peer_cert.forget();
+ peer_cert_ = Move(peer_cert);
return SECSuccess;
}
}
}
break;
default:
MOZ_CRASH(); // Can't happen
}