long SmtMapServerDevice111::WMTSGetCapabilities(void) { if (NULL == m_pJobData->pMapService) return SMT_ERR_FAILURE; if (NULL == m_pJobData->pMapService) return SMT_ERR_FAILURE; SmtLogManager * pLogMgr = SmtLogManager::GetSingletonPtr(); SmtLog *pLog = pLogMgr->GetLog(MAPSEVER_DEVICE_LOG_NAME); if (NULL == pLog) return SMT_ERR_FAILURE; char szTextBuf[MSVR_BUF_LENGTH_1K]; memset(szTextBuf,0,MSVR_BUF_LENGTH_1K); if (SMT_ERR_NONE == SendBuf(szTextBuf,MSVR_BUF_LENGTH_1K,MSVR_RSP_TEXT)) { return SMT_ERR_NONE; } return SMT_ERR_FAILURE; }
/// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < 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); ibuf.Read((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()) || (ibuf.GetLength() < 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]; // 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); ///- Read the remaining of the packet ibuf.Read((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); ByteBuffer pkt; _login = (const char*)ch->I; _build = ch->build; ///- 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); pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); std::string address = GetRemoteAddress(); loginDatabase.escape_string(address); QueryResult *result = loginDatabase.PQuery("SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); if(result) { pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); delete result; } else { ///- Get the account details from the account table // No SQL injection (escaped user name) result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '******'",_safelogin.c_str ()); if( result ) { ///- If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if((*result)[2].GetUInt8() == 1) // if ip is locked { DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) { DEBUG_LOG("[AuthChallenge] Account IP differs"); pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; locked=true; } else { DEBUG_LOG("[AuthChallenge] Account IP matches"); } } else { DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); } if (!locked) { //set expired bans to inactive loginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); ///- 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", (*result)[1].GetUInt32()); if(banresult) { if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) { pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); } else { pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); } delete banresult; } else { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = (*result)[0].GetCppString(); ///- Don't calculate (v, s) if there are already some in the database std::string databaseV = (*result)[5].GetCppString(); std::string databaseS = (*result)[6].GetCppString(); sLog.outDebug("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()); } b.SetRand(19 * 8); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16 * 8); ///- Fill the response packet with the result pkt << uint8(REALM_AUTH_SUCCESS); // 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); } uint8 secLevel = (*result)[4].GetUInt8(); _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]; 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)); // user authenticated => turn off autoreg, thus account creating _autoreg = false; } } delete result; } else if(_autoreg) // no account { // check username if(_safelogin.find_first_of(notAllowedChars)!=_safelogin.npos || _safelogin.length()<4) _autoreg = false; // check IP else if(uint32 amountip = sConfig.GetIntDefault("AmountIP", 0)) { QueryResult *result2 = loginDatabase.PQuery("SELECT COUNT(last_ip) FROM account WHERE last_ip = '%s'", GetRemoteAddress().c_str()); if (result2 && (*result2)[0].GetUInt8() >= amountip) { _autoreg = false; delete result2; } } // still all ok if(_autoreg) { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::transform(_safelogin.begin(), _safelogin.end(), _safelogin.begin(), std::towupper); Sha1Hash sha; std::string sI = _safelogin + ":" + _safelogin; sha.UpdateData(sI); sha.Finalize(); BigNumber bn; bn.SetBinary(sha.GetDigest(), sha.GetLength()); uint8 *val = bn.AsByteArray(); std::reverse(val, val+bn.GetNumBytes()); bn.SetBinary(val, bn.GetNumBytes()); const char* rI = bn.AsHexStr(); _SetVSFields(rI); OPENSSL_free((void*)rI); b.SetRand(19 * 8); BigNumber gmod=g.ModExp(b, N); B = ((v * 3) + gmod) % N; if (B.GetNumBytes() < 32) sLog.outDetail("Interesting, calculation of B in realmd is < 32."); ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16*8); ///- Fill the response packet with the result pkt << (uint8)REALM_AUTH_SUCCESS; pkt.append(B.AsByteArray(), 32); pkt << (uint8)1; pkt.append(g.AsByteArray(), 1); pkt << (uint8)32; pkt.append(N.AsByteArray(), 32); pkt.append(s.AsByteArray(), s.GetNumBytes()); pkt.append(unk3.AsByteArray(), 16); pkt << (uint8)0; // Added in 1.12.x client branch } else // username and/or IP is bad pkt << (uint8) REALM_AUTH_NO_MATCH; } else { // autoreg off in config, account is wrong pkt << (uint8) REALM_AUTH_NO_MATCH; } } SendBuf((char const*)pkt.contents(), pkt.size()); return true; }
/// 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; }
/// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < 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); ibuf.Read((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()) || (ibuf.GetLength() < 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]; // 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); ///- Read the remaining of the packet ibuf.Read((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); ByteBuffer pkt; _login = (const char*)ch->I; ///- 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; dbRealmServer.escape_string(_safelogin); ///- Check if the client has one of the expected version numbers bool valid_version=false; int accepted_versions[]=EXPECTED_MANGOS_CLIENT_BUILD; for(int i=0;accepted_versions[i];i++) if(ch->build==accepted_versions[i]) { valid_version=true; break; } /// <ul><li> if this is a valid version if(valid_version) { pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); std::string address = GetRemoteAddress(); dbRealmServer.escape_string(address); QueryResult *result = dbRealmServer.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); if(result) { pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); delete result; } else { ///- Get the account details from the account table // No SQL injection (escaped user name) result = dbRealmServer.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '******'",_safelogin.c_str ()); if( result ) { ///- If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if((*result)[2].GetUInt8() == 1) // if ip is locked { DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) { DEBUG_LOG("[AuthChallenge] Account IP differs"); pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; locked=true; } else { DEBUG_LOG("[AuthChallenge] Account IP matches"); } } else { DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); } if (!locked) { //set expired bans to inactive dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); ///- If the account is banned, reject the logon attempt QueryResult *banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); if(banresult) { if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) { pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); } else { pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); } delete banresult; } else { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = (*result)[0].GetCppString(); _SetVSFields(rI); b.SetRand(19 * 8); BigNumber gmod=g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16*8); ///- Fill the response packet with the result pkt << (uint8)REALM_AUTH_SUCCESS; // B may be calculated < 32B so we force minnimal 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); pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes pkt.append(unk3.AsByteArray(), 16); pkt << (uint8)0; // Added in 1.12.x client branch uint8 secLevel = (*result)[4].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; std::string localeName; localeName.resize(4); for(int i = 0; i <4; ++i) localeName[i] = ch->country[4-i-1]; _localization = GetLocaleByName(localeName); 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); } } delete result; } else //no account { pkt<< (uint8) REALM_AUTH_NO_MATCH; } } } //valid version else ///<li> else { ///- Check if we have the apropriate patch on the disk char tmp[64]; // No buffer overflow (fixed length of arguments) sprintf(tmp,"./patches/%d%c%c%c%c.mpq",ch->build,ch->country[3], ch->country[2],ch->country[1],ch->country[0]); // This will be closed at the destruction of the AuthSocket (client deconnection) FILE *pFile=fopen(tmp,"rb"); if(!pFile) { pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", ch->build); DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp); }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,REALM_AUTH_UPDATE_CLIENT}; 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> SendBuf((char const*)pkt.contents(), pkt.size()); return true; }
/// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < 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); ibuf.Read((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()) || (ibuf.GetLength() < 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]; // 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); ///- Read the remaining of the packet ibuf.Read((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); ByteBuffer pkt; _login = (const char*)ch->I; _build = ch->build; ///- 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; dbRealmServer.escape_string(_safelogin); pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); std::string address = GetRemoteAddress(); dbRealmServer.escape_string(address); QueryResult *result = dbRealmServer.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); if(result) { pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); delete result; } else { ///- Get the account details from the account table // No SQL injection (escaped user name) result = dbRealmServer.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '******'",_safelogin.c_str ()); if( result ) { ///- If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if((*result)[2].GetUInt8() == 1) // if ip is locked { DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) { DEBUG_LOG("[AuthChallenge] Account IP differs"); pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; locked=true; } else { DEBUG_LOG("[AuthChallenge] Account IP matches"); } } else { DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); } if (!locked) { //set expired bans to inactive dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); ///- If the account is banned, reject the logon attempt QueryResult *banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); if(banresult) { if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) { pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); } else { pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); } delete banresult; } else { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = (*result)[0].GetCppString(); _SetVSFields(rI); b.SetRand(19 * 8); BigNumber gmod=g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16*8); ///- Fill the response packet with the result pkt << (uint8)REALM_AUTH_SUCCESS; // B may be calculated < 32B so we force minnimal 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); pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes pkt.append(unk3.AsByteArray(), 16); pkt << (uint8)0; // Added in 1.12.x client branch uint8 secLevel = (*result)[4].GetUInt8(); _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]; 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)); } } delete result; } else //no account { pkt<< (uint8) REALM_AUTH_NO_MATCH; } } SendBuf((char const*)pkt.contents(), pkt.size()); return true; }
void ControlSocket::SendTelnetText(std::string s) { s += "\n\r"; SendBuf(s.c_str(),s.size()); }
/// %Realm List command handler bool AuthSocket::_HandleRealmList() { DEBUG_LOG("Entering _HandleRealmList"); if (ibuf.GetLength() < 5) return false; ibuf.Remove(5); ///- Get the user id (else close the connection) // No SQL injection (escaped user name) QueryResult *result = dbRealmServer.PQuery("SELECT `id`,`I` FROM `account` WHERE `username` = '%s'",_safelogin.c_str()); if(!result) { sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); this->Close(); return false; } uint32 id = (*result)[0].GetUInt32(); std::string rI = (*result)[1].GetCppString(); delete result; ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) uint8 AmountOfCharacters = 0; ByteBuffer pkt; pkt << (uint32) 0; pkt << (uint16) m_realmList.size(); RealmList::RealmMap::const_iterator i; for( i = m_realmList.begin(); i != m_realmList.end(); i++ ) { pkt << i->second->icon; // realm type pkt << (uint8) 0; // if 1, then realm locked pkt << i->second->color; // if 2, then realm is offline pkt << i->first; pkt << i->second->address; /// \todo Fix realm population pkt << (float) 0.0; //this is population 0.5 = low 1.0 = medium 2.0 high (float)(maxplayers / players)*2 // No SQL injection. id of realm is controlled by the database. result = dbRealmServer.PQuery( "SELECT `numchars` FROM `realmcharacters` WHERE `realmid` = '%d' AND `acctid`='%u'",i->second->m_ID,id); if( result ) { Field *fields = result->Fetch(); AmountOfCharacters = fields[0].GetUInt8(); delete result; } pkt << AmountOfCharacters; pkt << i->second->timezone; pkt << (uint8) 0x2C; // unk, may be realm number/id? } pkt << (uint8) 0x10; pkt << (uint8) 0x00; ByteBuffer hdr; hdr << (uint8) REALM_LIST; hdr << (uint16)pkt.size(); hdr.append(pkt); SendBuf((char *)hdr.contents(), hdr.size()); // Set check field before possable relogin to realm _SetVSFields(rI); return true; }
/// 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; }
// -------------------------------------------------------------------------------------- void Ajp13Socket::Respond(const HttpResponse& res) { char msg[8192]; msg[0] = 'A'; msg[1] = 'B'; m_res = res; // reply codes // 0x3 Send Body Chunk // 0x4 Send Headers // 0x5 End Response // 0x6 Get Body Chunk // 0x9 CPong Reply // check content length if (!m_res.ContentLength() && m_res.GetFile().size()) { // m_res.SetContentLength( m_res.GetFile().size() ); } // Send Headers { int ptr = 4; put_byte(msg, ptr, 0x04); // send headers put_integer(msg, ptr, m_res.HttpStatusCode() ); put_string(msg, ptr, m_res.HttpStatusMsg() ); put_integer(msg, ptr, (short)m_res.Headers().size() ); for (Utility::ncmap<std::string>::const_iterator it = m_res.Headers().begin(); it != m_res.Headers().end(); ++it) { Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( it -> first ); if (it2 != Init.ResponseHeader.end()) { put_integer(msg, ptr, it2 -> second); } else { put_string(msg, ptr, it -> first); } put_string(msg, ptr, it -> second); } std::list<std::string> vec = m_res.CookieNames(); { for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++) { Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( "set-cookie" ); if (it2 != Init.ResponseHeader.end()) { put_integer(msg, ptr, it2 -> second); } else { put_string(msg, ptr, "set-cookie"); } put_string(msg, ptr, m_res.Cookie(*it) ); } } short len = htons( ptr - 4 ); memcpy( msg + 2, &len, 2 ); SendBuf( msg, ptr ); } // Send Body Chunk OnTransferLimit(); }
/// 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(); BigNumber t4; t4.SetBinary(sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&t3, &t4, &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 and last login time in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket dbRealmServer.PExecute("UPDATE `account` SET `sessionkey` = '%s', `last_ip` = '%s', `last_login` = NOW(), `locale` = '%u' WHERE `username` = '%s'",K.AsHexStr(), GetRemoteAddress().c_str(), _localization, _safelogin.c_str() ); ///- 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.unk2 = 0; proof.unk3 = 0; 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)); } return true; }
int an_packet_transmit(an_packet_t *an_packet) { an_packet_encode(an_packet); return SendBuf(an_packet_pointer(an_packet), an_packet_size(an_packet)); }
void UdpSocket::Send(const std::string& str, int flags) { SendBuf(str.c_str(), (int)str.size(), flags); }
void OnRawData(const char *buf,size_t len) { if (g_b_nobuf) { SendBuf(buf, len); } }
void* handle_tcp_client(void * arg) { printf("handling tcp client\n"); char *buffer = NULL; Header hdr; int received = -1; long sock = reinterpret_cast<long> (arg); /* Receive message */ do { if ((received = recv(sock, &hdr, sizeof(Header), 0)) < 0) { printf("handle_tcp_client: no header"); break; } printf("received = %d\n", received); if (received == 0) break; while (received < sizeof(Header)) { int next_rec; if ((next_rec = recv(sock, (char*) &hdr + received, sizeof(Header) - received, 0)) <= 0) { break; } else { usleep(100); } received += next_rec; printf("received part = %d\n", next_rec); } if (received < sizeof(Header)) break; for (int i=0; i < received; i++) printf("%02x ", (reinterpret_cast<char*> (&hdr))[i]); printf("\n"); hdr.cookie = ntohs(hdr.cookie); hdr.id = ntohs(hdr.id); hdr.cmd = ntohs(hdr.cmd); hdr.len = ntohs(hdr.len); hdr.seq = ntohl(hdr.seq); printf("cookie=%x id=%d cmd=%d len=%d seq=%ld\n", hdr.cookie, hdr.id, hdr.cmd, (hdr.len), (hdr.seq)) ; if ((hdr.id == 0 && hdr.cookie == OK_COOKIE) || (hdr.id < MAX_ID && hdr.cookie == session[hdr.id].cookie)) { printf("OK\n"); if (hdr.len > 0) { buffer = (char*) malloc(hdr.len); if (buffer == NULL) { printf("out of memory\n"); break; } for (received = 0; received < hdr.len; ) { int next_rec = recv(sock, buffer + received, hdr.len - received, 0); if (next_rec < 0) { printf("couldn't get all buffer\n"); break; } received += next_rec; } if (received < hdr.len) break; printf("got payload\n"); } if ((Cmds) hdr.cmd == E_STORE) { printf("adding len=%d\n", hdr.len); if (AddBuf(hdr.id, hdr.seq, buffer, hdr.len)) { free(buffer); } buffer = NULL; } else if ((Cmds) hdr.cmd == E_GET) { printf("E_GET\n"); if (buffer) { free(buffer); buffer = NULL; } if (SendBuf(hdr.id, hdr.seq, sock)) break; } else if ((Cmds) hdr.cmd == E_STATUS) { if (hdr.len != sizeof(BUF_Status)) { printf("hdr.len != sizeof(BUF_Status)\n"); } else { printf("E_STATUS\n"); BUF_Status* status = (BUF_Status*) buffer; session[hdr.id].alert = ntohs(status->alert); session[hdr.id].last_access = time(NULL); } if (buffer != NULL) { free(buffer); buffer = NULL; } } else if ((Cmds) hdr.cmd == E_CHECK) { Response r; BUF_R_Check c; printf("E_CHECK\n"); time_t now = time(NULL); r.response = htons(E_R_CHECK); r.len = htons(sizeof(BUF_R_Check)); c.alert = htons(session[hdr.id].alert); c.last_access_sec = htons((int) difftime(now, session[hdr.id].last_access)); if (send(sock, &r, sizeof(r), 0) != sizeof(r)) break; if (send(sock, &c, sizeof(c), 0) != sizeof(c)) break; } else if ((Cmds) hdr.cmd == E_CREATE) { Response r; BUF_R_Create_Login c; time_t now = time(NULL); printf("E_CREATE\n"); if (hdr.len != sizeof(BUF_Create_Login)) { printf("hdr.len != sizeof(BUF_Create_Login)\n"); } else { BUF_Create_Login* status = (BUF_Create_Login*) buffer; char username[MAX_NAME_LEN]; char password[MAX_NAME_LEN]; strncpy(username, status->username, MAX_NAME_LEN); strncpy(password, status->password, MAX_NAME_LEN); username[MAX_NAME_LEN-1] = 0; password[MAX_NAME_LEN-1] = 0; bool done = false; for (int i = 0; i < MAX_ID; i++) { if (users[i].username[0] == 0 || !strcmp(users[i].username, username) || difftime(now, users[i].last_access) > 60*60*24) { strcpy(users[i].password, password); users[i].last_access = time(NULL); pthread_mutex_lock(&g_mutex); while (session[next_id].last_access != 0 && difftime(now, session[next_id].last_access) < 60) { next_id = (next_id + 1) & MAX_ID; usleep(1000); now = time(NULL); } int id = next_id; next_id = (next_id + 1) % MAX_ID; pthread_mutex_unlock(&g_mutex); pthread_mutex_lock(&session[next_id].mutex); for (int i = 0; i < MAX_BUFS; i++) if (session[id].buf[i] != NULL) { free(session[id].buf); session[id].buf[i] = NULL; } session[id].alert = 0; session[id].head = 0; session[id].tail = 0; session[id].last_access = time(NULL); session[id].cookie = (unsigned short) time(NULL); pthread_mutex_unlock(&session[id].mutex); Response r; BUF_R_Create_Login c; r.response = htons(E_R_CREATE); r.len = htons(sizeof(BUF_R_Create_Login)); c.id = htons(id); c.cookie = htons(session[id].cookie); done = true; if (send(sock, &r, sizeof(r), 0) != sizeof(r)) break; if (send(sock, &c, sizeof(c), 0) != sizeof(c)) break; break; } } if (!done) { Response r; BUF_R_Create_Login c; r.response = htons(E_R_CREATE); r.len = htons(sizeof(BUF_R_Create_Login)); c.id = htons(0xFFFF); c.cookie = htons(0xFFFF); if (send(sock, &r, sizeof(r), 0) != sizeof(r)) break; if (send(sock, &c, sizeof(c), 0) != sizeof(c)) break; } } } else if ((Cmds) hdr.cmd == E_LOGIN) { Response r; BUF_R_Create_Login c; printf("E_LOGIN"); if (hdr.len != sizeof(BUF_Create_Login)) { printf("hdr.len != sizeof(BUF_Create_Login)\n"); } else { BUF_Create_Login* status = (BUF_Create_Login*) buffer; char username[MAX_NAME_LEN]; char password[MAX_NAME_LEN]; strncpy(username, status->username, MAX_NAME_LEN); strncpy(password, status->password, MAX_NAME_LEN); username[MAX_NAME_LEN-1] = 0; password[MAX_NAME_LEN-1] = 0; printf("username=%s, password=%d\n", username, password); bool done = false; Response r; BUF_R_Create_Login c; r.response = htons(E_R_LOGIN); r.len = htons(sizeof(BUF_R_Create_Login)); c.id = htons(0xFFFF); c.cookie = htons(0xFFFF); for (int i = 0; i < MAX_ID; i++) { if (!strcmp(users[i].username, username)) { if (!strcmp(users[i].password, password)) { c.id = htons(users[i].id); c.cookie = htons(users[i].cookie); printf("found login\n"); break; } else { printf("username ok password not=%s\n", users[i].password); } } else { printf("not username=%s\n", users[i].username); } } if (send(sock, &r, sizeof(r), 0) != sizeof(r)) break; if (send(sock, &c, sizeof(c), 0) != sizeof(c)) break; } } else { printf("Unknown command\n"); if (buffer) { free(buffer); buffer = NULL; } } } } while (1); close(sock); if (buffer != NULL) { free(buffer); buffer = NULL; } printf("client closed\n"); pthread_exit( NULL ); }
/// %Realm List command handler bool AuthSocket::_HandleRealmList() { DEBUG_LOG("Entering _HandleRealmList"); if (ibuf.GetLength() < 5) return false; ibuf.Remove(5); ///- Get the user id (else close the connection) // No SQL injection (escaped user name) QueryResult *result = loginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '******'",_safelogin.c_str()); if(!result) { sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); SetCloseAndDelete(); return false; } uint32 id = (*result)[0].GetUInt32(); std::string rI = (*result)[1].GetCppString(); delete result; ///- Update realm list if need m_realmList.UpdateIfNeed(); ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) ByteBuffer pkt; pkt << (uint32) 0; pkt << (uint16) m_realmList.size(); RealmList::RealmMap::const_iterator i; for( i = m_realmList.begin(); i != m_realmList.end(); ++i ) { uint8 AmountOfCharacters; // No SQL injection. id of realm is controlled by the database. result = loginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); if( result ) { Field *fields = result->Fetch(); AmountOfCharacters = fields[0].GetUInt8(); delete result; } else AmountOfCharacters = 0; uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; pkt << i->second.icon; // realm type pkt << lock; // if 1, then realm locked pkt << i->second.color; // if 2, then realm is offline pkt << i->first; pkt << i->second.address; pkt << i->second.populationLevel; pkt << AmountOfCharacters; pkt << i->second.timezone; // realm category pkt << (uint8) 0x2C; // unk, may be realm number/id? } pkt << (uint8) 0x10; pkt << (uint8) 0x00; ByteBuffer hdr; hdr << (uint8) REALM_LIST; hdr << (uint16)pkt.size(); hdr.append(pkt); SendBuf((char const*)hdr.contents(), hdr.size()); return true; }
/// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < 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); ibuf.Read((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()) || (ibuf.GetLength() < 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 ibuf.Read((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; ///- 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); pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- 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 = GetRemoteAddress(); loginDatabase.escape_string(address); QueryResult *result = loginDatabase.PQuery("SELECT unbandate FROM ip_banned WHERE " // permanent still banned "(unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", address.c_str()); if (result) { pkt << (uint8)WOW_FAIL_BANNED; BASIC_LOG("[AuthChallenge] Banned ip %s tries to login!", GetRemoteAddress().c_str()); delete result; } else { ///- Get the account details from the account table // No SQL injection (escaped user name) result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s,trial_client FROM account WHERE username = '******'",_safelogin.c_str ()); if( result ) { ///- If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if((*result)[2].GetUInt8() == 1) // if ip is locked { DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) { DEBUG_LOG("[AuthChallenge] Account IP differs"); pkt << (uint8) WOW_FAIL_SUSPENDED; locked=true; } else { DEBUG_LOG("[AuthChallenge] Account IP matches"); } } else { DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); } if (!locked) { ///- 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)", (*result)[1].GetUInt32()); if(banresult) { if((*banresult)[0].GetUInt64() != (*banresult)[1].GetUInt64()) { pkt << (uint8) WOW_FAIL_BANNED; BASIC_LOG("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); } else { pkt << (uint8) WOW_FAIL_SUSPENDED; BASIC_LOG("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); } delete banresult; } else { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = (*result)[0].GetCppString(); ///- Don't calculate (v, s) if there are already some in the database std::string databaseV = (*result)[5].GetCppString(); std::string databaseS = (*result)[6].GetCppString(); 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()); } b.SetRand(19 * 8); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16 * 8); ///- Fill the response packet with the result pkt << uint8(WOW_SUCCESS); // 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); } uint8 secLevel = (*result)[4].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _isTrial = (*result)[7].GetUInt8() == 1 ? true : false; _localizationName.resize(4); for(int i = 0; i < 4; ++i) _localizationName[i] = ch->country[4-i-1]; BASIC_LOG("[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)); } } delete result; } else // no account { pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT; } } SendBuf((char const*)pkt.contents(), pkt.size()); return true; }
BOOL SocksParser::Auth(int s,char* username,char* password,BOOL NeedAuth) { /* +----+----------+----------+ |VER | NMETHODS | METHODS | +----+----------+----------+ | 1 | 1 | 1 to 255 | +----+----------+----------+ */ int i = 0; char buffer[1024]; RecvBuf(s,buffer,2); int type = buffer[1]; RecvBuf(s,buffer,type); for (i = 0;i < type;++i) if (buffer[i] == 0x02) break; /* +----+-----------------+ |VER | METHOD CHOSSED | +----+-----------------+ | 1 | 1 to 255 | +----+-----------------+ */ char replay[2]; replay[0] = 0x05; //需要身份认证 if (NeedAuth) { //没有密码 if (i == type) { replay[1] = 0xff; } else { replay[1] = 0x02; } } //不需要 else { replay[1] = 0x00; } SendBuf(s,replay,2); //只支持密码通信 if (replay[1] == 0xff) return FALSE; if (replay[1] == 0x00) return TRUE; /* +----+------+----------+------+----------+ |VER | ULEN | UNAME | PLEN | PASSWD | +----+------+----------+------+----------+ | 1 | 1 | 1 to 255 | 1 | 1 to 255 | +----+------+----------+------+----------+ */ RecvBuf(s,buffer,2); int nLen = buffer[1]; RecvBuf(s,buffer,nLen); buffer[nLen] = 0; char user[256]; strncpy(user,buffer,256); RecvBuf(s,buffer,1); int nPLen = buffer[0]; RecvBuf(s,buffer,nPLen); buffer[nPLen] = 0; char pwd[256]; strncpy(pwd,buffer,256); /* +----+--------+ |VER | STATUS | +----+--------+ | 1 | 1 | +----+--------+ */ replay[0] = 0x05; if (!strcmp(user,username) && !strcmp(pwd,password)) replay[1] = 0x00; else replay[1] = 0x01; SendBuf(s,replay,2); return replay[1] == 0x00; }
void GrabAndSendCameraData(CvCapture* aCamHandle, int i2c_handle, int skippedFrame, int delayPixelSending, unsigned int idPayloadNum, GPS_DATA *last_data, unsigned char rf_buffer_len) { unsigned char frameBuff[645*200], buff_gps_data[40]; unsigned int i, idPixel; //capture camera, skip n frame IplImage *img = 0; uint8_t cntSkipFrame = 0; while (cntSkipFrame < skippedFrame) { //grab frame img = cvQueryFrame(aCamHandle); if (img) cntSkipFrame++; } //get picture and resize it //cvSaveImage("/dev/shm/capture.jpg", img, 0); //create image to store IplImage *dest = cvCreateImage(cvSize(200, 200), img->depth, img->nChannels); //resize it cvResize(img, dest, CV_INTER_LANCZOS4); //save the resized image //~ cvSaveImage("resized.jpg", dest, 0); //view pixel info int hcnt, wcnt; //method 1: //print header paket gambar snprintf((char*) frameBuff, 10, "\r%.3d\xff\r", idPayloadNum); SendBuf(COM_PORT, frameBuff, 7); usleep(RF_DELAY_LESS_PACKET_US); //print pixel idPixel = 0; for (hcnt = 0; hcnt < dest->height; hcnt++) { //loop height unsigned char* row = &CV_IMAGE_ELEM(dest, unsigned char, hcnt, 0); //row scanline //print header frame //~ uchar dataTX[4] = {0xff}; //header data //~ dataTX[1] = ((hcnt + 1) / 100) + 0x30; //counter height //~ dataTX[2] = (((hcnt + 1) % 100) / 10) + 0x30; //~ dataTX[3] = ((hcnt + 1) % 10) + 0x30; frameBuff[idPixel++] = 0xff; frameBuff[idPixel++] = ((hcnt + 1) / 100) + 0x30; //counter height frameBuff[idPixel++] = (((hcnt + 1) % 100) / 10) + 0x30; frameBuff[idPixel++] = ((hcnt + 1) % 10) + 0x30; #if VERBOSE==1 printf("Processing frame #%d\r\n", hcnt + 1); #endif //send header //~ SendBuf(COM_PORT, dataTX, 4); //~ usleep(RF_DELAY_LESS_PACKET_US); //loop per width for (wcnt = 0; wcnt < dest->width * dest->nChannels; wcnt += dest->nChannels) { // opencv rgb data sequence = BGR // row[x] = {R,G,B}; //~ frameBuff[wcnt + 4] = (row[wcnt + 2] == 0xff) ? 0xfe : row[wcnt + 2]; //~ frameBuff[wcnt + 1 + 4] = (row[wcnt + 1] == 0xff) ? 0xfe : row[wcnt + 1]; //~ frameBuff[wcnt + 2 + 4] = (row[wcnt + 0] == 0xff) ? 0xfe : row[wcnt + 0]; frameBuff[idPixel++] = (row[wcnt + 2] == 0xff) ? 0xfe : row[wcnt + 2]; frameBuff[idPixel++] = (row[wcnt + 1] == 0xff) ? 0xfe : row[wcnt + 1]; frameBuff[idPixel++] = (row[wcnt + 0] == 0xff) ? 0xfe : row[wcnt + 0]; //~ SendByte(COM_PORT, (row[wcnt + 2] == 0xff) ? 0xfe : row[wcnt + 2]); //usleep(5); //~ SendByte(COM_PORT, (row[wcnt + 1] == 0xff) ? 0xfe : row[wcnt + 1]); //usleep(5); //~ SendByte(COM_PORT, (row[wcnt + 0] == 0xff) ? 0xfe : row[wcnt + 0]); //usleep(5); //delay for buffer radio //~ if(wcnt%32==0) //~ usleep(delayPixelSending); } //send frame package //SendBuf(COM_PORT, frameBuff, 600); //delay for transceiver //usleep(delayPixelSending); //get gps data //~ GetAndFormatGPSData(i2c_handle, buff_gps_data, last_data); GetAndFormatGPSData(i2c_handle, &frameBuff[idPixel], last_data); //send the gps data //~ SendBuf(COM_PORT, buff_gps_data, 18); //~ usleep(2000); //~ SendBuf(COM_PORT, &buff_gps_data[18], 19); //~ usleep(RF_DELAY_US); //delay buffer radio //~ usleep(delayPixelSending+2000); //tail //~ snprintf(buff_gps_data, 5, " INA"); idPixel += 37; snprintf(&frameBuff[idPixel], 6, " %s", "GPS"); idPixel += 4; //send the data //~ SendBuf(COM_PORT, buff_gps_data, 4); //~ for(i=0;i<672;i+=32) //~ { //~ SendBuf(COM_PORT, &frameBuff[i], 32); //~ usleep(RF_DELAY_HALF_DUPLEX_US); //~ } //~ for(i=0;i<672;i++) //~ { //~ SendByte(COM_PORT, frameBuff[i]); //~ if(i%32==0) //~ usleep(RF_DELAY_HALF_DUPLEX_US); //~ } //~ usleep(50000); //~ printf("F#%.3d = %.3d\r\n", hcnt, idPixel); //~ if(hcnt==0) break; } //save to file //~ FILE *fp; //~ fp=fopen("raw_cam.log", "wb+"); //~ fwrite( //~ frameBuff, //~ sizeof(frameBuff[0]), //~ /* sizeof(frameBuff)/sizeof(frameBuff[0]) */ //~ idPixel, //~ fp); //~ fclose(fp); //send all data printf("Going to send %ld byte with delay %d us\r\n", idPixel, delayPixelSending); //trw433 #ifdef RADIO_TYPE_TRW433 for(i=0;i<(idPixel);i++) { SendByte(COM_PORT, frameBuff[i]); if(i%(rf_buffer_len-1)==0) //~ usleep(RF_DELAY_HALF_DUPLEX_US); usleep(delayPixelSending); } usleep(RF_DELAY_LESS_PACKET_US); #endif //hm trp #ifdef RADIO_TYPE_HMTRP for(i=0;i<(idPixel);i++) { SendByte(COM_PORT, frameBuff[i]); if(i%(32-1)==0) //~ usleep(RF_DELAY_HALF_DUPLEX_US); usleep(delayPixelSending); } usleep(RF_DELAY_LESS_PACKET_US); #endif }
void HttpPostSocket::DoMultipartPost() { long length = 0; // calculate content_length of our post body std::string tmp; // fields { for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++) { std::string name = (*it).first; std::list<std::string>& ref = (*it).second; tmp = "--" + m_boundary + "\r\n" "content-disposition: form-data; name=\"" + name + "\"\r\n" "\r\n"; for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++) { std::string value = *it; tmp += value + "\r\n"; } length += (long)tmp.size(); } } // files { for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++) { std::string name = (*it).first; std::string filename = (*it).second; long content_length = m_content_length[filename]; std::string content_type = m_content_type[filename]; tmp = "--" + m_boundary + "\r\n" "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n" "content-type: " + content_type + "\r\n" "\r\n"; length += (long)tmp.size(); length += content_length; length += 2; // crlf after file } } // end tmp = "--" + m_boundary + "--\r\n"; length += (long)tmp.size(); // build header, send body SetMethod("POST"); SetHttpVersion( "HTTP/1.1" ); AddResponseHeader( "Host", m_host ); // oops - this is actually a request header that we're adding.. AddResponseHeader( "User-agent", MyUseragent()); AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" ); AddResponseHeader( "Connection", "close" ); AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary ); AddResponseHeader( "Content-length", Utility::l2string(length) ); SendRequest(); // send fields { for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++) { std::string name = (*it).first; std::list<std::string>& ref = (*it).second; tmp = "--" + m_boundary + "\r\n" "content-disposition: form-data; name=\"" + name + "\"\r\n" "\r\n"; for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++) { std::string value = *it; tmp += value + "\r\n"; } Send( tmp ); } } // send files { for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++) { std::string name = (*it).first; std::string filename = (*it).second; std::string content_type = m_content_type[filename]; tmp = "--" + m_boundary + "\r\n" "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n" "content-type: " + content_type + "\r\n" "\r\n"; Send( tmp ); { FILE *fil = fopen(filename.c_str(),"rb"); if (fil) { char slask[2000]; size_t n; while ((n = fread(slask, 1, 2000, fil)) > 0) { SendBuf(slask, n); } fclose(fil); } } Send("\r\n"); } } // end of send Send("--" + m_boundary + "--\r\n"); }