diff options
-rw-r--r-- | src/char/char.cpp | 31 | ||||
-rw-r--r-- | src/login/login.cpp | 250 | ||||
-rw-r--r-- | src/login/login.hpp | 1 | ||||
-rwxr-xr-x | tools/protocol.py | 16 |
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 |