Пример #1
0
    public uint GetMinorMajorBugfixVersionForBuild(uint build)
    {
        RealmBuildInfo buildInfo = ClientBuilds.FirstOrDefault(p =>
        {
            return(p.Build < build);
        });

        return(buildInfo != null ? (buildInfo.MajorVersion * 10000 + buildInfo.MinorVersion * 100 + buildInfo.BugfixVersion) : 0);
    }
Пример #2
0
    public byte[] GetRealmList(uint build, string subRegion)
    {
        var realmList = new RealmListUpdates();

        foreach (var realm in _realms)
        {
            if (realm.Value.Id.GetSubRegionAddress() != subRegion)
            {
                continue;
            }

            RealmFlags flag = realm.Value.Flags;
            if (realm.Value.Build != build)
            {
                flag |= RealmFlags.VersionMismatch;
            }

            RealmListUpdate realmListUpdate = new RealmListUpdate();
            realmListUpdate.Update.WowRealmAddress = (int)realm.Value.Id.GetAddress();
            realmListUpdate.Update.CfgTimezonesID  = 1;
            realmListUpdate.Update.PopulationState = (realm.Value.Flags.HasAnyFlag(RealmFlags.Offline) ? 0 : Math.Max((int)realm.Value.PopulationLevel, 1));
            realmListUpdate.Update.CfgCategoriesID = realm.Value.Timezone;

            RealmBuildInfo buildInfo = GetBuildInfo(realm.Value.Build);
            if (buildInfo != null)
            {
                realmListUpdate.Update.Version.Major    = (int)buildInfo.MajorVersion;
                realmListUpdate.Update.Version.Minor    = (int)buildInfo.MinorVersion;
                realmListUpdate.Update.Version.Revision = (int)buildInfo.BugfixVersion;
                realmListUpdate.Update.Version.Build    = (int)buildInfo.Build;
            }
            else
            {
                realmListUpdate.Update.Version.Major    = 7;
                realmListUpdate.Update.Version.Minor    = 1;
                realmListUpdate.Update.Version.Revision = 0;
                realmListUpdate.Update.Version.Build    = (int)realm.Value.Build;
            }

            realmListUpdate.Update.CfgRealmsID    = (int)realm.Value.Id.Realm;
            realmListUpdate.Update.Flags          = (int)flag;
            realmListUpdate.Update.Name           = realm.Value.Name;
            realmListUpdate.Update.CfgConfigsID   = (int)realm.Value.GetConfigId();
            realmListUpdate.Update.CfgLanguagesID = 1;

            realmListUpdate.Deleting = false;

            realmList.Updates.Add(realmListUpdate);
        }

        return(Json.Deflate("JSONRealmListUpdates", realmList));
    }
Пример #3
0
    public byte[] GetRealmEntryJSON(RealmHandle id, uint build)
    {
        byte[] compressed = new byte[0];
        Realm  realm      = GetRealm(id);

        if (realm != null)
        {
            if (!realm.Flags.HasAnyFlag(RealmFlags.Offline) && realm.Build == build)
            {
                var realmEntry = new RealmEntry();
                realmEntry.WowRealmAddress = (int)realm.Id.GetAddress();
                realmEntry.CfgTimezonesID  = 1;
                realmEntry.PopulationState = Math.Max((int)realm.PopulationLevel, 1);
                realmEntry.CfgCategoriesID = realm.Timezone;

                ClientVersion  version   = new ClientVersion();
                RealmBuildInfo buildInfo = GetBuildInfo(realm.Build);
                if (buildInfo != null)
                {
                    version.Major    = (int)buildInfo.MajorVersion;
                    version.Minor    = (int)buildInfo.MinorVersion;
                    version.Revision = (int)buildInfo.BugfixVersion;
                    version.Build    = (int)buildInfo.Build;
                }
                else
                {
                    version.Major    = 6;
                    version.Minor    = 2;
                    version.Revision = 4;
                    version.Build    = (int)realm.Build;
                }
                realmEntry.Version = version;

                realmEntry.CfgRealmsID    = (int)realm.Id.Realm;
                realmEntry.Flags          = (int)realm.Flags;
                realmEntry.Name           = realm.Name;
                realmEntry.CfgConfigsID   = (int)realm.GetConfigId();
                realmEntry.CfgLanguagesID = 1;

                compressed = Json.Deflate("JamJSONRealmEntry", realmEntry);
            }
        }

        return(compressed);
    }
Пример #4
0
    void LoadBuildInfo()
    {
        //                                         0             1             2              3              4      5              6
        SQLResult result = DB.Login.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build, win64AuthSeed, mac64AuthSeed FROM build_info ORDER BY build ASC");

        if (!result.IsEmpty())
        {
            do
            {
                RealmBuildInfo build = new RealmBuildInfo();
                build.MajorVersion  = result.Read <uint>(0);
                build.MinorVersion  = result.Read <uint>(1);
                build.BugfixVersion = result.Read <uint>(2);
                string hotfixVersion = result.Read <string>(3);
                if (!hotfixVersion.IsEmpty() && hotfixVersion.Length < build.HotfixVersion.Length)
                {
                    build.HotfixVersion = hotfixVersion.ToCharArray();
                }

                build.Build = result.Read <uint>(4);
                string win64AuthSeedHexStr = result.Read <string>(5);
                if (!win64AuthSeedHexStr.IsEmpty() && win64AuthSeedHexStr.Length == build.Win64AuthSeed.Length * 2)
                {
                    build.Win64AuthSeed = win64AuthSeedHexStr.ToByteArray();
                }

                string mac64AuthSeedHexStr = result.Read <string>(6);
                if (!mac64AuthSeedHexStr.IsEmpty() && mac64AuthSeedHexStr.Length == build.Mac64AuthSeed.Length * 2)
                {
                    build.Mac64AuthSeed = mac64AuthSeedHexStr.ToByteArray();
                }

                _builds.Add(build);
            } while (result.NextRow());
        }
    }
Пример #5
0
        void HandleAuthSessionCallback(AuthSession authSession, SQLResult result)
        {
            // Stop if the account is not found
            if (result.IsEmpty())
            {
                Log.outError(LogFilter.Network, "HandleAuthSession: Sent Auth Response (unknown account).");
                CloseSocket();
                return;
            }

            RealmBuildInfo buildInfo = Global.RealmMgr.GetBuildInfo(Global.WorldMgr.GetRealm().Build);

            if (buildInfo == null)
            {
                SendAuthResponseError(BattlenetRpcErrorCode.BadVersion);
                Log.outError(LogFilter.Network, $"WorldSocket.HandleAuthSessionCallback: Missing auth seed for realm build {Global.WorldMgr.GetRealm().Build} ({GetRemoteIpAddress().ToString()}).");
                CloseSocket();
                return;
            }

            AccountInfo account = new AccountInfo(result.GetFields());

            // For hook purposes, we get Remoteaddress at this point.
            string address = GetRemoteIpAddress().ToString();

            Sha256 digestKeyHash = new Sha256();

            digestKeyHash.Process(account.game.SessionKey, account.game.SessionKey.Length);
            if (account.game.OS == "Wn64")
            {
                digestKeyHash.Finish(buildInfo.Win64AuthSeed);
            }
            else if (account.game.OS == "Mc64")
            {
                digestKeyHash.Finish(buildInfo.Mac64AuthSeed);
            }
            else
            {
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Authentication failed for account: {0} ('{1}') address: {2}", account.game.Id, authSession.RealmJoinTicket, address);
                CloseSocket();
                return;
            }

            HmacSha256 hmac = new HmacSha256(digestKeyHash.Digest);

            hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Count);
            hmac.Process(_serverChallenge, 16);
            hmac.Finish(AuthCheckSeed, 16);

            // Check that Key and account name are the same on client and server
            if (!hmac.Digest.Compare(authSession.Digest))
            {
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Authentication failed for account: {0} ('{1}') address: {2}", account.game.Id, authSession.RealmJoinTicket, address);
                CloseSocket();
                return;
            }


            Sha256 keyData = new Sha256();

            keyData.Finish(account.game.SessionKey);

            HmacSha256 sessionKeyHmac = new HmacSha256(keyData.Digest);

            sessionKeyHmac.Process(_serverChallenge, 16);
            sessionKeyHmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Count);
            sessionKeyHmac.Finish(SessionKeySeed, 16);

            _sessionKey = new byte[40];
            var sessionKeyGenerator = new SessionKeyGenerator(sessionKeyHmac.Digest, 32);

            sessionKeyGenerator.Generate(_sessionKey, 40);

            HmacSha256 encryptKeyGen = new HmacSha256(_sessionKey);

            encryptKeyGen.Process(authSession.LocalChallenge, authSession.LocalChallenge.Count);
            encryptKeyGen.Process(_serverChallenge, 16);
            encryptKeyGen.Finish(EncryptionKeySeed, 16);

            // only first 16 bytes of the hmac are used
            Buffer.BlockCopy(encryptKeyGen.Digest, 0, _encryptKey, 0, 16);

            // As we don't know if attempted login process by ip works, we update last_attempt_ip right away
            PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_LAST_ATTEMPT_IP);

            stmt.AddValue(0, address);
            stmt.AddValue(1, authSession.RealmJoinTicket);

            DB.Login.Execute(stmt);
            // This also allows to check for possible "hack" attempts on account

            stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_ACCOUNT_INFO_CONTINUED_SESSION);
            stmt.AddValue(0, _sessionKey.ToHexString());
            stmt.AddValue(1, account.game.Id);
            DB.Login.Execute(stmt);

            // First reject the connection if packet contains invalid data or realm state doesn't allow logging in
            if (Global.WorldMgr.IsClosed())
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: World closed, denying client ({0}).", GetRemoteIpAddress());
                CloseSocket();
                return;
            }

            if (authSession.RealmID != Global.WorldMgr.GetRealm().Id.Realm)
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Client {0} requested connecting with realm id {1} but this realm has id {2} set in config.",
                             GetRemoteIpAddress().ToString(), authSession.RealmID, Global.WorldMgr.GetRealm().Id.Realm);
                CloseSocket();
                return;
            }

            // Must be done before WorldSession is created
            bool wardenActive = WorldConfig.GetBoolValue(WorldCfg.WardenEnabled);

            if (wardenActive && account.game.OS != "Win" && account.game.OS != "Wn64" && account.game.OS != "Mc64")
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Client {0} attempted to log in using invalid client OS ({1}).", address, account.game.OS);
                CloseSocket();
                return;
            }

            //Re-check ip locking (same check as in auth).
            if (account.battleNet.IsLockedToIP) // if ip is locked
            {
                if (account.battleNet.LastIP != address)
                {
                    SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked);
                    Log.outDebug(LogFilter.Network, "HandleAuthSession: Sent Auth Response (Account IP differs).");
                    CloseSocket();
                    return;
                }
            }
            else if (!account.battleNet.LockCountry.IsEmpty() && account.battleNet.LockCountry != "00" && !_ipCountry.IsEmpty())
            {
                if (account.battleNet.LockCountry != _ipCountry)
                {
                    SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked);
                    Log.outDebug(LogFilter.Network, "WorldSocket.HandleAuthSession: Sent Auth Response (Account country differs. Original country: {0}, new country: {1}).", account.battleNet.LockCountry, _ipCountry);
                    CloseSocket();
                    return;
                }
            }

            long mutetime = account.game.MuteTime;

            //! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
            if (mutetime < 0)
            {
                mutetime = Time.UnixTime + mutetime;

                stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_MUTE_TIME_LOGIN);
                stmt.AddValue(0, mutetime);
                stmt.AddValue(1, account.game.Id);
                DB.Login.Execute(stmt);
            }

            if (account.IsBanned()) // if account banned
            {
                SendAuthResponseError(BattlenetRpcErrorCode.GameAccountBanned);
                Log.outError(LogFilter.Network, "WorldSocket:HandleAuthSession: Sent Auth Response (Account banned).");
                CloseSocket();
                return;
            }

            // Check locked state for server
            AccountTypes allowedAccountType = Global.WorldMgr.GetPlayerSecurityLimit();

            if (allowedAccountType > AccountTypes.Player && account.game.Security < allowedAccountType)
            {
                SendAuthResponseError(BattlenetRpcErrorCode.ServerIsPrivate);
                Log.outInfo(LogFilter.Network, "WorldSocket:HandleAuthSession: User tries to login but his security level is not enough");
                CloseSocket();
                return;
            }

            Log.outDebug(LogFilter.Network, "WorldSocket:HandleAuthSession: Client '{0}' authenticated successfully from {1}.", authSession.RealmJoinTicket, address);

            // Update the last_ip in the database
            stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_LAST_IP);
            stmt.AddValue(0, address);
            stmt.AddValue(1, authSession.RealmJoinTicket);
            DB.Login.Execute(stmt);

            _worldSession = new WorldSession(account.game.Id, authSession.RealmJoinTicket, account.battleNet.Id, this, account.game.Security, (Expansion)account.game.Expansion,
                                             mutetime, account.game.OS, account.battleNet.Locale, account.game.Recruiter, account.game.IsRectuiter);

            // Initialize Warden system only if it is enabled by config
            //if (wardenActive)
            //_worldSession.InitWarden(_sessionKey);

            _queryProcessor.AddQuery(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback));
        }