summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/char/char.cpp31
-rw-r--r--src/login/login.cpp250
-rw-r--r--src/login/login.hpp1
-rwxr-xr-xtools/protocol.py16
4 files changed, 155 insertions, 143 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp
index f4e0542..eac1e06 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -1275,6 +1275,20 @@ void parse_tologin(Session *ls)
auth_fifo_iter->ip = fixed.ip;
auth_fifo_iter->client_version = fixed.client_protocol_version;
auth_fifo_iter++;
+
+ if (login_session)
+ {
+ // tell login server we accepted the auth details
+ Packet_Fixed<0x2742> fixed_2742;
+ fixed_2742.account_id = fixed.account_id;
+ fixed_2742.login_id1 = fixed.login_id1;
+ fixed_2742.login_id2 = fixed.login_id2;
+ fixed_2742.ip = fixed.ip;
+ fixed_2742.client_protocol_version = fixed.client_protocol_version;
+ send_fpacket<0x2742, 22>(login_session, fixed_2742);
+
+ CHAR_LOG_AND_ECHO("Received auth details for account %d [%s], replying to login server\n"_fmt, fixed.account_id, fixed.ip);
+ }
break;
}
@@ -1705,7 +1719,7 @@ void parse_frommap(Session *ms)
// here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value)
(afi.login_id2 == login_id2 || login_id2 == 0) && // relate to the versions higher than 18
afi.ip == ip
- && !afi.delflag)
+ && afi.delflag == 3)
{
CharPair *cp = nullptr;
for (CharPair& cdi : char_keys)
@@ -2208,7 +2222,7 @@ void handle_x0066(Session *s, struct char_session_data *sd, uint8_t rfifob_2, IP
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 = 0;
+ 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;
@@ -2343,16 +2357,9 @@ void parse_char(Session *s)
// authentification not found
{
{
- // there is always a login-server
- Packet_Fixed<0x2712> fixed_12;
- fixed_12.account_id = sd->account_id;
- fixed_12.login_id1 = sd->login_id1;
- fixed_12.login_id2 = sd->login_id2; // relate to the versions higher than 18
- fixed_12.sex = sd->sex;
- fixed_12.ip = s->client_ip;
- send_fpacket<0x2712, 19>(login_session, fixed_12);
-
- CHAR_LOG_AND_ECHO("Account %d [%s] authentication deferred, sending request to login-server for confirmation\n"_fmt, account_id, ip);
+ if (sd)
+ CHAR_LOG_AND_ECHO("Unauthenticated attempt to request chars from account %d (REJECTED IP: %s)!\n"_fmt, sd->account_id, ip);
+ s->set_eof();
}
}
}
diff --git a/src/login/login.cpp b/src/login/login.cpp
index 657a96e..90c387d 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -82,13 +82,21 @@
namespace tmwa
{
-DIAG_PUSH();
-DIAG_I(missing_noreturn);
-void SessionDeleter::operator()(SessionData *)
+namespace login
+{
+struct login_session_data : SessionData
+{
+ AccountId account_id;
+ int login_id1, login_id2;
+ IP4Address client_ip;
+ int auth_fifo_pos;
+};
+} // namespace login
+
+void SessionDeleter::operator()(SessionData *sd)
{
- assert(false && "login server does not have sessions anymore"_s);
+ really_delete1 static_cast<login::login_session_data *>(sd);
}
-DIAG_POP();
// out of namespace because ADL is dumb
bool extract(XString str, login::ACO *aco)
@@ -837,6 +845,9 @@ void char_anti_freeze_system(TimerData *, tick_t)
}
}
+static
+bool lan_ip_check(IP4Address p);
+
//--------------------------------
// Packet parsing for char-servers
//--------------------------------
@@ -865,79 +876,6 @@ void parse_fromchar(Session *s)
switch (packet_id)
{
- case 0x2712: // request from char-server to authentify an account
- {
- Packet_Fixed<0x2712> fixed;
- rv = recv_fpacket<0x2712, 19>(s, fixed);
- if (rv != RecvResult::Complete)
- break;
-
- {
- uint8_t invalid_code = 0x42; // 0x42 as default, for backward-compatibility with old clients
- AccountId acc = fixed.account_id;
- int i;
- for (i = 0; i < AUTH_FIFO_SIZE; i++)
- {
- if (auth_fifo[i].account_id == acc &&
- auth_fifo[i].login_id1 == fixed.login_id1 &&
- auth_fifo[i].login_id2 == fixed.login_id2 && // relate to the versions higher than 18
- auth_fifo[i].ip == fixed.ip
- && !auth_fifo[i].delflag)
- {
- auth_fifo[i].delflag = 1;
- LOGIN_LOG_AND_ECHO("Char-server '%s' (ip %s): authentication of the account %d accepted (ip: %s).\n"_fmt,
- server[id].name, ip, acc, fixed.ip);
- for (const AuthData& ad : auth_data)
- {
- if (ad.account_id == acc)
- {
- Packet_Head<0x2729> head_29;
- head_29.account_id = acc;
- std::vector<Packet_Repeat<0x2729>> repeat_29;
- int j;
- for (j = 0;
- j < ad.account_reg2_num;
- j++)
- {
- Packet_Repeat<0x2729> item;
- item.name = ad.account_reg2[j].str;
- item.value = ad.account_reg2[j].value;
- repeat_29.push_back(item);
- }
- send_vpacket<0x2729, 8, 36>(s, head_29, repeat_29);
-
- Packet_Fixed<0x2713> fixed_13;
- fixed_13.account_id = acc;
- fixed_13.invalid = 0;
- fixed_13.email = ad.email;
- fixed_13.client_protocol_version = auth_fifo[i].client_version;
-
- send_fpacket<0x2713, 55>(s, fixed_13);
- goto x2712_out;
- }
- }
- invalid_code = 2; // login auth data not found
- break;
- }
- }
- // authentification not found
- {
- LOGIN_LOG_AND_ECHO("Char-server '%s' (ip %s): authentication of the account %d REJECTED (REJECTED IP: %s).\n"_fmt,
- server[id].name, ip, acc, fixed.ip);
-
- Packet_Fixed<0x2713> fixed_13;
- fixed_13.account_id = acc;
- fixed_13.invalid = invalid_code; // 0x42: login session not found
- // fixed_13.email
- // fixed_13.connect_until
-
- send_fpacket<0x2713, 55>(s, fixed_13);
- }
- }
- }
- x2712_out:
- break;
-
case 0x2714:
{
Packet_Fixed<0x2714> fixed;
@@ -1313,6 +1251,79 @@ void parse_fromchar(Session *s)
break;
}
+ case 0x2742:
+ {
+ Packet_Fixed<0x2742> fixed;
+ rv = recv_fpacket<0x2742, 22>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ for (io::FD i : iter_fds())
+ {
+ Session *s2 = get_session(i);
+ if (!s2)
+ continue;
+ struct login_session_data *sd = static_cast<login_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->client_ip == fixed.ip &&
+ auth_fifo[sd->auth_fifo_pos].account_id == fixed.account_id)
+ {
+ auth_fifo[sd->auth_fifo_pos].consumed_by++; // one char server consumed this
+
+ LOGIN_LOG_AND_ECHO("Char server %i accepted 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_char_servers global var
+ for (int k = 0; k < MAX_SERVERS; k++)
+ if (server_session[k])
+ server_count++;
+
+ if (auth_fifo[sd->auth_fifo_pos].consumed_by == server_count) {
+ auth_fifo[sd->auth_fifo_pos].delflag = 1;
+
+ LOGIN_LOG_AND_ECHO("All char servers accepted auth details for account %d [%s], sending authorization to client...\n"_fmt,
+ fixed.account_id, fixed.ip);
+
+ // Load list of char servers into outbound packet
+ std::vector<Packet_Repeat<0x0069>> repeat_69;
+ for (int e = 0; e < MAX_SERVERS; e++)
+ {
+ if (server_session[e])
+ {
+ Packet_Repeat<0x0069> info;
+ if (lan_ip_check(ip))
+ info.ip = login_lan_conf.lan_char_ip;
+ else
+ info.ip = server[e].ip;
+ info.port = server[e].port;
+ info.server_name = server[e].name;
+ info.users = server[e].users;
+ info.maintenance = 0; //maintenance;
+ info.is_new = 0; //is_new;
+ repeat_69.push_back(info);
+ }
+ }
+
+ Packet_Head<0x0069> head_69;
+ head_69.login_id1 = fixed.login_id1;
+ head_69.account_id = fixed.account_id;
+ head_69.login_id2 = fixed.login_id2;
+ head_69.unused = 0;
+ //head_69.last_login_string = account.lastlogin;
+ head_69.unused2 = 0;
+ head_69.sex = SEX::UNSPECIFIED;
+ send_vpacket<0x0069, 47, 32>(s2, head_69, repeat_69);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
default:
{
{
@@ -2491,74 +2502,51 @@ void parse_login(Session *s)
}
}
- // Load list of char servers into outbound packet
- std::vector<Packet_Repeat<0x0069>> repeat_69;
- //if (fixed.flags & VERSION_2_SERVERORDER)
+ // send to char server and wait for a reply
+ bool has_char_server = false;
+ // FIXME: this is silly, we should have a active_char_servers global var
for (int i = 0; i < MAX_SERVERS; i++)
{
if (server_session[i])
{
- Packet_Repeat<0x0069> info;
- if (lan_ip_check(ip))
- info.ip = login_lan_conf.lan_char_ip;
- else
- info.ip = server[i].ip;
- info.port = server[i].port;
- info.server_name = server[i].name;
- info.users = server[i].users;
- info.maintenance = 0; //maintenance;
- info.is_new = 0; //is_new;
- repeat_69.push_back(info);
+ has_char_server = true;
+ break;
}
}
- // if at least 1 char-server
- if (repeat_69.size())
- {
- // pre-send the auth validation to char server
- {
- Packet_Fixed<0x2715> fixed_27;
- fixed_27.account_id = account.account_id;
- fixed_27.login_id1 = account.login_id1;
- fixed_27.login_id2 = account.login_id2;
- fixed_27.ip = s->client_ip;
- fixed_27.client_protocol_version = fixed.client_protocol_version;
- for (Session *ss : iter_char_sessions())
- send_fpacket<0x2715, 22>(ss, fixed_27);
- }
-
- // since char server already knows our auth ids this
- // shouldn't be necessary, but we're keeping it just
- // in case, because why not
- {
+ if (has_char_server)
+ {
+ { // this will be verified after we receive 0x2742
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
auth_fifo_pos = 0;
- auth_fifo[auth_fifo_pos].account_id =
- account.account_id;
- auth_fifo[auth_fifo_pos].login_id1 =
- account.login_id1;
- auth_fifo[auth_fifo_pos].login_id2 =
- account.login_id2;
+ auth_fifo[auth_fifo_pos].account_id = account.account_id;
+ auth_fifo[auth_fifo_pos].login_id1 = account.login_id1;
+ auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
auth_fifo[auth_fifo_pos].sex = account.sex;
auth_fifo[auth_fifo_pos].delflag = 0;
- auth_fifo[auth_fifo_pos].ip =
- s->client_ip;
- auth_fifo[auth_fifo_pos].client_version =
- fixed.client_protocol_version;
+ auth_fifo[auth_fifo_pos].consumed_by = 0; // 0 char servers replied yet
+ auth_fifo[auth_fifo_pos].ip = s->client_ip;
+ auth_fifo[auth_fifo_pos].client_version = fixed.client_protocol_version;
auth_fifo_pos++;
+
+ s->session_data = make_unique<login_session_data, SessionDeleter>();
+ struct login_session_data *sd = static_cast<login_session_data *>(s->session_data.get());
+ sd->account_id = account.account_id;
+ sd->login_id1 = account.login_id1;
+ sd->login_id2 = account.login_id2;
+ sd->client_ip = s->client_ip;
+ sd->auth_fifo_pos = auth_fifo_pos - 1;
}
- Packet_Head<0x0069> head_69;
- head_69.login_id1 = account.login_id1;
- head_69.account_id = account.account_id;
- head_69.login_id2 = account.login_id2;
- head_69.unused = 0; // in old version, that was for ip (not longer used)
- head_69.last_login_string = account.lastlogin; // in old version, that was for name (not longer used)
- head_69.unused2 = 0;
- head_69.sex = account.sex;
- send_vpacket<0x0069, 47, 32>(s, head_69, repeat_69);
+ Packet_Fixed<0x2715> fixed_27;
+ fixed_27.account_id = account.account_id;
+ fixed_27.login_id1 = account.login_id1;
+ fixed_27.login_id2 = account.login_id2;
+ fixed_27.ip = s->client_ip;
+ fixed_27.client_protocol_version = fixed.client_protocol_version;
- // if no char-server, don't send void list of servers, just disconnect the player with proper message
+ for (Session *ss : iter_char_sessions())
+ send_fpacket<0x2715, 22>(ss, fixed_27);
}
else
{
diff --git a/src/login/login.hpp b/src/login/login.hpp
index ed44e68..5837cfb 100644
--- a/src/login/login.hpp
+++ b/src/login/login.hpp
@@ -79,6 +79,7 @@ struct AuthFifo
IP4Address ip;
SEX sex;
int delflag;
+ int consumed_by;
ClientVersion client_version;
};
} // namespace login
diff --git a/tools/protocol.py b/tools/protocol.py
index 12f8ead..2940744 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -5250,6 +5250,22 @@ def build_context():
Password changed or not.
''',
)
+ login_char.r(0x2742, 'auth send success',
+ fixed=[
+ at(0, u16, 'packet id'),
+ at(2, account_id, 'account id'),
+ at(6, u32, 'login id1'),
+ at(10, u32, 'login id2'),
+ at(14, ip4, 'ip'),
+ at(18, client_version, 'client protocol version'),
+ ],
+ fixed_size=22,
+ pre=[0x0065],
+ post=[0x006b, 0x006c],
+ desc='''
+ Notify login server that we accepted the auth data
+ ''',
+ )
# TOC_CHARMAP
# char map