2014-10-30 02:04:54 +00:00
/*
2018-01-01 00:40:17 +01:00
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
2014-10-30 02:04:54 +00:00
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AuthenticationPackets.h"
2017-05-18 23:52:58 +02:00
#include "BigNumber.h"
2017-01-29 16:09:46 +01:00
#include "CharacterTemplateDataStore.h"
2014-11-06 18:49:19 +01:00
#include "HmacHash.h"
2017-05-18 23:52:58 +02:00
#include "ObjectMgr.h"
2017-12-25 21:41:34 +01:00
#include "RSA.h"
2017-05-18 23:52:58 +02:00
#include "Util.h"
2014-10-30 02:04:54 +00:00
2017-05-13 17:25:21 +02:00
ByteBuffer & operator << ( ByteBuffer & data , WorldPackets :: Auth :: VirtualRealmNameInfo const & virtualRealmInfo )
{
data . WriteBit ( virtualRealmInfo . IsLocal );
data . WriteBit ( virtualRealmInfo . IsInternalRealm );
data . WriteBits ( virtualRealmInfo . RealmNameActual . length (), 8 );
data . WriteBits ( virtualRealmInfo . RealmNameNormalized . length (), 8 );
data . FlushBits ();
data . WriteString ( virtualRealmInfo . RealmNameActual );
data . WriteString ( virtualRealmInfo . RealmNameNormalized );
return data ;
}
ByteBuffer & operator << ( ByteBuffer & data , WorldPackets :: Auth :: VirtualRealmInfo const & virtualRealmInfo )
{
data << uint32 ( virtualRealmInfo . RealmAddress );
data << virtualRealmInfo . RealmNameInfo ;
return data ;
}
2016-07-07 18:12:50 +02:00
bool WorldPackets :: Auth :: EarlyProcessClientPacket :: ReadNoThrow ()
{
try
{
Read ();
return true ;
}
2016-08-01 16:10:07 +02:00
catch ( ByteBufferPositionException const & /*ex*/ )
2016-07-07 18:12:50 +02:00
{
}
return false ;
}
void WorldPackets :: Auth :: Ping :: Read ()
{
_worldPacket >> Serial ;
_worldPacket >> Latency ;
}
const WorldPacket * WorldPackets :: Auth :: Pong :: Write ()
{
_worldPacket << uint32 ( Serial );
return & _worldPacket ;
}
2014-11-03 20:23:21 +01:00
WorldPacket const * WorldPackets :: Auth :: AuthChallenge :: Write ()
2014-10-31 01:20:53 +01:00
{
2014-11-02 12:23:15 +01:00
_worldPacket . append ( DosChallenge , 8 );
2016-03-25 21:33:55 +01:00
_worldPacket . append ( Challenge . data (), Challenge . size ());
2014-10-31 01:20:53 +01:00
_worldPacket << uint8 ( DosZeroBits );
2014-11-03 20:23:21 +01:00
return & _worldPacket ;
2014-10-31 01:20:53 +01:00
}
void WorldPackets :: Auth :: AuthSession :: Read ()
{
2016-05-30 23:51:06 +02:00
uint32 realmJoinTicketSize ;
2014-10-31 01:20:53 +01:00
2016-05-30 23:51:06 +02:00
_worldPacket >> DosResponse ;
2014-10-31 01:20:53 +01:00
_worldPacket >> Build ;
2016-03-25 21:33:55 +01:00
_worldPacket >> BuildType ;
2014-10-31 01:20:53 +01:00
_worldPacket >> RegionID ;
_worldPacket >> BattlegroupID ;
_worldPacket >> RealmID ;
2016-03-25 21:33:55 +01:00
_worldPacket . read ( LocalChallenge . data (), LocalChallenge . size ());
_worldPacket . read ( Digest . data (), Digest . size ());
2016-05-30 23:51:06 +02:00
UseIPv6 = _worldPacket . ReadBit ();
2016-03-25 21:33:55 +01:00
_worldPacket >> realmJoinTicketSize ;
if ( realmJoinTicketSize )
{
RealmJoinTicket . resize ( std :: min ( realmJoinTicketSize , uint32 ( _worldPacket . size () - _worldPacket . rpos ())));
_worldPacket . read ( reinterpret_cast < uint8 *> ( & RealmJoinTicket [ 0 ]), RealmJoinTicket . size ());
2014-10-31 01:20:53 +01:00
}
}
2016-11-27 12:29:31 +01:00
ByteBuffer & operator << ( ByteBuffer & data , WorldPackets :: Auth :: AuthWaitInfo const & waitInfo )
{
data << uint32 ( waitInfo . WaitCount );
data << uint32 ( waitInfo . WaitTime );
data . WriteBit ( waitInfo . HasFCM );
data . FlushBits ();
return data ;
}
2014-10-30 02:04:54 +00:00
WorldPackets :: Auth :: AuthResponse :: AuthResponse ()
2014-10-31 14:47:56 +01:00
: ServerPacket ( SMSG_AUTH_RESPONSE , 132 )
2014-10-30 02:04:54 +00:00
{
}
2014-11-03 20:23:21 +01:00
WorldPacket const * WorldPackets :: Auth :: AuthResponse :: Write ()
2014-10-30 02:04:54 +00:00
{
2016-03-25 21:33:55 +01:00
_worldPacket << uint32 ( Result );
2015-04-26 23:45:52 +02:00
_worldPacket . WriteBit ( SuccessInfo . is_initialized ());
_worldPacket . WriteBit ( WaitInfo . is_initialized ());
2015-04-30 19:42:13 +02:00
_worldPacket . FlushBits ();
2014-10-30 02:04:54 +00:00
2015-04-26 23:45:52 +02:00
if ( SuccessInfo )
2014-10-30 02:04:54 +00:00
{
2015-04-26 23:45:52 +02:00
_worldPacket << uint32 ( SuccessInfo -> VirtualRealmAddress );
_worldPacket << uint32 ( SuccessInfo -> VirtualRealms . size ());
_worldPacket << uint32 ( SuccessInfo -> TimeRested );
_worldPacket << uint8 ( SuccessInfo -> ActiveExpansionLevel );
_worldPacket << uint8 ( SuccessInfo -> AccountExpansionLevel );
_worldPacket << uint32 ( SuccessInfo -> TimeSecondsUntilPCKick );
_worldPacket << uint32 ( SuccessInfo -> AvailableClasses -> size ());
_worldPacket << uint32 ( SuccessInfo -> Templates . size ());
_worldPacket << uint32 ( SuccessInfo -> CurrencyID );
2016-10-25 19:13:32 +02:00
_worldPacket << int32 ( SuccessInfo -> Time );
2015-04-26 23:45:52 +02:00
2017-01-29 16:09:46 +01:00
for ( auto const & klass : * SuccessInfo -> AvailableClasses )
2016-05-30 23:51:06 +02:00
{
_worldPacket << uint8 ( klass . first ); /// the current class
_worldPacket << uint8 ( klass . second ); /// the required Expansion
}
_worldPacket . WriteBit ( SuccessInfo -> IsExpansionTrial );
_worldPacket . WriteBit ( SuccessInfo -> ForceCharacterTemplate );
_worldPacket . WriteBit ( SuccessInfo -> NumPlayersHorde . is_initialized ());
_worldPacket . WriteBit ( SuccessInfo -> NumPlayersAlliance . is_initialized ());
_worldPacket . FlushBits ();
2016-03-28 15:23:41 +02:00
{
_worldPacket << uint32 ( SuccessInfo -> Billing . BillingPlan );
_worldPacket << uint32 ( SuccessInfo -> Billing . TimeRemain );
2018-06-17 20:41:46 +02:00
_worldPacket << uint32 ( SuccessInfo -> Billing . Unknown735 );
2016-03-28 15:23:41 +02:00
// 3x same bit is not a mistake - preserves legacy client behavior of BillingPlanFlags::SESSION_IGR
_worldPacket . WriteBit ( SuccessInfo -> Billing . InGameRoom ); // inGameRoom check in function checking which lua event to fire when remaining time is near end - BILLING_NAG_DIALOG vs IGR_BILLING_NAG_DIALOG
_worldPacket . WriteBit ( SuccessInfo -> Billing . InGameRoom ); // inGameRoom lua return from Script_GetBillingPlan
_worldPacket . WriteBit ( SuccessInfo -> Billing . InGameRoom ); // not used anywhere in the client
_worldPacket . FlushBits ();
}
2016-05-30 23:51:06 +02:00
if ( SuccessInfo -> NumPlayersHorde )
_worldPacket << uint16 ( * SuccessInfo -> NumPlayersHorde );
if ( SuccessInfo -> NumPlayersAlliance )
_worldPacket << uint16 ( * SuccessInfo -> NumPlayersAlliance );
2017-05-13 17:25:21 +02:00
for ( VirtualRealmInfo const & virtualRealm : SuccessInfo -> VirtualRealms )
_worldPacket << virtualRealm ;
2014-10-30 02:04:54 +00:00
2017-01-29 16:09:46 +01:00
for ( CharacterTemplate const * templat : SuccessInfo -> Templates )
2014-10-30 02:04:54 +00:00
{
2017-01-29 16:09:46 +01:00
_worldPacket << uint32 ( templat -> TemplateSetId );
_worldPacket << uint32 ( templat -> Classes . size ());
for ( CharacterTemplateClass const & templateClass : templat -> Classes )
2014-10-30 02:04:54 +00:00
{
2015-04-19 23:37:29 +02:00
_worldPacket << uint8 ( templateClass . ClassID );
_worldPacket << uint8 ( templateClass . FactionGroup );
2014-10-30 02:04:54 +00:00
}
2017-01-29 16:09:46 +01:00
_worldPacket . WriteBits ( templat -> Name . length (), 7 );
_worldPacket . WriteBits ( templat -> Description . length (), 10 );
2015-04-30 19:42:13 +02:00
_worldPacket . FlushBits ();
2017-01-29 16:09:46 +01:00
_worldPacket . WriteString ( templat -> Name );
_worldPacket . WriteString ( templat -> Description );
2014-10-30 02:04:54 +00:00
}
}
2015-04-26 23:45:52 +02:00
if ( WaitInfo )
2016-11-27 12:29:31 +01:00
_worldPacket << * WaitInfo ;
return & _worldPacket ;
}
WorldPacket const * WorldPackets :: Auth :: WaitQueueUpdate :: Write ()
{
_worldPacket << WaitInfo ;
2014-10-30 02:04:54 +00:00
2014-11-03 20:23:21 +01:00
return & _worldPacket ;
2014-10-31 01:20:53 +01:00
}
2014-11-06 18:49:19 +01:00
std :: string const WorldPackets :: Auth :: ConnectTo :: Haiku ( "An island of peace \n Corruption is brought ashore \n Pandarens will rise \n\0\0 " , 71 );
2014-11-09 21:36:06 +01:00
uint8 const WorldPackets :: Auth :: ConnectTo :: PiDigits [ 130 ] =
2014-11-06 18:49:19 +01:00
{
0x31 , 0x41 , 0x59 , 0x26 , 0x53 , 0x58 , 0x97 , 0x93 , 0x23 , 0x84 ,
0x62 , 0x64 , 0x33 , 0x83 , 0x27 , 0x95 , 0x02 , 0x88 , 0x41 , 0x97 ,
0x16 , 0x93 , 0x99 , 0x37 , 0x51 , 0x05 , 0x82 , 0x09 , 0x74 , 0x94 ,
0x45 , 0x92 , 0x30 , 0x78 , 0x16 , 0x40 , 0x62 , 0x86 , 0x20 , 0x89 ,
0x98 , 0x62 , 0x80 , 0x34 , 0x82 , 0x53 , 0x42 , 0x11 , 0x70 , 0x67 ,
0x98 , 0x21 , 0x48 , 0x08 , 0x65 , 0x13 , 0x28 , 0x23 , 0x06 , 0x64 ,
0x70 , 0x93 , 0x84 , 0x46 , 0x09 , 0x55 , 0x05 , 0x82 , 0x23 , 0x17 ,
0x25 , 0x35 , 0x94 , 0x08 , 0x12 , 0x84 , 0x81 , 0x11 , 0x74 , 0x50 ,
0x28 , 0x41 , 0x02 , 0x70 , 0x19 , 0x38 , 0x52 , 0x11 , 0x05 , 0x55 ,
0x96 , 0x44 , 0x62 , 0x29 , 0x48 , 0x95 , 0x49 , 0x30 , 0x38 , 0x19 ,
0x64 , 0x42 , 0x88 , 0x10 , 0x97 , 0x56 , 0x65 , 0x93 , 0x34 , 0x46 ,
0x12 , 0x84 , 0x75 , 0x64 , 0x82 , 0x33 , 0x78 , 0x67 , 0x83 , 0x16 ,
0x52 , 0x71 , 0x20 , 0x19 , 0x09 , 0x14 , 0x56 , 0x48 , 0x56 , 0x69 ,
};
2017-12-25 21:41:34 +01:00
namespace
2014-11-06 18:49:19 +01:00
{
2017-12-29 12:50:12 +01:00
std :: string RSAPrivateKey = R "(-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA7rPc1NPDtFRRzmZbyzK48PeSU8YZ8gyFL4omqXpFn2DE683q
f41Z2FeyYHsJTJtouMft7x6ADeZrN1tTkOsYEw1 / Q2SD2pjmrMIwooKlxsvH + 4 af
n6kCagNJxTj7wMhVzMDOJZG + hc / R0TfOzIPS6jCAB3uAn51EVCIpvoba20jFqfkT
NpUjdvEO3IQNlAISqJfzOxTuqm + YBSdOH6Ngpana2BffM8viE1SLGLDKubuIZAbf
dabXYQC7sFoOetR3CE0V4hCDsASqnot3qQaJXQhdD7gua8HLZM9uXNtPWGUIUfsN
SBpvtj0fC93 + Gx3wv7Ana / WOvMdAAf + nC4DWXwIDAQABAoIBACKa5q / gB2Y0Nyvi
APrDXrZoXclRVd + WWxSaRaKaPE + vuryovI9DUbwgcpa0H5QAj70CFwdsd4oMVozO
6519 x56zfTiq8MaXFhIDkQNuR1Q7pMFdMfT2jogJ8 / 7 olO7M3EtzxC8EIwfJKhTX
r15M2h3jbBwplmsNZKOB1GVvrXjOm1KtOZ4CTTM0WrPaLVDT9ax8pykjmFw16vGP
j / R5Dky9VpabtfZOu / AEW259XDEiQgTrB4Eg + S4GJjHqAzPZBmMy / xhlDK4oMXef
qXScfD4w0RxuuCFr6lxLPZz0S35BK1kIWmIkuv + 9 eQuI4Hr1CyVwch4fkfvrp84x
8 tvAFnkCgYEA87NZaG9a8 / Mob6GgY4BVLHJVOSzzFdNyMA + 4L fSbtzgON2RSZyeD
0 JpDowwXssw5XOyUUctj2cLLdlMCpDfdzk4F / PEakloDJWpason3lmur0 / 5 Oq3T9
3 + fnNUl4d3UOs1jcJ1yGQ / BfrTyRTcEoZx8Mu9mJ4ituVkKuLeG5vX0CgYEA + r / w
QBJS6kDyQPj1k / SMClUhWhyADwDod03hHTQHc9BleJyjXmVy +/ pWhN7aELhjgLbf
o / Gm3aKJjCxS4qBmqUKwAvGoSVux1Bo2ZjcfF7sX9BXBOlFTG + bPVCZUoaksTyXN
g7GsA1frKkWWkgQuOeK3o / p9IZoBl93vEgcTGgsCgYEAv5ucCIjFMllUybCCsrkM
Ps4GQ9YbqmV9ulwhq8BPTlc8lkDCqWhgM3uXAnNXjrUTxQQd + dG4yFZoMrhBs2xZ
cQPXoXDQO5GaN6jPduETUamGiD / DCvwJQCrNlxAVL5dR36FWN3x / 9 JriHwsoE8Jz
SeEX2frIdpM / RYNX / 6 sipuECgYEA + rwFRDxOdvm8hGWuQ2WMxyQ7Nn07PEV / LxVM
HkSRkyh23vVakyDEqty3uSOSUJfgv6ud07TnU8ac3fLQatdT8LrDgB4fVkN / fYU8
kldaGwO1vxgl4OfDQCo7dXzisciViwtVBvQZ + jnm6J0vJBFUHAPt9 + WZTIlQQIjm
71L tseMCgYBSAhs6lshtz + ujR3fmc4QqJVGqeXvEBPAVm6yYoKYRLwVs / rFv3WLN
LOwwBQ6lz7P9RqYYB5wVlaRvEhb9 + lCve / xVcxMeZ5GkOBPxVygYV9l / wNdE25Nz
OHYtKG3GK3GEcFDwZU2LPHq21EroUAdtRfbrJ4KW2yc8igtXKxTBYw ==
----- END RSA PRIVATE KEY -----
) ";
2017-12-25 21:41:34 +01:00
std :: unique_ptr < Trinity :: Crypto :: RSA > ConnectToRSA ;
2014-11-06 18:49:19 +01:00
uint8 const WherePacketHmac [] =
{
0x2C , 0x1F , 0x1D , 0x80 , 0xC3 , 0x8C , 0x23 , 0x64 , 0xDA , 0x90 , 0xCA , 0x8E , 0x2C , 0xFC , 0x0C , 0xCE ,
0x09 , 0xD3 , 0x62 , 0xF9 , 0xF3 , 0x8B , 0xBE , 0x9F , 0x19 , 0xEF , 0x58 , 0xA1 , 0x1C , 0x34 , 0x14 , 0x41 ,
0x3F , 0x23 , 0xFD , 0xD3 , 0xE8 , 0x14 , 0xEC , 0x2A , 0xFD , 0x4F , 0x95 , 0xBA , 0x30 , 0x7E , 0x56 , 0x5D ,
0x83 , 0x95 , 0x81 , 0x69 , 0xB0 , 0x5A , 0xB4 , 0x9D , 0xA8 , 0x55 , 0xFF , 0xFC , 0xEE , 0x58 , 0x0A , 0x2F
};
2017-12-25 21:41:34 +01:00
}
bool WorldPackets :: Auth :: ConnectTo :: InitializeEncryption ()
{
std :: unique_ptr < Trinity :: Crypto :: RSA > rsa = Trinity :: make_unique < Trinity :: Crypto :: RSA > ();
if ( ! rsa -> LoadFromString ( RSAPrivateKey , Trinity :: Crypto :: RSA :: PrivateKey {}))
return false ;
ConnectToRSA = std :: move ( rsa );
return true ;
}
2014-11-06 18:49:19 +01:00
2015-03-27 22:21:24 +01:00
WorldPackets :: Auth :: ConnectTo :: ConnectTo () : ServerPacket ( SMSG_CONNECT_TO , 8 + 4 + 256 + 1 )
2014-11-06 18:49:19 +01:00
{
2017-07-20 21:54:36 +02:00
Payload . Where . fill ( 0 );
2014-11-06 18:49:19 +01:00
HexStrToByteArray ( "F41DCB2D728CF3337A4FF338FA89DB01BBBE9C3B65E9DA96268687353E48B94C" , Payload . PanamaKey );
Payload . Adler32 = 0xA0A66C10 ;
}
WorldPacket const * WorldPackets :: Auth :: ConnectTo :: Write ()
{
HmacSha1 hmacHash ( 64 , WherePacketHmac );
2017-05-13 11:49:09 +02:00
hmacHash . UpdateData ( Payload . Where . data (), 16 );
hmacHash . UpdateData (( uint8 * const ) & Payload . Type , 1 );
hmacHash . UpdateData (( uint8 * const ) & Payload . Port , 2 );
2014-11-06 18:49:19 +01:00
hmacHash . UpdateData (( uint8 * const ) Haiku . c_str (), 71 );
hmacHash . UpdateData ( Payload . PanamaKey , 32 );
hmacHash . UpdateData ( PiDigits , 108 );
hmacHash . UpdateData ( & Payload . XorMagic , 1 );
hmacHash . Finalize ();
2017-05-13 11:49:09 +02:00
ByteBuffer payload ;
2015-11-21 21:30:05 +01:00
payload << uint32 ( Payload . Adler32 );
2017-05-13 11:49:09 +02:00
payload << uint8 ( Payload . Type );
payload . append ( Payload . Where . data (), 16 );
payload << uint16 ( Payload . Port );
2016-03-25 21:33:55 +01:00
payload . append ( Haiku . data (), 71 );
payload . append ( Payload . PanamaKey , 32 );
payload . append ( PiDigits , 108 );
2015-11-21 21:30:05 +01:00
payload << uint8 ( Payload . XorMagic );
2016-03-25 21:33:55 +01:00
payload . append ( hmacHash . GetDigest (), hmacHash . GetLength ());
2014-11-06 18:49:19 +01:00
2017-12-25 21:41:34 +01:00
uint32 rsaSize = ConnectToRSA -> GetOutputSize ();
if ( payload . size () < rsaSize )
payload . resize ( rsaSize );
2014-11-06 18:49:19 +01:00
_worldPacket << uint64 ( Key );
_worldPacket << uint32 ( Serial );
2017-12-25 21:41:34 +01:00
size_t encryptedPayloadPos = _worldPacket . wpos ();
_worldPacket . resize ( _worldPacket . size () + rsaSize );
2014-11-06 18:49:19 +01:00
_worldPacket << uint8 ( Con );
2017-12-25 21:41:34 +01:00
ConnectToRSA -> Encrypt ( payload . contents (), payload . size (),
_worldPacket . contents () + encryptedPayloadPos ,
Trinity :: Crypto :: RSA :: PrivateKey {},
Trinity :: Crypto :: RSA :: NoPadding {});
2014-11-06 18:49:19 +01:00
return & _worldPacket ;
}
2014-11-09 00:37:33 +01:00
void WorldPackets :: Auth :: AuthContinuedSession :: Read ()
{
_worldPacket >> DosResponse ;
_worldPacket >> Key ;
2016-03-25 21:33:55 +01:00
_worldPacket . read ( LocalChallenge . data (), LocalChallenge . size ());
_worldPacket . read ( Digest . data (), Digest . size ());
2014-11-09 00:37:33 +01:00
}
2015-02-23 22:35:26 +01:00
void WorldPackets :: Auth :: ConnectToFailed :: Read ()
{
2015-02-24 00:32:01 +01:00
Serial = _worldPacket . read < ConnectToSerial > ();
2015-02-23 22:35:26 +01:00
_worldPacket >> Con ;
}