2014-10-30 02:04:54 +00:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
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"
2019-07-12 20:41:33 +02:00
#include "SHA256.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
{
2019-07-12 20:41:33 +02:00
_worldPacket . append ( DosChallenge . data (), DosChallenge . size ());
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 >> 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 ());
2018-10-04 18:50:21 +02:00
_worldPacket . WriteBit ( SuccessInfo -> ExpansionTrialExpiration . is_initialized ());
2016-05-30 23:51:06 +02:00
_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 );
2018-10-04 18:50:21 +02:00
if ( SuccessInfo -> ExpansionTrialExpiration )
_worldPacket << int32 ( * SuccessInfo -> ExpansionTrialExpiration );
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
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 ;
}
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
2019-07-12 20:41:33 +02:00
WorldPackets :: Auth :: ConnectTo :: ConnectTo () : ServerPacket ( SMSG_CONNECT_TO , 256 + 1 + 16 + 2 + 4 + 1 + 8 )
2014-11-06 18:49:19 +01:00
{
}
WorldPacket const * WorldPackets :: Auth :: ConnectTo :: Write ()
{
2019-07-12 20:41:33 +02:00
ByteBuffer whereBuffer ;
whereBuffer << uint8 ( Payload . Where . Type );
switch ( Payload . Where . Type )
{
case IPv4 :
whereBuffer . append ( Payload . Where . Address . V4 . data (), Payload . Where . Address . V4 . size ());
break ;
case IPv6 :
whereBuffer . append ( Payload . Where . Address . V6 . data (), Payload . Where . Address . V6 . size ());
break ;
case NamedSocket :
whereBuffer << Payload . Where . Address . Name . data ();
break ;
default :
break ;
}
2014-11-06 18:49:19 +01:00
2019-07-12 20:41:33 +02:00
uint32 type = Payload . Where . Type ;
SHA256Hash hash ;
hash . UpdateData ( whereBuffer . contents (), whereBuffer . size ());
hash . UpdateData ( reinterpret_cast < uint8 const *> ( & type ), 4 );
hash . UpdateData ( reinterpret_cast < uint8 const *> ( & Payload . Port ), 2 );
hash . Finalize ();
ConnectToRSA -> Sign ( hash . GetDigest (), hash . GetLength (), Payload . Signature . data (), Trinity :: Crypto :: RSA :: SHA256 {});
_worldPacket . append ( Payload . Signature . data (), Payload . Signature . size ());
_worldPacket . append ( whereBuffer );
_worldPacket << uint16 ( Payload . Port );
2014-11-06 18:49:19 +01:00
_worldPacket << uint32 ( Serial );
_worldPacket << uint8 ( Con );
2019-07-12 20:41:33 +02:00
_worldPacket << uint64 ( Key );
2017-12-25 21:41:34 +01:00
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 ;
}
2019-07-12 20:41:33 +02:00
uint8 constexpr EnableEncryptionSeed [ 16 ] = { 0x90 , 0x9C , 0xD0 , 0x50 , 0x5A , 0x2C , 0x14 , 0xDD , 0x5C , 0x2C , 0xC0 , 0x64 , 0x14 , 0xF3 , 0xFE , 0xC9 };
WorldPacket const * WorldPackets :: Auth :: EnableEncryption :: Write ()
{
HmacSha256 hash ( 16 , EncryptionKey );
hash . UpdateData ( reinterpret_cast < uint8 const *> ( & Enabled ), 1 );
hash . UpdateData ( EnableEncryptionSeed , 16 );
hash . Finalize ();
_worldPacket . resize ( _worldPacket . size () + ConnectToRSA -> GetOutputSize ());
ConnectToRSA -> Sign ( hash . GetDigest (), hash . GetLength (), _worldPacket . contents (), Trinity :: Crypto :: RSA :: SHA256 {});
_worldPacket . WriteBit ( Enabled );
_worldPacket . FlushBits ();
return & _worldPacket ;
}