Show
Ignore:
Timestamp:
11/19/08 13:31:47 (17 years ago)
Author:
yumileroy
Message:

[svn] * Fixed compile from r78
* Fixed: not apply healling bonus to spell 40972 heal amount. - Source Mangos
* Item 30627 hidden cooldown - Source Mangos
* Fixed Trinityrealm autopatching system - Source Arrai
* Add support for autoconf 2.6.2 and newer - Source Derex
Some decent sized changes, please test before deploying - KP

Original author: KingPin?
Date: 2008-10-19 21:08:34-05:00

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/trinityrealm/AuthSocket.cpp

    r44 r74  
    138138    uint8 cmd;                                              // XFER_INITIATE 
    139139    uint8 fileNameLen;                                      // strlen(fileName); 
    140     uint8 fileName[1];                                      // fileName[fileNameLen] 
     140    uint8 fileName[5];                                      // fileName[fileNameLen] 
    141141    uint64 file_size;                                       // file size (bytes) 
    142142    uint8 md5[MD5_DIGEST_LENGTH];                           // MD5 
     
    218218    g.SetDword(7); 
    219219    _authed = false; 
    220     pPatch=NULL; 
     220    pPatch = NULL; 
    221221 
    222222    _accountSecurityLevel = SEC_PLAYER; 
     
    226226AuthSocket::~AuthSocket() 
    227227{ 
     228    ZThread::Guard<ZThread::Mutex> g(patcherLock); 
    228229    if(pPatch) 
    229230        fclose(pPatch); 
     
    361362 
    362363    _login = (const char*)ch->I; 
     364    _build = ch->build; 
    363365 
    364366    ///- Normalize account name 
     
    370372    dbRealmServer.escape_string(_safelogin); 
    371373 
     374    pkt << (uint8) AUTH_LOGON_CHALLENGE; 
     375    pkt << (uint8) 0x00; 
     376 
     377    ///- Verify that this IP is not in the ip_banned table 
     378    // No SQL injection possible (paste the IP address as passed by the socket) 
     379    dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); 
     380 
     381    std::string address = GetRemoteAddress(); 
     382    dbRealmServer.escape_string(address); 
     383    QueryResult *result = dbRealmServer.PQuery(  "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); 
     384    if(result) 
     385    { 
     386        pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; 
     387        sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); 
     388        delete result; 
     389    } 
     390    else 
     391    { 
     392        ///- Get the account details from the account table 
     393        // No SQL injection (escaped user name) 
     394 
     395        result = dbRealmServer.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ()); 
     396        if( result ) 
     397        { 
     398            ///- If the IP is 'locked', check that the player comes indeed from the correct IP address 
     399            bool locked = false; 
     400            if((*result)[2].GetUInt8() == 1)            // if ip is locked 
     401            { 
     402                DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); 
     403                DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); 
     404                if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) 
     405                { 
     406                    DEBUG_LOG("[AuthChallenge] Account IP differs"); 
     407                    pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; 
     408                    locked=true; 
     409                } 
     410                else 
     411                { 
     412                    DEBUG_LOG("[AuthChallenge] Account IP matches"); 
     413                } 
     414            } 
     415            else 
     416            { 
     417                DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); 
     418            } 
     419 
     420            if (!locked) 
     421            { 
     422                //set expired bans to inactive 
     423                dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); 
     424                ///- If the account is banned, reject the logon attempt 
     425                QueryResult *banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); 
     426                if(banresult) 
     427                { 
     428                    if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) 
     429                    { 
     430                        pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; 
     431                        sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); 
     432                    } 
     433                    else 
     434                    { 
     435                        pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; 
     436                        sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); 
     437                    } 
     438 
     439                    delete banresult; 
     440                } 
     441                else 
     442                { 
     443                    ///- Get the password from the account table, upper it, and make the SRP6 calculation 
     444                    std::string rI = (*result)[0].GetCppString(); 
     445                    _SetVSFields(rI); 
     446 
     447                    b.SetRand(19 * 8); 
     448                    BigNumber gmod=g.ModExp(b, N); 
     449                    B = ((v * 3) + gmod) % N; 
     450 
     451                    ASSERT(gmod.GetNumBytes() <= 32); 
     452 
     453                    BigNumber unk3; 
     454                    unk3.SetRand(16*8); 
     455 
     456                    ///- Fill the response packet with the result 
     457                    pkt << (uint8)REALM_AUTH_SUCCESS; 
     458 
     459                    // B may be calculated < 32B so we force minnimal length to 32B 
     460                    pkt.append(B.AsByteArray(32), 32);   // 32 bytes 
     461                    pkt << (uint8)1; 
     462                    pkt.append(g.AsByteArray(), 1); 
     463                    pkt << (uint8)32; 
     464                    pkt.append(N.AsByteArray(), 32); 
     465                    pkt.append(s.AsByteArray(), s.GetNumBytes());   // 32 bytes 
     466                    pkt.append(unk3.AsByteArray(), 16); 
     467                    pkt << (uint8)0;                    // Added in 1.12.x client branch 
     468 
     469                    uint8 secLevel = (*result)[4].GetUInt8(); 
     470                    _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; 
     471 
     472                    _localizationName.resize(4); 
     473                    for(int i = 0; i <4; ++i) 
     474                        _localizationName[i] = ch->country[4-i-1]; 
     475 
     476                    sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], GetLocaleByName(_localizationName)); 
     477                } 
     478            } 
     479            delete result; 
     480        } 
     481        else                                            //no account 
     482        { 
     483            pkt<< (uint8) REALM_AUTH_NO_MATCH; 
     484        } 
     485    } 
     486    SendBuf((char const*)pkt.contents(), pkt.size()); 
     487    return true; 
     488} 
     489 
     490/// Logon Proof command handler 
     491bool AuthSocket::_HandleLogonProof() 
     492{ 
     493    DEBUG_LOG("Entering _HandleLogonProof"); 
     494    ///- Read the packet 
     495    if (ibuf.GetLength() < sizeof(sAuthLogonProof_C)) 
     496        return false; 
     497    sAuthLogonProof_C lp; 
     498    ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); 
     499 
    372500    ///- Check if the client has one of the expected version numbers 
    373501    bool valid_version=false; 
    374502    int accepted_versions[]=EXPECTED_TRINITY_CLIENT_BUILD; 
    375503    for(int i=0;accepted_versions[i];i++) 
    376         if(ch->build==accepted_versions[i]) 
    377     { 
    378         valid_version=true; 
    379         break; 
    380     } 
    381  
    382     /// <ul><li> if this is a valid version 
    383     if(valid_version) 
    384     { 
    385         pkt << (uint8) AUTH_LOGON_CHALLENGE; 
    386         pkt << (uint8) 0x00; 
    387  
    388         ///- Verify that this IP is not in the ip_banned table 
    389         // No SQL injection possible (paste the IP address as passed by the socket) 
    390         dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); 
    391  
    392         std::string address = GetRemoteAddress(); 
    393         dbRealmServer.escape_string(address); 
    394         QueryResult *result = dbRealmServer.PQuery(  "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); 
    395         if(result) 
    396         { 
    397             pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; 
    398             sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); 
    399             delete result; 
    400         } 
    401         else 
    402         { 
    403             ///- Get the account details from the account table 
    404             // No SQL injection (escaped user name) 
    405  
    406             result = dbRealmServer.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ()); 
    407             if( result ) 
    408             { 
    409                 ///- If the IP is 'locked', check that the player comes indeed from the correct IP address 
    410                 bool locked = false; 
    411                 if((*result)[2].GetUInt8() == 1)            // if ip is locked 
    412                 { 
    413                     DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); 
    414                     DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); 
    415                     if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) 
    416                     { 
    417                         DEBUG_LOG("[AuthChallenge] Account IP differs"); 
    418                         pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; 
    419                         locked=true; 
    420                     } 
    421                     else 
    422                     { 
    423                         DEBUG_LOG("[AuthChallenge] Account IP matches"); 
    424                     } 
    425                 } 
    426                 else 
    427                 { 
    428                     DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); 
    429                 } 
    430  
    431                 if (!locked) 
    432                 { 
    433                     //set expired bans to inactive 
    434                     dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); 
    435                     ///- If the account is banned, reject the logon attempt 
    436                     QueryResult *banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); 
    437                     if(banresult) 
    438                     { 
    439                         if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) 
    440                         { 
    441                             pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; 
    442                             sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); 
    443                         } 
    444                         else 
    445                         { 
    446                             pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; 
    447                             sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); 
    448                         } 
    449  
    450                         delete banresult; 
    451                     } 
    452                     else 
    453                     { 
    454                         ///- Get the password from the account table, upper it, and make the SRP6 calculation 
    455                         std::string rI = (*result)[0].GetCppString(); 
    456                         _SetVSFields(rI); 
    457  
    458                         b.SetRand(19 * 8); 
    459                         BigNumber gmod=g.ModExp(b, N); 
    460                         B = ((v * 3) + gmod) % N; 
    461  
    462                         ASSERT(gmod.GetNumBytes() <= 32); 
    463  
    464                         BigNumber unk3; 
    465                         unk3.SetRand(16*8); 
    466  
    467                         ///- Fill the response packet with the result 
    468                         pkt << (uint8)REALM_AUTH_SUCCESS; 
    469  
    470                         // B may be calculated < 32B so we force minnimal length to 32B 
    471                         pkt.append(B.AsByteArray(32), 32);   // 32 bytes 
    472                         pkt << (uint8)1; 
    473                         pkt.append(g.AsByteArray(), 1); 
    474                         pkt << (uint8)32; 
    475                         pkt.append(N.AsByteArray(), 32); 
    476                         pkt.append(s.AsByteArray(), s.GetNumBytes());   // 32 bytes 
    477                         pkt.append(unk3.AsByteArray(), 16); 
    478                         pkt << (uint8)0;                    // Added in 1.12.x client branch 
    479  
    480                         uint8 secLevel = (*result)[4].GetUInt8(); 
    481                         _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; 
    482  
    483                         std::string localeName; 
    484                         localeName.resize(4); 
    485                         for(int i = 0; i <4; ++i) 
    486                             localeName[i] = ch->country[4-i-1]; 
    487  
    488                         _localization = GetLocaleByName(localeName); 
    489  
    490                         sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], _localization); 
    491                     } 
    492                 } 
    493                 delete result; 
    494             } 
    495             else                                            //no account 
    496             { 
    497                 pkt<< (uint8) REALM_AUTH_NO_MATCH; 
    498             } 
    499         } 
    500     }                                                       //valid version 
    501     else 
    502         ///<li> else 
     504    { 
     505        if(_build==accepted_versions[i]) 
     506        { 
     507            valid_version=true; 
     508            break; 
     509        } 
     510    } 
     511 
     512    /// <ul><li> If the client has no valid version 
     513    if(!valid_version) 
    503514    { 
    504515        ///- Check if we have the apropriate patch on the disk 
    505         char tmp[64]; 
     516 
     517        // 24 = len("./patches/65535enGB.mpq")+1 
     518        char tmp[24]; 
    506519        // No buffer overflow (fixed length of arguments) 
    507         sprintf(tmp,"./patches/%d%c%c%c%c.mpq",ch->build,ch->country[3], 
    508             ch->country[2],ch->country[1],ch->country[0]); 
     520        sprintf(tmp,"./patches/%d%s.mpq",_build, _localizationName.c_str()); 
    509521        // This will be closed at the destruction of the AuthSocket (client deconnection) 
    510522        FILE *pFile=fopen(tmp,"rb"); 
     523 
    511524        if(!pFile) 
    512525        { 
     526            ByteBuffer pkt; 
    513527            pkt << (uint8) AUTH_LOGON_CHALLENGE; 
    514528            pkt << (uint8) 0x00; 
    515529            pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; 
    516             DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", ch->build); 
     530            DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build); 
    517531            DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp); 
    518         }else 
    519         {                                                   //have patch 
     532            SendBuf((char const*)pkt.contents(), pkt.size()); 
     533            return true; 
     534        } 
     535        else                                                // have patch 
     536        { 
    520537            pPatch=pFile; 
    521538            XFER_INIT xferh; 
     
    547564    } 
    548565    /// </ul> 
    549     SendBuf((char const*)pkt.contents(), pkt.size()); 
    550     return true; 
    551 } 
    552  
    553 /// Logon Proof command handler 
    554 bool AuthSocket::_HandleLogonProof() 
    555 { 
    556     DEBUG_LOG("Entering _HandleLogonProof"); 
    557     ///- Read the packet 
    558     if (ibuf.GetLength() < sizeof(sAuthLogonProof_C)) 
    559         return false; 
    560  
    561     sAuthLogonProof_C lp; 
    562     ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); 
    563566 
    564567    ///- Continue the SRP6 calculation based on data received from the client 
     
    639642        // No SQL injection (escaped user name) and IP address as received by socket 
    640643        const char* K_hex = K.AsHexStr(); 
    641         dbRealmServer.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(),  _localization, _safelogin.c_str() ); 
     644        dbRealmServer.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() ); 
    642645        OPENSSL_free((void*)K_hex); 
    643646 
     
    685688                    { 
    686689                        uint32 acc_id = fields[0].GetUInt32(); 
    687                         dbRealmServer.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realm','Failed login autoban',1)", 
     690                        dbRealmServer.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", 
    688691                            acc_id, WrongPassBanTime); 
    689692                        sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", 
     
    694697                        std::string current_ip = GetRemoteAddress(); 
    695698                        dbRealmServer.escape_string(current_ip); 
    696                         dbRealmServer.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realm','Failed login autoban')", 
     699                        dbRealmServer.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", 
    697700                            current_ip.c_str(), WrongPassBanTime); 
    698701                        sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", 
     
    851854void PatcherRunnable::run() 
    852855{ 
     856    ZThread::Guard<ZThread::Mutex> g(mySocket->patcherLock); 
    853857    XFER_DATA_STRUCT xfdata; 
    854858    xfdata.opcode = XFER_DATA; 
     
    869873/// Preload MD5 hashes of existing patch files on server 
    870874#ifndef _WIN32 
    871 #include <sys/dir.h> 
     875#include <dirent.h> 
    872876#include <errno.h> 
    873877void Patcher::LoadPatchesInfo() 
     
    912916        return;                                             //no patches were found 
    913917 
    914     LoadPatchMD5(fil.cFileName); 
    915  
    916     while(FindNextFile(hFil,&fil)) 
     918    do 
     919    { 
    917920        LoadPatchMD5(fil.cFileName); 
     921    } 
     922    while(FindNextFile(hFil,&fil)); 
    918923} 
    919924#endif