예제 #1
0
        public static ServerAuth.StartAuthSessionResult StartAuthSession(byte[] authTicketData, ulong clientSteamID)
        {
            if (instance == null || !instance.isInitialized || instance.server == null)
            {
                return(ServerAuth.StartAuthSessionResult.ServerNotConnectedToSteam);
            }

            DebugConsole.Log("SteamManager authenticating Steam client " + clientSteamID);
            ServerAuth.StartAuthSessionResult startResult = instance.server.Auth.StartSession(authTicketData, clientSteamID);
            if (startResult != ServerAuth.StartAuthSessionResult.OK)
            {
                DebugConsole.Log("Authentication failed: failed to start auth session (" + startResult.ToString() + ")");
            }

            return(startResult);
        }
예제 #2
0
        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.MapToIPv4()) &&
                        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;
                }

                Int32 contentPackageCount = inc.ReadVariableInt32();
                List <ClientContentPackage> contentPackages = new List <ClientContentPackage>();
                for (int i = 0; i < contentPackageCount; i++)
                {
                    string packageName = inc.ReadString();
                    string packageHash = inc.ReadString();
                    contentPackages.Add(new ClientContentPackage(packageName, packageHash));
                }

                List <ContentPackage> missingPackages = new List <ContentPackage>();
                foreach (ContentPackage contentPackage in GameMain.SelectedPackages)
                {
                    if (!contentPackage.HasMultiplayerIncompatibleContent)
                    {
                        continue;
                    }
                    bool packageFound = false;
                    for (int i = 0; i < contentPackageCount; i++)
                    {
                        if (contentPackages[i].Name == contentPackage.Name && contentPackages[i].Hash == contentPackage.MD5hash.Hash)
                        {
                            packageFound = true;
                            break;
                        }
                    }
                    if (!packageFound)
                    {
                        missingPackages.Add(contentPackage);
                    }
                }

                if (missingPackages.Count == 1)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage,
                                        $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
                    GameServer.Log(name + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") 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.ToString() + ") couldn't join the server (missing 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) &&
                        !requireSteamAuth)
                    {
                        pendingClient.Name               = name;
                        pendingClient.OwnerKey           = ownKey;
                        pendingClient.InitializationStep = ConnectionInitialization.Success;
                    }
                    else
                    {
                        ServerAuth.StartAuthSessionResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
                        if (authSessionStartState != ServerAuth.StartAuthSessionResult.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.Success;
                }
                else
                {
                    pendingClient.Retries++;

                    if (pendingClient.Retries >= 3)
                    {
                        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;
            }
        }