Skip to content

Commit a1ec953

Browse files
committed
Refactor code that sets identity and certificates.
This is to enable cacfhing of certificates and relay tickets to a durable cache, especially on consoles. - InternalClearIdentity is virtual, this will give the SDR class a chance to nuke any existing tickets when we reset our identity. - Added InternalOnGotIdentity - Refactored SetCertificate and added some flags so that we can control how it interacts with the cache. Things can get a bit tangled because in some sitautions the certificate is how we learn what our identity is. P4:7307221
1 parent d9a7295 commit a1ec953

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

src/steamnetworkingsockets/clientlib/csteamnetworkingsockets.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ void CSteamNetworkingSockets::InternalClearIdentity()
442442
m_bEverGotCert = false;
443443
}
444444

445+
void CSteamNetworkingSockets::InternalOnGotIdentity( int nIdentitySetFlags )
446+
{
447+
// No base class action
448+
}
449+
445450
CSteamNetworkingSockets::~CSteamNetworkingSockets()
446451
{
447452
SteamNetworkingGlobalLock::AssertHeldByCurrentThread();
@@ -676,6 +681,15 @@ bool CSteamNetworkingSockets::GetCertificateRequest( int *pcbBlob, void *pBlob,
676681

677682
bool CSteamNetworkingSockets::SetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg )
678683
{
684+
SteamNetworkingGlobalLock scopeLock( "SetCertificate" );
685+
int nIdentitySetFlags = 0; // Allowing any reading/writing to the durable cache as appropriate
686+
return InternalSetCertificate( pCertificate, cbCertificate, errMsg, nIdentitySetFlags );
687+
}
688+
689+
bool CSteamNetworkingSockets::InternalSetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg, int nIdentitySetFlags )
690+
{
691+
SteamNetworkingGlobalLock::AssertHeldByCurrentThread( "InternalSetCertificate" );
692+
679693
// Crack the blob
680694
CMsgSteamDatagramCertificateSigned msgCertSigned;
681695
if ( !msgCertSigned.ParseFromArray( pCertificate, cbCertificate ) )
@@ -684,8 +698,6 @@ bool CSteamNetworkingSockets::SetCertificate( const void *pCertificate, int cbCe
684698
return false;
685699
}
686700

687-
SteamNetworkingGlobalLock scopeLock( "SetCertificate" );
688-
689701
// Crack the cert, and check the signature. If *we* aren't even willing
690702
// to trust it, assume that our peers won't either
691703
CMsgSteamDatagramCertificate msgCert;
@@ -706,13 +718,27 @@ bool CSteamNetworkingSockets::SetCertificate( const void *pCertificate, int cbCe
706718
return false;
707719
}
708720

721+
// If we already have an identity, it must match the cert
722+
bool bSetIdentity = false;
723+
if ( m_identity.IsInvalid() || m_identity.IsLocalHost() )
724+
{
725+
bSetIdentity = true;
726+
}
727+
else if ( !( m_identity == certIdentity ) )
728+
{
729+
V_sprintf_safe( errMsg, "Cert is for identity '%s'. We are '%s'", SteamNetworkingIdentityRender( certIdentity ).c_str(), SteamNetworkingIdentityRender( m_identity ).c_str() );
730+
return false;
731+
}
732+
709733
// We currently only support one key type
710734
if ( msgCert.key_type() != CMsgSteamDatagramCertificate_EKeyType_ED25519 || msgCert.key_data().size() != 32 )
711735
{
712736
V_strcpy_safe( errMsg, "Cert has invalid public key" );
713737
return false;
714738
}
715739

740+
// FIXME - should we check if we already have a newer, equivalent cert?
741+
716742
// Does cert contain a private key?
717743
if ( msgCertSigned.has_private_key_data() )
718744
{
@@ -767,23 +793,23 @@ bool CSteamNetworkingSockets::SetCertificate( const void *pCertificate, int cbCe
767793

768794
// If we don't know our identity, then set it now. Otherwise,
769795
// it better match.
770-
if ( m_identity.IsInvalid() || m_identity.IsLocalHost() )
796+
if ( bSetIdentity )
771797
{
772798
m_identity = certIdentity;
773799
SpewMsg( "Local identity established from certificate. We are '%s'\n", SteamNetworkingIdentityRender( m_identity ).c_str() );
774800
}
775-
else if ( !( m_identity == certIdentity ) )
776-
{
777-
V_sprintf_safe( errMsg, "Cert is for identity '%s'. We are '%s'", SteamNetworkingIdentityRender( certIdentity ).c_str(), SteamNetworkingIdentityRender( m_identity ).c_str() );
778-
return false;
779-
}
780801

781802
// Save it off
782803
m_msgSignedCert = std::move( msgCertSigned );
783804
m_msgCert = std::move( msgCert );
784805
// If shouldn't already be expired.
785806
AssertMsg( GetSecondsUntilCertExpiry() > 0, "Cert already invalid / expired?" );
786807

808+
// If we just got our identity, let derived classes take action. But our caller is
809+
// setting a specific cert, so don't try to load any other cert from the cache
810+
if ( bSetIdentity )
811+
InternalOnGotIdentity( nIdentitySetFlags | k_nIdentitySetFlag_NoLoadCert );
812+
787813
// We've got a valid cert
788814
SetCertStatus( k_ESteamNetworkingAvailability_Current, "OK" );
789815

@@ -801,7 +827,14 @@ void CSteamNetworkingSockets::ResetIdentity( const SteamNetworkingIdentity *pIde
801827
KillConnections();
802828
InternalClearIdentity();
803829
if ( pIdentity )
830+
{
804831
m_identity = *pIdentity;
832+
if ( m_identity.IsInvalid() || m_identity.IsLocalHost() )
833+
{
834+
int nIdentitySetFlags = k_nIdentitySetFlag_NoSave; // Allow us to check the durable cache for any credentials, but we know we are empty, so don't save anything
835+
InternalOnGotIdentity( nIdentitySetFlags );
836+
}
837+
}
805838
}
806839

807840
ESteamNetworkingAvailability CSteamNetworkingSockets::InitAuthentication()

src/steamnetworkingsockets/clientlib/csteamnetworkingsockets.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class CSteamNetworkingSockets : public IClientNetworkingSockets
112112
virtual int GetP2P_Transport_ICE_Enable( const SteamNetworkingIdentity &identityRemote, int *pOutUserFlags );
113113

114114
virtual bool GetCertificateRequest( int *pcbBlob, void *pBlob, SteamNetworkingErrMsg &errMsg ) override;
115-
virtual bool SetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg ) override;
115+
virtual bool SetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg ) override final; // Final. Override InternalSetCertificate to customize
116116
virtual void ResetIdentity( const SteamNetworkingIdentity *pIdentity ) override;
117117

118118
virtual HSteamListenSocket CreateListenSocketP2PFakeIP( int idxFakePort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) override;
@@ -239,7 +239,20 @@ class CSteamNetworkingSockets : public IClientNetworkingSockets
239239
/// Figure out the current authentication status. And if it has changed, send out callbacks
240240
virtual void DeduceAuthenticationStatus();
241241

242-
void InternalClearIdentity();
242+
// Flags that specify what actions to take wrt to any durable cache, when we are assigned an identity or certificate.
243+
static constexpr int k_nIdentitySetFlag_NoLoadCert = (1<<0);
244+
static constexpr int k_nIdentitySetFlag_NoLoadTickets = (1<<1);
245+
static constexpr int k_nIdentitySetFlag_NoLoad = k_nIdentitySetFlag_NoLoadCert | k_nIdentitySetFlag_NoLoadTickets;
246+
static constexpr int k_nIdentitySetFlag_NoSave = (1<<2);
247+
static constexpr int k_nIdentitySetFlag_NoCacheAccess = -1;
248+
249+
/// Called when we get a valid identity
250+
virtual void InternalOnGotIdentity( int nIdentitySetFlags );
251+
252+
/// Set certificate and/or private key
253+
virtual bool InternalSetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg, int nIdentitySetFlags );
254+
255+
virtual void InternalClearIdentity();
243256
void KillConnections();
244257

245258
SteamNetworkingIdentity m_identity;

0 commit comments

Comments
 (0)