Handshake and Authentication
Last Updated: MapTool 1.11
The handshake and authentication occurs via protocol buffers messages before any Hessian serialization occurs. Once the handshake and authentication is successful only then will Hessian serialization be used for passing messages between server and client. (This is likely to change in MapTool 1.11 or MapTool 1.12 where Hessian will be completely replaced by protocol buffers)
Blocked Player#
If a player is blocked then the Server will inform the client of this before trying perform any password or public key authentication.
%%{init: {'theme': 'base', 'themeVariables': { 'signalColor': '#e0081a', 'textColor': '#e0081a' }}}%%
sequenceDiagram
Client->>Server: ClientInitMsg
Server->>Server: Lookup Player from ClientInitMsg<br/>
Server->>Client: Send PlayerBlockedMsg
Client->>Client: Inform Player<br/>and disconnect.
Player using public key authentication#
If the player is not blocked and is authenticating with a public key then the following authentication/handshake sequence occurs. The public key has to be known to the Server before a player can attempt to authenticate this way.
if Not using MapTool easy connect the public key is not sent from client to server via MapTool so the server must know of the public key before hand. The server then encrypts the handshake challenge using the public key which the client will only be able to decrypt if it has access to the matching private key, once decrypted the client sends back the handshake challenge in plaintext as it needs to do no more to show it has the correct private key.
%%{init: {'theme': 'base', 'themeVariables': { 'signalColor': '#e0081a', 'textColor': '#e0081a' }}}%%
sequenceDiagram
Client->>Server: ClientInitMsg
Server->>Server: Lookup Player from ClientInitMsg<br/>and retrieve the public key
Server->>Server: Create HandshakeChallenge
Server->>Server: Encrypt Challenge with public key
Server->>Client: Send UseAuthTypeMsg
Note right of Server: auth_type = ASYMMETRIC_KEY<br/> challenge[0] = HandshakeChallenge.challenge
Client->>Client: Decrypt Handshake Challeng and reverse random string
Client->>Server: Send ClientAuthMsg
Note left of Client:(not encrypted)<br/>challenge_response = HandshakeChallenge.response (reversed string)
Server->>Client: Send ConnectionSuccessfulMsg
Connecting with MapTool Easy Connect (uses public key)#
If the player is already defined in the player database (and having the same public key that they are trying to connect with) the authentication process follows the above flow of connecting with a public key. Otherwise the following flow is followed.
%%{init: {'theme': 'base', 'themeVariables': { 'signalColor': '#e0081a', 'textColor': '#e0081a' }}}%%
sequenceDiagram
Client->>Server: ClientInitMsg
Server->>Server: Lookup Player + Public Key from ClientInitMsg<br/>fails.
Server->>Client: RequestPublicKeyMsg (with PIN code expected).
Client->>Server: PublicKeyUploadMsg
Server->>Client: PublicKeyAddedMsg
Note right of Server: From here on the flow is the same as the public key<br/>flow above.
Client->>Server: ClientInitMsg
Server->>Server: Lookup Player from ClientInitMsg<br/>and retrieve the public key
Server->>Server: Create HandshakeChallenge
Server->>Server: Encrypt Challenge with public key
Server->>Client: Send UseAuthTypeMsg
Note right of Server: auth_type = ASYMMETRIC_KEY<br/> challenge[0] = HandshakeChallenge.challenge
Client->>Client: Decrypt Handshake Challenge and reverse the random string
Client->>Server: Send ClientAuthMsg
Note left of Client:(not encrypted)<br/>challenge_response = HandshakeChallenge.response (reversed string)
Server->>Client: Send ConnectionSuccessfulMsg
Player using shared password authentication#
If the player is not blocked and is authenticating with a shared password the following authentication/handshake sequence occurs. As a shared password could be per player or role based (i.e. a single password for players and another single password for GMs) the server creates a challenge for both GM and Player and which ever the client can respond to determines the role. If a password database is used where the role is recorded and the Server knows if the player is a GM or not then a new random password will be used to encrypt the non pertinent handshake challenge ensuring it should never match.
Password information is never sent between the client and the server instead it is used on both sides to encrypt/decrypt the handshake challenge.
%%{init: {'theme': 'base', 'themeVariables': { 'signalColor': '#e0081a', 'textColor': '#e0081a' }}}%%
sequenceDiagram
Client->>Server: ClientInitMsg
Server->>Server: Lookup Player from ClientInitMsg and<br/>retrieve password salt
Server->>Server: Create HandshakeChallenge<br/>Player Password
note right of Server: If using player database<br/> with known players and player<br/>is GM then a new random<br/>password is used so this<br/> would never match.
Server->>Server: Create HandshakeChallenge<br/>GM Password
note right of Server: If using player database<br/> with known players and player<br/>is not a GM then a new random<br/>password is used so this<br/> would never match.
Server->>Client: Send UseAuthTypeMsg
note right of Client: auth_type = SHARED_PASSWORD<br/> salt = retrieved password salt<br/> challenge[0] = HandshakeChallenge.challenge (gm)<br/> challenge[1] = HandshakeChallenge.challenge (player)<br/>
Client->>Client: Hash password with<br/>PBKDF2WithHmacSHA1<br/>using salt sent by Server
Client->>Client: Try decrypt both challenges and reverse random string
Client->>Client: Encrypt HandshakeChallenge.response
Client->>Server: Send ClientAuthMsg
note right of Server: challenge_response = Encrypted HandshakeChallenge.response (reversed string)
Server->>Server: Compare client challenge response to<br/>pre-encrypted challenge response on server<br/>side to determine which password was used this will be reversed string
Server->>Client: Send ConnectionSuccessfulMsg
Protocol Buffers#
Handshake Protocol Buffers