예제 #1
0
AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd)
{
    QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
    if (!result)
        return AOR_NAME_NOT_EXIST;                          // account doesn't exist

    if (utf8length(new_uname) > MAX_ACCOUNT_STR)
        return AOR_NAME_TOO_LONG;

    if (utf8length(new_passwd) > MAX_ACCOUNT_STR)
        return AOR_PASS_TOO_LONG;

    normalizeString(new_uname);
    normalizeString(new_passwd);

    LoginDatabase.EscapeString(new_uname);
    LoginDatabase.EscapeString(new_passwd);

    if (!LoginDatabase.PExecute("UPDATE account SET username='******', sha_pass_hash=Sha1(CONCAT('%s', ':', '%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
        return AOR_DB_INTERNAL_ERROR;                       // unexpected error

    return AOR_OK;
}
예제 #2
0
AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd)
{
    QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
    if (!result)
        return AOR_NAME_NOT_EXIST;                          // account doesn't exist

    if (utf8length(new_uname) > MAX_ACCOUNT_STR)
        return AOR_NAME_TOO_LONG;

    if (utf8length(new_passwd) > MAX_ACCOUNT_STR)
        return AOR_PASS_TOO_LONG;

    normalizeString(new_uname);
    normalizeString(new_passwd);

    std::string safe_new_uname = new_uname;
    LoginDatabase.escape_string(safe_new_uname);

    LoginDatabase.PExecute("UPDATE account SET v='0',s='0',username='******',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(),
                CalculateShaPassHash(new_uname, new_passwd).c_str(), accid);

    return AOR_OK;
}
예제 #3
0
파일: AuthSocket.cpp 프로젝트: Adeer/server
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
    DEBUG_LOG("Entering _HandleLogonProof");
    ///- Read the packet
    sAuthLogonProof_C lp;
    if (!recv((char*)&lp, sizeof(sAuthLogonProof_C)))
        return false;

    ///- Check if the client has one of the expected version numbers
    bool valid_version = FindBuildInfo(_build) != NULL;

    /// <ul><li> If the client has no valid version
    if (!valid_version)
    {
        if (this->patch_ != ACE_INVALID_HANDLE)
            return false;

        ///- Check if we have the apropriate patch on the disk
        // file looks like: 65535enGB.mpq
        char tmp[64];

        snprintf(tmp, 24, "./patches/%d%s.mpq", _build, _localizationName.c_str());

        char filename[PATH_MAX];
        if (ACE_OS::realpath(tmp, filename) != NULL)
        {
            patch_ = ACE_OS::open(filename, GENERIC_READ | FILE_FLAG_SEQUENTIAL_SCAN);
        }

        if (patch_ == ACE_INVALID_HANDLE)
        {
            // no patch found
            ByteBuffer pkt;
            pkt << (uint8) CMD_AUTH_LOGON_CHALLENGE;
            pkt << (uint8) 0x00;
            pkt << (uint8) WOW_FAIL_VERSION_INVALID;
            DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build);
            DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp);
            send((char const*)pkt.contents(), pkt.size());
            return true;
        }

        XFER_INIT xferh;

        ACE_OFF_T file_size = ACE_OS::filesize(this->patch_);

        if (file_size == -1)
        {
            close_connection();
            return false;
        }

        if (!PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5))
        {
            // calculate patch md5, happens if patch was added while realmd was running
            PatchCache::instance()->LoadPatchMD5(tmp);
            PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5);
        }

        uint8 data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_VERSION_UPDATE};
        send((const char*)data, sizeof(data));

        memcpy(&xferh, "0\x05Patch", 7);
        xferh.cmd = CMD_XFER_INITIATE;
        xferh.file_size = file_size;

        send((const char*)&xferh, sizeof(xferh));
        return true;
    }
    /// </ul>

    ///- Continue the SRP6 calculation based on data received from the client
    BigNumber A;

    A.SetBinary(lp.A, 32);

    // SRP safeguard: abort if A==0
    if (A.isZero())
        return false;

    Sha1Hash sha;
    sha.UpdateBigNumbers(&A, &B, NULL);
    sha.Finalize();
    BigNumber u;
    u.SetBinary(sha.GetDigest(), 20);
    BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

    uint8 t[32];
    uint8 t1[16];
    uint8 vK[40];
    memcpy(t, S.AsByteArray(32), 32);
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2] = sha.GetDigest()[i];
    }
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2 + 1];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2 + 1] = sha.GetDigest()[i];
    }
    K.SetBinary(vK, 40);

    uint8 hash[20];

    sha.Initialize();
    sha.UpdateBigNumbers(&N, NULL);
    sha.Finalize();
    memcpy(hash, sha.GetDigest(), 20);
    sha.Initialize();
    sha.UpdateBigNumbers(&g, NULL);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        hash[i] ^= sha.GetDigest()[i];
    }
    BigNumber t3;
    t3.SetBinary(hash, 20);

    sha.Initialize();
    sha.UpdateData(_login);
    sha.Finalize();
    uint8 t4[SHA_DIGEST_LENGTH];
    memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

    sha.Initialize();
    sha.UpdateBigNumbers(&t3, NULL);
    sha.UpdateData(t4, SHA_DIGEST_LENGTH);
    sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
    sha.Finalize();
    BigNumber M;
    M.SetBinary(sha.GetDigest(), 20);

    ///- Check if SRP6 results match (password is correct), else send an error
    if (!memcmp(M.AsByteArray(), lp.M1, 20))
    {
        BASIC_LOG("User '%s' successfully authenticated", _login.c_str());

        ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
        // No SQL injection (escaped user name) and IP address as received by socket
        const char* K_hex = K.AsHexStr();
        LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '******'", K_hex, get_remote_address().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str());
        OPENSSL_free((void*)K_hex);

        ///- Finish SRP6 and send the final result to the client
        sha.Initialize();
        sha.UpdateBigNumbers(&A, &M, &K, NULL);
        sha.Finalize();

        SendProof(sha);

        ///- Set _authed to true!
        _authed = true;
    }
    else
    {
        if (_build > 6005)                                  // > 1.12.2
        {
            char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
            send(data, sizeof(data));
        }
        else
        {
            // 1.x not react incorrectly at 4-byte message use 3 as real error
            char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT};
            send(data, sizeof(data));
        }
        BASIC_LOG("[AuthChallenge] account %s tried to login with wrong password!", _login.c_str());

        uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
        if (MaxWrongPassCount > 0)
        {
            // Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
            LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '******'", _safelogin.c_str());

            if (QueryResult* loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str()))
            {
                Field* fields = loginfail->Fetch();
                uint32 failed_logins = fields[1].GetUInt32();

                if (failed_logins >= MaxWrongPassCount)
                {
                    uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                    bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                    if (WrongPassBanType)
                    {
                        uint32 acc_id = fields[0].GetUInt32();
                        LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban',1)",
                                               acc_id, WrongPassBanTime);
                        BASIC_LOG("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                                  _login.c_str(), WrongPassBanTime, failed_logins);
                    }
                    else
                    {
                        std::string current_ip = get_remote_address();
                        LoginDatabase.escape_string(current_ip);
                        LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban')",
                                               current_ip.c_str(), WrongPassBanTime);
                        BASIC_LOG("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                                  current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                    }
                }
                delete loginfail;
            }
        }
    }
    return true;
}
예제 #4
0
void AccountMgr::LockAccount(uint32 acc_id, bool lock)
{
    LoginDatabase.PExecute( "UPDATE account SET locked = '%u' WHERE id = '%u'", uint32(lock), acc_id);
}
예제 #5
0
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
    DEBUG_LOG("Entering _HandleLogonProof");
    ///- Read the packet
    if (ibuf.GetLength() < sizeof(sAuthLogonProof_C))
        return false;
    sAuthLogonProof_C lp;
    ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));

    ///- Check if the client has one of the expected version numbers
    bool valid_version = FindBuildInfo(_build) != NULL;

    /// <ul><li> If the client has no valid version
    /// Ignore if its trial client account
    if(!valid_version && !_isTrial)
    {
        ///- Check if we have the apropriate patch on the disk

        // 24 = len("./patches/65535enGB.mpq")+1
        char tmp[24];
        // No buffer overflow (fixed length of arguments)
        sprintf(tmp, "./patches/%d%s.mpq", _build, _localizationName.c_str());
        // This will be closed at the destruction of the AuthSocket (client disconnection)
        FILE *pFile = fopen(tmp, "rb");

        if(!pFile)
        {
            ByteBuffer pkt;
            pkt << (uint8) AUTH_LOGON_CHALLENGE;
            pkt << (uint8) 0x00;
            pkt << (uint8) WOW_FAIL_VERSION_INVALID;
            DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build);
            DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp);
            SendBuf((char const*)pkt.contents(), pkt.size());
            return true;
        }
        else                                                // have patch
        {
            pPatch = pFile;
            XFER_INIT xferh;

            ///- Get the MD5 hash of the patch file (get it from preloaded Patcher cache or calculate it)
            if(PatchesCache.GetHash(tmp, (uint8*)&xferh.md5))
            {
                DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s", tmp);
            }
            else
            {                                               // calculate patch md5
                printf("\n[AuthChallenge] Patch info for %s was not cached.", tmp);
                PatchesCache.LoadPatchMD5(tmp);
                PatchesCache.GetHash(tmp, (uint8*)&xferh.md5);
            }

            ///- Send a packet to the client with the file length and MD5 hash
            uint8 data[2] = { AUTH_LOGON_PROOF, WOW_FAIL_VERSION_UPDATE };
            SendBuf((const char*)data, sizeof(data));

            memcpy(&xferh, "0\x05Patch", 7);
            xferh.cmd = XFER_INITIATE;
            fseek(pPatch, 0, SEEK_END);
            xferh.file_size = ftell(pPatch);

            SendBuf((const char*)&xferh, sizeof(xferh));
            return true;
        }
    }
    /// </ul>

    ///- Continue the SRP6 calculation based on data received from the client
    BigNumber A;

    A.SetBinary(lp.A, 32);

    // SRP safeguard: abort if A==0
    if (A.isZero())
        return false;

    Sha1Hash sha;
    sha.UpdateBigNumbers(&A, &B, NULL);
    sha.Finalize();
    BigNumber u;
    u.SetBinary(sha.GetDigest(), 20);
    BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

    uint8 t[32];
    uint8 t1[16];
    uint8 vK[40];
    memcpy(t, S.AsByteArray(32), 32);
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2] = sha.GetDigest()[i];
    }
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2 + 1];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2 + 1] = sha.GetDigest()[i];
    }
    K.SetBinary(vK, 40);

    uint8 hash[20];

    sha.Initialize();
    sha.UpdateBigNumbers(&N, NULL);
    sha.Finalize();
    memcpy(hash, sha.GetDigest(), 20);
    sha.Initialize();
    sha.UpdateBigNumbers(&g, NULL);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        hash[i] ^= sha.GetDigest()[i];
    }
    BigNumber t3;
    t3.SetBinary(hash, 20);

    sha.Initialize();
    sha.UpdateData(_login);
    sha.Finalize();
    uint8 t4[SHA_DIGEST_LENGTH];
    memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

    sha.Initialize();
    sha.UpdateBigNumbers(&t3, NULL);
    sha.UpdateData(t4, SHA_DIGEST_LENGTH);
    sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
    sha.Finalize();
    BigNumber M;
    M.SetBinary(sha.GetDigest(), 20);

    ///- Check if SRP6 results match (password is correct), else send an error
    if (!memcmp(M.AsByteArray(), lp.M1, 20))
    {
        BASIC_LOG("User '%s' successfully authenticated", _login.c_str());

        ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
        // No SQL injection (escaped user name) and IP address as received by socket
        const char* K_hex = K.AsHexStr();
        loginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '******'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() );
        OPENSSL_free((void*)K_hex);

        ///- Finish SRP6 and send the final result to the client
        sha.Initialize();
        sha.UpdateBigNumbers(&A, &M, &K, NULL);
        sha.Finalize();

        SendProof(sha);

        ///- Set _authed to true!
        _authed = true;
    }
    else
    {
        char data[4]= { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
        SendBuf(data, sizeof(data));
        BASIC_LOG("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());

        uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
        if(MaxWrongPassCount > 0)
        {
            //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
            loginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '******'",_safelogin.c_str());

            if(QueryResult *loginfail = loginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str()))
            {
                Field* fields = loginfail->Fetch();
                uint32 failed_logins = fields[1].GetUInt32();

                if( failed_logins >= MaxWrongPassCount )
                {
                    uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                    bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                    if(WrongPassBanType)
                    {
                        uint32 acc_id = fields[0].GetUInt32();
                        loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban',1)",
                            acc_id, WrongPassBanTime);
                        BASIC_LOG("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                            _login.c_str(), WrongPassBanTime, failed_logins);
                    }
                    else
                    {
                        std::string current_ip = GetRemoteAddress();
                        loginDatabase.escape_string(current_ip);
                        loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban')",
                            current_ip.c_str(), WrongPassBanTime);
                        BASIC_LOG("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                            current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                    }
                }
                delete loginfail;
            }
        }
    }
    return true;
}
예제 #6
0
파일: AuthSocket.cpp 프로젝트: Dump/mangos
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
    DEBUG_LOG("Entering _HandleLogonProof");
    ///- Read the packet
    if (ibuf.GetLength() < sizeof(sAuthLogonProof_C))
        return false;

    sAuthLogonProof_C lp;
    ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));

    ///- Continue the SRP6 calculation based on data received from the client
    BigNumber A;
    A.SetBinary(lp.A, 32);

    Sha1Hash sha;
    sha.UpdateBigNumbers(&A, &B, NULL);
    sha.Finalize();
    BigNumber u;
    u.SetBinary(sha.GetDigest(), 20);
    BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

    uint8 t[32];
    uint8 t1[16];
    uint8 vK[40];
    memcpy(t, S.AsByteArray(), 32);
    for (int i = 0; i < 16; i++)
    {
        t1[i] = t[i*2];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; i++)
    {
        vK[i*2] = sha.GetDigest()[i];
    }
    for (int i = 0; i < 16; i++)
    {
        t1[i] = t[i*2+1];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; i++)
    {
        vK[i*2+1] = sha.GetDigest()[i];
    }
    K.SetBinary(vK, 40);

    uint8 hash[20];

    sha.Initialize();
    sha.UpdateBigNumbers(&N, NULL);
    sha.Finalize();
    memcpy(hash, sha.GetDigest(), 20);
    sha.Initialize();
    sha.UpdateBigNumbers(&g, NULL);
    sha.Finalize();
    for (int i = 0; i < 20; i++)
    {
        hash[i] ^= sha.GetDigest()[i];
    }
    BigNumber t3;
    t3.SetBinary(hash, 20);

    sha.Initialize();
    sha.UpdateData(_login);
    sha.Finalize();
    uint8 t4[SHA_DIGEST_LENGTH];
    memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

    sha.Initialize();
    sha.UpdateBigNumbers(&t3, NULL);
    sha.UpdateData(t4, SHA_DIGEST_LENGTH);
    sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
    sha.Finalize();
    BigNumber M;
    M.SetBinary(sha.GetDigest(), 20);

    ///- Check if SRP6 results match (password is correct), else send an error
    if (!memcmp(M.AsByteArray(), lp.M1, 20))
    {
        sLog.outBasic("User '%s' successfully authenticated", _login.c_str());

        ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
        // No SQL injection (escaped user name) and IP address as received by socket
        const char* K_hex = K.AsHexStr();
        dbRealmServer.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '******'", K_hex, GetRemoteAddress().c_str(),  _localization, _safelogin.c_str() );
        OPENSSL_free((void*)K_hex);

        ///- Finish SRP6 and send the final result to the client
        sha.Initialize();
        sha.UpdateBigNumbers(&A, &M, &K, NULL);
        sha.Finalize();

        sAuthLogonProof_S proof;
        memcpy(proof.M2, sha.GetDigest(), 20);
        proof.cmd = AUTH_LOGON_PROOF;
        proof.error = 0;
        proof.unk1 = 0x00800000;
        proof.unk2 = 0x00;
        proof.unk3 = 0x00;

        SendBuf((char *)&proof, sizeof(proof));

        ///- Set _authed to true!
        _authed = true;
    }
    else
    {
        char data[4]={AUTH_LOGON_PROOF,REALM_AUTH_NO_MATCH,3,0};
        SendBuf(data,sizeof(data));
        sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());

        uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
        if(MaxWrongPassCount > 0)
        {
            //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
            dbRealmServer.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '******'",_safelogin.c_str());

            if(QueryResult *loginfail = dbRealmServer.PQuery("SELECT id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str()))
            {
                Field* fields = loginfail->Fetch();
                uint32 failed_logins = fields[1].GetUInt32();

                if( failed_logins >= MaxWrongPassCount )
                {
                    uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                    bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                    if(WrongPassBanType)
                    {
                        uint32 acc_id = fields[0].GetUInt32();
                        dbRealmServer.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban',1)",
                            acc_id, WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                            _login.c_str(), WrongPassBanTime, failed_logins);
                    }
                    else
                    {
                        std::string current_ip = GetRemoteAddress();
                        dbRealmServer.escape_string(current_ip);
                        dbRealmServer.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban')",
                            current_ip.c_str(), WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                            current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                    }
                }
                delete loginfail;
            }
        }
    }
    return true;
}
예제 #7
0
/// Logon Challenge command handler
bool AuthSocket::_HandleLogonChallenge()
{
    DEBUG_LOG("Entering _HandleLogonChallenge");
    if (recv_len() < sizeof(sAuthLogonChallenge_C))
        return false;

    ///- Read the first 4 bytes (header) to get the length of the remaining of the packet
    std::vector<uint8> buf;
    buf.resize(4);

    recv((char *)&buf[0], 4);

    EndianConvert(*((uint16*)(buf[0])));
    uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
    DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining);

    if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining))
        return false;

    //No big fear of memory outage (size is int16, i.e. < 65536)
    buf.resize(remaining + buf.size() + 1);
    buf[buf.size() - 1] = 0;
    sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];

    ///- Read the remaining of the packet
    recv((char *)&buf[4], remaining);
    DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
    DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);

    // BigEndian code, nop in little endian case
    // size already converted
    EndianConvert(*((uint32*)(&ch->gamename[0])));
    EndianConvert(ch->build);
    EndianConvert(*((uint32*)(&ch->platform[0])));
    EndianConvert(*((uint32*)(&ch->os[0])));
    EndianConvert(*((uint32*)(&ch->country[0])));
    EndianConvert(ch->timezone_bias);
    EndianConvert(ch->ip);

    ByteBuffer pkt;

    _login = (const char*)ch->I;
    _build = ch->build;
    _os = (const char*)ch->os;

    if(_os.size() > 4)
        return false;

    ///- Normalize account name
    //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form

    //Escape the user login to avoid further SQL injection
    //Memory will be freed on AuthSocket object destruction
    _safelogin = _login;
    LoginDatabase.escape_string(_safelogin);

    // Starting CMD_AUTH_LOGON_CHALLENGE
    AuthResult result = WOW_FAIL_UNKNOWN0;

    ///- Verify that this IP is not in the ip_banned table
    // No SQL injection possible (paste the IP address as passed by the socket)
    std::string address = get_remote_address();
    LoginDatabase.escape_string(address);
    QueryResult* qresult = LoginDatabase.PQuery("SELECT unbandate FROM ip_banned WHERE "
    //    permanent                    still banned
        "(unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", address.c_str());

    if (qresult)
    {
        result = WOW_FAIL_BANNED;
        BASIC_LOG("[AuthChallenge] Banned ip %s tries to login!", get_remote_address().c_str());
        delete qresult;
    }
    else
    {
        ///- Get the account details from the account table
        // No SQL injection (escaped user name)

        //qresult = LoginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '******'",_safelogin.c_str());
        qresult = LoginDatabase.PQuery("SELECT a.sha_pass_hash,a.id,a.locked,a.last_ip,aa.gmlevel,a.v,a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = '******'", _safelogin.c_str());

        if (qresult)
        {
            std::string rI = (*qresult)[0].GetCppString();
            uint32 accountId = (*qresult)[1].GetUInt32();
            uint8 locked = (*qresult)[2].GetUInt8();
            std::string lastIP = (*qresult)[3].GetString();
            uint8 secLevel = (*qresult)[4].GetUInt8();
            std::string databaseV = (*qresult)[5].GetCppString();
            std::string databaseS = (*qresult)[6].GetCppString();

            bool blockLogin = false;
            if (sConfig.GetBoolDefault("MultiIPCheck", false))
            {
                int32 iplimit = sConfig.GetIntDefault("MultiIPLimit", 10);
                int32 multiIPdelay = sConfig.GetIntDefault("MultiIPPeriodInHours", 48);
                // If a GM account login ignore MultiIP
                QueryResult* ipcheck = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s' AND id != %u AND last_login > NOW() - INTERVAL %u HOUR ORDER BY last_login DESC;", get_remote_address().c_str(), accountId, multiIPdelay);
                if (ipcheck)
                {
                    // build whitelist
                    std::list<uint32> accountsInWhitelist;
                    accountsInWhitelist.clear();
                    QueryResult* IDsinwhite = LoginDatabase.PQuery("SELECT whitelist FROM multi_IP_whitelist WHERE whitelist LIKE '%|%u|%'", accountId);
                    if (IDsinwhite)
                    {
                        Tokens whitelistaccounts((*IDsinwhite)[0].GetCppString(),'|');
                        bool isInWhite = false;
                        for (Tokens::const_iterator itr = whitelistaccounts.begin(); itr != whitelistaccounts.end(); ++itr)
                            accountsInWhitelist.push_back(atoi(*itr));
                        delete IDsinwhite;
                    }

                    do
                    {
                        Field* pFields =ipcheck->Fetch();
                        uint32 MultiAccountID = pFields[0].GetUInt32();
                        bool isInWhite = false;
                        for (std::list<uint32>::const_iterator itr = accountsInWhitelist.begin(); itr != accountsInWhitelist.end(); ++itr)
                        {
                            if (*itr == MultiAccountID)
                                isInWhite = true;
                        }
                        if (!isInWhite)
                        {
                            --iplimit;
                        }
                    }
                    while (ipcheck->NextRow());

                    delete ipcheck;
                }
                /*
                 * default case 10 allowed account with same last_ip
                 * we found 9 account with current ip. NOTE: actual account is not in list
                 * 10 - 9 - 1
                 *          ^ current account
                 *      ^ account in list
                 * ^ allowed
                 */
                if (iplimit < 1)
                {
                    DEBUG_LOG("[AuthChallenge] Account '%s' is multi IP - '%s'", _login.c_str(), lastIP.c_str());
                    result = WOW_FAIL_PARENTCONTROL;
                    blockLogin = true;
                }
            }
            ///- If the IP is 'locked', check that the player comes indeed from the correct IP address
            if (locked == 1)                // if ip is locked
            {
                DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), lastIP.c_str());
                DEBUG_LOG("[AuthChallenge] Player address is '%s'", get_remote_address().c_str());
                if (strcmp(lastIP.c_str(),get_remote_address().c_str()) )
                {
                    DEBUG_LOG("[AuthChallenge] Account IP differs");
                    result = WOW_FAIL_SUSPENDED;
                    blockLogin = true;
                }
                else
                {
                    DEBUG_LOG("[AuthChallenge] Account IP matches");
                }
            }
            else
            {
                DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str());
            }

            if (!blockLogin)
            {
                ///- If the account is banned, reject the logon attempt
                QueryResult* banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE "
                    "id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)", accountId);
                if (banresult)
                {
                    if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64())
                    {
                        result = WOW_FAIL_BANNED;
                        BASIC_LOG("[AuthChallenge] Banned account %s (Id: %u) tries to login!", _login.c_str(), accountId);
                    }
                    else
                    {
                        result = WOW_FAIL_SUSPENDED;
                        BASIC_LOG("[AuthChallenge] Temporarily banned account %s (Id: %u) tries to login!",_login.c_str(), accountId);
                    }

                    delete banresult;
                }
                else
                {
                    DEBUG_LOG("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());

                    // multiply with 2, bytes are stored as hexstring
                    if (databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2)
                        _SetVSFields(rI);
                    else
                    {
                        s.SetHexStr(databaseS.c_str());
                        v.SetHexStr(databaseV.c_str());
                    }

                    result = WOW_SUCCESS;

                    _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;

                    _localizationName.resize(4);
                    for (int i = 0; i < 4; ++i)
                        _localizationName[i] = ch->country[4-i-1];

                    BASIC_LOG("[AuthChallenge] account %s (Id: %u) is using '%c%c%c%c' locale (%u)", _login.c_str (), accountId, ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName));
                }
            }
            delete qresult;
        }
        else if (sConfig.GetBoolDefault("AutoRegistration", false))
        {
            if (_safelogin.find_first_of("\t\v\b\f\a\n\r\\\"\'\? <>[](){}_=+-|/!@#$%^&*~`.,\0") == _safelogin.npos && _safelogin.length() > 3)
            {
                QueryResult* checkIPresult = LoginDatabase.PQuery("SELECT COUNT(last_ip) FROM account WHERE last_ip = '%s'",get_remote_address().c_str());

                int32 regCount = checkIPresult ? (*checkIPresult)[0].GetUInt32() : 0;

                if (regCount >= sConfig.GetIntDefault("AutoRegistration.Amount", 1))
                {
                    BASIC_LOG("[AuthChallenge] Impossible auto-register account %s, number of auto-registered accouts is %u, but allowed only %u",
                         _safelogin.c_str(),regCount, sConfig.GetIntDefault("AutoRegistration.Amount", 1));
//                    result = WOW_FAIL_DB_BUSY;
                    result = WOW_FAIL_DISCONNECTED;
                }
                else
                {
                    std::transform(_safelogin.begin(), _safelogin.end(), _safelogin.begin(), std::towupper); 

                    Sha1Hash sha;
                    sha.Initialize();
                    sha.UpdateData(_safelogin);
                    sha.UpdateData(":");
                    sha.UpdateData(_safelogin);
                    sha.Finalize();

                    std::string encoded;
                    hexEncodeByteArray(sha.GetDigest(), sha.GetLength(), encoded);

                    LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", _safelogin.c_str(), encoded.c_str());

                    _SetVSFields(encoded);

                    BASIC_LOG("[AuthChallenge] account %s auto-registered (count %u)!",_safelogin.c_str(), ++regCount);

                    result = WOW_SUCCESS;
                    _accountSecurityLevel = SEC_PLAYER;

                    _localizationName.resize(4);
                    for (int i = 0; i < 4; ++i)
                        _localizationName[i] = ch->country[4-i-1];
                }

                if (checkIPresult)
                    delete checkIPresult;
            }
        }
        else
            result = WOW_FAIL_UNKNOWN_ACCOUNT;
    }

    pkt << uint8(CMD_AUTH_LOGON_CHALLENGE);
    pkt << uint8(0x00);
    pkt << uint8(result);

    switch (result)
    {
        case WOW_SUCCESS:
        {
            b.SetRand(19 * 8);
            BigNumber gmod = g.ModExp(b, N);
            B = ((v * 3) + gmod) % N;

            MANGOS_ASSERT(gmod.GetNumBytes() <= 32);

            BigNumber unk3;
            unk3.SetRand(16 * 8);

            // B may be calculated < 32B so we force minimal length to 32B
            pkt.append(B.AsByteArray(32), 32);      // 32 bytes
            pkt << uint8(1);
            pkt.append(g.AsByteArray(), 1);
            pkt << uint8(32);
            pkt.append(N.AsByteArray(32), 32);
            pkt.append(s.AsByteArray(), s.GetNumBytes());// 32 bytes
            pkt.append(unk3.AsByteArray(16), 16);
            uint8 securityFlags = 0;
            pkt << uint8(securityFlags);            // security flags (0x0...0x04)

            if (securityFlags & 0x01)               // PIN input
            {
                pkt << uint32(0);
                pkt << uint64(0) << uint64(0);      // 16 bytes hash?
            }

            if (securityFlags & 0x02)               // Matrix input
            {
                pkt << uint8(0);
                pkt << uint8(0);
                pkt << uint8(0);
                pkt << uint8(0);
                pkt << uint64(0);
            }

            if (securityFlags & 0x04)               // Security token input
            {
                pkt << uint8(1);
            }

            break;
        }
        case WOW_FAIL_UNKNOWN0:
        case WOW_FAIL_UNKNOWN1:
        case WOW_FAIL_SUSPENDED:
        case WOW_FAIL_BANNED:
        case WOW_FAIL_UNKNOWN_ACCOUNT:
        case WOW_FAIL_INCORRECT_PASSWORD:
        case WOW_FAIL_ALREADY_ONLINE:
        case WOW_FAIL_NO_TIME:
        case WOW_FAIL_DB_BUSY:
        case WOW_FAIL_VERSION_INVALID:
        case WOW_FAIL_VERSION_UPDATE:
        case WOW_FAIL_INVALID_SERVER:
        case WOW_FAIL_FAIL_NOACCESS:
        case WOW_SUCCESS_SURVEY:
        case WOW_FAIL_PARENTCONTROL:
        case WOW_FAIL_LOCKED_ENFORCED:
        case WOW_FAIL_TRIAL_ENDED:
        case WOW_FAIL_USE_BATTLENET:
        case WOW_FAIL_TOO_FAST:
        case WOW_FAIL_CHARGEBACK:
        case WOW_FAIL_GAME_ACCOUNT_LOCKED:
        case WOW_FAIL_INTERNET_GAME_ROOM_WITHOUT_BNET:
        case WOW_FAIL_UNLOCKABLE_LOCK:
        case WOW_FAIL_DISCONNECTED:
            break;
        default:
            BASIC_LOG("[AuthChallenge] unknown CMD_AUTH_LOGON_CHALLENGE execution result %u!", result);
            break;
    }

    send((char const*)pkt.contents(), pkt.size());
    return true;
}
예제 #8
0
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
    DEBUG_LOG("Entering _HandleLogonProof");
    ///- Read the packet
    sAuthLogonProof_C lp;

    if (!socket().recv((char *)&lp, sizeof(sAuthLogonProof_C)))
        return false;

    /// <ul><li> If the client has no valid version
    if (_expversion == NO_VALID_EXP_FLAG)
    {
        ///- Check if we have the appropriate patch on the disk

        sLog.outDebug("Client with invalid version, patching is not implemented");
        socket().shutdown();
        return true;
    }
    /// </ul>

    ///- Continue the SRP6 calculation based on data received from the client
    BigNumber A;

    A.SetBinary(lp.A, 32);

    // SRP safeguard: abort if A==0
    if (A.isZero())
    {
        socket().shutdown();
        return true;
    }

    Sha1Hash sha;
    sha.UpdateBigNumbers(&A, &B, NULL);
    sha.Finalize();
    BigNumber u;
    u.SetBinary(sha.GetDigest(), 20);
    BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

    uint8 t[32];
    uint8 t1[16];
    uint8 vK[40];
    memcpy(t, S.AsByteArray(32), 32);
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2] = sha.GetDigest()[i];
    }
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2 + 1];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2 + 1] = sha.GetDigest()[i];
    }
    K.SetBinary(vK, 40);

    uint8 hash[20];

    sha.Initialize();
    sha.UpdateBigNumbers(&N, NULL);
    sha.Finalize();
    memcpy(hash, sha.GetDigest(), 20);
    sha.Initialize();
    sha.UpdateBigNumbers(&g, NULL);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        hash[i] ^= sha.GetDigest()[i];
    }
    BigNumber t3;
    t3.SetBinary(hash, 20);

    sha.Initialize();
    sha.UpdateData(_login);
    sha.Finalize();
    uint8 t4[SHA_DIGEST_LENGTH];
    memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

    sha.Initialize();
    sha.UpdateBigNumbers(&t3, NULL);
    sha.UpdateData(t4, SHA_DIGEST_LENGTH);
    sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
    sha.Finalize();
    BigNumber M;
    M.SetBinary(sha.GetDigest(), 20);

    ///- Check if SRP6 results match (password is correct), else send an error
    if (!memcmp(M.AsByteArray(), lp.M1, 20))
    {
        sLog.outBasic("User '%s' successfully authenticated", _login.c_str());

        ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
        // No SQL injection (escaped user name) and IP address as received by socket
        const char* K_hex = K.AsHexStr();
        LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '******'", K_hex, socket().get_remote_address().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str());
        OPENSSL_free((void*)K_hex);

        ///- Finish SRP6 and send the final result to the client
        sha.Initialize();
        sha.UpdateBigNumbers(&A, &M, &K, NULL);
        sha.Finalize();

        if (_expversion & POST_BC_EXP_FLAG)//2.4.3 and 3.1.3 clients (10146 is Chinese build for 3.1.3)
        {
            sAuthLogonProof_S proof;
            memcpy(proof.M2, sha.GetDigest(), 20);
            proof.cmd = AUTH_LOGON_PROOF;
            proof.error = 0;
            proof.unk1 = 0x00800000;
            proof.unk2 = 0x00;
            proof.unk3 = 0x00;
            socket().send((char *)&proof, sizeof(proof));
        }
        else
        {
            sAuthLogonProof_S_Old proof;
            memcpy(proof.M2, sha.GetDigest(), 20);
            proof.cmd = AUTH_LOGON_PROOF;
            proof.error = 0;
            //proof.unk1 = 0x00800000;
            proof.unk2 = 0x00;
            //proof.unk3 = 0x00;
            socket().send((char *)&proof, sizeof(proof));
        }

        ///- Set _authed to true!
        _authed = true;
    }
    else
    {
        char data[4]= { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
        socket().send(data, sizeof(data));
        sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());

        uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
        if (MaxWrongPassCount > 0)
        {
            //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
            LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '******'",_safelogin.c_str());

            if (QueryResult_AutoPtr loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str()))
            {
                Field* fields = loginfail->Fetch();
                uint32 failed_logins = fields[1].GetUInt32();

                if (failed_logins >= MaxWrongPassCount)
                {
                    uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                    bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                    if (WrongPassBanType)
                    {
                        uint32 acc_id = fields[0].GetUInt32();
                        LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)",
                            acc_id, WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                            _login.c_str(), WrongPassBanTime, failed_logins);
                    }
                    else
                    {
                        std::string current_ip(socket().get_remote_address().c_str());
                        LoginDatabase.escape_string(current_ip);
                        LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')",
                            current_ip.c_str(), WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                            current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                    }
                }
            }
        }
    }

    return true;
}
예제 #9
0
파일: Main.cpp 프로젝트: Wisznu/mangos
/// Launch the realm server
extern int main(int argc, char **argv)
{
    ///- Command line parsing
    char const* cfg_file = _REALMD_CONFIG;

#ifdef WIN32
    char const *options = ":c:s:";
#else
    char const *options = ":c:";
#endif

    ACE_Get_Opt cmd_opts(argc, argv, options);
    cmd_opts.long_option("version", 'v');

    int option;
    while ((option = cmd_opts()) != EOF)
    {
        switch (option)
        {
            case 'c':
                cfg_file = cmd_opts.opt_arg();
                break;
            case 'v':
                printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
                return 0;
#ifdef WIN32
            case 's':
            {
                const char *mode = cmd_opts.opt_arg();

                if (!strcmp(mode, "install"))
                {
                    if (WinServiceInstall())
                        sLog.outString("Installing service");
                    return 1;
                }
                else if (!strcmp(mode, "uninstall"))
                {
                    if (WinServiceUninstall())
                        sLog.outString("Uninstalling service");
                    return 1;
                }
                else if (!strcmp(mode, "run"))
                    WinServiceRun();
                else
                {
                    sLog.outError("Runtime-Error: -%c unsupported argument %s", cmd_opts.opt_opt(), mode);
                    usage(argv[0]);
                    Log::WaitBeforeContinueIfNeed();
                    return 1;
                }
                break;
            }
#endif
            case ':':
                sLog.outError("Runtime-Error: -%c option requires an input argument", cmd_opts.opt_opt());
                usage(argv[0]);
                Log::WaitBeforeContinueIfNeed();
                return 1;
            default:
                sLog.outError("Runtime-Error: bad format of commandline arguments");
                usage(argv[0]);
                Log::WaitBeforeContinueIfNeed();
                return 1;
        }
    }

    if (!sConfig.SetSource(cfg_file))
    {
        sLog.outError("Could not find configuration file %s.", cfg_file);
        Log::WaitBeforeContinueIfNeed();
        return 1;
    }
    sLog.Initialize();

    sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
    sLog.outString( "<Ctrl-C> to stop.\n" );
    sLog.outString("Using configuration file %s.", cfg_file);

    ///- Check the version of the configuration file
    uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
    if (confVersion < _REALMDCONFVERSION)
    {
        sLog.outError("*****************************************************************************");
        sLog.outError(" WARNING: Your realmd.conf version indicates your conf file is out of date!");
        sLog.outError("          Please check for updates, as your current default values may cause");
        sLog.outError("          strange behavior.");
        sLog.outError("*****************************************************************************");
        Log::WaitBeforeContinueIfNeed();
    }

    DETAIL_LOG("%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
    if (SSLeay() < 0x009080bfL )
    {
        DETAIL_LOG("WARNING: Outdated version of OpenSSL lib. Logins to server may not work!");
        DETAIL_LOG("WARNING: Minimal required version [OpenSSL 0.9.8k]");
    }

    DETAIL_LOG("Using ACE: %s", ACE_VERSION);

#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
    ACE_Reactor::instance(new ACE_Reactor(new ACE_Dev_Poll_Reactor(ACE::max_handles(), 1), 1), true);
#else
    ACE_Reactor::instance(new ACE_Reactor(new ACE_TP_Reactor(), true), true);
#endif

    sLog.outBasic("Max allowed open files is %d", ACE::max_handles());

    /// realmd PID file creation
    std::string pidfile = sConfig.GetStringDefault("PidFile", "");
    if(!pidfile.empty())
    {
        uint32 pid = CreatePIDFile(pidfile);
        if( !pid )
        {
            sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
            Log::WaitBeforeContinueIfNeed();
            return 1;
        }

        sLog.outString( "Daemon PID: %u\n", pid );
    }

    ///- Initialize the database connection
    if(!StartDB())
    {
        Log::WaitBeforeContinueIfNeed();
        return 1;
    }

    ///- Get the list of realms for the server
    sRealmList.Initialize(sConfig.GetIntDefault("RealmsStateUpdateDelay", 20));
    if (sRealmList.size() == 0)
    {
        sLog.outError("No valid realms specified.");
        Log::WaitBeforeContinueIfNeed();
        return 1;
    }

    // cleanup query
    // set expired bans to inactive
    LoginDatabase.BeginTransaction();
    LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
    LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
    LoginDatabase.CommitTransaction();

    ///- Launch the listening network socket
    ACE_Acceptor<AuthSocket, ACE_SOCK_Acceptor> acceptor;

    uint16 rmport = sConfig.GetIntDefault("RealmServerPort", DEFAULT_REALMSERVER_PORT);
    std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0");

    ACE_INET_Addr bind_addr(rmport, bind_ip.c_str());

    if(acceptor.open(bind_addr, ACE_Reactor::instance(), ACE_NONBLOCK) == -1)
    {
        sLog.outError("MaNGOS realmd can not bind to %s:%d", bind_ip.c_str(), rmport);
        Log::WaitBeforeContinueIfNeed();
        return 1;
    }

    // FG: "bad points" system related
    uint32 badPointsDropInterval = sConfig.GetIntDefault("BadPoints.DropInterval", HOUR);
    uint32 badPointsDropAmount = sConfig.GetIntDefault("BadPoints.DropAmount", 1);
    uint32 badPointsDropWaitTime = sConfig.GetIntDefault("BadPoints.WaitTime", WEEK); 
    IntervalTimer badPointsTimer;
    badPointsTimer.SetInterval(badPointsDropInterval * IN_MILLISECONDS);

    ///- Catch termination signals
    HookSignals();

    ///- Handle affinity for multiple processors and process priority on Windows
    #ifdef WIN32
    {
        HANDLE hProcess = GetCurrentProcess();

        uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
        if(Aff > 0)
        {
            ULONG_PTR appAff;
            ULONG_PTR sysAff;

            if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
            {
                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors

                if(!curAff )
                {
                    sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff,appAff);
                }
                else
                {
                    if(SetProcessAffinityMask(hProcess,curAff))
                        sLog.outString("Using processors (bitmask, hex): %x", curAff);
                    else
                        sLog.outError("Can't set used processors (hex): %x", curAff);
                }
            }
            sLog.outString();
        }

        bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);

        if(Prio)
        {
            if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
                sLog.outString("realmd process priority class set to HIGH");
            else
                sLog.outError("Can't set realmd process priority class.");
            sLog.outString();
        }
    }
    #endif

    //server has started up successfully => enable async DB requests
    LoginDatabase.AllowAsyncTransactions();

    // maximum counter for next ping
    uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
    uint32 loopCounter = 0;

    uint32 last_ping_time = 0;
    uint32 now = WorldTimer::getMSTime();
    uint32 diff;
    uint32 lasttime = now;
    uint32 last_ipprops_cleanup = 0;

    ///- Wait for termination signal
    while (!stopEvent)
    {
        // dont move this outside the loop, the reactor will modify it
        ACE_Time_Value interval(0, 100000);

        if (ACE_Reactor::instance()->run_reactor_event_loop(interval) == -1)
            break;

        now = WorldTimer::getMSTime();
        diff = WorldTimer::getMSTimeDiff(lasttime, now);
        lasttime = now;

        badPointsTimer.Update(diff);

        if( (++loopCounter) == numLoops )
        {
            // FG: protect against network system overloading
            // if that happens, force realmd close (autorestarter ftw!)
            
            if(WorldTimer::getMSTimeDiff(last_ping_time, now) < 10000)
            {
                sLog.outError("NETWORK SYSTEM OVERLOAD");
                raise(SIGSEGV); // force close
                abort();
            }

            last_ping_time = now;
            loopCounter = 0;
            DETAIL_LOG("Ping MySQL to keep connection alive");
            LoginDatabase.Ping();
        }

        // FG: clear flood protect buffer periodically
        if(WorldTimer::getMSTimeDiff(last_ipprops_cleanup, now) > 30000) // flush stored IPs every 30 secs
        {
            last_ipprops_cleanup = now;
            uint32 flushed = 0, blocked = 0, stored = 0;
            CleanupIPPropmap(flushed, blocked, stored);
            sLog.outDetail("IPProp: Flushed %u total, %u of them blocked, now %u stored", flushed, blocked, stored);
        }

        // FG: handle "bad points" drop
        if(badPointsTimer.Passed())
        {
            badPointsTimer.Reset();
            if(badPointsDropAmount)
            {
                uint64 goodtime = uint64(time(NULL)) - badPointsDropWaitTime;
                LoginDatabase.Execute("UPDATE account_badpoints SET maxpts = curpts WHERE maxpts < curpts");
                LoginDatabase.PExecute("UPDATE account_badpoints SET curpts = 0 WHERE curpts <= %u AND lasttime < "UI64FMTD,
                    badPointsDropAmount, goodtime);
                LoginDatabase.PExecute("UPDATE account_badpoints SET curpts = curpts - %u WHERE curpts > %u AND lasttime < "UI64FMTD,
                    badPointsDropAmount, badPointsDropAmount, goodtime);
            }
        }


#ifdef WIN32
        if (m_ServiceStatus == 0) stopEvent = true;
        while (m_ServiceStatus == 2) Sleep(1000);
#endif
    }

    ///- Wait for the delay thread to exit
    LoginDatabase.HaltDelayThread();

    ///- Remove signal handling before leaving
    UnhookSignals();

    sLog.outString( "Halting process..." );
    return 0;
}
예제 #10
0
void SendDefaultMenu_Pnj_depart(Player* player, Creature* pCreature, uint32 uiAction)
{
	if (player->isInCombat())
    {
        player->CLOSE_GOSSIP_MENU();
        pCreature->MonsterSay(IN_COMBAT, LANG_UNIVERSAL, NULL);
	    return;
    }  

	Config SD2Config;
    if (!SD2Config.SetSource(_SCRIPTDEV2_CONFIG))
        error_log("SD2: Unable to open configuration file. Database will be unaccessible. Configuration values will use default.");
    else
        outstring_log("SD2: Using configuration file %s",_SCRIPTDEV2_CONFIG);
    if (SD2Config.GetIntDefault("ConfVersion", 0) != SD2_CONF_VERSION)
        error_log("SD2: Configuration file version doesn't match expected version. Some config variables may be wrong or missing.");
    
    switch(uiAction)
    { 
		    case 1003:
            player->CLOSE_GOSSIP_MENU();
			pCreature->MonsterWhisper(GOODBYE_PLAYER, player);
		    break;

	        case 1005:
            player->SetLevel(70);
            player->resetTalents(true);
            player->InitStatsForLevel(true);
            player->SaveToDB();

            wait(1);

			for (uint32 i = 0; i <LIMITE_COMP_ARME; i++)
            player->learnSpell(comp_arme[i],false);

			player->UpdateSkillsToMaxSkillsForLevel(); 
			player->SetTaxiCheater(true);

            wait(1);

			if(player->getClass() == 4)
			{			
			   for (uint32 i = 0; i <LIMITE_ROGUE; i++)
               player->learnSpell(rogue_sort[i],false);
			}

            if(player->getClass() == 1)
			{ 
			   for (uint32 i = 0; i <LIMITE_WARRIOR; i++)
               player->learnSpell(warrior_sort[i],false);
			}
            
            if(player->getClass() == 2)
			{ 
			   for (uint32 i = 0; i <LIMITE_PALADIN; i++)
               player->learnSpell(paladin_sort[i],false);
			}

			if(player->getClass() == 3)
			{ 
			   for (uint32 i = 0; i <LIMITE_HUNTER; i++)
               player->learnSpell(hunter_sort[i],false);
			}

            if(player->getClass() == 5)
			{ 
			   for (uint32 i = 0; i <LIMITE_PRIEST; i++)
               player->learnSpell(priest_sort[i],false);
			}

			if(player->getClass() == 7)
			{ 
			   for (uint32 i = 0; i <LIMITE_SHAMAN; i++)
               player->learnSpell(shaman_sort[i],false);
			}
            
			if(player->getClass() == 8)
			{ 
			   for (uint32 i = 0; i <LIMITE_MAGE; i++)
               player->learnSpell(mage_sort[i],false);
			}

			if(player->getClass() == 9)
			{ 
			   for (uint32 i = 0; i <LIMITE_WARLOCK; i++)
               player->learnSpell(warlock_sort[i],false);
			}

            if(player->getClass() == 11)
			{ 
			   for (uint32 i = 0; i <LIMITE_DRUID; i++)
               player->learnSpell(druid_sort[i],false);
			}

			wait(1);

			if (player->GetTeam() == ALLIANCE )
			{
			   player->TeleportTo(0, -8960.14f, 516.266f, 96.3568f, 0.0f);
			}
			else
			{
			   player->TeleportTo(1, 1552.5f, -4420.66f, 8.94802f, 0.0f);
			}
			player->RemoveAurasDueToSpell(38505);
            CharacterDatabase.PExecute(REQUETE_CHOICE_2, player->GetGUIDLow());
			player->CLOSE_GOSSIP_MENU();
			break;

			case 1001:
			player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, CONFIRME_CHOICE  ,GOSSIP_SENDER_MAIN, 1005);
	        player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, REWARD_PAGE            ,GOSSIP_SENDER_MAIN, 1070);
            player->SEND_GOSSIP_MENU(4, pCreature->GetObjectGuid());
			break;
 
			case 1000:
            player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, CONFIRME_CHOICE  ,GOSSIP_SENDER_MAIN, 1004);
			player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, REWARD_PAGE            ,GOSSIP_SENDER_MAIN, 1070);
            player->SEND_GOSSIP_MENU(3, pCreature->GetObjectGuid());
            break;
            
			case 1004:
			player->learnSpell((SD2Config.GetFloatDefault("pnj_Bienvenue.SpellMount",0)), true); // mount 6653
			player->learnSpell((SD2Config.GetFloatDefault("pnj_Bienvenue.SpellMiniPet",0)), true); // mini-pet 51716
			player->learnSpell(33388, false); // apprenti mount 
			player->RemoveAurasDueToSpell(38505);
			CharacterDatabase.PExecute(REQUETE_CHOICE_1, player->GetGUIDLow());			
			player->DestroyItemCount(6948, 1, true);
     		player->CLOSE_GOSSIP_MENU();
			break;

			case 1070:
			player->ADD_GOSSIP_ITEM( 0, START_ADVENTURE  ,GOSSIP_SENDER_MAIN, 1000);
	        player->ADD_GOSSIP_ITEM( 0, START_LEVEL_UP   ,GOSSIP_SENDER_MAIN, 1001);
			player->ADD_GOSSIP_ITEM( 0, GOODBYE          ,GOSSIP_SENDER_MAIN, 1003);
            player->SEND_GOSSIP_MENU(5, pCreature->GetObjectGuid());
			break;
	}
}
예제 #11
0
void AcctContainer::LoadAll()
{
    // Load accounts
    QueryResult* result = dbRealmServer.PQuery("SELECT id,username,sha_pass_hash,gmlevel,last_ip,locked,expansion,locale FROM account ORDER BY id");
    uint32 count = 0;

    if(!result)
        return;

    //temp set for banned accid to avoid many sql querys
    std::set<uint32> BannedAcc;

    QueryResult* banresult = dbRealmServer.PQuery("SELECT id FROM account_banned WHERE active = 1");
    if(banresult)
    {
        do
        {
            Field *fields = banresult->Fetch();

            //check exist if exist skip;
            if (BannedAcc.find(fields[0].GetUInt32()) != BannedAcc.end())
                continue;
            BannedAcc.insert(fields[0].GetUInt32());

        } while (banresult->NextRow());

        delete banresult;
    }

    sLog.outString("Loading Accounts In Progress...");
    barGoLink bar( result->GetRowCount());

    // Periodic Database Update ...
    dbRealmServer.PExecute("UPDATE account_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate");
    dbRealmServer.PExecute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate");

    Account *acc;
    do
    {
        Field *fields = result->Fetch();

        bar.step();

        // Create the account by id
        acc = new Account();
        bool banned = false;
        if (BannedAcc.find(fields[0].GetUInt32()) != BannedAcc.end())
            banned = true;

        FillAccount(acc, fields[0].GetUInt32(), fields[3].GetUInt8(), fields[7].GetUInt8(), fields[6].GetUInt8(), banned, fields[5].GetUInt8(), fields[2].GetCppString(), fields[4].GetCppString());
        m_accounts[fields[1].GetCppString()] = acc;
        count++;

    } while (result->NextRow());

    sLog.outString();
    sLog.outString(">> Loaded %u accounts", count);

    //clean up set
    BannedAcc.clear();

    delete result;

    // Now load ip bans

    result = dbRealmServer.PQuery("SELECT ip FROM ip_banned");

    // If there is no ban don't load
    if(result)
    {
        sLog.outString();
        count = 0;

        sLog.outString("Loading Ban Ip In Progress...");

        barGoLink bar( result->GetRowCount());

        do
        {
            Field *fields = result->Fetch();
            bar.step();

            m_banips.insert(fields[0].GetCppString());
            count++;

        }while (result->NextRow());

        delete result;
        sLog.outString();

        sLog.outString(">> Loaded %u ip banned", count);

        count = 0;
    }

    // Now load Realm Characters

    result = dbRealmServer.PQuery("SELECT acctid, realmid, numchars FROM realmcharacters ORDER BY acctid");

    // If there is no ban don't load
    if(result)
    {
        sLog.outString();

        count = 0;

        sLog.outString("Loading Realm Characters In Progress...");

        barGoLink bar( result->GetRowCount());

        do
        {
            Field *fields = result->Fetch();

            bar.step();

            m_realmcharacters[MAKE_PAIR64(fields[0].GetUInt32(),fields[1].GetUInt32())] = fields[2].GetUInt8();
            count++;

        }while (result->NextRow());

        delete result;

        sLog.outString();

        sLog.outString(">> Loaded %u realm characters", count);
    }

}