protected override void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket) { if (pendingClient.SteamID == null) { bool requireSteamAuth = GameMain.Config.RequireSteamAuthentication; #if DEBUG requireSteamAuth = false; #endif //steam auth cannot be done (SteamManager not initialized or no ticket given), //but it's not required either -> let the client join without auth if ((!Steam.SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) && !requireSteamAuth) { pendingClient.Connection.Name = name; pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } else { Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { if (requireSteamAuth) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); return; } else { steamId = 0; pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } } pendingClient.SteamID = steamId; pendingClient.Connection.Name = name; pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.AuthSessionStarted = true; } } else { if (pendingClient.SteamID != steamId) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch"); return; } } }
public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, ulong clientSteamID) { if (!isInitialized || !Steamworks.SteamServer.IsValid) { return(Steamworks.BeginAuthResult.ServerNotConnectedToSteam); } DebugConsole.Log("SteamManager authenticating Steam client " + clientSteamID); Steamworks.BeginAuthResult startResult = Steamworks.SteamServer.BeginAuthSession(authTicketData, clientSteamID); if (startResult != Steamworks.BeginAuthResult.OK) { DebugConsole.Log("Authentication failed: failed to start auth session (" + startResult.ToString() + ")"); } return(startResult); }
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel) { if (!isActive) { return; } RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamId); if (remotePeer == null || remotePeer.DisconnectTime != null) { return; } IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write(steamId); outMsg.Write(data, 1, dataLength - 1); DeliveryMethod deliveryMethod = (DeliveryMethod)data[0]; byte incByte = data[1]; bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0; bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0; bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0; bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0; bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0; if (!remotePeer.Authenticated) { if (!remotePeer.Authenticating) { if (isConnectionInitializationStep) { remotePeer.DisconnectTime = null; IReadMessage authMsg = new ReadOnlyMessage(data, isCompressed, 2, dataLength - 2, null); ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte(); //Console.WriteLine("received init step from "+steamId.ToString()+" ("+initializationStep.ToString()+")"); if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { remotePeer.Authenticating = true; authMsg.ReadString(); //skip name authMsg.ReadInt32(); //skip owner key authMsg.ReadUInt64(); //skip steamid UInt16 ticketLength = authMsg.ReadUInt16(); byte[] ticket = authMsg.ReadBytes(ticketLength); Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam auth session failed to start: " + authSessionStartState.ToString()); return; } } } } } if (remotePeer.Authenticating) { remotePeer.UnauthedMessages.Add(new RemotePeer.UnauthedMessage() { DeliveryMethod = deliveryMethod, Message = outMsg }); } else { byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); Array.Resize(ref msgToSend, outMsg.LengthBytes); ChildServerRelay.Write(msgToSend); } }
private void ReadConnectionInitializationStep(PendingClient pendingClient, NetIncomingMessage inc) { if (netServer == null) { return; } pendingClient.TimeOut = NetworkConnection.TimeoutThreshold; ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); //DebugConsole.NewMessage(initializationStep+" "+pendingClient.InitializationStep); if (pendingClient.InitializationStep != initializationStep) { return; } pendingClient.UpdateTime = Timing.TotalTime + Timing.Step; switch (initializationStep) { case ConnectionInitialization.SteamTicketAndVersion: string name = Client.SanitizeName(inc.ReadString()); int ownKey = inc.ReadInt32(); UInt64 steamId = inc.ReadUInt64(); UInt16 ticketLength = inc.ReadUInt16(); byte[] ticket = inc.ReadBytes(ticketLength); if (!Client.IsValidName(name, serverSettings)) { if (OwnerConnection != null || !IPAddress.IsLoopback(pendingClient.Connection.RemoteEndPoint.Address.MapToIPv4NoThrow()) && ownerKey == null || ownKey == 0 && ownKey != ownerKey) { RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "The name \"" + name + "\" is invalid"); return; } } string version = inc.ReadString(); bool isCompatibleVersion = NetworkMember.IsCompatible(version, GameMain.Version.ToString()) ?? false; if (!isCompatibleVersion) { RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion, $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={version}"); GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible game version)", ServerLog.MessageType.Error); DebugConsole.NewMessage(name + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red); return; } int contentPackageCount = inc.ReadVariableInt32(); List <ClientContentPackage> clientContentPackages = new List <ClientContentPackage>(); for (int i = 0; i < contentPackageCount; i++) { string packageName = inc.ReadString(); string packageHash = inc.ReadString(); clientContentPackages.Add(new ClientContentPackage(packageName, packageHash)); } //check if the client is missing any of our packages List <ContentPackage> missingPackages = new List <ContentPackage>(); foreach (ContentPackage serverContentPackage in GameMain.SelectedPackages) { if (!serverContentPackage.HasMultiplayerIncompatibleContent) { continue; } bool packageFound = clientContentPackages.Any(cp => cp.Name == serverContentPackage.Name && cp.Hash == serverContentPackage.MD5hash.Hash); if (!packageFound) { missingPackages.Add(serverContentPackage); } } //check if the client is using packages we don't have List <ClientContentPackage> redundantPackages = new List <ClientContentPackage>(); foreach (ClientContentPackage clientContentPackage in clientContentPackages) { bool packageFound = GameMain.SelectedPackages.Any(cp => cp.Name == clientContentPackage.Name && cp.MD5hash.Hash == clientContentPackage.Hash); if (!packageFound) { redundantPackages.Add(clientContentPackage); } } if (missingPackages.Count == 1) { RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}"); GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error); return; } else if (missingPackages.Count > 1) { List <string> packageStrs = new List <string>(); missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}"); GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } if (redundantPackages.Count == 1) { RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr(redundantPackages[0])}"); GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address + ") couldn't join the server (using an incompatible content package " + GetPackageStr(redundantPackages[0]) + ")", ServerLog.MessageType.Error); return; } if (redundantPackages.Count > 1) { List <string> packageStrs = new List <string>(); redundantPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}"); GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address + ") couldn't join the server (using incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } if (pendingClient.SteamID == null) { bool requireSteamAuth = GameMain.Config.RequireSteamAuthentication; #if DEBUG requireSteamAuth = false; #endif //steam auth cannot be done (SteamManager not initialized or no ticket given), //but it's not required either -> let the client join without auth if ((!Steam.SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) && !requireSteamAuth) { pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; } else { Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); return; } pendingClient.SteamID = steamId; pendingClient.Name = name; pendingClient.OwnerKey = ownKey; pendingClient.AuthSessionStarted = true; } } else //TODO: could remove since this seems impossible { if (pendingClient.SteamID != steamId) { RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch"); return; } } break; case ConnectionInitialization.Password: int pwLength = inc.ReadByte(); byte[] incPassword = new byte[pwLength]; inc.ReadBytes(incPassword, 0, pwLength); if (pendingClient.PasswordSalt == null) { DebugConsole.ThrowError("Received password message from client without salt"); return; } if (serverSettings.IsPasswordCorrect(incPassword, pendingClient.PasswordSalt.Value)) { pendingClient.InitializationStep = ConnectionInitialization.ContentPackageOrder; } else { pendingClient.Retries++; if (serverSettings.BanAfterWrongPassword && pendingClient.Retries > serverSettings.MaxPasswordRetriesBeforeBan) { string banMsg = "Failed to enter correct password too many times"; if (pendingClient.SteamID != null) { serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.SteamID.Value, banMsg, null); } serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.Connection.RemoteEndPoint.Address, banMsg, null); RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg); return; } } pendingClient.UpdateTime = Timing.TotalTime; break; case ConnectionInitialization.ContentPackageOrder: pendingClient.InitializationStep = ConnectionInitialization.Success; pendingClient.UpdateTime = Timing.TotalTime; break; } }