// Ran on server internal static void HandleHailResponse(ulong clientId, Stream stream) { if (!NetworkingManager.Singleton.PendingClients.ContainsKey(clientId) || NetworkingManager.Singleton.PendingClients[clientId].ConnectionState != PendingClient.State.PendingHail) { return; } if (!NetworkingManager.Singleton.NetworkConfig.EnableEncryption) { return; } using (PooledBitReader reader = PooledBitReader.Get(stream)) { if (NetworkingManager.Singleton.PendingClients[clientId].KeyExchange != null) { byte[] diffieHellmanPublic = reader.ReadByteArray(); NetworkingManager.Singleton.PendingClients[clientId].AesKey = NetworkingManager.Singleton.PendingClients[clientId].KeyExchange.GetSharedSecret(diffieHellmanPublic); } } NetworkingManager.Singleton.PendingClients[clientId].ConnectionState = PendingClient.State.PendingConnection; NetworkingManager.Singleton.PendingClients[clientId].KeyExchange = null; // Give to GC // Send greetings, they have passed all the handshakes using (PooledBitStream outStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(outStream)) { writer.WriteInt64Packed(DateTime.Now.Ticks); // This serves no purpose. } InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_GREETINGS, "MLAPI_INTERNAL", outStream, SecuritySendFlags.None, null); } }
/// <summary> /// [6th step] This function run only on the macchine hosting the game, and check if we need to acquire a new frame, if true it send a broadcast command /// </summary> private void AcquireIfNeccessary() { long currentFrame = (long)Math.Floor((Time.time - timeInitAcquisition) / secBetweenFrame); if (currentFrame <= frameCounter) return; Debug.Log("Time remain expired, schedule frame: " + frameCounter); for (int c = 0; c < 1; c++) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteInt64Packed(frameCounter); InvokeClientRpcOnEveryonePerformance(ScheduleAcquisitionPerformance, stream, "MLAPI_TIME_SYNC"); } } } frameCounter++; }
// Ran on server internal static void HandleHailResponse(uint clientId, Stream stream, int channelId) { if (!netManager.PendingClients.ContainsKey(clientId) || netManager.PendingClients[clientId].ConnectionState != PendingClient.State.PendingHail) { return; } if (!netManager.NetworkConfig.EnableEncryption) { return; } using (PooledBitReader reader = PooledBitReader.Get(stream)) { if (NetworkingManager.Singleton.PendingClients[clientId].KeyExchange != null) { byte[] diffieHellmanPublic = reader.ReadByteArray(); netManager.PendingClients[clientId].AesKey = netManager.PendingClients[clientId].KeyExchange.GetSharedSecret(diffieHellmanPublic); if (netManager.NetworkConfig.SignKeyExchange) { byte[] diffieHellmanPublicSignature = reader.ReadByteArray(); X509Certificate2 certificate = netManager.NetworkConfig.ServerX509Certificate; RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider; if (rsa != null) { using (SHA256Managed sha = new SHA256Managed()) { byte[] clientHash = rsa.Decrypt(diffieHellmanPublicSignature, false); byte[] serverHash = sha.ComputeHash(diffieHellmanPublic); if (clientHash.Length != serverHash.Length) { //Man in the middle. if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Signature length doesnt match for the key exchange public part. Disconnecting"); } } netManager.DisconnectClient(clientId); return; } for (int i = 0; i < clientHash.Length; i++) { if (clientHash[i] != serverHash[i]) { //Man in the middle. if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Signature doesnt match for the key exchange public part. Disconnecting"); } } netManager.DisconnectClient(clientId); return; } } } } else { throw new CryptographicException("[MLAPI] Only RSA certificates are supported. No valid RSA key was found"); } } } } netManager.PendingClients[clientId].ConnectionState = PendingClient.State.PendingConnection; netManager.PendingClients[clientId].KeyExchange = null; // Give to GC // Send greetings, they have passed all the handshakes using (PooledBitStream outStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(outStream)) { writer.WriteInt64Packed(DateTime.Now.Ticks); // This serves no purpose. } InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_GREETINGS, "MLAPI_INTERNAL", outStream, SecuritySendFlags.None, true); } }