protected void HandleConnectAccept(IPEndPoint address, BitStream stream) { var nonce = new Nonce(); var serverNonce = new Nonce(); nonce.Read(stream); serverNonce.Read(stream); var decryptPos = stream.GetBytePosition(); stream.SetBytePosition(decryptPos); var conn = FindPendingConnection(address); if (conn == null || conn.ConnectionState != NetConnectionState.AwaitingConnectResponse) { return; } var cParams = conn.GetConnectionParameters(); if (cParams.Nonce != nonce || cParams.ServerNonce != serverNonce) { return; } if (cParams.UsingCrypto) { var theCipher = new SymmetricCipher(cParams.SharedSecret); if (!stream.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher)) { return; } } stream.Read(out uint recvSequence); conn.SetInitialRecvSequence(recvSequence); string errorString = null; if (!conn.ReadConnectAccept(stream, ref errorString)) { RemovePendingConnection(conn); return; } if (cParams.UsingCrypto) { stream.Read(SymmetricCipher.KeySize, cParams.InitVector); conn.SetSymmetricCipher(new SymmetricCipher(cParams.SymmetricKey, cParams.InitVector)); } AddConnection(conn); RemovePendingConnection(conn); conn.ConnectionState = NetConnectionState.Connected; conn.OnConnectionEstablished(); }
protected void HandleConnectChallengeRequest(IPEndPoint addr, BitStream stream) { if (!AllowConnections) { return; } var clientNonce = new Nonce(); clientNonce.Read(stream); var wantsKeyExchange = stream.ReadFlag(); var wantsCertificate = stream.ReadFlag(); SendConnectChallengeResponse(addr, clientNonce, wantsKeyExchange, wantsCertificate); }
protected void HandleDisconnect(IPEndPoint client, BitStream reader) { var conn = FindConnection(client); if (conn == null) { return; } var cParams = conn.GetConnectionParameters(); var nonce = new Nonce(); nonce.Read(reader); var serverNonce = new Nonce(); serverNonce.Read(reader); if (nonce != cParams.Nonce || serverNonce != cParams.ServerNonce) { return; } var decryptPos = reader.GetBytePosition(); reader.SetBytePosition(decryptPos); if (cParams.UsingCrypto) { var theCipher = new SymmetricCipher(cParams.SharedSecret); if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher)) { return; } } reader.ReadString(out string reason); conn.ConnectionState = NetConnectionState.Disconnected; conn.OnConnectionTerminated(TerminationReason.ReasonRemoteDisconnectPacket, reason); RemoveConnection(conn); }
protected void HandleConnectReject(IPEndPoint address, BitStream stream) { var nonce = new Nonce(); var serverNonce = new Nonce(); nonce.Read(stream); serverNonce.Read(stream); var conn = FindPendingConnection(address); if (conn == null || (conn.ConnectionState != NetConnectionState.AwaitingChallengeResponse && conn.ConnectionState != NetConnectionState.AwaitingConnectResponse)) { return; } var cParams = conn.GetConnectionParameters(); if (cParams.Nonce != nonce || cParams.ServerNonce != serverNonce) { return; } stream.ReadString(out string reason); if (reason == "Puzzle") { cParams.PuzzleRetried = true; conn.ConnectionState = NetConnectionState.AwaitingChallengeResponse; conn.ConnectSendCount = 0; cParams.Nonce.GetRandom(); SendConnectChallengeRequest(conn); return; } conn.ConnectionState = NetConnectionState.ConnectRejected; conn.OnConnectTerminated(TerminationReason.ReasonRemoteHostRejectedConnection, reason); RemovePendingConnection(conn); }
protected void HandlePunch(IPEndPoint address, BitStream stream) { var firstNonce = new Nonce(); firstNonce.Read(stream); Console.WriteLine("Received punch packet from {0} - {1}", address, Convert.ToBase64String(firstNonce.Data)); var found = false; NetConnection conn = null; foreach (var pair in PendingConnections) { conn = pair.Value; var cParams = conn.GetConnectionParameters(); if (conn.ConnectionState != NetConnectionState.SendingPunchPackets) { continue; } if ((cParams.IsInitiator && firstNonce != cParams.ServerNonce) || (!cParams.IsInitiator && firstNonce != cParams.Nonce)) { continue; } if (cParams.PossibleAddresses.Contains(address)) { if (cParams.IsInitiator) { found = true; break; } continue; } var cont = cParams.PossibleAddresses.Any(ep => ep.Address.Equals(address.Address) && ep.AddressFamily == address.AddressFamily); if (!cont) { continue; } if (cParams.PossibleAddresses.Count < 5) { cParams.PossibleAddresses.Add(address); } if (cParams.IsInitiator) { found = true; break; } } if (!found) { return; } var cParam = conn.GetConnectionParameters(); var theCipher = new SymmetricCipher(cParam.ArrangedSecret); if (stream.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, stream.GetBytePosition(), theCipher)) { return; } var nextNonce = new Nonce(); nextNonce.Read(stream); if (nextNonce != cParam.Nonce) { return; } if (stream.ReadFlag()) { if (stream.ReadFlag()) { cParam.Certificate = new Certificate(stream); if (!cParam.Certificate.IsValid() || !conn.ValidateCertificate(cParam.Certificate, true)) { return; } cParam.PublicKey = cParam.Certificate.GetPublicKey(); } else { cParam.PublicKey = new AsymmetricKey(stream); if (!cParam.PublicKey.IsValid() || !conn.ValidatePublicKey(cParam.PublicKey, true)) { return; } } if (PrivateKey == null || PrivateKey.GetKeySize() != cParam.PublicKey.GetKeySize()) { cParam.PrivateKey = new AsymmetricKey(cParam.PublicKey.GetKeySize()); } else { cParam.PrivateKey = PrivateKey; } cParam.SharedSecret = cParam.PrivateKey.ComputeSharedSecretKey(cParam.PublicKey); RandomUtil.Read(cParam.SymmetricKey, SymmetricCipher.KeySize); cParam.UsingCrypto = true; } }
protected void HandleConnectChallengeResponse(IPEndPoint address, BitStream stream) { var conn = FindPendingConnection(address); if (conn == null || conn.ConnectionState != NetConnectionState.AwaitingChallengeResponse) { return; } var theNonce = new Nonce(); theNonce.Read(stream); var cParams = conn.GetConnectionParameters(); if (theNonce != cParams.Nonce) { return; } stream.Read(out cParams.ClientIdentity); cParams.ServerNonce.Read(stream); stream.Read(out cParams.PuzzleDifficulty); if (cParams.PuzzleDifficulty > ClientPuzzleManager.MaxPuzzleDifficulty) { return; } if (stream.ReadFlag()) { if (stream.ReadFlag()) { cParams.Certificate = new Certificate(stream); if (!cParams.Certificate.IsValid() || !conn.ValidateCertificate(cParams.Certificate, true)) { return; } cParams.PublicKey = cParams.Certificate.GetPublicKey(); } else { cParams.PublicKey = new AsymmetricKey(stream); if (!cParams.PublicKey.IsValid() || !conn.ValidatePublicKey(cParams.PublicKey, true)) { return; } } if (PrivateKey == null || PrivateKey.GetKeySize() != cParams.PublicKey.GetKeySize()) { cParams.PrivateKey = new AsymmetricKey(cParams.PublicKey.GetKeySize()); } else { cParams.PrivateKey = PrivateKey; } cParams.SharedSecret = cParams.PrivateKey.ComputeSharedSecretKey(cParams.PublicKey); RandomUtil.Read(cParams.SymmetricKey, SymmetricCipher.KeySize); cParams.UsingCrypto = true; } conn.ConnectionState = NetConnectionState.ComputingPuzzleSolution; conn.ConnectSendCount = 0; cParams.PuzzleSolution = 0; conn.ConnectLastSendTime = CurrentTime; ContinuePuzzleSolution(conn); }
protected void HandleArrangedConnectRequest(IPEndPoint client, BitStream reader) { var nonce = new Nonce(); nonce.Read(reader); var oldConnection = FindConnection(client); if (oldConnection != null) { var cp = oldConnection.GetConnectionParameters(); if (cp.Nonce == nonce) { SendConnectAccept(oldConnection); return; } } NetConnection conn = null; var found = false; foreach (var pair in PendingConnections) { conn = pair.Value; var cp = conn.GetConnectionParameters(); if (conn.ConnectionState != NetConnectionState.SendingPunchPackets || cp.IsInitiator) { continue; } if (nonce != cp.Nonce) { continue; } if (cp.PossibleAddresses.Any(ep => ep.Address.Equals(client.Address) && ep.AddressFamily == client.AddressFamily)) { found = true; break; } } if (!found) { return; } var cParams = conn.GetConnectionParameters(); var theCipher = new SymmetricCipher(cParams.ArrangedSecret); if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, reader.GetBytePosition(), theCipher)) { return; } reader.SetBytePosition(reader.GetBytePosition()); var serverNonce = new Nonce(); serverNonce.Read(reader); if (serverNonce != cParams.ServerNonce) { return; } if (reader.ReadFlag()) { if (PrivateKey == null) { return; } cParams.UsingCrypto = true; cParams.PublicKey = new AsymmetricKey(reader); cParams.PrivateKey = PrivateKey; var decryptPos = reader.GetBytePosition(); reader.SetBytePosition(decryptPos); cParams.SharedSecret = cParams.PrivateKey.ComputeSharedSecretKey(cParams.PublicKey); var theCipher2 = new SymmetricCipher(cParams.SharedSecret); if (!reader.DecryptAndCheckHash(NetConnection.MessageSignatureBytes, decryptPos, theCipher2)) { return; } reader.Read(NetConnection.MessageSignatureBytes, cParams.SymmetricKey); RandomUtil.Read(cParams.InitVector, SymmetricCipher.KeySize); } cParams.DebugObjectSizes = reader.ReadFlag(); reader.Read(out uint connectSequence); if (oldConnection != null) { Disconnect(oldConnection, TerminationReason.ReasonSelfDisconnect, ""); } conn.SetNetAddress(client); conn.SetInitialRecvSequence(connectSequence); if (cParams.UsingCrypto) { conn.SetSymmetricCipher(new SymmetricCipher(cParams.SymmetricKey, cParams.InitVector)); } string errorString = null; if (!conn.ReadConnectRequest(reader, ref errorString)) { SendConnectReject(cParams, client, errorString); RemovePendingConnection(conn); return; } AddConnection(conn); RemovePendingConnection(conn); conn.ConnectionState = NetConnectionState.Connected; conn.OnConnectionEstablished(); SendConnectAccept(conn); }