Skip to content

Commit

Permalink
Don't notify OnSessionEstablishmentError after OnSessionEstablished. (#…
Browse files Browse the repository at this point in the history
…22261)

A PairingSession that has sent an OnSessionEstablished notification should not
send an OnSessionEstablishmentError notification after that (e.g. if the session
gets evicted).  The session is established at that point, and the
_establishment_ cannot hit an error.

This is needed to allow PASE sessions to be sanely evicted (e.g. when we're done
with them) without triggering spurious errors.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Nov 7, 2023
1 parent 287b8a0 commit 3c21ec1
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/protocols/secure_channel/CASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void CASESession::OnSessionReleased()
{
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
NotifySessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
}

void CASESession::Clear()
Expand Down Expand Up @@ -294,7 +294,7 @@ void CASESession::AbortPendingEstablish(CHIP_ERROR err)
{
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(err);
NotifySessionEstablishmentError(err);
}

CHIP_ERROR CASESession::DeriveSecureSession(CryptoContext & session) const
Expand Down
6 changes: 3 additions & 3 deletions src/protocols/secure_channel/PASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void PASESession::OnSessionReleased()
{
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
NotifySessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
}

void PASESession::Finish()
Expand Down Expand Up @@ -242,7 +242,7 @@ void PASESession::OnResponseTimeout(ExchangeContext * ec)
DiscardExchange();
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(CHIP_ERROR_TIMEOUT);
NotifySessionEstablishmentError(CHIP_ERROR_TIMEOUT);
}

CHIP_ERROR PASESession::DeriveSecureSession(CryptoContext & session) const
Expand Down Expand Up @@ -859,7 +859,7 @@ CHIP_ERROR PASESession::OnMessageReceived(ExchangeContext * exchange, const Payl
Clear();
ChipLogError(SecureChannel, "Failed during PASE session setup: %" CHIP_ERROR_FORMAT, err.Format());
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(err);
NotifySessionEstablishmentError(err);
}
return err;
}
Expand Down
21 changes: 19 additions & 2 deletions src/protocols/secure_channel/PairingSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ void PairingSession::Finish()
if (err == CHIP_NO_ERROR)
{
VerifyOrDie(mSecureSessionHolder);
mDelegate->OnSessionEstablished(mSecureSessionHolder.Get().Value());
// Make sure to null out mDelegate so we don't send it any other
// notifications.
auto * delegate = mDelegate;
mDelegate = nullptr;
delegate->OnSessionEstablished(mSecureSessionHolder.Get().Value());
}
else
{
mDelegate->OnSessionEstablishmentError(err);
NotifySessionEstablishmentError(err);
}
}

Expand Down Expand Up @@ -165,4 +169,17 @@ void PairingSession::Clear()
mSessionManager = nullptr;
}

void PairingSession::NotifySessionEstablishmentError(CHIP_ERROR error)
{
if (mDelegate == nullptr)
{
// Already notified success or error.
return;
}

auto * delegate = mDelegate;
mDelegate = nullptr;
delegate->OnSessionEstablishmentError(error);
}

} // namespace chip
6 changes: 6 additions & 0 deletions src/protocols/secure_channel/PairingSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ class DLL_EXPORT PairingSession : public SessionDelegate
// TODO: remove Clear, we should create a new instance instead reset the old instance.
void Clear();

/**
* Notify our delegate about a session establishment error, if we have not
* notified it of an error or success before.
*/
void NotifySessionEstablishmentError(CHIP_ERROR error);

protected:
CryptoContext::SessionRole mRole;
SessionHolderWithDelegate mSecureSessionHolder;
Expand Down
8 changes: 6 additions & 2 deletions src/protocols/secure_channel/SessionEstablishmentDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class DLL_EXPORT SessionEstablishmentDelegate
{
public:
/**
* Called when session establishment fails with an error
* Called when session establishment fails with an error. This will be
* called at most once per session establishment and will not be called if
* OnSessionEstablished is called.
*/
virtual void OnSessionEstablishmentError(CHIP_ERROR error) {}

Expand All @@ -46,7 +48,9 @@ class DLL_EXPORT SessionEstablishmentDelegate
virtual void OnSessionEstablishmentStarted() {}

/**
* Called when the new secure session has been established
* Called when the new secure session has been established. This is
* mututally exclusive with OnSessionEstablishmentError for a give session
* establishment.
*/
virtual void OnSessionEstablished(const SessionHandle & session) {}

Expand Down
17 changes: 17 additions & 0 deletions src/protocols/secure_channel/tests/TestPASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, S
// Let's make sure atleast number is >= than the minimum messages required to complete the
// handshake.
NL_TEST_ASSERT(inSuite, loopback.mSentMessageCount >= sTestPaseMessageCount);
NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingErrors == 0);
NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1);
NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingErrors == 0);
NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1);

if (mrpCommissionerConfig.HasValue())
Expand All @@ -313,6 +315,21 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, S
mrpAccessoryConfig.Value().mActiveRetransTimeout);
}

// Now evict the PASE sessions.
auto session = pairingCommissioner.CopySecureSession();
NL_TEST_ASSERT(inSuite, session.HasValue());
session.Value()->AsSecureSession()->MarkForEviction();

session = pairingAccessory.CopySecureSession();
NL_TEST_ASSERT(inSuite, session.HasValue());
session.Value()->AsSecureSession()->MarkForEviction();

// And check that this did not result in any new notifications.
NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingErrors == 0);
NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1);
NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingErrors == 0);
NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1);

loopback.SetLoopbackTransportDelegate(nullptr);
}

Expand Down

0 comments on commit 3c21ec1

Please sign in to comment.