TrinityCore
Loading...
Searching...
No Matches
AuthenticationPackets.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
19#include "BigNumber.h"
21#include "Ed25519.h"
22#include "HMAC.h"
23#include "ObjectMgr.h"
24#include "PacketOperators.h"
25#include "RSA.h"
26
28{
29ByteBuffer& operator<<(ByteBuffer& data, VirtualRealmNameInfo const& virtualRealmInfo)
30{
31 data << WorldPackets::Bits<1>(virtualRealmInfo.IsLocal);
32 data << WorldPackets::Bits<1>(virtualRealmInfo.IsInternalRealm);
33 data << WorldPackets::SizedString::BitsSize<8>(virtualRealmInfo.RealmNameActual);
34 data << WorldPackets::SizedString::BitsSize<8>(virtualRealmInfo.RealmNameNormalized);
35 data.FlushBits();
36
37 data << SizedString::Data(virtualRealmInfo.RealmNameActual);
38 data << SizedString::Data(virtualRealmInfo.RealmNameNormalized);
39
40 return data;
41}
42
43ByteBuffer& operator<<(ByteBuffer& data, VirtualRealmInfo const& virtualRealmInfo)
44{
45 data << uint32(virtualRealmInfo.RealmAddress);
46 data << virtualRealmInfo.RealmNameInfo;
47
48 return data;
49}
50
52{
55}
56
58{
60 return &_worldPacket;
61}
62
67
75
77{
78 uint32 realmJoinTicketSize;
79
85 _worldPacket.read(Digest.data(), Digest.size());
86 _worldPacket >> Bits<1>(UseIPv6);
87 _worldPacket >> realmJoinTicketSize;
88 if (realmJoinTicketSize)
89 {
90 RealmJoinTicket.resize(std::min(realmJoinTicketSize, uint32(_worldPacket.size() - _worldPacket.rpos())));
92 }
93}
94
95ByteBuffer& operator<<(ByteBuffer& data, GameTime const& gameTime)
96{
97 data << uint32(gameTime.BillingType);
98 data << uint32(gameTime.MinutesRemaining);
99 data << uint32(gameTime.RealBillingType);
100 data << Bits<1>(gameTime.IsInIGR);
101 data << Bits<1>(gameTime.IsPaidForByIGR);
102 data << Bits<1>(gameTime.IsCAISEnabled);
103 data.FlushBits();
104
105 return data;
106}
107
109{
110 for (std::size_t i = 0; i < 16; ++i)
111 {
112 data << buildKey.BuildKey[i];
113 data << buildKey.ConfigKey[i];
114 }
115
116 return data;
117}
118
120{
121 data << uint32(successInfo.VirtualRealmAddress);
122 data << Size<uint32>(successInfo.VirtualRealms);
123 data << uint32(successInfo.TimeRested);
124 data << uint8(successInfo.ActiveExpansionLevel);
125 data << uint8(successInfo.AccountExpansionLevel);
126 data << uint32(successInfo.TimeSecondsUntilPCKick);
127 data << Size<uint32>(*successInfo.AvailableClasses);
128 data << Size<uint32>(successInfo.Templates);
129 data << uint32(successInfo.CurrencyID);
130 data << successInfo.GameTimeInfo;
131 data << successInfo.Time;
132
133 for (VirtualRealmInfo const& virtualRealm : successInfo.VirtualRealms)
134 data << virtualRealm;
135
136 for (RaceClassAvailability const& raceClassAvailability : *successInfo.AvailableClasses)
137 {
138 data << uint8(raceClassAvailability.RaceID);
139 data << Size<uint32>(raceClassAvailability.Classes);
140
141 for (ClassAvailability const& classAvailability : raceClassAvailability.Classes)
142 {
143 data << uint8(classAvailability.ClassID);
144 data << uint8(classAvailability.ActiveExpansionLevel);
145 data << uint8(classAvailability.AccountExpansionLevel);
146 data << uint8(classAvailability.MinActiveExpansionLevel);
147 }
148 }
149
150 for (CharacterTemplate const* characterTemplate : successInfo.Templates)
151 {
152 data << uint32(characterTemplate->TemplateSetId);
153 data << Size<uint32>(characterTemplate->Classes);
154 for (CharacterTemplateClass const& templateClass : characterTemplate->Classes)
155 {
156 data << uint8(templateClass.ClassID);
157 data << uint8(templateClass.FactionGroup);
158 }
159
160 data << SizedString::BitsSize<7>(characterTemplate->Name);
161 data << SizedString::BitsSize<10>(characterTemplate->Description);
162 data.FlushBits();
163
164 data << SizedString::Data(characterTemplate->Name);
165 data << SizedString::Data(characterTemplate->Description);
166 }
167
168 data << Bits<1>(successInfo.IsExpansionTrial);
169 data << Bits<1>(successInfo.ForceCharacterTemplate);
170 data << OptionalInit(successInfo.NumPlayersHorde);
171 data << OptionalInit(successInfo.NumPlayersAlliance);
172 data << OptionalInit(successInfo.ExpansionTrialExpiration);
173 data << OptionalInit(successInfo.CurrentBuild);
174 data.FlushBits();
175
176 if (successInfo.NumPlayersHorde)
177 data << uint16(*successInfo.NumPlayersHorde);
178
179 if (successInfo.NumPlayersAlliance)
180 data << uint16(*successInfo.NumPlayersAlliance);
181
182 if (successInfo.ExpansionTrialExpiration)
183 data << *successInfo.ExpansionTrialExpiration;
184
185 if (successInfo.CurrentBuild)
186 data << *successInfo.CurrentBuild;
187
188 return data;
189}
190
192{
193 data << uint32(waitInfo.WaitCount);
194 data << uint32(waitInfo.WaitTime);
196 data << WorldPackets::Bits<1>(waitInfo.HasFCM);
197 data << WorldPackets::Bits<1>(waitInfo.CanCreateOnlyIfExisting);
198 data.FlushBits();
199
200 return data;
201}
202
218
220{
222
223 return &_worldPacket;
224}
225
226namespace
227{
228std::string const RSAPrivateKey = R"(-----BEGIN RSA PRIVATE KEY-----
229MIIEpAIBAAKCAQEA7rPc1NPDtFRRzmZbyzK48PeSU8YZ8gyFL4omqXpFn2DE683q
230f41Z2FeyYHsJTJtouMft7x6ADeZrN1tTkOsYEw1/Q2SD2pjmrMIwooKlxsvH+4af
231n6kCagNJxTj7wMhVzMDOJZG+hc/R0TfOzIPS6jCAB3uAn51EVCIpvoba20jFqfkT
232NpUjdvEO3IQNlAISqJfzOxTuqm+YBSdOH6Ngpana2BffM8viE1SLGLDKubuIZAbf
233dabXYQC7sFoOetR3CE0V4hCDsASqnot3qQaJXQhdD7gua8HLZM9uXNtPWGUIUfsN
234SBpvtj0fC93+Gx3wv7Ana/WOvMdAAf+nC4DWXwIDAQABAoIBACKa5q/gB2Y0Nyvi
235APrDXrZoXclRVd+WWxSaRaKaPE+vuryovI9DUbwgcpa0H5QAj70CFwdsd4oMVozO
2366519x56zfTiq8MaXFhIDkQNuR1Q7pMFdMfT2jogJ8/7olO7M3EtzxC8EIwfJKhTX
237r15M2h3jbBwplmsNZKOB1GVvrXjOm1KtOZ4CTTM0WrPaLVDT9ax8pykjmFw16vGP
238j/R5Dky9VpabtfZOu/AEW259XDEiQgTrB4Eg+S4GJjHqAzPZBmMy/xhlDK4oMXef
239qXScfD4w0RxuuCFr6lxLPZz0S35BK1kIWmIkuv+9eQuI4Hr1CyVwch4fkfvrp84x
2408tvAFnkCgYEA87NZaG9a8/Mob6GgY4BVLHJVOSzzFdNyMA+4LfSbtzgON2RSZyeD
2410JpDowwXssw5XOyUUctj2cLLdlMCpDfdzk4F/PEakloDJWpason3lmur0/5Oq3T9
2423+fnNUl4d3UOs1jcJ1yGQ/BfrTyRTcEoZx8Mu9mJ4ituVkKuLeG5vX0CgYEA+r/w
243QBJS6kDyQPj1k/SMClUhWhyADwDod03hHTQHc9BleJyjXmVy+/pWhN7aELhjgLbf
244o/Gm3aKJjCxS4qBmqUKwAvGoSVux1Bo2ZjcfF7sX9BXBOlFTG+bPVCZUoaksTyXN
245g7GsA1frKkWWkgQuOeK3o/p9IZoBl93vEgcTGgsCgYEAv5ucCIjFMllUybCCsrkM
246Ps4GQ9YbqmV9ulwhq8BPTlc8lkDCqWhgM3uXAnNXjrUTxQQd+dG4yFZoMrhBs2xZ
247cQPXoXDQO5GaN6jPduETUamGiD/DCvwJQCrNlxAVL5dR36FWN3x/9JriHwsoE8Jz
248SeEX2frIdpM/RYNX/6sipuECgYEA+rwFRDxOdvm8hGWuQ2WMxyQ7Nn07PEV/LxVM
249HkSRkyh23vVakyDEqty3uSOSUJfgv6ud07TnU8ac3fLQatdT8LrDgB4fVkN/fYU8
250kldaGwO1vxgl4OfDQCo7dXzisciViwtVBvQZ+jnm6J0vJBFUHAPt9+WZTIlQQIjm
25171LtseMCgYBSAhs6lshtz+ujR3fmc4QqJVGqeXvEBPAVm6yYoKYRLwVs/rFv3WLN
252LOwwBQ6lz7P9RqYYB5wVlaRvEhb9+lCve/xVcxMeZ5GkOBPxVygYV9l/wNdE25Nz
253OHYtKG3GK3GEcFDwZU2LPHq21EroUAdtRfbrJ4KW2yc8igtXKxTBYw==
254-----END RSA PRIVATE KEY-----
255)";
256
257std::array<uint8, 32> constexpr EnterEncryptedModePrivateKey =
258{
259 0x08, 0xBD, 0xC7, 0xA3, 0xCC, 0xC3, 0x4F, 0x3F,
260 0x6A, 0x0B, 0xFF, 0xCF, 0x31, 0xC1, 0xB6, 0x97,
261 0x69, 0x1E, 0x72, 0x9A, 0x0A, 0xAB, 0x2C, 0x77,
262 0xC3, 0x6F, 0x8A, 0xE7, 0x5A, 0x9A, 0xA7, 0xC9
263};
264
265std::unique_ptr<Trinity::Crypto::RsaSignature> ConnectToRSA;
266std::unique_ptr<Trinity::Crypto::Ed25519> EnterEncryptedModeSigner;
267}
268
270{
271 data << SizedString::BitsSize<5>(bleepToken.Token);
272 data << SizedCString::BitsSize<24>(bleepToken.ProxyId);
273 data << SizedString::BitsSize<6>(bleepToken.Address);
274 data << bleepToken.TokenLifespan;
275 data << SizedString::Data(bleepToken.Token);
276 data << SizedCString::Data(bleepToken.ProxyId);
277 data << SizedString::Data(bleepToken.Address);
278
279 return data;
280}
281
283{
284 data << uint8(payload.Address.Type);
285 switch (payload.Address.Type)
286 {
287 case ConnectTo::IPv4:
288 data.append(payload.Address.Address.V4.data(), payload.Address.Address.V4.size());
289 break;
290 case ConnectTo::IPv6:
291 data.append(payload.Address.Address.V6.data(), payload.Address.Address.V6.size());
292 break;
294 data << payload.Address.Address.Name.data();
295 break;
296 default:
297 break;
298 }
299
300 data << uint16(payload.Port);
301 data << payload.Token;
302
303 return data;
304}
305
307{
308 std::unique_ptr<Trinity::Crypto::RsaSignature> rsa = std::make_unique<Trinity::Crypto::RsaSignature>();
309 if (!rsa->LoadKeyFromString(RSAPrivateKey))
310 return false;
311
312 ConnectToRSA = std::move(rsa);
313 return true;
314}
315
317{
318 ConnectToRSA.reset();
319}
320
322{
323 _worldPacket << Size<uint32>(Payload);
329
330 for (ConnectPayload const& payload : Payload)
331 _worldPacket << payload;
332
333 return &_worldPacket;
334}
335
345
347{
348 _worldPacket >> Con;
349 _worldPacket >> As<uint32>(Serial);
350}
351
353{
354 std::unique_ptr<Trinity::Crypto::Ed25519> ed25519 = std::make_unique<Trinity::Crypto::Ed25519>();
355 if (!ed25519->LoadFromByteArray(EnterEncryptedModePrivateKey))
356 return false;
357
358 EnterEncryptedModeSigner = std::move(ed25519);
359 return true;
360}
361
363{
364 EnterEncryptedModeSigner.reset();
365}
366
367std::array<uint8, 32> constexpr EnableEncryptionSeed = { 0x66, 0xBE, 0x29, 0x79, 0xEF, 0xF2, 0xD5, 0xB5, 0x61, 0x53, 0xF6, 0x5F, 0x45, 0xAE, 0x81, 0xCB,
368 0x32, 0xEC, 0x94, 0xEC, 0x75, 0xB3, 0x5F, 0x44, 0x6A, 0x63, 0x43, 0x67, 0x17, 0x20, 0x44, 0x34 };
369std::array<uint8, 16> constexpr EnableEncryptionContext = { 0xA7, 0x1F, 0xB6, 0x9B, 0xC9, 0x7C, 0xDD, 0x96, 0xE9, 0xBB, 0xB8, 0x21, 0x39, 0x8D, 0x5A, 0xD4 };
370
372{
373 std::array<uint8, 64> toSign = Trinity::Crypto::HMAC_SHA512::GetDigestOf(EncryptionKey,
374 std::array<uint8, 1>{uint8(Enabled ? 1 : 0)},
376
377 Trinity::Crypto::Ed25519 ed25519(*EnterEncryptedModeSigner);
378 std::vector<uint8> signature;
379
380 ed25519.SignWithContext(toSign, { EnableEncryptionContext.begin(), EnableEncryptionContext.end() }, signature);
381
383 _worldPacket.append(signature.data(), signature.size());
384 _worldPacket << Bits<1>(Enabled);
386
387 return &_worldPacket;
388}
389
394}
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
size_t rpos() const
Definition ByteBuffer.h:449
void resize(size_t newsize)
Definition ByteBuffer.h:583
void append(T value)
Definition ByteBuffer.h:131
size_t size() const
Definition ByteBuffer.h:580
void FlushBits()
Definition ByteBuffer.h:142
static Digest GetDigestOf(Container const &seed, uint8 const *data, size_t len)
Definition HMAC.h:41
WorldPacket const * Write() override
std::array< uint8, DigestLength > Digest
uint32 Result
the result of the authentication process, possible values are BattlenetRpcErrorCode
WorldPacket const * Write() override
Optional< AuthWaitInfo > WaitInfo
contains the queue wait information in case the account is in the login queue.
Optional< AuthSuccessInfo > SuccessInfo
contains the packet data in case that it has account information (It is never set when WaitInfo is se...
std::array< uint8, DigestLength > Digest
WorldPacket const * Write() override
std::vector< ConnectPayload > Payload
std::array< uint8, 32 > const & EncryptionKey
WorldPacket const * Write() override
WorldPacket _worldPacket
Definition Packet.h:43
std::array< uint8, 32 > constexpr EnableEncryptionSeed
ByteBuffer & operator<<(ByteBuffer &data, VirtualRealmNameInfo const &virtualRealmInfo)
std::array< uint8, 16 > constexpr EnableEncryptionContext
DataWriter< Container > Data(Container const &value)
DataWriter< Container > Data(Container const &value)
OptionalInitWriter< T > OptionalInit(Optional< T > const &value)
std::vector< RaceClassAvailability > const * AvailableClasses
the minimum AccountExpansion required to select race/class combinations
uint8 ActiveExpansionLevel
the current server expansion, the possible values are in Expansions
uint8 AccountExpansionLevel
the current expansion of this account, the possible values are in Expansions
bool ForceCharacterTemplate
forces the client to always use a character template when creating a new character.
uint32 TimeRested
affects the return value of the GetBillingTimeRested() client API call, it is the number of seconds y...
std::vector< CharacterTemplate const * > Templates
list of pre-made character templates.
Optional< Timestamp<> > ExpansionTrialExpiration
expansion trial expiration unix timestamp
Optional< uint16 > NumPlayersAlliance
number of alliance players in this realm.
uint32 VirtualRealmAddress
a special identifier made from the Index, BattleGroup and Region.
uint32 CurrencyID
this is probably used for the ingame shop.
std::vector< VirtualRealmInfo > VirtualRealms
list of realms connected to this one (inclusive)
Optional< uint16 > NumPlayersHorde
number of horde players in this realm.
bool HasFCM
true if the account has a forced character migration pending.
bool CanCreateOnlyIfExisting
Can create characters on realm only if player has other existing characters there.
uint32 WaitCount
position of the account in the login queue
uint32 WaitTime
Wait time in login queue in minutes, if sent queued and this value is 0 client displays "unknown time...
Duration< std::chrono::nanoseconds > TokenLifespan
union WorldPackets::Auth::ConnectTo::SocketAddress::@312 Address
uint32 RealmAddress
the virtual address of this realm, constructed as RealmHandle::Region << 24 | RealmHandle::Battlegrou...
std::string RealmNameActual
the name of the realm
std::string RealmNameNormalized
the name of the realm without spaces
bool IsLocal
true if the realm is the same as the account's home realm