mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Battle.net: Implemented authserver
This commit is contained in:
@@ -136,6 +136,146 @@ LOCK TABLES `autobroadcast` WRITE;
|
||||
/*!40000 ALTER TABLE `autobroadcast` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_account_bans`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_account_bans`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_account_bans` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Account id',
|
||||
`bandate` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`unbandate` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`bannedby` varchar(50) NOT NULL,
|
||||
`banreason` varchar(255) NOT NULL,
|
||||
`active` tinyint(3) unsigned NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`,`bandate`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Ban List';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_account_bans`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_account_bans` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_account_bans` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `battlenet_account_bans` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_accounts`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_accounts`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_accounts` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Identifier',
|
||||
`email` varchar(320) NOT NULL,
|
||||
`sha_pass_hash` varchar(64) NOT NULL DEFAULT '',
|
||||
`v` varchar(256) NOT NULL DEFAULT '',
|
||||
`s` varchar(64) NOT NULL DEFAULT '',
|
||||
`joindate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_ip` varchar(15) NOT NULL DEFAULT '127.0.0.1',
|
||||
`failed_logins` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`locked` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`lock_country` varchar(2) NOT NULL DEFAULT '00',
|
||||
`last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`locale` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`os` varchar(3) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='Account System';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
-- Table structure for table `battlenet_components`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_components`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_components` (
|
||||
`Program` varchar(4) NOT NULL,
|
||||
`Platform` varchar(4) NOT NULL,
|
||||
`Build` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`Program`,`Platform`,`Build`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_components`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_components` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_components` DISABLE KEYS */;
|
||||
INSERT INTO `battlenet_components` VALUES
|
||||
('Bnet','Cmp1',3),
|
||||
('Bnet','Win',21719),
|
||||
('Bnet','Win',26487),
|
||||
('Bnet','Wn64',26487),
|
||||
('Tool','Win',1569),
|
||||
('Tool','Win',2736),
|
||||
('WoW','base',12340),
|
||||
('WoW','base',15595),
|
||||
('WoW','enGB',12340),
|
||||
('WoW','enGB',15595),
|
||||
('WoW','enUS',12340),
|
||||
('WoW','enUS',15595),
|
||||
('WoW','Win',12340),
|
||||
('WoW','Win',15595),
|
||||
('WoW','Wn64',15595);
|
||||
/*!40000 ALTER TABLE `battlenet_components` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_modules`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_modules`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_modules` (
|
||||
`Hash` varchar(64) NOT NULL,
|
||||
`Name` varchar(64) NOT NULL DEFAULT '',
|
||||
`Type` varchar(8) NOT NULL,
|
||||
`System` varchar(8) NOT NULL,
|
||||
`Data` text,
|
||||
PRIMARY KEY (`Hash`),
|
||||
UNIQUE KEY `uk_name_type_system` (`Name`,`Type`,`System`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_modules`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_modules` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_modules` DISABLE KEYS */;
|
||||
INSERT INTO `battlenet_modules` VALUES
|
||||
('19c91b68752b7826df498bf73aca1103c86962a9a55a0a7033e5ad895f4d927c','Password','auth','Mc64',NULL),
|
||||
('1af5418a448f8ad05451e3f7dbb2d9af9cb13458eea2368ebfc539476b954f1c','RiskFingerprint','auth','Mc64',NULL),
|
||||
('207640724f4531d3b2a21532224d1486e8c4d2d805170381cbc3093264157960','SelectGameAccount','auth','Mac',NULL),
|
||||
('2e6d53adab37a41542b38e01f62cd365eab8805ed0de73c307cc6d9d1dfe478c','Password','auth','Win',NULL),
|
||||
('36b27cd911b33c61730a8b82c8b2495fd16e8024fc3b2dde08861c77a852941c','Thumbprint','auth','Win','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('393ca8d75aff6f04f79532cf95a88b91e5743bc59121520ac31fc4508019fe60','Token','auth','Mac',NULL),
|
||||
('3c2f63e5949aa6fd6cf330b109ca5b9adcd215beac846b7462ed3aa01d5ad6bb','Password','auth','Mac',NULL),
|
||||
('52e2978db6468dfade7c61da89513f443c9225692b5085fbe956749870993703','SelectGameAccount','auth','Mc64',NULL),
|
||||
('548b5ef9e0dd5c2f89f59c3e0979249b27505c51f0c77d2b27133726eaee0ad0','Thumbprint','auth','Mac','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('5e298e530698af905e1247e51ef0b109b352ac310ce7802a1f63613db980ed17','RiskFingerprint','auth','Win',NULL),
|
||||
('851c1d2ef926e9b9a345a460874e65517195129b9e3bdec7cc77710fa0b1fad6','Password','auth','Wn64',NULL),
|
||||
('894d25d3219d97d085ea5a8b98e66df5bd9f460ec6f104455246a12b8921409d','SelectGameAccount','auth','Wn64',NULL),
|
||||
('8c43bda10be33a32abbc09fb2279126c7f5953336391276cff588565332fcd40','RiskFingerprint','auth','Wn64',NULL),
|
||||
('a1edab845d9e13e9c84531369be2f61b930a37c8e7a9c66d11ef8963380e178a','Token','auth','Mc64',NULL),
|
||||
('a330f388b6687f8a42fe8fbb592a3df724b20b65fb0989342bb8261f2f452318','Token','auth','Wn64',NULL),
|
||||
('abc6bb719a73ec1055296001910e26afa561f701ad9995b1ecd7f55f9d3ca37c','SelectGameAccount','auth','Win',NULL),
|
||||
('b37136b39add83cfdbafa81857de3dd8f15b34e0135ec6cd9c3131d3a578d8c2','Thumbprint','auth','Mc64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('c0f38d05aa1b83065e839c9bd96c831e9f7e42477085138752657a6a9bb9c520','RiskFingerprint','auth','Mac',NULL),
|
||||
('c3a1ac0694979e709c3b5486927e558af1e2be02ca96e5615c5a65aacc829226','Thumbprint','auth','Wn64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('fbe675a99fb5f4b7fb3eb5e5a22add91a4cabf83e3c5930c6659ad13c457ba18','Token','auth','Win',NULL);
|
||||
/*!40000 ALTER TABLE `battlenet_modules` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ip2nation`
|
||||
--
|
||||
@@ -390,6 +530,8 @@ CREATE TABLE `realmlist` (
|
||||
`allowedSecurityLevel` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`population` float unsigned NOT NULL DEFAULT '0',
|
||||
`gamebuild` int(10) unsigned NOT NULL DEFAULT '15595',
|
||||
`Region` tinyint(3) unsigned NOT NULL DEFAULT '2',
|
||||
`Battlegroup` tinyint(3) unsigned NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_name` (`name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='Realm System';
|
||||
@@ -401,7 +543,7 @@ CREATE TABLE `realmlist` (
|
||||
|
||||
LOCK TABLES `realmlist` WRITE;
|
||||
/*!40000 ALTER TABLE `realmlist` DISABLE KEYS */;
|
||||
INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,15595);
|
||||
INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,15595,2,1);
|
||||
/*!40000 ALTER TABLE `realmlist` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
144
sql/updates/auth/2014_xx_xx_00_auth_battlenet.sql
Normal file
144
sql/updates/auth/2014_xx_xx_00_auth_battlenet.sql
Normal file
@@ -0,0 +1,144 @@
|
||||
ALTER TABLE `realmlist`
|
||||
ADD `Region` tinyint(3) UNSIGNED NOT NULL DEFAULT 2 AFTER `gamebuild`,
|
||||
ADD `Battlegroup` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `Region`;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_account_bans`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_account_bans`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_account_bans` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Account id',
|
||||
`bandate` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`unbandate` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`bannedby` varchar(50) NOT NULL,
|
||||
`banreason` varchar(255) NOT NULL,
|
||||
`active` tinyint(3) unsigned NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`,`bandate`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Ban List';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_account_bans`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_account_bans` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_account_bans` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `battlenet_account_bans` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_accounts`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_accounts`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_accounts` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Identifier',
|
||||
`email` varchar(320) NOT NULL,
|
||||
`sha_pass_hash` varchar(64) NOT NULL DEFAULT '',
|
||||
`v` varchar(256) NOT NULL DEFAULT '',
|
||||
`s` varchar(64) NOT NULL DEFAULT '',
|
||||
`joindate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_ip` varchar(15) NOT NULL DEFAULT '127.0.0.1',
|
||||
`failed_logins` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`locked` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`lock_country` varchar(2) NOT NULL DEFAULT '00',
|
||||
`last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`locale` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`os` varchar(3) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='Account System';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
-- Table structure for table `battlenet_components`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_components`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_components` (
|
||||
`Program` varchar(4) NOT NULL,
|
||||
`Platform` varchar(4) NOT NULL,
|
||||
`Build` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`Program`,`Platform`,`Build`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_components`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_components` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_components` DISABLE KEYS */;
|
||||
INSERT INTO `battlenet_components` VALUES
|
||||
('Bnet','Cmp1',3),
|
||||
('Bnet','Win',21719),
|
||||
('Bnet','Win',26487),
|
||||
('Bnet','Wn64',26487),
|
||||
('Tool','Win',1569),
|
||||
('Tool','Win',2736),
|
||||
('WoW','base',12340),
|
||||
('WoW','base',15595),
|
||||
('WoW','enGB',12340),
|
||||
('WoW','enGB',15595),
|
||||
('WoW','enUS',12340),
|
||||
('WoW','enUS',15595),
|
||||
('WoW','Win',12340),
|
||||
('WoW','Win',15595),
|
||||
('WoW','Wn64',15595);
|
||||
/*!40000 ALTER TABLE `battlenet_components` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `battlenet_modules`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `battlenet_modules`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `battlenet_modules` (
|
||||
`Hash` varchar(64) NOT NULL,
|
||||
`Name` varchar(64) NOT NULL DEFAULT '',
|
||||
`Type` varchar(8) NOT NULL,
|
||||
`System` varchar(8) NOT NULL,
|
||||
`Data` text,
|
||||
PRIMARY KEY (`Hash`),
|
||||
UNIQUE KEY `uk_name_type_system` (`Name`,`Type`,`System`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `battlenet_modules`
|
||||
--
|
||||
|
||||
LOCK TABLES `battlenet_modules` WRITE;
|
||||
/*!40000 ALTER TABLE `battlenet_modules` DISABLE KEYS */;
|
||||
INSERT INTO `battlenet_modules` VALUES
|
||||
('19c91b68752b7826df498bf73aca1103c86962a9a55a0a7033e5ad895f4d927c','Password','auth','Mc64',NULL),
|
||||
('1af5418a448f8ad05451e3f7dbb2d9af9cb13458eea2368ebfc539476b954f1c','RiskFingerprint','auth','Mc64',NULL),
|
||||
('207640724f4531d3b2a21532224d1486e8c4d2d805170381cbc3093264157960','SelectGameAccount','auth','Mac',NULL),
|
||||
('2e6d53adab37a41542b38e01f62cd365eab8805ed0de73c307cc6d9d1dfe478c','Password','auth','Win',NULL),
|
||||
('36b27cd911b33c61730a8b82c8b2495fd16e8024fc3b2dde08861c77a852941c','Thumbprint','auth','Win','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('393ca8d75aff6f04f79532cf95a88b91e5743bc59121520ac31fc4508019fe60','Token','auth','Mac',NULL),
|
||||
('3c2f63e5949aa6fd6cf330b109ca5b9adcd215beac846b7462ed3aa01d5ad6bb','Password','auth','Mac',NULL),
|
||||
('52e2978db6468dfade7c61da89513f443c9225692b5085fbe956749870993703','SelectGameAccount','auth','Mc64',NULL),
|
||||
('548b5ef9e0dd5c2f89f59c3e0979249b27505c51f0c77d2b27133726eaee0ad0','Thumbprint','auth','Mac','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('5e298e530698af905e1247e51ef0b109b352ac310ce7802a1f63613db980ed17','RiskFingerprint','auth','Win',NULL),
|
||||
('851c1d2ef926e9b9a345a460874e65517195129b9e3bdec7cc77710fa0b1fad6','Password','auth','Wn64',NULL),
|
||||
('894d25d3219d97d085ea5a8b98e66df5bd9f460ec6f104455246a12b8921409d','SelectGameAccount','auth','Wn64',NULL),
|
||||
('8c43bda10be33a32abbc09fb2279126c7f5953336391276cff588565332fcd40','RiskFingerprint','auth','Wn64',NULL),
|
||||
('a1edab845d9e13e9c84531369be2f61b930a37c8e7a9c66d11ef8963380e178a','Token','auth','Mc64',NULL),
|
||||
('a330f388b6687f8a42fe8fbb592a3df724b20b65fb0989342bb8261f2f452318','Token','auth','Wn64',NULL),
|
||||
('abc6bb719a73ec1055296001910e26afa561f701ad9995b1ecd7f55f9d3ca37c','SelectGameAccount','auth','Win',NULL),
|
||||
('b37136b39add83cfdbafa81857de3dd8f15b34e0135ec6cd9c3131d3a578d8c2','Thumbprint','auth','Mc64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('c0f38d05aa1b83065e839c9bd96c831e9f7e42477085138752657a6a9bb9c520','RiskFingerprint','auth','Mac',NULL),
|
||||
('c3a1ac0694979e709c3b5486927e558af1e2be02ca96e5615c5a65aacc829226','Thumbprint','auth','Wn64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('fbe675a99fb5f4b7fb3eb5e5a22add91a4cabf83e3c5930c6659ad13c457ba18','Token','auth','Win',NULL);
|
||||
/*!40000 ALTER TABLE `battlenet_modules` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "RealmList.h"
|
||||
#include "BattlenetManager.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) { }
|
||||
@@ -31,7 +32,7 @@ void RealmList::Initialize(uint32 updateInterval)
|
||||
UpdateRealms(true);
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build)
|
||||
void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build, uint8 region, uint8 battlegroup)
|
||||
{
|
||||
// Create new if not exist or update existed
|
||||
Realm& realm = m_realms[name];
|
||||
@@ -49,6 +50,8 @@ void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr co
|
||||
realm.LocalAddress = localAddr;
|
||||
realm.LocalSubnetMask = localSubmask;
|
||||
realm.gamebuild = build;
|
||||
realm.Region = region;
|
||||
realm.Battlegroup = battlegroup;
|
||||
}
|
||||
|
||||
void RealmList::UpdateIfNeed()
|
||||
@@ -91,12 +94,14 @@ void RealmList::UpdateRealms(bool init)
|
||||
uint8 allowedSecurityLevel = fields[9].GetUInt8();
|
||||
float pop = fields[10].GetFloat();
|
||||
uint32 build = fields[11].GetUInt32();
|
||||
uint8 region = fields[12].GetUInt8();
|
||||
uint8 battlegroup = fields[13].GetUInt8();
|
||||
|
||||
ACE_INET_Addr externalAddr(port, externalAddress.c_str(), AF_INET);
|
||||
ACE_INET_Addr localAddr(port, localAddress.c_str(), AF_INET);
|
||||
ACE_INET_Addr submask(0, localSubmask.c_str(), AF_INET);
|
||||
|
||||
UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
|
||||
UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build, region, battlegroup);
|
||||
|
||||
if (init)
|
||||
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.get_host_addr(), port);
|
||||
@@ -104,3 +109,16 @@ void RealmList::UpdateRealms(bool init)
|
||||
while (result->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const
|
||||
{
|
||||
auto itr = std::find_if(m_realms.begin(), m_realms.end(), [id](RealmMap::value_type const& pair)
|
||||
{
|
||||
return pair.second.Region == id.Region && pair.second.Battlegroup == id.Battlegroup && pair.second.m_ID == id.Index;
|
||||
});
|
||||
|
||||
if (itr != m_realms.end())
|
||||
return &itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,15 @@ struct Realm
|
||||
AccountTypes allowedSecurityLevel;
|
||||
float populationLevel;
|
||||
uint32 gamebuild;
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
};
|
||||
|
||||
namespace Battlenet
|
||||
{
|
||||
struct RealmId;
|
||||
}
|
||||
|
||||
/// Storage object for the list of realms on the server
|
||||
class RealmList
|
||||
{
|
||||
@@ -71,10 +78,11 @@ public:
|
||||
RealmMap::const_iterator begin() const { return m_realms.begin(); }
|
||||
RealmMap::const_iterator end() const { return m_realms.end(); }
|
||||
uint32 size() const { return m_realms.size(); }
|
||||
Realm const* GetRealm(Battlenet::RealmId const& id) const;
|
||||
|
||||
private:
|
||||
void UpdateRealms(bool init=false);
|
||||
void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build);
|
||||
void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build, uint8 region, uint8 battlegroup);
|
||||
|
||||
RealmMap m_realms;
|
||||
uint32 m_UpdateInterval;
|
||||
|
||||
@@ -986,7 +986,7 @@ bool AuthSocket::_HandleRealmList()
|
||||
pkt << AmountOfCharacters;
|
||||
pkt << realm.timezone; // realm category
|
||||
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||
pkt << uint8(0x2C); // unk, may be realm number/id?
|
||||
pkt << uint8(realm.m_ID);
|
||||
else
|
||||
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <ace/Auto_Ptr.h>
|
||||
#include <ace/Stack_Trace.h>
|
||||
|
||||
namespace Battlenet
|
||||
@@ -70,14 +72,14 @@ namespace Battlenet
|
||||
return str;
|
||||
}
|
||||
|
||||
uint8* ReadBytes(uint32 count)
|
||||
ACE_Auto_Array_Ptr<uint8> ReadBytes(uint32 count)
|
||||
{
|
||||
AlignToNextByte();
|
||||
if (_readPos + count * 8 > _numBits)
|
||||
throw BitStreamPositionException();
|
||||
|
||||
uint8* buf = new uint8[count];
|
||||
memcpy(buf, &_buffer[_readPos >> 3], count);
|
||||
ACE_Auto_Array_Ptr<uint8> buf(new uint8[count]);
|
||||
memcpy(buf.get(), &_buffer[_readPos >> 3], count);
|
||||
_readPos += count * 8;
|
||||
return buf;
|
||||
}
|
||||
@@ -105,7 +107,9 @@ namespace Battlenet
|
||||
template<typename T>
|
||||
T Read(uint32 bitCount)
|
||||
{
|
||||
T ret = 0;
|
||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type");
|
||||
|
||||
uint64 ret = 0;
|
||||
while (bitCount != 0)
|
||||
{
|
||||
uint32 bitPos = (_readPos & 7);
|
||||
@@ -114,10 +118,11 @@ namespace Battlenet
|
||||
bitsLeftInByte = bitCount;
|
||||
|
||||
bitCount -= bitsLeftInByte;
|
||||
ret |= static_cast<T>((uint64)(_buffer[_readPos >> 3] >> bitPos & (uint32)((uint8)(1 << bitsLeftInByte) - 1)) << bitCount);
|
||||
ret |= (uint64)(_buffer[_readPos >> 3] >> bitPos & (uint32)((uint8)(1 << bitsLeftInByte) - 1)) << bitCount;
|
||||
_readPos += bitsLeftInByte;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return static_cast<T>(ret);
|
||||
}
|
||||
|
||||
void WriteString(std::string const& str, uint32 bitCount, int32 baseLength = 0)
|
||||
@@ -141,7 +146,12 @@ namespace Battlenet
|
||||
_writePos += count * 8;
|
||||
}
|
||||
|
||||
//WriteFloat
|
||||
void WriteFloat(float value)
|
||||
{
|
||||
uint32 intVal = *reinterpret_cast<uint32*>(&value);
|
||||
Write(intVal, 32);
|
||||
}
|
||||
|
||||
void WriteFourCC(std::string const& fcc)
|
||||
{
|
||||
uint32 intVal = *(uint32*)fcc.c_str();
|
||||
@@ -157,6 +167,8 @@ namespace Battlenet
|
||||
template<typename T>
|
||||
void Write(T value, uint32 bitCount)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type");
|
||||
|
||||
if (_writePos + bitCount >= 8 * MaxSize)
|
||||
throw BitStreamPositionException();
|
||||
|
||||
|
||||
@@ -73,6 +73,14 @@ namespace Battlenet
|
||||
uint32 DataSize;
|
||||
uint8* Data;
|
||||
};
|
||||
|
||||
struct RealmId
|
||||
{
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
uint32 Index;
|
||||
uint32 Build;
|
||||
};
|
||||
}
|
||||
|
||||
class BattlenetMgr
|
||||
|
||||
@@ -75,6 +75,12 @@ std::string Battlenet::AuthChallenge::ToString() const
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
Battlenet::ProofRequest::~ProofRequest()
|
||||
{
|
||||
for (size_t i = 0; i < Modules.size(); ++i)
|
||||
delete Modules[i];
|
||||
}
|
||||
|
||||
void Battlenet::ProofRequest::Write()
|
||||
{
|
||||
_stream.Write(Modules.size(), 3);
|
||||
@@ -93,7 +99,7 @@ std::string Battlenet::ProofRequest::ToString() const
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::ProofRequest modules " << Modules.size();
|
||||
for (ModuleInfo const* module : Modules)
|
||||
stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", BlobSize " << module->DataSize;
|
||||
stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize);
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
@@ -101,7 +107,7 @@ std::string Battlenet::ProofRequest::ToString() const
|
||||
Battlenet::ProofResponse::~ProofResponse()
|
||||
{
|
||||
for (size_t i = 0; i < Modules.size(); ++i)
|
||||
delete[] Modules[i].Data;
|
||||
delete Modules[i];
|
||||
}
|
||||
|
||||
void Battlenet::ProofResponse::Read()
|
||||
@@ -109,9 +115,9 @@ void Battlenet::ProofResponse::Read()
|
||||
Modules.resize(_stream.Read<uint32>(3));
|
||||
for (size_t i = 0; i < Modules.size(); ++i)
|
||||
{
|
||||
ModuleData& data = Modules[i];
|
||||
data.Size = _stream.Read<uint32>(10);
|
||||
data.Data = _stream.ReadBytes(data.Size);
|
||||
BitStream*& dataStream = Modules[i];
|
||||
dataStream = new BitStream(_stream.Read<uint32>(10));
|
||||
memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,10 +125,10 @@ std::string Battlenet::ProofResponse::ToString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::ProofResponse Modules " << Modules.size();
|
||||
for (ModuleData const& module : Modules)
|
||||
for (BitStream* module : Modules)
|
||||
{
|
||||
std::string hexStr = ByteArrayToHexStr(module.Data, module.Size);
|
||||
stream << std::endl << "Battlenet::ProofResponse::ModuleData Size: " << module.Size << ", Data: " << hexStr;
|
||||
std::string hexStr = ByteArrayToHexStr(module->GetBuffer(), module->GetSize());
|
||||
stream << std::endl << "Battlenet::ProofResponse::ModuleData Size: " << module->GetSize() << ", Data: " << hexStr;
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
@@ -156,7 +162,20 @@ void Battlenet::AuthComplete::Write()
|
||||
}
|
||||
}
|
||||
|
||||
// todo more
|
||||
_stream.WriteString(FirstName, 8); // First name
|
||||
_stream.WriteString(LastName, 8); // Last name - not set for WoW
|
||||
|
||||
_stream.Write(GameAccountId, 32);
|
||||
|
||||
_stream.Write(2, 8);
|
||||
_stream.Write(0, 64);
|
||||
_stream.Write(2, 8);
|
||||
|
||||
_stream.WriteString(GameAccountName, 5, -1);
|
||||
|
||||
_stream.Write(0, 64); // Account flags
|
||||
_stream.Write(0, 32);
|
||||
_stream.Write(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -174,8 +193,8 @@ void Battlenet::AuthComplete::Write()
|
||||
_stream.Write(ErrorType, 2);
|
||||
if (ErrorType == 1)
|
||||
{
|
||||
_stream.Write<uint16>(Result, 16);
|
||||
_stream.Write(0, 32);
|
||||
_stream.Write(Result, 16);
|
||||
_stream.Write(0x80000000, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,3 +209,127 @@ void Battlenet::AuthComplete::SetAuthResult(AuthResult result)
|
||||
ErrorType = result != AUTH_OK ? 1 : 0;
|
||||
Result = result;
|
||||
}
|
||||
|
||||
Battlenet::RealmCharacterCounts::~RealmCharacterCounts()
|
||||
{
|
||||
for (ServerPacket* realmData : RealmData)
|
||||
delete realmData;
|
||||
}
|
||||
|
||||
void Battlenet::RealmCharacterCounts::Write()
|
||||
{
|
||||
_stream.Write(false, 1); // failure
|
||||
_stream.Write(CharacterCounts.size(), 7);
|
||||
for (CharacterCountEntry const& entry : CharacterCounts)
|
||||
{
|
||||
_stream.Write(entry.Realm.Region, 8);
|
||||
_stream.Write(0, 12);
|
||||
_stream.Write(entry.Realm.Battlegroup, 8);
|
||||
_stream.Write(entry.Realm.Index, 32);
|
||||
_stream.Write(entry.CharacterCount, 16);
|
||||
}
|
||||
|
||||
for (ServerPacket* realmData : RealmData)
|
||||
{
|
||||
realmData->Write();
|
||||
_stream.WriteBytes(realmData->GetData(), realmData->GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
std::string Battlenet::RealmCharacterCounts::ToString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::RealmCharacterCounts Realms " << CharacterCounts.size();
|
||||
|
||||
for (CharacterCountEntry const& entry : CharacterCounts)
|
||||
stream << std::endl << "Region " << entry.Realm.Region << " Battlegroup " << entry.Realm.Region << " Index " << entry.Realm.Index << " Characters " << entry.CharacterCount;
|
||||
|
||||
return stream.str().c_str();
|
||||
}
|
||||
|
||||
void Battlenet::RealmUpdate::Write()
|
||||
{
|
||||
_stream.Write(true, 1); // Success
|
||||
_stream.Write(Timezone, 32);
|
||||
_stream.WriteFloat(Population);
|
||||
_stream.Write(Lock, 8);
|
||||
_stream.Write(0, 19);
|
||||
_stream.Write(Type + std::numeric_limits<int32>::min(), 32);
|
||||
_stream.WriteString(Name, 10);
|
||||
|
||||
_stream.Write(!Version.empty(), 1);
|
||||
if (!Version.empty())
|
||||
{
|
||||
_stream.WriteString(Version, 5);
|
||||
_stream.Write(Build, 32);
|
||||
|
||||
uint32 ip = Address.get_ip_address();
|
||||
uint16 port = Address.get_port_number();
|
||||
|
||||
EndianConvertReverse(ip);
|
||||
EndianConvertReverse(port);
|
||||
|
||||
_stream.WriteBytes(&ip, 4);
|
||||
_stream.WriteBytes(&port, 2);
|
||||
}
|
||||
|
||||
_stream.Write(Flags, 8);
|
||||
_stream.Write(Region, 8);
|
||||
_stream.Write(0, 12);
|
||||
_stream.Write(Battlegroup, 8);
|
||||
_stream.Write(Index, 32);
|
||||
}
|
||||
|
||||
std::string Battlenet::RealmUpdate::ToString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::RealmUpdate Timezone " << Timezone << " Population " << Population << " Lock " << Lock << " Type " << Type << " Name " << Name
|
||||
<< " Flags " << Flags << " Region " << Region << " Battlegroup " << Battlegroup << " Index " << Index;
|
||||
|
||||
if (!Version.empty())
|
||||
stream << " Version " << Version;
|
||||
|
||||
return stream.str().c_str();
|
||||
}
|
||||
|
||||
void Battlenet::RealmJoinRequest::Read()
|
||||
{
|
||||
ClientSeed = _stream.Read<uint32>(32);
|
||||
Unknown = _stream.Read<uint32>(20);
|
||||
Realm.Region = _stream.Read<uint8>(8);
|
||||
_stream.Read<uint16>(12);
|
||||
Realm.Battlegroup = _stream.Read<uint8>(8);
|
||||
Realm.Index = _stream.Read<uint32>(32);
|
||||
}
|
||||
|
||||
std::string Battlenet::RealmJoinRequest::ToString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::RealmJoinRequest ClientSeed" << ClientSeed << " Region " << Realm.Region << " Battlegroup " << Realm.Battlegroup << " Index " << Realm.Index;
|
||||
return stream.str().c_str();
|
||||
}
|
||||
|
||||
void Battlenet::RealmJoinResult::Write()
|
||||
{
|
||||
_stream.Write(0, 1); // Fail
|
||||
_stream.Write(ServerSeed, 32);
|
||||
_stream.Write(IPv4.size(), 5);
|
||||
for (ACE_INET_Addr const& addr : IPv4)
|
||||
{
|
||||
uint32 ip = addr.get_ip_address();
|
||||
uint16 port = addr.get_port_number();
|
||||
|
||||
EndianConvertReverse(ip);
|
||||
EndianConvertReverse(port);
|
||||
|
||||
_stream.WriteBytes(&ip, 4);
|
||||
_stream.WriteBytes(&port, 2);
|
||||
}
|
||||
|
||||
_stream.Write(0, 5); // IPv6 addresses
|
||||
}
|
||||
|
||||
std::string Battlenet::RealmJoinResult::ToString() const
|
||||
{
|
||||
return "Battlenet::RealmJoinResult";
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ namespace Battlenet
|
||||
|
||||
enum Channel
|
||||
{
|
||||
NOT_SPECIFIED = -1,
|
||||
|
||||
AUTHENTICATION = 0,
|
||||
CREEP = 1,
|
||||
WOW = 2
|
||||
@@ -48,10 +46,29 @@ namespace Battlenet
|
||||
SMSG_AUTH_PROOF_REQUEST = 0x2,
|
||||
};
|
||||
|
||||
enum CreepOpcodes
|
||||
{
|
||||
CMSG_PING = 0x0,
|
||||
CMSG_ENABLE_ENCRYPTION = 0x5,
|
||||
|
||||
SMSG_PONG = 0x0
|
||||
};
|
||||
|
||||
enum WoWOpcodes
|
||||
{
|
||||
CMSG_REALM_UPDATE = 0x0,
|
||||
CMSG_JOIN_REQUEST = 0x8,
|
||||
|
||||
SMSG_CHARACTER_COUNTS = 0x0,
|
||||
SMSG_REALM_UPDATE = 0x2,
|
||||
SMSG_REALM_UPDATE_END = 0x3,
|
||||
SMSG_JOIN_RESULT = 0x8
|
||||
};
|
||||
|
||||
struct PacketHeader
|
||||
{
|
||||
PacketHeader(uint32 opcode, uint32 channel) : Opcode(opcode), Channel(channel) { }
|
||||
PacketHeader() : Opcode(0), Channel(NOT_SPECIFIED) { }
|
||||
PacketHeader() : Opcode(0), Channel(AUTHENTICATION) { }
|
||||
|
||||
uint32 Opcode;
|
||||
int32 Channel;
|
||||
@@ -142,11 +159,12 @@ namespace Battlenet
|
||||
{
|
||||
public:
|
||||
ProofRequest() : ServerPacket(PacketHeader(SMSG_AUTH_PROOF_REQUEST, AUTHENTICATION)) { }
|
||||
~ProofRequest();
|
||||
|
||||
void Write() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
std::vector<ModuleInfo const*> Modules;
|
||||
std::vector<ModuleInfo*> Modules;
|
||||
};
|
||||
|
||||
class ProofResponse final : public ClientPacket
|
||||
@@ -159,23 +177,18 @@ namespace Battlenet
|
||||
|
||||
~ProofResponse();
|
||||
|
||||
struct ModuleData
|
||||
{
|
||||
uint32 Size;
|
||||
uint8* Data;
|
||||
};
|
||||
|
||||
void Read() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
std::vector<ModuleData> Modules;
|
||||
std::vector<BitStream*> Modules;
|
||||
};
|
||||
|
||||
class AuthComplete final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
AuthComplete() : ServerPacket(PacketHeader(SMSG_AUTH_COMPLETE, AUTHENTICATION)),
|
||||
Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(1000000), Rate(1000)
|
||||
Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(25000000), Rate(1000),
|
||||
FirstName(""), LastName(""), GameAccountId(0), GameAccountName("")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -192,6 +205,108 @@ namespace Battlenet
|
||||
uint32 Rate;
|
||||
std::string FirstName;
|
||||
std::string LastName;
|
||||
uint32 GameAccountId;
|
||||
std::string GameAccountName;
|
||||
uint64 AccountFlags;
|
||||
};
|
||||
|
||||
class Pong final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
Pong() : ServerPacket(PacketHeader(SMSG_PONG, CREEP))
|
||||
{
|
||||
}
|
||||
|
||||
void Write() override { }
|
||||
std::string ToString() const override { return "Battlenet::Pong"; }
|
||||
};
|
||||
|
||||
class RealmCharacterCounts final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
RealmCharacterCounts() : ServerPacket(PacketHeader(SMSG_CHARACTER_COUNTS, WOW))
|
||||
{
|
||||
}
|
||||
~RealmCharacterCounts();
|
||||
|
||||
struct CharacterCountEntry
|
||||
{
|
||||
RealmId Realm;
|
||||
uint32 CharacterCount;
|
||||
};
|
||||
|
||||
void Write() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
std::vector<CharacterCountEntry> CharacterCounts;
|
||||
std::vector<ServerPacket*> RealmData;
|
||||
};
|
||||
|
||||
class RealmUpdate final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
RealmUpdate() : ServerPacket(PacketHeader(SMSG_REALM_UPDATE, WOW)),
|
||||
Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""),
|
||||
Address(), Flags(0), Region(0), Battlegroup(0), Index(0), Build(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Write() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
uint32 Timezone;
|
||||
float Population;
|
||||
uint8 Lock;
|
||||
uint32 Type;
|
||||
std::string Name;
|
||||
std::string Version;
|
||||
ACE_INET_Addr Address;
|
||||
uint8 Flags;
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
uint32 Index;
|
||||
uint32 Build;
|
||||
};
|
||||
|
||||
class RealmUpdateComplete final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
RealmUpdateComplete() : ServerPacket(PacketHeader(SMSG_REALM_UPDATE_END, WOW))
|
||||
{
|
||||
}
|
||||
|
||||
void Write() override { }
|
||||
std::string ToString() const override { return "Battlenet::RealmUpdateComplete"; }
|
||||
};
|
||||
|
||||
class RealmJoinRequest final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
RealmJoinRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
{
|
||||
ASSERT(header == PacketHeader(CMSG_JOIN_REQUEST, WOW) && "Invalid packet header for RealmJoinRequest");
|
||||
}
|
||||
|
||||
void Read() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
uint32 ClientSeed;
|
||||
uint32 Unknown;
|
||||
RealmId Realm;
|
||||
};
|
||||
|
||||
class RealmJoinResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
RealmJoinResult() : ServerPacket(PacketHeader(SMSG_JOIN_RESULT, WOW)), ServerSeed(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Write() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
uint32 ServerSeed;
|
||||
std::vector<ACE_INET_Addr> IPv4;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,134 @@
|
||||
#include "AuthCodes.h"
|
||||
#include "BattlenetBitStream.h"
|
||||
#include "BattlenetSocket.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "HmacHash.h"
|
||||
#include "Log.h"
|
||||
#include "RealmList.h"
|
||||
#include "SHA256.h"
|
||||
#include <map>
|
||||
|
||||
uint32 const Battlenet::Socket::SRP6_V_Size = 128;
|
||||
uint32 const Battlenet::Socket::SRP6_S_Size = 32;
|
||||
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> InitHandlers()
|
||||
{
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> handlers;
|
||||
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE_NEW, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthProofResponse;
|
||||
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_PING, Battlenet::CREEP)] = &Battlenet::Socket::HandlePing;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_ENABLE_ENCRYPTION, Battlenet::CREEP)] = &Battlenet::Socket::HandleEnableEncryption;
|
||||
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_REALM_UPDATE, Battlenet::WOW)] = &Battlenet::Socket::HandleRealmUpdate;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_JOIN_REQUEST, Battlenet::WOW)] = &Battlenet::Socket::HandleRealmJoinRequest;
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> Handlers = InitHandlers();
|
||||
|
||||
Battlenet::Socket::ModuleHandler const Battlenet::Socket::ModuleHandlers[MODULE_COUNT] =
|
||||
{
|
||||
&Battlenet::Socket::HandlePasswordModule,
|
||||
&Battlenet::Socket::UnhandledModule,
|
||||
&Battlenet::Socket::UnhandledModule,
|
||||
&Battlenet::Socket::HandleSelectGameAccountModule,
|
||||
&Battlenet::Socket::HandleRiskFingerprintModule,
|
||||
};
|
||||
|
||||
Battlenet::Socket::Socket(RealmSocket& socket) : _socket(socket), _accountId(0), _accountName(), _locale(),
|
||||
_os(), _build(0), _gameAccountId(0), _accountSecurityLevel(SEC_PLAYER)
|
||||
{
|
||||
static uint8 const N_Bytes[] =
|
||||
{
|
||||
0xAB, 0x24, 0x43, 0x63, 0xA9, 0xC2, 0xA6, 0xC3, 0x3B, 0x37, 0xE4, 0x61, 0x84, 0x25, 0x9F, 0x8B,
|
||||
0x3F, 0xCB, 0x8A, 0x85, 0x27, 0xFC, 0x3D, 0x87, 0xBE, 0xA0, 0x54, 0xD2, 0x38, 0x5D, 0x12, 0xB7,
|
||||
0x61, 0x44, 0x2E, 0x83, 0xFA, 0xC2, 0x21, 0xD9, 0x10, 0x9F, 0xC1, 0x9F, 0xEA, 0x50, 0xE3, 0x09,
|
||||
0xA6, 0xE5, 0x5E, 0x23, 0xA7, 0x77, 0xEB, 0x00, 0xC7, 0xBA, 0xBF, 0xF8, 0x55, 0x8A, 0x0E, 0x80,
|
||||
0x2B, 0x14, 0x1A, 0xA2, 0xD4, 0x43, 0xA9, 0xD4, 0xAF, 0xAD, 0xB5, 0xE1, 0xF5, 0xAC, 0xA6, 0x13,
|
||||
0x1C, 0x69, 0x78, 0x64, 0x0B, 0x7B, 0xAF, 0x9C, 0xC5, 0x50, 0x31, 0x8A, 0x23, 0x08, 0x01, 0xA1,
|
||||
0xF5, 0xFE, 0x31, 0x32, 0x7F, 0xE2, 0x05, 0x82, 0xD6, 0x0B, 0xED, 0x4D, 0x55, 0x32, 0x41, 0x94,
|
||||
0x29, 0x6F, 0x55, 0x7D, 0xE3, 0x0F, 0x77, 0x19, 0xE5, 0x6C, 0x30, 0xEB, 0xDE, 0xF6, 0xA7, 0x86
|
||||
};
|
||||
|
||||
N.SetBinary(N_Bytes, sizeof(N_Bytes));
|
||||
g.SetDword(2);
|
||||
|
||||
SHA256Hash sha;
|
||||
sha.UpdateBigNumbers(&N, &g, NULL);
|
||||
sha.Finalize();
|
||||
k.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
}
|
||||
|
||||
void Battlenet::Socket::_SetVSFields(std::string const& pstr)
|
||||
{
|
||||
s.SetRand(SRP6_S_Size * 8);
|
||||
|
||||
BigNumber p;
|
||||
p.SetHexStr(pstr.c_str());
|
||||
|
||||
SHA256Hash sha;
|
||||
sha.UpdateBigNumbers(&s, &p, NULL);
|
||||
sha.Finalize();
|
||||
BigNumber x;
|
||||
x.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
v = g.ModExp(x, N);
|
||||
|
||||
char* v_hex = v.AsHexStr();
|
||||
char* s_hex = s.AsHexStr();
|
||||
|
||||
LoginDatabase.PExecute("UPDATE battlenet_accounts SET s = '%s', v = '%s' WHERE email ='%s'", s_hex, v_hex, _accountName.c_str());
|
||||
|
||||
OPENSSL_free(v_hex);
|
||||
OPENSSL_free(s_hex);
|
||||
}
|
||||
|
||||
ACE_INET_Addr const& Battlenet::Socket::GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr)
|
||||
{
|
||||
// Attempt to send best address for client
|
||||
if (clientAddr.is_loopback())
|
||||
{
|
||||
// Try guessing if realm is also connected locally
|
||||
if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback())
|
||||
return clientAddr;
|
||||
|
||||
// Assume that user connecting from the machine that authserver is located on
|
||||
// has all realms available in his local network
|
||||
return realm.LocalAddress;
|
||||
}
|
||||
|
||||
// Check if connecting client is in the same network
|
||||
if (IsIPAddrInNetwork(realm.LocalAddress, clientAddr, realm.LocalSubnetMask))
|
||||
return realm.LocalAddress;
|
||||
|
||||
// Return external IP
|
||||
return realm.ExternalAddress;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleAuthChallenge(PacketHeader& header, BitStream& packet)
|
||||
{
|
||||
|
||||
// Verify that this IP is not in the ip_banned table
|
||||
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
|
||||
|
||||
std::string const& ip_address = _socket.getRemoteAddress();
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED);
|
||||
stmt->setString(0, ip_address);
|
||||
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(LOGIN_BANNED);
|
||||
Send(complete);
|
||||
TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Banned ip '%s:%d' tries to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort());
|
||||
return true;
|
||||
}
|
||||
|
||||
AuthChallenge info(header, packet);
|
||||
info.Read();
|
||||
|
||||
printf("%s\n", info.ToString().c_str());
|
||||
|
||||
if (info.Program != "WoW")
|
||||
{
|
||||
AuthComplete complete;
|
||||
@@ -66,109 +185,642 @@ bool Battlenet::Socket::HandleAuthChallenge(PacketHeader& header, BitStream& pac
|
||||
Send(complete);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (component.Platform == "base")
|
||||
_build = component.Build;
|
||||
}
|
||||
|
||||
_accountName = info.Login;
|
||||
_locale = info.Locale;
|
||||
_os = info.Platform;
|
||||
|
||||
Utf8ToUpperOnlyLatin(_accountName);
|
||||
LoginDatabase.EscapeString(_accountName);
|
||||
// 0 1 2 3 4 5 6
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT sha_pass_hash, id, locked, lock_country, last_ip, v, s FROM battlenet_accounts WHERE email = '%s'", _accountName.c_str());
|
||||
if (!result)
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
|
||||
Send(complete);
|
||||
return true;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
_accountId = fields[1].GetUInt32();
|
||||
|
||||
// If the IP is 'locked', check that the player comes indeed from the correct IP address
|
||||
if (fields[2].GetUInt8() == 1) // if ip is locked
|
||||
{
|
||||
TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str());
|
||||
|
||||
if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0)
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(AUTH_ACCOUNT_LOCKED);
|
||||
Send(complete);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to ip", _accountName.c_str());
|
||||
std::string accountCountry = fields[3].GetString();
|
||||
if (accountCountry.empty() || accountCountry == "00")
|
||||
TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to country", _accountName.c_str());
|
||||
else if (!accountCountry.empty())
|
||||
{
|
||||
uint32 ip = inet_addr(ip_address.c_str());
|
||||
EndianConvertReverse(ip);
|
||||
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
|
||||
stmt->setUInt32(0, ip);
|
||||
if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt))
|
||||
{
|
||||
std::string loginCountry = (*sessionCountryQuery)[0].GetString();
|
||||
TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str());
|
||||
if (loginCountry != accountCountry)
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(AUTH_ACCOUNT_LOCKED);
|
||||
Send(complete);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//set expired bans to inactive
|
||||
LoginDatabase.DirectExecute("UPDATE battlenet_account_bans SET active = 0 WHERE active = 1 AND unbandate <> bandate AND unbandate <= UNIX_TIMESTAMP()");
|
||||
|
||||
// If the account is banned, reject the logon attempt
|
||||
QueryResult banresult = LoginDatabase.PQuery("SELECT bandate, unbandate FROM battlenet_account_bans WHERE id = %u AND active = 1", _accountId);
|
||||
if (banresult)
|
||||
{
|
||||
Field* fields = banresult->Fetch();
|
||||
if (fields[0].GetUInt32() == fields[1].GetUInt32())
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(LOGIN_BANNED);
|
||||
Send(complete);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(LOGIN_SUSPENDED);
|
||||
Send(complete);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SHA256Hash sha;
|
||||
sha.UpdateData(_accountName);
|
||||
sha.Finalize();
|
||||
|
||||
I.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
|
||||
ModuleInfo* password = new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "Password" }));
|
||||
ModuleInfo* thumbprint = new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "Thumbprint" }));
|
||||
|
||||
std::string pStr = fields[0].GetString();
|
||||
|
||||
std::string databaseV = fields[5].GetString();
|
||||
std::string databaseS = fields[6].GetString();
|
||||
|
||||
if (databaseV.size() != SRP6_V_Size * 2 || databaseS.size() != SRP6_S_Size * 2)
|
||||
_SetVSFields(pStr);
|
||||
else
|
||||
{
|
||||
s.SetHexStr(databaseS.c_str());
|
||||
v.SetHexStr(databaseV.c_str());
|
||||
}
|
||||
|
||||
b.SetRand(128 * 8);
|
||||
B = ((v * k) + g.ModExp(b, N)) % N;
|
||||
|
||||
BitStream passwordData;
|
||||
uint8 state = 0;
|
||||
passwordData.WriteBytes(&state, 1);
|
||||
passwordData.WriteBytes(I.AsByteArray(32).get(), 32);
|
||||
passwordData.WriteBytes(s.AsByteArray(32).get(), 32);
|
||||
passwordData.WriteBytes(B.AsByteArray(128).get(), 128);
|
||||
passwordData.WriteBytes(b.AsByteArray(128).get(), 128);
|
||||
|
||||
password->DataSize = passwordData.GetSize();
|
||||
password->Data = new uint8[password->DataSize];
|
||||
memcpy(password->Data, passwordData.GetBuffer(), password->DataSize);
|
||||
|
||||
_modulesWaitingForData.push(MODULE_PASSWORD);
|
||||
|
||||
ProofRequest request;
|
||||
request.Modules.push_back(password);
|
||||
// if has authenticator, send Token module
|
||||
request.Modules.push_back(thumbprint);
|
||||
Send(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleAuthProofResponse(PacketHeader& header, BitStream& packet)
|
||||
{
|
||||
ProofResponse response(header, packet);
|
||||
response.Read();
|
||||
ProofResponse proof(header, packet);
|
||||
proof.Read();
|
||||
|
||||
printf("%s\n", response.ToString().c_str());
|
||||
if (_modulesWaitingForData.size() < proof.Modules.size())
|
||||
{
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
Send(complete);
|
||||
return true;
|
||||
}
|
||||
|
||||
AuthComplete complete;
|
||||
complete.SetAuthResult(AUTH_USE_GRUNT_LOGON);
|
||||
Send(complete);
|
||||
ServerPacket* response = nullptr;
|
||||
for (size_t i = 0; i < proof.Modules.size(); ++i)
|
||||
{
|
||||
if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proof.Modules[i], &response))
|
||||
break;
|
||||
|
||||
_modulesWaitingForData.pop();
|
||||
}
|
||||
|
||||
if (!response)
|
||||
{
|
||||
response = new AuthComplete();
|
||||
static_cast<AuthComplete*>(response)->SetAuthResult(AUTH_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
Send(*response);
|
||||
delete response;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> InitHandlers()
|
||||
bool Battlenet::Socket::HandlePing(PacketHeader& /*header*/, BitStream& /*packet*/)
|
||||
{
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> handlers;
|
||||
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE_NEW, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
|
||||
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthProofResponse;
|
||||
|
||||
return handlers;
|
||||
Pong pong;
|
||||
Send(pong);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> Handlers = InitHandlers();
|
||||
|
||||
Battlenet::Socket::Socket(RealmSocket& socket) : _socket(socket), _currentChannel(0)
|
||||
bool Battlenet::Socket::HandleEnableEncryption(PacketHeader& /*header*/, BitStream& packet)
|
||||
{
|
||||
_crypt.Init(&K);
|
||||
_crypt.DecryptRecv(packet.GetBuffer() + 2, packet.GetSize() - 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleRealmUpdate(PacketHeader& /*header*/, BitStream& /*packet*/)
|
||||
{
|
||||
sRealmList->UpdateIfNeed();
|
||||
|
||||
RealmCharacterCounts counts;
|
||||
|
||||
ACE_INET_Addr clientAddr;
|
||||
_socket.peer().get_remote_addr(clientAddr);
|
||||
|
||||
for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
|
||||
{
|
||||
Realm const& realm = i->second;
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM);
|
||||
stmt->setUInt32(0, realm.m_ID);
|
||||
stmt->setUInt32(1, _gameAccountId);
|
||||
|
||||
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
|
||||
counts.CharacterCounts.push_back({ { realm.Region, realm.Battlegroup, realm.m_ID, 0 }, (*result)[0].GetUInt8() });
|
||||
|
||||
uint32 flag = realm.flag;
|
||||
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild);
|
||||
if (realm.gamebuild != _build)
|
||||
{
|
||||
if (!buildInfo)
|
||||
continue;
|
||||
|
||||
flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
|
||||
}
|
||||
|
||||
if (!buildInfo)
|
||||
flag &= ~REALM_FLAG_SPECIFYBUILD;
|
||||
|
||||
RealmUpdate* update = new RealmUpdate();
|
||||
update->Timezone = realm.timezone;
|
||||
update->Population = realm.populationLevel;
|
||||
update->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||
update->Type = realm.icon;
|
||||
update->Name = realm.name;
|
||||
|
||||
if (flag & REALM_FLAG_SPECIFYBUILD)
|
||||
{
|
||||
std::ostringstream version;
|
||||
version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->HotfixVersion;
|
||||
|
||||
update->Version = version.str();
|
||||
update->Address = GetAddressForClient(realm, clientAddr);
|
||||
update->Build = realm.gamebuild;
|
||||
}
|
||||
|
||||
update->Flags = flag;
|
||||
update->Region = realm.Region;
|
||||
update->Battlegroup = realm.Battlegroup;
|
||||
update->Index = realm.m_ID;
|
||||
|
||||
counts.RealmData.push_back(update);
|
||||
}
|
||||
|
||||
counts.RealmData.push_back(new RealmUpdateComplete());
|
||||
|
||||
Send(counts);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleRealmJoinRequest(PacketHeader& header, BitStream& packet)
|
||||
{
|
||||
RealmJoinRequest join(header, packet);
|
||||
join.Read();
|
||||
|
||||
RealmJoinResult result;
|
||||
Realm const* realm = sRealmList->GetRealm(join.Realm);
|
||||
if (!realm)
|
||||
{
|
||||
Send(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
result.ServerSeed = uint32(rand32());
|
||||
|
||||
uint8 sessionKey[40];
|
||||
HmacHash hmac(K.GetNumBytes(), K.AsByteArray().get(), EVP_sha1(), SHA_DIGEST_LENGTH);
|
||||
hmac.UpdateData((uint8*)"WoW\0", 4);
|
||||
hmac.UpdateData((uint8*)&join.ClientSeed, 4);
|
||||
hmac.UpdateData((uint8*)&result.ServerSeed, 4);
|
||||
hmac.Finalize();
|
||||
|
||||
memcpy(sessionKey, hmac.GetDigest(), hmac.GetLength());
|
||||
|
||||
HmacHash hmac2(K.GetNumBytes(), K.AsByteArray().get(), EVP_sha1(), SHA_DIGEST_LENGTH);
|
||||
hmac2.UpdateData((uint8*)"WoW\0", 4);
|
||||
hmac2.UpdateData((uint8*)&result.ServerSeed, 4);
|
||||
hmac2.UpdateData((uint8*)&join.ClientSeed, 4);
|
||||
hmac2.Finalize();
|
||||
|
||||
memcpy(sessionKey + hmac.GetLength(), hmac2.GetDigest(), hmac2.GetLength());
|
||||
|
||||
LoginDatabase.DirectPExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u",
|
||||
ByteArrayToHexStr(sessionKey, 40, true).c_str(), _socket.getRemoteAddress().c_str(), GetLocaleByName(_locale), _os.c_str(), _gameAccountId);
|
||||
|
||||
result.IPv4.push_back(realm->ExternalAddress);
|
||||
if (realm->ExternalAddress != realm->LocalAddress)
|
||||
result.IPv4.push_back(realm->LocalAddress);
|
||||
|
||||
Send(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Battlenet::Socket::OnRead()
|
||||
{
|
||||
while (1)
|
||||
size_t length = _socket.recv_len();
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
BitStream packet(length);
|
||||
if (!_socket.recv((char*)packet.GetBuffer(), length))
|
||||
return;
|
||||
|
||||
_crypt.DecryptRecv(packet.GetBuffer(), length);
|
||||
|
||||
while (!packet.IsRead())
|
||||
{
|
||||
size_t length = _socket.recv_len();
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
BitStream packet(length);
|
||||
if (!_socket.recv((char*)packet.GetBuffer(), length))
|
||||
return;
|
||||
|
||||
while (!packet.IsRead())
|
||||
try
|
||||
{
|
||||
try
|
||||
PacketHeader header;
|
||||
header.Opcode = packet.Read<uint32>(6);
|
||||
if (packet.Read<bool>(1))
|
||||
header.Channel = packet.Read<int32>(4);
|
||||
|
||||
TC_LOG_TRACE("server.battlenet", "Battlenet::Socket::OnRead %s", header.ToString().c_str());
|
||||
std::map<PacketHeader, PacketHandler>::const_iterator itr = Handlers.find(header);
|
||||
if (itr != Handlers.end())
|
||||
{
|
||||
PacketHeader header;
|
||||
header.Opcode = packet.Read<uint32>(6);
|
||||
if (packet.Read<uint32>(1))
|
||||
_currentChannel = header.Channel = packet.Read<int32>(4);
|
||||
else
|
||||
header.Channel = _currentChannel;
|
||||
|
||||
printf("Battlenet::Socket::OnRead %s\n", header.ToString().c_str());
|
||||
std::map<PacketHeader, PacketHandler>::const_iterator itr = Handlers.find(header);
|
||||
if (itr != Handlers.end())
|
||||
{
|
||||
if (!(this->*(itr->second))(header, packet))
|
||||
{
|
||||
_socket.shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Battlenet::Socket::OnRead Unhandled opcode %s\n", header.ToString().c_str());
|
||||
|
||||
packet.AlignToNextByte();
|
||||
if ((this->*(itr->second))(header, packet))
|
||||
break;
|
||||
}
|
||||
catch (BitStreamPositionException const& e)
|
||||
else
|
||||
{
|
||||
printf("Battlenet::Socket::OnRead Exception: %s\n", e.what());
|
||||
_socket.shutdown();
|
||||
TC_LOG_DEBUG("server.battlenet", "Battlenet::Socket::OnRead Unhandled opcode %s", header.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
packet.AlignToNextByte();
|
||||
}
|
||||
catch (BitStreamPositionException const& e)
|
||||
{
|
||||
TC_LOG_ERROR("server.battlenet", "Battlenet::Socket::OnRead Exception: %s", e.what());
|
||||
_socket.shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Battlenet::Socket::OnAccept()
|
||||
{
|
||||
printf("Battlenet::Socket::OnAccept\n");
|
||||
TC_LOG_TRACE("server.battlenet", "Battlenet::Socket::OnAccept");
|
||||
}
|
||||
|
||||
void Battlenet::Socket::OnClose()
|
||||
{
|
||||
printf("Battlenet::Socket::OnClose\n");
|
||||
TC_LOG_TRACE("server.battlenet", "Battlenet::Socket::OnClose");
|
||||
}
|
||||
|
||||
void Battlenet::Socket::Send(ServerPacket& packet)
|
||||
{
|
||||
printf("Battlenet::Socket::Send %s\n", packet.ToString().c_str());
|
||||
|
||||
packet.Write();
|
||||
|
||||
_crypt.EncryptSend(const_cast<uint8*>(packet.GetData()), packet.GetSize());
|
||||
_socket.send(reinterpret_cast<char const*>(packet.GetData()), packet.GetSize());
|
||||
}
|
||||
|
||||
inline void ReplaceResponse(Battlenet::ServerPacket** oldResponse, Battlenet::ServerPacket* newResponse)
|
||||
{
|
||||
if (*oldResponse)
|
||||
delete *oldResponse;
|
||||
|
||||
*oldResponse = newResponse;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandlePasswordModule(BitStream* dataStream, ServerPacket** response)
|
||||
{
|
||||
if (dataStream->GetSize() != 1 + 128 + 32 + 128)
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dataStream->Read<uint8>(8) != 2) // State
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BigNumber A, clientM1, clientChallenge;
|
||||
A.SetBinary(dataStream->ReadBytes(128).get(), 128);
|
||||
clientM1.SetBinary(dataStream->ReadBytes(32).get(), 32);
|
||||
clientChallenge.SetBinary(dataStream->ReadBytes(128).get(), 128);
|
||||
|
||||
if (A.isZero())
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
SHA256Hash sha;
|
||||
sha.UpdateBigNumbers(&A, &B, NULL);
|
||||
sha.Finalize();
|
||||
|
||||
BigNumber u;
|
||||
u.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
|
||||
BigNumber S = ((A * v.ModExp(u, N)) % N).ModExp(b, N);
|
||||
|
||||
uint8 S_bytes[128];
|
||||
memcpy(S_bytes, S.AsByteArray(128).get(), 128);
|
||||
|
||||
uint8 part1[64];
|
||||
uint8 part2[64];
|
||||
|
||||
for (int i = 0; i < 64; ++i)
|
||||
{
|
||||
part1[i] = S_bytes[i * 2];
|
||||
part2[i] = S_bytes[i * 2 + 1];
|
||||
}
|
||||
|
||||
SHA256Hash part1sha, part2sha;
|
||||
part1sha.UpdateData(part1, 64);
|
||||
part1sha.Finalize();
|
||||
part2sha.UpdateData(part2, 64);
|
||||
part2sha.Finalize();
|
||||
|
||||
uint8 sessionKey[SHA256_DIGEST_LENGTH * 2];
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
|
||||
{
|
||||
sessionKey[i * 2] = part1sha.GetDigest()[i];
|
||||
sessionKey[i * 2 + 1] = part2sha.GetDigest()[i];
|
||||
}
|
||||
|
||||
K.SetBinary(sessionKey, SHA256_DIGEST_LENGTH * 2);
|
||||
|
||||
BigNumber M1;
|
||||
|
||||
uint8 hash[SHA256_DIGEST_LENGTH];
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&N, NULL);
|
||||
sha.Finalize();
|
||||
memcpy(hash, sha.GetDigest(), sha.GetLength());
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&g, NULL);
|
||||
sha.Finalize();
|
||||
|
||||
for (int i = 0; i < sha.GetLength(); ++i)
|
||||
hash[i] ^= sha.GetDigest()[i];
|
||||
|
||||
SHA256Hash shaI;
|
||||
shaI.UpdateData(ByteArrayToHexStr(I.AsByteArray().get(), 32));
|
||||
shaI.Finalize();
|
||||
|
||||
// Concat all variables for M1 hash
|
||||
sha.Initialize();
|
||||
sha.UpdateData(hash, SHA256_DIGEST_LENGTH);
|
||||
sha.UpdateData(shaI.GetDigest(), shaI.GetLength());
|
||||
sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
|
||||
sha.Finalize();
|
||||
|
||||
M1.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
|
||||
if (memcmp(M1.AsByteArray().get(), clientM1.AsByteArray().get(), 32))
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 numAccounts = 0;
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT a.username, a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_account = '%u'", _accountId);
|
||||
if (result)
|
||||
numAccounts = result->GetRowCount();
|
||||
|
||||
if (!numAccounts)
|
||||
{
|
||||
AuthComplete* noAccounts = new AuthComplete();
|
||||
noAccounts->SetAuthResult(LOGIN_NO_GAME_ACCOUNT);
|
||||
ReplaceResponse(response, noAccounts);
|
||||
return false;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
//set expired game account bans to inactive
|
||||
LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS));
|
||||
|
||||
BigNumber M;
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&A, &M1, &K, NULL);
|
||||
sha.Finalize();
|
||||
M.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
|
||||
BitStream stream;
|
||||
ModuleInfo* password = new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "Password" }));
|
||||
uint8 state = 3;
|
||||
|
||||
stream.WriteBytes(&state, 1);
|
||||
stream.WriteBytes(M.AsByteArray(32).get(), 32);
|
||||
stream.WriteBytes(b.AsByteArray(128).get(), 128);
|
||||
|
||||
password->DataSize = stream.GetSize();
|
||||
password->Data = new uint8[password->DataSize];
|
||||
memcpy(password->Data, stream.GetBuffer(), password->DataSize);
|
||||
|
||||
ProofRequest* request = new ProofRequest();
|
||||
request->Modules.push_back(password);
|
||||
if (numAccounts > 1)
|
||||
{
|
||||
BitStream accounts;
|
||||
state = 0;
|
||||
accounts.WriteBytes(&state, 1);
|
||||
accounts.Write(numAccounts, 8);
|
||||
do
|
||||
{
|
||||
fields = result->Fetch();
|
||||
accounts.Write(2, 8);
|
||||
accounts.WriteString(fields[0].GetString(), 8);
|
||||
} while (result->NextRow());
|
||||
|
||||
ModuleInfo* selectGameAccount = new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "SelectGameAccount" }));
|
||||
selectGameAccount->DataSize = accounts.GetSize();
|
||||
selectGameAccount->Data = new uint8[selectGameAccount->DataSize];
|
||||
memcpy(selectGameAccount->Data, accounts.GetBuffer(), selectGameAccount->DataSize);
|
||||
request->Modules.push_back(selectGameAccount);
|
||||
_modulesWaitingForData.push(MODULE_SELECT_GAME_ACCOUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fields[4].GetBool())
|
||||
{
|
||||
delete request;
|
||||
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
if (fields[2].GetUInt32() == fields[3].GetUInt32())
|
||||
{
|
||||
complete->SetAuthResult(LOGIN_BANNED);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
complete->SetAuthResult(LOGIN_SUSPENDED);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
}
|
||||
|
||||
ReplaceResponse(response, complete);
|
||||
return true;
|
||||
}
|
||||
|
||||
_gameAccountId = (*result)[1].GetUInt32();
|
||||
|
||||
request->Modules.push_back(new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "RiskFingerprint" })));
|
||||
_modulesWaitingForData.push(MODULE_RISK_FINGERPRINT);
|
||||
}
|
||||
|
||||
ReplaceResponse(response, request);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response)
|
||||
{
|
||||
if (dataStream->Read<uint8>(8) != 1)
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
dataStream->Read<uint8>(8);
|
||||
std::string account = dataStream->ReadString(8);
|
||||
|
||||
LoginDatabase.EscapeString(account);
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE username = '%s' AND battlenet_account = '%u'", account.c_str(), _accountId);
|
||||
if (!result)
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
if (fields[3].GetBool())
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
if (fields[1].GetUInt32() == fields[2].GetUInt32())
|
||||
{
|
||||
complete->SetAuthResult(LOGIN_BANNED);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
complete->SetAuthResult(LOGIN_SUSPENDED);
|
||||
TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", _socket.getRemoteAddress().c_str(), _socket.getRemotePort(), _accountName.c_str());
|
||||
}
|
||||
|
||||
ReplaceResponse(response, complete);
|
||||
return true;
|
||||
}
|
||||
|
||||
_gameAccountId = fields[0].GetUInt32();
|
||||
|
||||
ProofRequest* request = new ProofRequest();
|
||||
request->Modules.push_back(new ModuleInfo(*sBattlenetMgr->GetModule({ _os, "RiskFingerprint" })));
|
||||
ReplaceResponse(response, request);
|
||||
|
||||
_modulesWaitingForData.push(MODULE_RISK_FINGERPRINT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response)
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
if (dataStream->Read<uint8>(8) == 1)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << _gameAccountId << "#1";
|
||||
|
||||
complete->GameAccountId = _gameAccountId;
|
||||
complete->GameAccountName = str.str();
|
||||
complete->AccountFlags = 0x800000; // 0x1 IsGMAccount, 0x8 IsTrialAccount, 0x800000 IsProPassAccount
|
||||
|
||||
LoginDatabase.PExecute("UPDATE battlenet_accounts SET last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u", _socket.getRemoteAddress().c_str(), GetLocaleByName(_locale), _os.c_str(), _accountId);
|
||||
}
|
||||
else
|
||||
complete->SetAuthResult(AUTH_BAD_VERSION_HASH);
|
||||
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Battlenet::Socket::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response)
|
||||
{
|
||||
AuthComplete* complete = new AuthComplete();
|
||||
complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
|
||||
ReplaceResponse(response, complete);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,22 +21,48 @@
|
||||
#include "RealmSocket.h"
|
||||
#include "BattlenetPackets.h"
|
||||
#include "BattlenetPacketCrypt.h"
|
||||
#include "BigNumber.h"
|
||||
|
||||
class ACE_INET_Addr;
|
||||
|
||||
namespace Battlenet
|
||||
{
|
||||
struct PacketHeader;
|
||||
class BitStream;
|
||||
|
||||
enum ModuleType
|
||||
{
|
||||
MODULE_PASSWORD,
|
||||
MODULE_TOKEN,
|
||||
MODULE_THUMBPRINT,
|
||||
MODULE_SELECT_GAME_ACCOUNT,
|
||||
MODULE_RISK_FINGERPRINT,
|
||||
|
||||
MODULE_COUNT
|
||||
};
|
||||
|
||||
class Socket : public RealmSocket::Session
|
||||
{
|
||||
public:
|
||||
static uint32 const SRP6_V_Size;
|
||||
static uint32 const SRP6_S_Size;
|
||||
|
||||
Socket(RealmSocket& socket);
|
||||
|
||||
typedef bool(Socket::*PacketHandler)(PacketHeader& socket, BitStream& packet);
|
||||
|
||||
// Auth
|
||||
bool HandleAuthChallenge(PacketHeader& header, BitStream& packet);
|
||||
bool HandleAuthProofResponse(PacketHeader& header, BitStream& packet);
|
||||
|
||||
// Creep
|
||||
bool HandlePing(PacketHeader& header, BitStream& packet);
|
||||
bool HandleEnableEncryption(PacketHeader& header, BitStream& packet);
|
||||
|
||||
// WoW
|
||||
bool HandleRealmUpdate(PacketHeader& header, BitStream& packet);
|
||||
bool HandleRealmJoinRequest(PacketHeader& header, BitStream& packet);
|
||||
|
||||
void OnRead() override;
|
||||
void OnAccept() override;
|
||||
void OnClose() override;
|
||||
@@ -44,12 +70,40 @@ namespace Battlenet
|
||||
void Send(ServerPacket& packet);
|
||||
|
||||
private:
|
||||
RealmSocket& _socket;
|
||||
uint32 _currentChannel;
|
||||
void _SetVSFields(std::string const& rI);
|
||||
static ACE_INET_Addr const& GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr);
|
||||
|
||||
typedef bool(Socket::*ModuleHandler)(BitStream* dataStream, ServerPacket** response);
|
||||
static ModuleHandler const ModuleHandlers[MODULE_COUNT];
|
||||
|
||||
bool HandlePasswordModule(BitStream* dataStream, ServerPacket** response);
|
||||
bool HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response);
|
||||
bool HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response);
|
||||
bool UnhandledModule(BitStream* dataStream, ServerPacket** response);
|
||||
|
||||
RealmSocket& _socket;
|
||||
|
||||
uint32 _accountId;
|
||||
std::string _accountName;
|
||||
std::string _locale;
|
||||
std::string _os;
|
||||
uint32 _build;
|
||||
uint32 _gameAccountId;
|
||||
AccountTypes _accountSecurityLevel;
|
||||
|
||||
BigNumber N;
|
||||
BigNumber g;
|
||||
BigNumber k;
|
||||
|
||||
BigNumber I;
|
||||
BigNumber s;
|
||||
BigNumber v;
|
||||
|
||||
BigNumber b;
|
||||
BigNumber B;
|
||||
BigNumber K; // session key
|
||||
|
||||
std::queue<ModuleType> _modulesWaitingForData;
|
||||
|
||||
PacketCrypt _crypt;
|
||||
};
|
||||
|
||||
@@ -32,17 +32,17 @@ AccountMgr::~AccountMgr()
|
||||
ClearRBAC();
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email = "")
|
||||
AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/)
|
||||
{
|
||||
if (utf8length(username) > MAX_ACCOUNT_STR)
|
||||
return AOR_NAME_TOO_LONG; // username's too long
|
||||
return AccountOpResult::AOR_NAME_TOO_LONG; // username's too long
|
||||
|
||||
normalizeString(username);
|
||||
normalizeString(password);
|
||||
normalizeString(email);
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(password);
|
||||
Utf8ToUpperOnlyLatin(email);
|
||||
|
||||
if (GetId(username))
|
||||
return AOR_NAME_ALREADY_EXIST; // username does already exist
|
||||
return AccountOpResult::AOR_NAME_ALREADY_EXIST; // username does already exist
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT);
|
||||
|
||||
@@ -56,7 +56,7 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT);
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
return AOR_OK; // everything's fine
|
||||
return AccountOpResult::AOR_OK; // everything's fine
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
|
||||
@@ -67,7 +67,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
if (!result)
|
||||
return AOR_NAME_NOT_EXIST;
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST;
|
||||
|
||||
// Obtain accounts characters
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID);
|
||||
@@ -128,7 +128,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
|
||||
|
||||
LoginDatabase.CommitTransaction(trans);
|
||||
|
||||
return AOR_OK;
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
|
||||
@@ -139,16 +139,16 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
if (!result)
|
||||
return AOR_NAME_NOT_EXIST;
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST;
|
||||
|
||||
if (utf8length(newUsername) > MAX_ACCOUNT_STR)
|
||||
return AOR_NAME_TOO_LONG;
|
||||
return AccountOpResult::AOR_NAME_TOO_LONG;
|
||||
|
||||
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
|
||||
return AOR_PASS_TOO_LONG;
|
||||
return AccountOpResult::AOR_PASS_TOO_LONG;
|
||||
|
||||
normalizeString(newUsername);
|
||||
normalizeString(newPassword);
|
||||
Utf8ToUpperOnlyLatin(newUsername);
|
||||
Utf8ToUpperOnlyLatin(newPassword);
|
||||
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME);
|
||||
|
||||
@@ -158,7 +158,7 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser
|
||||
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
return AOR_OK;
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPassword)
|
||||
@@ -166,13 +166,13 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass
|
||||
std::string username;
|
||||
|
||||
if (!GetName(accountId, username))
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
|
||||
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
|
||||
return AOR_PASS_TOO_LONG;
|
||||
return AccountOpResult::AOR_PASS_TOO_LONG;
|
||||
|
||||
normalizeString(username);
|
||||
normalizeString(newPassword);
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(newPassword);
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_PASSWORD);
|
||||
|
||||
@@ -189,7 +189,7 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass
|
||||
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
return AOR_OK;
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
|
||||
@@ -197,13 +197,13 @@ AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
|
||||
std::string username;
|
||||
|
||||
if (!GetName(accountId, username))
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
|
||||
if (utf8length(newEmail) > MAX_EMAIL_STR)
|
||||
return AOR_EMAIL_TOO_LONG;
|
||||
return AccountOpResult::AOR_EMAIL_TOO_LONG;
|
||||
|
||||
normalizeString(username);
|
||||
normalizeString(newEmail);
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(newEmail);
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EMAIL);
|
||||
|
||||
@@ -212,7 +212,7 @@ AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
|
||||
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
return AOR_OK;
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmail)
|
||||
@@ -220,13 +220,13 @@ AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmai
|
||||
std::string username;
|
||||
|
||||
if (!GetName(accountId, username))
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
|
||||
if (utf8length(newEmail) > MAX_EMAIL_STR)
|
||||
return AOR_EMAIL_TOO_LONG;
|
||||
return AccountOpResult::AOR_EMAIL_TOO_LONG;
|
||||
|
||||
normalizeString(username);
|
||||
normalizeString(newEmail);
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(newEmail);
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_REG_EMAIL);
|
||||
|
||||
@@ -235,7 +235,7 @@ AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmai
|
||||
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
return AOR_OK;
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
uint32 AccountMgr::GetId(std::string const& username)
|
||||
@@ -303,8 +303,8 @@ bool AccountMgr::CheckPassword(uint32 accountId, std::string password)
|
||||
if (!GetName(accountId, username))
|
||||
return false;
|
||||
|
||||
normalizeString(username);
|
||||
normalizeString(password);
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(password);
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD);
|
||||
stmt->setUInt32(0, accountId);
|
||||
@@ -322,8 +322,8 @@ bool AccountMgr::CheckEmail(uint32 accountId, std::string newEmail)
|
||||
if (!GetEmail(accountId, oldEmail))
|
||||
return false;
|
||||
|
||||
normalizeString(oldEmail);
|
||||
normalizeString(newEmail);
|
||||
Utf8ToUpperOnlyLatin(oldEmail);
|
||||
Utf8ToUpperOnlyLatin(newEmail);
|
||||
|
||||
if (strcmp(oldEmail.c_str(), newEmail.c_str()) == 0)
|
||||
return true;
|
||||
@@ -341,19 +341,6 @@ uint32 AccountMgr::GetCharactersCount(uint32 accountId)
|
||||
return (result) ? (*result)[0].GetUInt64() : 0;
|
||||
}
|
||||
|
||||
bool AccountMgr::normalizeString(std::string& utf8String)
|
||||
{
|
||||
wchar_t buffer[MAX_ACCOUNT_STR+1];
|
||||
|
||||
size_t maxLength = MAX_ACCOUNT_STR;
|
||||
if (!Utf8toWStr(utf8String, buffer, maxLength))
|
||||
return false;
|
||||
|
||||
std::transform(&buffer[0], buffer+maxLength, &buffer[0], wcharToUpperOnlyLatin);
|
||||
|
||||
return WStrToUtf8(buffer, maxLength, utf8String);
|
||||
}
|
||||
|
||||
std::string AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password)
|
||||
{
|
||||
SHA1Hash sha;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "RBAC.h"
|
||||
#include <ace/Singleton.h>
|
||||
|
||||
enum AccountOpResult
|
||||
enum class AccountOpResult : uint8
|
||||
{
|
||||
AOR_OK,
|
||||
AOR_NAME_TOO_LONG,
|
||||
@@ -40,6 +40,7 @@ enum PasswordChangeSecurity
|
||||
PW_RBAC
|
||||
};
|
||||
|
||||
#define MAX_PASS_STR 16
|
||||
#define MAX_ACCOUNT_STR 16
|
||||
#define MAX_EMAIL_STR 64
|
||||
|
||||
@@ -58,7 +59,7 @@ class AccountMgr
|
||||
~AccountMgr();
|
||||
|
||||
public:
|
||||
AccountOpResult CreateAccount(std::string username, std::string password, std::string email);
|
||||
AccountOpResult CreateAccount(std::string username, std::string password, std::string email = "");
|
||||
static AccountOpResult DeleteAccount(uint32 accountId);
|
||||
static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
|
||||
static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
|
||||
@@ -75,7 +76,6 @@ class AccountMgr
|
||||
static uint32 GetCharactersCount(uint32 accountId);
|
||||
|
||||
static std::string CalculateShaPassHash(std::string const& name, std::string const& password);
|
||||
static bool normalizeString(std::string& utf8String);
|
||||
static bool IsPlayerAccount(uint32 gmlevel);
|
||||
static bool IsAdminAccount(uint32 gmlevel);
|
||||
static bool IsConsoleAccount(uint32 gmlevel);
|
||||
|
||||
133
src/server/game/Accounts/BattlenetAccountMgr.cpp
Normal file
133
src/server/game/Accounts/BattlenetAccountMgr.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* 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 "AccountMgr.h"
|
||||
#include "BattlenetAccountMgr.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Util.h"
|
||||
#include "SHA256.h"
|
||||
|
||||
AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, std::string password)
|
||||
{
|
||||
if (utf8length(email) > 64)
|
||||
return AccountOpResult::AOR_NAME_TOO_LONG;
|
||||
|
||||
Utf8ToUpperOnlyLatin(email);
|
||||
Utf8ToUpperOnlyLatin(password);
|
||||
|
||||
if (GetId(email))
|
||||
return AccountOpResult::AOR_NAME_ALREADY_EXIST;
|
||||
|
||||
LoginDatabase.EscapeString(email);
|
||||
LoginDatabase.DirectPExecute("INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES ('%s', '%s')", email.c_str(), CalculateShaPassHash(email, password).c_str());
|
||||
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult Battlenet::AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
|
||||
{
|
||||
// Check if accounts exists
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT 1 FROM battlenet_accounts WHERE id = %u", accountId);
|
||||
|
||||
if (!result)
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST;
|
||||
|
||||
if (utf8length(newUsername) > MAX_ACCOUNT_STR)
|
||||
return AccountOpResult::AOR_NAME_TOO_LONG;
|
||||
|
||||
if (utf8length(newPassword) > MAX_PASS_STR)
|
||||
return AccountOpResult::AOR_PASS_TOO_LONG;
|
||||
|
||||
Utf8ToUpperOnlyLatin(newUsername);
|
||||
Utf8ToUpperOnlyLatin(newPassword);
|
||||
|
||||
LoginDatabase.EscapeString(newUsername);
|
||||
LoginDatabase.EscapeString(newPassword);
|
||||
LoginDatabase.PExecute("UPDATE account SET v = '', s = '', username = '%s', sha_pass_hash = '%s' WHERE id = '%u'",
|
||||
newUsername.c_str(), CalculateShaPassHash(newUsername, newPassword).c_str(), newPassword.c_str(), accountId);
|
||||
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
AccountOpResult Battlenet::AccountMgr::ChangePassword(uint32 accountId, std::string newPassword)
|
||||
{
|
||||
std::string username;
|
||||
if (!GetName(accountId, username))
|
||||
return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
|
||||
if (utf8length(newPassword) > MAX_PASS_STR)
|
||||
return AccountOpResult::AOR_PASS_TOO_LONG;
|
||||
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(newPassword);
|
||||
|
||||
LoginDatabase.EscapeString(newPassword);
|
||||
LoginDatabase.PExecute("UPDATE account SET v = '', s = '', sha_pass_hash = '%s' WHERE id = '%u'",
|
||||
CalculateShaPassHash(username, newPassword).c_str(), newPassword.c_str(), accountId);
|
||||
|
||||
return AccountOpResult::AOR_OK;
|
||||
}
|
||||
|
||||
uint32 Battlenet::AccountMgr::GetId(std::string const& username)
|
||||
{
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT id FROM battlenet_accounts WHERE email = '%s'", username.c_str());
|
||||
|
||||
return result ? (*result)[0].GetUInt32() : 0;
|
||||
}
|
||||
|
||||
bool Battlenet::AccountMgr::GetName(uint32 accountId, std::string& name)
|
||||
{
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT email FROM battlenet_accounts WHERE id = '%u'", accountId);
|
||||
|
||||
if (result)
|
||||
{
|
||||
name = (*result)[0].GetString();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password)
|
||||
{
|
||||
std::string username;
|
||||
|
||||
if (!GetName(accountId, username))
|
||||
return false;
|
||||
|
||||
Utf8ToUpperOnlyLatin(username);
|
||||
Utf8ToUpperOnlyLatin(password);
|
||||
|
||||
QueryResult result = LoginDatabase.PQuery("SELECT 1 FROM battlenet_accounts WHERE id = %u AND sha_pass_hash = '%s'", accountId, CalculateShaPassHash(username, password));
|
||||
|
||||
return (result) ? true : false;
|
||||
}
|
||||
|
||||
std::string Battlenet::AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password)
|
||||
{
|
||||
SHA256Hash email;
|
||||
email.UpdateData(name);
|
||||
email.Finalize();
|
||||
|
||||
SHA256Hash sha;
|
||||
sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength()));
|
||||
sha.UpdateData(":");
|
||||
sha.UpdateData(password);
|
||||
sha.Finalize();
|
||||
|
||||
return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true);
|
||||
}
|
||||
45
src/server/game/Accounts/BattlenetAccountMgr.h
Normal file
45
src/server/game/Accounts/BattlenetAccountMgr.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef BattlenetAccountMgr_h__
|
||||
#define BattlenetAccountMgr_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include <string>
|
||||
#include <ace/Singleton.h>
|
||||
|
||||
enum class AccountOpResult : uint8;
|
||||
|
||||
#define MAX_BNET_EMAIL_STR 320
|
||||
|
||||
namespace Battlenet
|
||||
{
|
||||
namespace AccountMgr
|
||||
{
|
||||
AccountOpResult CreateBattlenetAccount(std::string email, std::string password);
|
||||
AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
|
||||
AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
|
||||
bool CheckPassword(uint32 accountId, std::string password);
|
||||
|
||||
uint32 GetId(std::string const& username);
|
||||
bool GetName(uint32 accountId, std::string& name);
|
||||
|
||||
std::string CalculateShaPassHash(std::string const& name, std::string const& password);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BattlenetAccountMgr_h__
|
||||
@@ -23,6 +23,7 @@ Category: commandscripts
|
||||
EndScriptData */
|
||||
|
||||
#include "AccountMgr.h"
|
||||
#include "BattlenetAccountMgr.h"
|
||||
#include "Chat.h"
|
||||
#include "Language.h"
|
||||
#include "Player.h"
|
||||
@@ -126,10 +127,15 @@ public:
|
||||
if (!accountName || !password)
|
||||
return false;
|
||||
|
||||
AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email);
|
||||
AccountOpResult result;
|
||||
if (strchr(accountName, '@'))
|
||||
result = Battlenet::AccountMgr::CreateBattlenetAccount(std::string(accountName), std::string(password));
|
||||
else
|
||||
result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName);
|
||||
if (handler->GetSession())
|
||||
{
|
||||
@@ -139,15 +145,15 @@ public:
|
||||
accountName, email.c_str());
|
||||
}
|
||||
break;
|
||||
case AOR_NAME_TOO_LONG:
|
||||
case AccountOpResult::AOR_NAME_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_ACCOUNT_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_NAME_ALREADY_EXIST:
|
||||
case AccountOpResult::AOR_NAME_ALREADY_EXIST:
|
||||
handler->SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_DB_INTERNAL_ERROR:
|
||||
case AccountOpResult::AOR_DB_INTERNAL_ERROR:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, accountName);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -173,7 +179,7 @@ public:
|
||||
return false;
|
||||
|
||||
std::string accountName = account;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -197,14 +203,14 @@ public:
|
||||
AccountOpResult result = AccountMgr::DeleteAccount(accountId);
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_DELETED, accountName.c_str());
|
||||
break;
|
||||
case AOR_NAME_NOT_EXIST:
|
||||
case AccountOpResult::AOR_NAME_NOT_EXIST:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_DB_INTERNAL_ERROR:
|
||||
case AccountOpResult::AOR_DB_INTERNAL_ERROR:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -416,14 +422,14 @@ public:
|
||||
AccountOpResult result = AccountMgr::ChangeEmail(handler->GetSession()->GetAccountId(), std::string(email));
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->SendSysMessage(LANG_COMMAND_EMAIL);
|
||||
TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Email from [%s] to [%s].",
|
||||
handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(),
|
||||
handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(),
|
||||
oldEmail, email);
|
||||
break;
|
||||
case AOR_EMAIL_TOO_LONG:
|
||||
case AccountOpResult::AOR_EMAIL_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_EMAIL_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -501,13 +507,13 @@ public:
|
||||
AccountOpResult result = AccountMgr::ChangePassword(handler->GetSession()->GetAccountId(), std::string(newPassword));
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->SendSysMessage(LANG_COMMAND_PASSWORD);
|
||||
TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Password.",
|
||||
handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(),
|
||||
handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow());
|
||||
break;
|
||||
case AOR_PASS_TOO_LONG:
|
||||
case AccountOpResult::AOR_PASS_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_PASSWORD_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -586,7 +592,7 @@ public:
|
||||
{
|
||||
///- Convert Account name to Upper Format
|
||||
accountName = account;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -656,7 +662,7 @@ public:
|
||||
if (isAccountNameGiven)
|
||||
{
|
||||
targetAccountName = arg1;
|
||||
if (!AccountMgr::normalizeString(targetAccountName))
|
||||
if (!Utf8ToUpperOnlyLatin(targetAccountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -744,7 +750,7 @@ public:
|
||||
return false;
|
||||
|
||||
std::string accountName = account;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -775,14 +781,14 @@ public:
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->SendSysMessage(LANG_COMMAND_PASSWORD);
|
||||
break;
|
||||
case AOR_NAME_NOT_EXIST:
|
||||
case AccountOpResult::AOR_NAME_NOT_EXIST:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_PASS_TOO_LONG:
|
||||
case AccountOpResult::AOR_PASS_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_PASSWORD_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -813,7 +819,7 @@ public:
|
||||
}
|
||||
|
||||
std::string accountName = account;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -843,16 +849,16 @@ public:
|
||||
AccountOpResult result = AccountMgr::ChangeEmail(targetAccountId, email);
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->SendSysMessage(LANG_COMMAND_EMAIL);
|
||||
TC_LOG_INFO("entities.player.character", "ChangeEmail: Account %s [Id: %u] had it's email changed to %s.",
|
||||
accountName.c_str(), targetAccountId, email);
|
||||
break;
|
||||
case AOR_NAME_NOT_EXIST:
|
||||
case AccountOpResult::AOR_NAME_NOT_EXIST:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_EMAIL_TOO_LONG:
|
||||
case AccountOpResult::AOR_EMAIL_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_EMAIL_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
@@ -889,7 +895,7 @@ public:
|
||||
}
|
||||
|
||||
std::string accountName = account;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -919,16 +925,16 @@ public:
|
||||
AccountOpResult result = AccountMgr::ChangeRegEmail(targetAccountId, email);
|
||||
switch (result)
|
||||
{
|
||||
case AOR_OK:
|
||||
case AccountOpResult::AOR_OK:
|
||||
handler->SendSysMessage(LANG_COMMAND_EMAIL);
|
||||
TC_LOG_INFO("entities.player.character", "ChangeRegEmail: Account %s [Id: %u] had it's Registration Email changed to %s.",
|
||||
accountName.c_str(), targetAccountId, email);
|
||||
break;
|
||||
case AOR_NAME_NOT_EXIST:
|
||||
case AccountOpResult::AOR_NAME_NOT_EXIST:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case AOR_EMAIL_TOO_LONG:
|
||||
case AccountOpResult::AOR_EMAIL_TOO_LONG:
|
||||
handler->SendSysMessage(LANG_EMAIL_TOO_LONG);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
|
||||
@@ -174,7 +174,7 @@ public:
|
||||
switch (mode)
|
||||
{
|
||||
case BAN_ACCOUNT:
|
||||
if (!AccountMgr::normalizeString(nameOrIP))
|
||||
if (!Utf8ToUpperOnlyLatin(nameOrIP))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
return false;
|
||||
|
||||
std::string accountName = nameStr;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
@@ -710,7 +710,7 @@ public:
|
||||
switch (mode)
|
||||
{
|
||||
case BAN_ACCOUNT:
|
||||
if (!AccountMgr::normalizeString(nameOrIP))
|
||||
if (!Utf8ToUpperOnlyLatin(nameOrIP))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
|
||||
@@ -858,7 +858,7 @@ public:
|
||||
return false;
|
||||
|
||||
std::string accountName = accountStr;
|
||||
if (!AccountMgr::normalizeString(accountName))
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
|
||||
@@ -1218,8 +1218,7 @@ public:
|
||||
char* limitStr = strtok(NULL, " ");
|
||||
int32 limit = limitStr ? atoi(limitStr) : -1;
|
||||
|
||||
if (!AccountMgr::normalizeString
|
||||
(account))
|
||||
if (!Utf8ToUpperOnlyLatin(account))
|
||||
return false;
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME);
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
{
|
||||
accountName = param1;
|
||||
|
||||
if (AccountMgr::normalizeString(accountName))
|
||||
if (Utf8ToUpperOnlyLatin(accountName))
|
||||
accountId = AccountMgr::GetId(accountName);
|
||||
|
||||
if (!accountId)
|
||||
|
||||
@@ -22,7 +22,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
||||
if (!m_reconnecting)
|
||||
m_stmts.resize(MAX_LOGINDATABASE_STATEMENTS);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED, "SELECT * FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -524,6 +524,17 @@ void vutf8printf(FILE* out, const char *str, va_list* ap)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Utf8ToUpperOnlyLatin(std::string& utf8String)
|
||||
{
|
||||
std::wstring wstr;
|
||||
if (!Utf8toWStr(utf8String, wstr))
|
||||
return false;
|
||||
|
||||
std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin);
|
||||
|
||||
return WStrToUtf8(wstr, utf8String);
|
||||
}
|
||||
|
||||
std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse /* = false */)
|
||||
{
|
||||
int32 init = 0;
|
||||
|
||||
@@ -343,6 +343,7 @@ bool consoleToUtf8(const std::string& conStr, std::string& utf8str);
|
||||
bool Utf8FitTo(const std::string& str, std::wstring search);
|
||||
void utf8printf(FILE* out, const char *str, ...);
|
||||
void vutf8printf(FILE* out, const char *str, va_list* ap);
|
||||
bool Utf8ToUpperOnlyLatin(std::string& utf8String);
|
||||
|
||||
bool IsIPAddress(char const* ipaddress);
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ int RASocket::check_access_level(const std::string& user)
|
||||
{
|
||||
std::string safeUser = user;
|
||||
|
||||
AccountMgr::normalizeString(safeUser);
|
||||
Utf8ToUpperOnlyLatin(safeUser);
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS);
|
||||
stmt->setString(0, safeUser);
|
||||
@@ -215,10 +215,10 @@ int RASocket::check_access_level(const std::string& user)
|
||||
int RASocket::check_password(const std::string& user, const std::string& pass)
|
||||
{
|
||||
std::string safe_user = user;
|
||||
AccountMgr::normalizeString(safe_user);
|
||||
Utf8ToUpperOnlyLatin(safe_user);
|
||||
|
||||
std::string safe_pass = pass;
|
||||
AccountMgr::normalizeString(safe_pass);
|
||||
Utf8ToUpperOnlyLatin(safe_pass);
|
||||
|
||||
std::string hash = AccountMgr::CalculateShaPassHash(safe_user, safe_pass);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user