mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1840144 - clean up some TLS socket creation error handling a=RyanVM
Original Revision: https://phabricator.services.mozilla.com/D193722 Differential Revision: https://phabricator.services.mozilla.com/D195287
This commit is contained in:
parent
fa1c9b453d
commit
cdb7fc5e80
@ -235,9 +235,6 @@ class nsPtrHashKey;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc,
|
||||
PR_Close);
|
||||
|
||||
namespace dom::indexedDB {
|
||||
|
||||
using namespace mozilla::dom::quota;
|
||||
|
@ -321,7 +321,7 @@ nsresult NSSSocketControl::ActivateSSL() {
|
||||
|
||||
mHandshakePending = true;
|
||||
|
||||
return SetResumptionTokenFromExternalCache();
|
||||
return SetResumptionTokenFromExternalCache(mFd);
|
||||
}
|
||||
|
||||
nsresult NSSSocketControl::GetFileDescPtr(PRFileDesc** aFilePtr) {
|
||||
@ -508,7 +508,6 @@ PRStatus NSSSocketControl::CloseSocketAndDestroy() {
|
||||
if (status != PR_SUCCESS) return status;
|
||||
|
||||
popped->identity = PR_INVALID_IO_LAYER;
|
||||
NS_RELEASE_THIS();
|
||||
popped->dtor(popped);
|
||||
|
||||
return PR_SUCCESS;
|
||||
@ -624,15 +623,15 @@ NSSSocketControl::GetPeerId(nsACString& aResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NSSSocketControl::SetResumptionTokenFromExternalCache() {
|
||||
nsresult NSSSocketControl::SetResumptionTokenFromExternalCache(PRFileDesc* fd) {
|
||||
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
|
||||
if (!mFd) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!fd) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// If SSL_NO_CACHE option was set, we must not use the cache
|
||||
PRIntn val;
|
||||
if (SSL_OptionGet(mFd, SSL_NO_CACHE, &val) != SECSuccess) {
|
||||
if (SSL_OptionGet(fd, SSL_NO_CACHE, &val) != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -659,7 +658,7 @@ nsresult NSSSocketControl::SetResumptionTokenFromExternalCache() {
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus srv = SSL_SetResumptionToken(mFd, token.Elements(), token.Length());
|
||||
SECStatus srv = SSL_SetResumptionToken(fd, token.Elements(), token.Length());
|
||||
if (srv == SECFailure) {
|
||||
PRErrorCode error = PR_GetError();
|
||||
mozilla::net::SSLTokensCache::Remove(peerId, tokenId);
|
||||
|
@ -220,7 +220,7 @@ class NSSSocketControl final : public CommonSocketControl {
|
||||
|
||||
void SetSharedOwningReference(mozilla::psm::SharedSSLState* ref);
|
||||
|
||||
nsresult SetResumptionTokenFromExternalCache();
|
||||
nsresult SetResumptionTokenFromExternalCache(PRFileDesc* fd);
|
||||
|
||||
void SetPreliminaryHandshakeInfo(const SSLChannelInfo& channelInfo,
|
||||
const SSLCipherSuiteInfo& cipherInfo);
|
||||
@ -260,7 +260,10 @@ class NSSSocketControl final : public CommonSocketControl {
|
||||
}
|
||||
|
||||
private:
|
||||
~NSSSocketControl() = default;
|
||||
~NSSSocketControl() {
|
||||
MOZ_RELEASE_ASSERT(!mFd,
|
||||
"NSSSocketControl must outlive its file descriptor!");
|
||||
}
|
||||
|
||||
PRFileDesc* mFd;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/RandomNum.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/StaticPrefs_security.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
@ -1246,43 +1247,46 @@ nsresult nsSSLIOLayerNewSocket(int32_t family, const char* host, int32_t port,
|
||||
static PRFileDesc* nsSSLIOLayerImportFD(PRFileDesc* fd,
|
||||
NSSSocketControl* infoObject,
|
||||
const char* host, bool haveHTTPSProxy) {
|
||||
// Memory allocated here is released when fd is closed, regardless of the
|
||||
// success of this function.
|
||||
PRFileDesc* sslSock = SSL_ImportFD(nullptr, fd);
|
||||
if (!sslSock) {
|
||||
MOZ_ASSERT_UNREACHABLE("NSS: Error importing socket");
|
||||
return nullptr;
|
||||
}
|
||||
SSL_SetPKCS11PinArg(sslSock, (nsIInterfaceRequestor*)infoObject);
|
||||
SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject);
|
||||
SSL_SetCanFalseStartCallback(sslSock, CanFalseStartCallback, infoObject);
|
||||
if (SSL_SetPKCS11PinArg(sslSock, infoObject) != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
if (SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject) !=
|
||||
SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
if (SSL_SetCanFalseStartCallback(sslSock, CanFalseStartCallback,
|
||||
infoObject) != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Disable this hook if we connect anonymously. See bug 466080.
|
||||
uint32_t flags = 0;
|
||||
infoObject->GetProviderFlags(&flags);
|
||||
uint32_t flags = infoObject->GetProviderFlags();
|
||||
SSLGetClientAuthData clientAuthDataHook = SSLGetClientAuthDataHook;
|
||||
// Provide the client cert to HTTPS proxy no matter if it is anonymous.
|
||||
if (flags & nsISocketProvider::ANONYMOUS_CONNECT && !haveHTTPSProxy &&
|
||||
!(flags & nsISocketProvider::ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT)) {
|
||||
SSL_GetClientAuthDataHook(sslSock, nullptr, infoObject);
|
||||
} else {
|
||||
SSL_GetClientAuthDataHook(sslSock, SSLGetClientAuthDataHook, infoObject);
|
||||
clientAuthDataHook = nullptr;
|
||||
}
|
||||
if (SSL_GetClientAuthDataHook(sslSock, clientAuthDataHook, infoObject) !=
|
||||
SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SECSuccess !=
|
||||
SSL_AuthCertificateHook(sslSock, AuthCertificateHook, infoObject)) {
|
||||
MOZ_ASSERT_UNREACHABLE("Failed to configure AuthCertificateHook");
|
||||
goto loser;
|
||||
if (SSL_AuthCertificateHook(sslSock, AuthCertificateHook, infoObject) !=
|
||||
SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SECSuccess != SSL_SetURL(sslSock, host)) {
|
||||
MOZ_ASSERT_UNREACHABLE("SSL_SetURL failed");
|
||||
goto loser;
|
||||
if (SSL_SetURL(sslSock, host) != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sslSock;
|
||||
loser:
|
||||
if (sslSock) {
|
||||
PR_Close(sslSock);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Please change getSignatureName in nsNSSCallbacks.cpp when changing the list
|
||||
@ -1540,11 +1544,6 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
|
||||
nsITLSSocketControl** tlsSocketControl,
|
||||
bool forSTARTTLS, uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags) {
|
||||
PRFileDesc* layer = nullptr;
|
||||
PRFileDesc* plaintextLayer = nullptr;
|
||||
nsresult rv;
|
||||
PRStatus stat;
|
||||
|
||||
SharedSSLState* sharedState = nullptr;
|
||||
RefPtr<SharedSSLState> allocatedState;
|
||||
if (providerTlsFlags) {
|
||||
@ -1557,12 +1556,13 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
|
||||
sharedState = isPrivate ? PrivateSSLState() : PublicSSLState();
|
||||
}
|
||||
|
||||
NSSSocketControl* infoObject =
|
||||
RefPtr<NSSSocketControl> infoObject(
|
||||
new NSSSocketControl(nsDependentCString(host), port, *sharedState,
|
||||
providerFlags, providerTlsFlags);
|
||||
if (!infoObject) return NS_ERROR_FAILURE;
|
||||
providerFlags, providerTlsFlags));
|
||||
if (!infoObject) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
infoObject->SetForSTARTTLS(forSTARTTLS);
|
||||
infoObject->SetOriginAttributes(originAttributes);
|
||||
if (allocatedState) {
|
||||
@ -1573,7 +1573,10 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
|
||||
bool haveHTTPSProxy = false;
|
||||
if (proxy) {
|
||||
nsAutoCString proxyHost;
|
||||
proxy->GetHost(proxyHost);
|
||||
nsresult rv = proxy->GetHost(proxyHost);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
haveProxy = !proxyHost.IsEmpty();
|
||||
nsAutoCString type;
|
||||
haveHTTPSProxy = haveProxy && NS_SUCCEEDED(proxy->GetType(type)) &&
|
||||
@ -1582,46 +1585,61 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
|
||||
|
||||
// A plaintext observer shim is inserted so we can observe some protocol
|
||||
// details without modifying nss
|
||||
plaintextLayer =
|
||||
PRFileDesc* plaintextLayer =
|
||||
PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity,
|
||||
&nsSSLIOLayerHelpers::nsSSLPlaintextLayerMethods);
|
||||
if (plaintextLayer) {
|
||||
plaintextLayer->secret = (PRFilePrivate*)infoObject;
|
||||
stat = PR_PushIOLayer(fd, PR_TOP_IO_LAYER, plaintextLayer);
|
||||
if (stat == PR_FAILURE) {
|
||||
plaintextLayer->dtor(plaintextLayer);
|
||||
plaintextLayer = nullptr;
|
||||
}
|
||||
if (!plaintextLayer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
plaintextLayer->secret = (PRFilePrivate*)infoObject.get();
|
||||
if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, plaintextLayer) != PR_SUCCESS) {
|
||||
plaintextLayer->dtor(plaintextLayer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
auto plaintextLayerCleanup = MakeScopeExit([&fd] {
|
||||
// Note that PR_*IOLayer operations may modify the stack of fds, so a
|
||||
// previously-valid pointer may no longer point to what we think it points
|
||||
// to after calling PR_PopIOLayer. We must operate on the pointer returned
|
||||
// by PR_PopIOLayer.
|
||||
PRFileDesc* plaintextLayer =
|
||||
PR_PopIOLayer(fd, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity);
|
||||
if (plaintextLayer) {
|
||||
plaintextLayer->dtor(plaintextLayer);
|
||||
}
|
||||
});
|
||||
|
||||
PRFileDesc* sslSock =
|
||||
nsSSLIOLayerImportFD(fd, infoObject, host, haveHTTPSProxy);
|
||||
if (!sslSock) {
|
||||
MOZ_ASSERT_UNREACHABLE("NSS: Error importing socket");
|
||||
goto loser;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
infoObject->SetFileDescPtr(sslSock);
|
||||
|
||||
rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host, port,
|
||||
infoObject);
|
||||
|
||||
if (NS_FAILED(rv)) goto loser;
|
||||
nsresult rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host,
|
||||
port, infoObject);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Now, layer ourselves on top of the SSL socket...
|
||||
layer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
|
||||
&nsSSLIOLayerHelpers::nsSSLIOLayerMethods);
|
||||
if (!layer) goto loser;
|
||||
|
||||
layer->secret = (PRFilePrivate*)infoObject;
|
||||
stat = PR_PushIOLayer(sslSock, PR_GetLayersIdentity(sslSock), layer);
|
||||
|
||||
if (stat == PR_FAILURE) {
|
||||
goto loser;
|
||||
PRFileDesc* layer =
|
||||
PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
|
||||
&nsSSLIOLayerHelpers::nsSSLIOLayerMethods);
|
||||
if (!layer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Socket set up", (void*)sslSock));
|
||||
*tlsSocketControl = do_AddRef(infoObject).take();
|
||||
layer->secret = (PRFilePrivate*)infoObject.get();
|
||||
if (PR_PushIOLayer(sslSock, PR_GetLayersIdentity(sslSock), layer) !=
|
||||
PR_SUCCESS) {
|
||||
layer->dtor(layer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
auto layerCleanup = MakeScopeExit([&fd] {
|
||||
PRFileDesc* layer =
|
||||
PR_PopIOLayer(fd, nsSSLIOLayerHelpers::nsSSLIOLayerIdentity);
|
||||
if (layer) {
|
||||
layer->dtor(layer);
|
||||
}
|
||||
});
|
||||
|
||||
// We are going use a clear connection first //
|
||||
if (forSTARTTLS || haveProxy) {
|
||||
@ -1630,28 +1648,22 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
|
||||
|
||||
infoObject->SharedState().NoteSocketCreated();
|
||||
|
||||
rv = infoObject->SetResumptionTokenFromExternalCache();
|
||||
rv = infoObject->SetResumptionTokenFromExternalCache(sslSock);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
SSL_SetResumptionTokenCallback(sslSock, &StoreResumptionToken, infoObject);
|
||||
if (SSL_SetResumptionTokenCallback(sslSock, &StoreResumptionToken,
|
||||
infoObject) != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Socket set up", (void*)sslSock));
|
||||
|
||||
(void)infoObject->SetFileDescPtr(sslSock);
|
||||
layerCleanup.release();
|
||||
plaintextLayerCleanup.release();
|
||||
*tlsSocketControl = infoObject.forget().take();
|
||||
return NS_OK;
|
||||
loser:
|
||||
NS_IF_RELEASE(infoObject);
|
||||
if (layer) {
|
||||
layer->dtor(layer);
|
||||
}
|
||||
if (plaintextLayer) {
|
||||
// Note that PR_*IOLayer operations may modify the stack of fds, so a
|
||||
// previously-valid pointer may no longer point to what we think it points
|
||||
// to after calling PR_PopIOLayer. We must operate on the pointer returned
|
||||
// by PR_PopIOLayer.
|
||||
plaintextLayer =
|
||||
PR_PopIOLayer(fd, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity);
|
||||
plaintextLayer->dtor(plaintextLayer);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
already_AddRefed<IPCClientCertsChild> GetIPCClientCertsActor() {
|
||||
|
Loading…
Reference in New Issue
Block a user