ValveSoftware / GameNetworkingSockets

Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption.
BSD 3-Clause "New" or "Revised" License
8.25k stars 620 forks source link

How to disable cert checking via the api? #259

Closed Yorizuka closed 2 months ago

Yorizuka commented 1 year ago

I want to implement a "no auth" mode into my client & server where unauthenticated clients can join the server and the server will just accept any identity its given when in this mode, without any cert authority. (I need this for testing)

when I initialize via GameNetworkingSockets_Init if I leave the identity null then I have no problems connecting, after I configure IP_AllowWithoutAuth & Unencrypted via SetGlobalConfigValue.

but that is not a good solution for me. my game is persistent and I use the identity for selecting the correct user data for this session/connection.

[#3104342239 UDP invalid@127.0.0.1:25569 'PS client'] problem detected locally (5002): Need a cert authority!`
[#3104342239 UDP invalid@127.0.0.1:25569] problem (5002) Need a cert authority!, but connection already dead (0 5002 Need a cert authority!)

I can not figure out how to do this, if the api supports it, how do I do this, and if not then I think it should be able to. I think my use case is not that odd.

zpostfacto commented 1 year ago

I might need some help debugging this, as this is not a use case I work with regularly.

Can you tell me what happens in this code in CSteamNetworkConnectionBase::BThinkCryptoReady:

    // Check if we want to intentionally disable auth
    if ( AllowLocalUnsignedCert() == k_EUnsignedCert_Allow )
    {
        SetLocalCertUnsigned();
        return true;
    }

Step into AllowLocalUnsignedCert function:

EUnsignedCert CSteamNetworkConnectionBase::AllowLocalUnsignedCert()
{
    // Base class - we will not attempt connections without a local cert,
    // unless we are running in a way that is configured without one
    if ( !m_pSteamNetworkingSocketsInterface->BCanRequestCert() )
        return k_EUnsignedCert_Allow;
    else
        return k_EUnsignedCert_Disallow;
}

My expectation is that BCanRequestCert should return false, and then it should return k_EUnsignedCert_Allow. What are you seeing when you reproduce this problem?

Yorizuka commented 1 year ago

here is console output given via the debug print callback

Bug: src/steamnetworkingsockets/clientlib/steamnetworkingsockets_connections.cpp(2966): [#3019161547 UDP invalid@127.0.0.1:25569] problem (5002) Need a cert authority!, but connection already dead (0 5002 Need a cert authority!)
Bug: src/steamnetworkingsockets/clientlib/steamnetworkingsockets_connections.cpp(1158): Assertion Failed: false
Msg: [#3019161547 UDP invalid@127.0.0.1:25569 'PS client'] problem detected locally (5002): Need a cert authority!

stepping in bool CSteamNetworkConnectionBase::BThinkCryptoReady( SteamNetworkingMicroseconds usecNow ) the following checks did not return true.

and we reach "Otherwise, we don't have a signed cert (yet?)." and Msg: [#3019161547 UDP invalid@127.0.0.1:25569 'PS client'] problem detected locally (5002): Need a cert authority! is printed

Yorizuka commented 1 year ago

inside of EUnsignedCert CSteamNetworkConnectionUDP::AllowRemoteUnsignedCert()

int nAllow = m_connectionConfig.m_IP_AllowWithoutAuth.Get(); is a value of 1

EUnsignedCert CSteamNetworkConnectionUDP::AllowRemoteUnsignedCert()
{
    // NOTE: No special override for localhost.
    // Should we add a separate convar for this?
    // For the CSteamNetworkConnectionlocalhostLoopback connection,
    // we know both ends are us.  but if they are just connecting to
    // 127.0.0.1, it's not clear that we should handle this any
    // differently from any other connection

    // Enabled by convar?
    int nAllow = m_connectionConfig.m_IP_AllowWithoutAuth.Get();
    if ( nAllow > 1 )
        return k_EUnsignedCert_Allow;
    if ( nAllow == 1 )
        return k_EUnsignedCert_AllowWarn;

    // Lock it down
    return k_EUnsignedCert_Disallow;
}

that should return, k_EUnsignedCert_AllowWarn.

the stack (ignore 8 to 13):

#0  SteamNetworkingSocketsLib::CSteamNetworkConnectionUDP::AllowRemoteUnsignedCert(this = 0x5555565ea710) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_udp.cpp:1776
#1  SteamNetworkingSocketsLib::CSteamNetworkConnectionUDP::AllowLocalUnsignedCert(this = 0x5555565ea710) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_udp.cpp:1789
#2  SteamNetworkingSocketsLib::CSteamNetworkConnectionBase::BThinkCryptoReady(this = 0x5555565ea710, usecNow = 3000002271339) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_connections.cpp:1149
#3  SteamNetworkingSocketsLib::CSteamNetworkConnectionBase::InitConnectionCrypto(this = 0x5555565ea710, usecNow = 3000002271339) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_connections.cpp:1023
#4  SteamNetworkingSocketsLib::CSteamNetworkConnectionBase::BInitConnection(this = 0x5555565ea710, usecNow = 3000002271339, nOptions = 1, pOptions = 0x7fffffffddc0, errMsg = @0x7fffffffd8e0: ")\?\?\?\?\\?\?\\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\?w\?UUU\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\\?\?e\?\?UUU\?\?\?\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\?\?\\vVUU\?\?\?\?\?\?\?\\?\?\?\?\?UUU\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\\a\?\?\?\?\?\?\?\?\?\?\?\?\?\?\? \?\?\?\?\\?\?\?\?\?\?\?\\?\?)\?\?UUU\?\?\?\?\\vVUU\?\?"...) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_connections.cpp:981
#5  SteamNetworkingSocketsLib::CSteamNetworkConnectionUDP::BInitConnect(this = 0x5555565ea710, addressRemote = , nOptions = 1, pOptions = 0x7fffffffddc0, errMsg = @0x7fffffffd8e0: ")\?\?\?\?\\?\?\\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\?w\?UUU\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\\?\?e\?\?UUU\?\?\?\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\\?\?\?\?\?\?\?\?\?\\vVUU\?\?\?\?\?\?\?\\?\?\?\?\?UUU\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\\a\?\?\?\?\?\?\?\?\?\?\?\?\?\?\? \?\?\?\?\\?\?\?\?\?\?\?\\?\?)\?\?UUU\?\?\?\?\\vVUU\?\?"...) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_udp.cpp:1169
#6  SteamNetworkingSocketsLib::CSteamNetworkingSockets::ConnectByIPAddress(this = 0x555556137a40, address = , nOptions = 1, pOptions = 0x7fffffffddc0) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/csteamnetworkingsockets.cpp:1113
#7  SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(self = 0x555556137a40, address = , nOptions = 1, pOptions = 0x7fffffffddc0) at /home/yori/Desktop/projects/runic/srcC/GNS/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_flat.cpp:26
#8  _D4rune5steam10networking23ISteamNetworkingSockets18ConnectByIPAddressMFKxSQCvQCtQCq21SteamNetworkingIPAddrixPSQEfQEdQEa28SteamNetworkingConfigValue_tZSQFuQFsQFp19HSteamNetConnection(this = , pOptions = 0x7fffffffddc0, nOptions = 1, address = ) at src/rune/steam/networking.d:2898
#9  _D4rune3ent11play_spaces22PlaySpaceManagerClient10connect_toFNeAyaZv(connect_to = "127.0.0.1:25560") at src/rune/ent/play_spaces.d:322
#10  _D4rune10event_loop6game3d__T16Rune3dGameClientTS5runic6common10GameConfigZQBu18join_single_playerMFNeZv(this = 0x7ffff7b52060) at src/rune/event_loop/game3d.d:112
#11  _D4rune10event_loop6game3d__T16Rune3dGameClientTS5runic6common10GameConfigZQBu8on_startMFNeCQDmQDk4main13RuneGameMainIAyaE3std8typecons__T4FlagVQBaa10_546f446576576f726c64ZQBiZv(this = 0x7ffff7b52060, to_dev_world = true, direct_join_to = 0x0, rune_game_main = 0x7fffffffe0b8) at src/rune/event_loop/game3d.d:87
#12  _D4rune10event_loop4main__T18RuneGameMainStructTS5runic6common10GameConfigTCQBbQy11RunicClientTCQBvQBs11RunicServerZQDlQDwMFNeAAyaZv(this = 0x7fffffffe0a8, arguments = ) at src/rune/event_loop/main.d:141
#13  _Dmain(arguments = ) at src/rune/event_loop/main.d:173

that leads to CSteamNetworkConnectionBase::BThinkCryptoReady not use a unsigned cert.

// Check if we want to intentionally disable auth
if ( AllowLocalUnsignedCert() == k_EUnsignedCert_Allow )
{
    SetLocalCertUnsigned();
    return true;
}

my guess is that if ( AllowLocalUnsignedCert() == k_EUnsignedCert_Allow ) should become if ( AllowLocalUnsignedCert() != k_EUnsignedCert_Disallow )

zpostfacto commented 1 year ago

I see. I think the bug is actually in this function:

EUnsignedCert CSteamNetworkConnectionUDP::AllowLocalUnsignedCert()
{
    // Same logic actually applies for remote and local
    return AllowRemoteUnsignedCert();
}

It isn't using the base class behaviour which is checking whether we are running in an environment with no cert authority.

Yorizuka commented 1 year ago

I edited ( AllowLocalUnsignedCert() == k_EUnsignedCert_Allow ) to ( AllowLocalUnsignedCert() != k_EUnsignedCert_Disallow ) and it seems to be doing what I want, but, im not sure if this is a correct solution.

zpostfacto commented 1 year ago

That's a fine fix in your situation. I'm thinking through how things "should" work in all the different use cases and what the correct fix is. It might end up being exactly what you are suggesting. :)