summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgumi <git@gumi.ca>2018-12-30 16:06:06 -0500
committergumi <git@gumi.ca>2018-12-30 16:32:51 -0500
commita56b3ea671e9cc74b3f9ea723bc149e83212b998 (patch)
treea595027339f278c83e4ca8c30454900bdff7f70a
parenta860cff760e39dc63de529991131fe295e03f543 (diff)
downloadtmwa-a56b3ea671e9cc74b3f9ea723bc149e83212b998.tar.gz
tmwa-a56b3ea671e9cc74b3f9ea723bc149e83212b998.tar.bz2
tmwa-a56b3ea671e9cc74b3f9ea723bc149e83212b998.tar.xz
tmwa-a56b3ea671e9cc74b3f9ea723bc149e83212b998.zip
pre-send the auth details to map servers instead of blindly trusting 0x0072
-rw-r--r--src/char/char.cpp175
-rw-r--r--src/map/chrif.cpp24
-rw-r--r--src/map/chrif.hpp2
-rw-r--r--src/map/clif.cpp27
-rw-r--r--src/map/fwd.hpp2
-rw-r--r--src/map/globals.cpp3
-rw-r--r--src/map/globals.hpp3
-rw-r--r--src/map/intif.cpp10
-rw-r--r--src/map/map.hpp15
-rwxr-xr-xtools/protocol.py32
10 files changed, 238 insertions, 55 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp
index eac1e06..81b2ab7 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -103,6 +103,7 @@ struct char_session_data : SessionData
SEX sex;
ClientVersion client_version;
AccountEmail email;
+ int consumed_by; // amount of map servers for which we are authed
};
} // namespace char_
@@ -1601,6 +1602,37 @@ void map_anti_freeze_system(TimerData *, tick_t)
}
static
+int search_mapserver(XString map)
+{
+ for (int i = 0; i < MAX_MAP_SERVERS; i++)
+ {
+ if (server_session[i])
+ {
+ for (int j = 0; server[i].maps[j]; j++)
+ {
+ if (server[i].maps[j] == map)
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------
+// Test to know if an IP come from LAN or WAN. by [Yor]
+//-----------------------------------------------------
+static
+int lan_ip_check(IP4Address addr)
+{
+ bool lancheck = char_lan_conf.lan_subnet.covers(addr);
+
+ PRINTF("LAN test (result): %s.\n"_fmt,
+ (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET ""_s : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET ""_s);
+ return lancheck;
+}
+
+static
void parse_frommap(Session *ms)
{
int id;
@@ -2105,6 +2137,86 @@ void parse_frommap(Session *ms)
}
}
+ case 0x3830:
+ {
+ Packet_Fixed<0x3830> fixed;
+ rv = recv_fpacket<0x3830, 22>(ms, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ for (io::FD i : iter_fds())
+ {
+ Session *s2 = get_session(i);
+ if (!s2)
+ continue;
+ struct char_session_data *sd = static_cast<char_session_data *>(s2->session_data.get());
+
+ if (sd && sd->account_id == fixed.account_id &&
+ sd->login_id1 == fixed.login_id1 &&
+ sd->login_id2 == fixed.login_id2 /*&&
+ sd->ip == fixed.ip &&*/)
+ {
+ sd->consumed_by++; // one char server consumed this
+
+ CHAR_LOG_AND_ECHO("Map server %i accepted pre-auth details for account %d [%s].\n"_fmt,
+ id, fixed.account_id, fixed.ip);
+
+ int server_count = 0;
+ // FIXME: this is silly, we should have a active_map_servers global var
+ for (Session *ss : iter_map_sessions())
+ if (ss)
+ server_count++;
+
+ if (sd->consumed_by == server_count) {
+
+ CHAR_LOG_AND_ECHO("All map servers accepted pre-auth details for account %d [%s], sending authorization to client...\n"_fmt,
+ fixed.account_id, fixed.ip);
+
+ CharPair *cp = nullptr;
+ for (CharPair& cdi : char_keys)
+ {
+ if (cdi.key.account_id == sd->account_id && cdi.key.char_id == fixed.char_id)
+ {
+ cp = &cdi;
+ break;
+ }
+ }
+
+ if (!cp)
+ return;
+ CharKey *ck = &cp->key;
+ CharData *cd = cp->data.get();
+ int mi = search_mapserver(cd->last_point.map_);
+
+ // now that preauth is done we prepare for actual auth
+ if (auth_fifo_iter == auth_fifo.end())
+ auth_fifo_iter = auth_fifo.begin();
+ auth_fifo_iter->account_id = sd->account_id;
+ auth_fifo_iter->char_id = ck->char_id;
+ auth_fifo_iter->login_id1 = sd->login_id1;
+ auth_fifo_iter->login_id2 = sd->login_id2;
+ auth_fifo_iter->delflag = 3;
+ auth_fifo_iter->sex = sd->sex;
+ auth_fifo_iter->ip = s2->client_ip;
+ auth_fifo_iter->client_version = sd->client_version;
+ auth_fifo_iter++;
+
+ Packet_Fixed<0x0071> fixed_71;
+ fixed_71.char_id = ck->char_id;
+ fixed_71.map_name = cd->last_point.map_;
+ if (lan_ip_check(s2->client_ip))
+ fixed_71.ip = char_lan_conf.lan_map_ip;
+ else
+ fixed_71.ip = server[mi].ip;
+ fixed_71.port = server[mi].port;
+ send_fpacket<0x0071, 28>(s2, fixed_71);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
default:
// inter server処理に渡す
{
@@ -2126,37 +2238,6 @@ void parse_frommap(Session *ms)
}
static
-int search_mapserver(XString map)
-{
- for (int i = 0; i < MAX_MAP_SERVERS; i++)
- {
- if (server_session[i])
- {
- for (int j = 0; server[i].maps[j]; j++)
- {
- if (server[i].maps[j] == map)
- return i;
- }
- }
- }
-
- return -1;
-}
-
-//-----------------------------------------------------
-// Test to know if an IP come from LAN or WAN. by [Yor]
-//-----------------------------------------------------
-static
-int lan_ip_check(IP4Address addr)
-{
- bool lancheck = char_lan_conf.lan_subnet.covers(addr);
-
- PRINTF("LAN test (result): %s.\n"_fmt,
- (lancheck) ? SGR_BOLD SGR_CYAN "LAN source" SGR_RESET ""_s : SGR_BOLD SGR_GREEN "WAN source" SGR_RESET ""_s);
- return lancheck;
-}
-
-static
void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP4Address ip)
{
{
@@ -2206,27 +2287,16 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP
}
}
- Packet_Fixed<0x0071> fixed_71;
- fixed_71.char_id = ck->char_id;
- fixed_71.map_name = cd->last_point.map_;
- if (lan_ip_check(ip))
- fixed_71.ip = char_lan_conf.lan_map_ip;
- else
- fixed_71.ip = server[i].ip;
- fixed_71.port = server[i].port;
- send_fpacket<0x0071, 28>(s, fixed_71);
-
- if (auth_fifo_iter == auth_fifo.end())
- auth_fifo_iter = auth_fifo.begin();
- auth_fifo_iter->account_id = sd->account_id;
- auth_fifo_iter->char_id = ck->char_id;
- auth_fifo_iter->login_id1 = sd->login_id1;
- auth_fifo_iter->login_id2 = sd->login_id2;
- auth_fifo_iter->delflag = 3;
- auth_fifo_iter->sex = sd->sex;
- auth_fifo_iter->ip = s->client_ip;
- auth_fifo_iter->client_version = sd->client_version;
- auth_fifo_iter++;
+ // send auth details to map server, wait for a reply
+ Packet_Fixed<0x3829> fixed_3829;
+ fixed_3829.account_id = ck->account_id;
+ fixed_3829.char_id = ck->char_id;
+ fixed_3829.login_id1 = sd->login_id1;
+ fixed_3829.login_id2 = sd->login_id2;
+ fixed_3829.ip = ip;
+ sd->consumed_by = 0;
+ for (Session *ss : iter_map_sessions())
+ send_fpacket<0x3829, 22>(ss, fixed_3829);
}
}
}
@@ -2305,6 +2375,7 @@ void parse_char(Session *s)
sd->login_id2 = fixed.login_id2;
sd->sex = fixed.sex;
sd->auth = false; // not authed yet
+ sd->consumed_by = 0;
// formerly: send back account_id
Packet_Payload<0x8000> special;
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index 42a13cf..9361c2e 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -340,6 +340,30 @@ int chrif_charselectreq(dumb_ptr<map_session_data> sd)
return 0;
}
+void chrif_parse_preauth(Session *s, const Packet_Fixed<0x3829>& fixed)
+{
+ if (auth_fifo_iter == auth_fifo.end())
+ auth_fifo_iter = auth_fifo.begin();
+ auth_fifo_iter->account_id = fixed.account_id;
+ auth_fifo_iter->char_id = fixed.char_id;
+ auth_fifo_iter->login_id1 = fixed.login_id1;
+ auth_fifo_iter->login_id2 = fixed.login_id2;
+ auth_fifo_iter->ip = fixed.ip;
+ auth_fifo_iter->delflag = 0;
+ auth_fifo_iter++;
+
+ // tell char server we accepted the auth details
+ Packet_Fixed<0x3830> fixed_3830;
+ fixed_3830.account_id = fixed.account_id;
+ fixed_3830.char_id = fixed.char_id;
+ fixed_3830.login_id1 = fixed.login_id1;
+ fixed_3830.login_id2 = fixed.login_id2;
+ fixed_3830.ip = fixed.ip;
+ send_fpacket<0x3830, 22>(s, fixed_3830);
+
+ MAP_LOG_AND_ECHO("Received pre-auth details for account %d [%s], replying to char server\n"_fmt, fixed.account_id, fixed.ip);
+}
+
/*==========================================
* Change Email
*------------------------------------------
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
index 655103d..ea8096c 100644
--- a/src/map/chrif.hpp
+++ b/src/map/chrif.hpp
@@ -44,6 +44,8 @@ void chrif_char_ask_name(AccountId id, CharName character_name, short operation_
int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd);
int chrif_send_divorce(CharId char_id);
+void chrif_parse_preauth(Session *s, const Packet_Fixed<0x3829>& fixed);
+
void do_init_chrif(void);
} // namespace map
} // namespace tmwa
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index f2667ac..a2f3b3a 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -3539,15 +3539,36 @@ RecvResult clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd
if (rv != RecvResult::Complete)
return rv;
- {
- account_id = fixed.account_id;
- }
+ account_id = fixed.account_id;
// formerly: account id
Packet_Payload<0x8000> special;
special.magic_packet_length = 4;
send_ppacket<0x8000>(s, special);
+ bool is_valid = false;
+ for (AuthFifoEntry& afi : auth_fifo)
+ {
+ if (afi.account_id == fixed.account_id
+ && afi.char_id == fixed.char_id
+ && afi.login_id1 == fixed.login_id1
+ //&& afi.login_id2 == sd->login_id2
+ && afi.ip == s->client_ip
+ && afi.delflag == 0)
+ {
+ is_valid = true;
+ afi.delflag = 1;
+ break;
+ }
+ }
+
+ if (!is_valid)
+ {
+ MAP_LOG_AND_ECHO("Attempt to connect without correct authentication (REJECTED IP: %s)!\n"_fmt, s->client_ip);
+ s->set_eof();
+ return RecvResult::Complete;
+ }
+
// if same account already connected, we disconnect the 2 sessions
dumb_ptr<map_session_data> old_sd = map_id2sd(account_to_block(account_id));
if (old_sd)
diff --git a/src/map/fwd.hpp b/src/map/fwd.hpp
index 74e0ccf..fc6b284 100644
--- a/src/map/fwd.hpp
+++ b/src/map/fwd.hpp
@@ -69,5 +69,7 @@ struct ScriptState;
struct str_data_t;
class SIR;
+struct AuthFifoEntry;
+
} // namespace map
} // namespace tmwa
diff --git a/src/map/globals.cpp b/src/map/globals.cpp
index 49d6074..97533c8 100644
--- a/src/map/globals.cpp
+++ b/src/map/globals.cpp
@@ -51,6 +51,9 @@ namespace tmwa
Map<ItemNameId, item_data> item_db;
Map<QuestId, quest_data> quest_db;
+ std::array<AuthFifoEntry, 256> auth_fifo;
+ decltype(auth_fifo)::iterator auth_fifo_iter = auth_fifo.begin();
+
DMap<BlockId, dumb_ptr<block_list>> id_db;
UPMap<MapName, map_abstract> maps_db;
DMap<CharName, dumb_ptr<map_session_data>> nick_db;
diff --git a/src/map/globals.hpp b/src/map/globals.hpp
index 1c8e70d..acf52fd 100644
--- a/src/map/globals.hpp
+++ b/src/map/globals.hpp
@@ -95,5 +95,8 @@ namespace tmwa
extern earray<skill_db_, SkillID, SkillID::MAX_SKILL_DB> skill_db;
extern BlockId skill_area_temp_id;
extern int skill_area_temp_hp;
+
+ extern std::array<AuthFifoEntry, 256> auth_fifo;
+ extern AuthFifoEntry *auth_fifo_iter;
} // namespace map
} // namespace tmwa
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index fc34a64..379bb1d 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -743,6 +743,16 @@ RecvResult intif_parse(Session *s, uint16_t packet_id)
intif_parse_PartyLeaderChanged(s, fixed);
break;
}
+ case 0x3829:
+ {
+ Packet_Fixed<0x3829> fixed;
+ rv = recv_fpacket<0x3829, 22>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ chrif_parse_preauth(s, fixed);
+ break;
+ }
default:
return RecvResult::Error;
}
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 24037e9..2f6ef21 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -584,6 +584,12 @@ void map_log(XString line);
#define MAP_LOG(format, ...) \
map_log(STRPRINTF(format, ## __VA_ARGS__))
+#define MAP_LOG_AND_ECHO(...) \
+ do { \
+ PRINTF(__VA_ARGS__); \
+ MAP_LOG(__VA_ARGS__); \
+ } while (0)
+
#define MAP_LOG_PC(sd, fmt, ...) \
MAP_LOG("PC%d %s:%d,%d " fmt, \
sd->status_key.char_id, (sd->bl_m->name_), sd->bl_x, sd->bl_y, ## __VA_ARGS__)
@@ -692,5 +698,14 @@ struct charid2nick
CharName nick;
int req_id;
};
+
+struct AuthFifoEntry
+{
+ AccountId account_id;
+ CharId char_id;
+ int login_id1, login_id2;
+ IP4Address ip;
+ int delflag;
+};
} // namespace map
} // namespace tmwa
diff --git a/tools/protocol.py b/tools/protocol.py
index 2940744..413bb67 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -6231,6 +6231,38 @@ def build_context():
Party leader was changed.
''',
)
+ char_map.s(0x3829, 'account auth',
+ fixed=[
+ at(0, u16, 'packet id'),
+ at(2, account_id, 'account id'),
+ at(6, char_id, 'char id'),
+ at(10, u32, 'login id1'),
+ at(14, u32, 'login id2'),
+ at(18, ip4, 'ip'),
+ ],
+ fixed_size=22,
+ pre=[],
+ post=[],
+ desc='''
+ send auth data to map server
+ ''',
+ )
+ char_map.r(0x3830, 'account auth reply',
+ fixed=[
+ at(0, u16, 'packet id'),
+ at(2, account_id, 'account id'),
+ at(6, char_id, 'char id'),
+ at(10, u32, 'login id1'),
+ at(14, u32, 'login id2'),
+ at(18, ip4, 'ip'),
+ ],
+ fixed_size=22,
+ pre=[],
+ post=[],
+ desc='''
+ reply to char server
+ ''',
+ )
# TOC_MISC
# any client