|
@@ -8,6 +8,7 @@
|
|
|
|
|
|
#include <common/malloc.hpp>
|
|
#include <common/malloc.hpp>
|
|
#include <common/md5calc.hpp>
|
|
#include <common/md5calc.hpp>
|
|
|
|
+#include <common/packets.hpp>
|
|
#include <common/random.hpp>
|
|
#include <common/random.hpp>
|
|
#include <common/showmsg.hpp> //show notice
|
|
#include <common/showmsg.hpp> //show notice
|
|
#include <common/socket.hpp> //wfifo session
|
|
#include <common/socket.hpp> //wfifo session
|
|
@@ -31,10 +32,12 @@
|
|
* <result>.B (SC_NOTIFY_BAN)
|
|
* <result>.B (SC_NOTIFY_BAN)
|
|
*/
|
|
*/
|
|
static void logclif_sent_auth_result(int fd,char result){
|
|
static void logclif_sent_auth_result(int fd,char result){
|
|
- WFIFOHEAD(fd,3);
|
|
|
|
- WFIFOW(fd,0) = 0x81;
|
|
|
|
- WFIFOB(fd,2) = result;
|
|
|
|
- WFIFOSET(fd,3);
|
|
|
|
|
|
+ PACKET_SC_NOTIFY_BAN p = {};
|
|
|
|
+
|
|
|
|
+ p.packetType = HEADER_SC_NOTIFY_BAN;
|
|
|
|
+ p.result = result;
|
|
|
|
+
|
|
|
|
+ socket_send( fd, p );
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -49,16 +52,6 @@ static void logclif_auth_ok(struct login_session_data* sd) {
|
|
uint32 subnet_char_ip;
|
|
uint32 subnet_char_ip;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
-#if PACKETVER < 20170315
|
|
|
|
- int cmd = 0x69; // AC_ACCEPT_LOGIN
|
|
|
|
- int header = 47;
|
|
|
|
- int size = 32;
|
|
|
|
-#else
|
|
|
|
- int cmd = 0xac4; // AC_ACCEPT_LOGIN3
|
|
|
|
- int header = 64;
|
|
|
|
- int size = 160;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
if( !global_core->is_running() ){
|
|
if( !global_core->is_running() ){
|
|
// players can only login while running
|
|
// players can only login while running
|
|
logclif_sent_auth_result(fd,1); // server closed
|
|
logclif_sent_auth_result(fd,1); // server closed
|
|
@@ -118,33 +111,39 @@ static void logclif_auth_ok(struct login_session_data* sd) {
|
|
login_log(ip, sd->userid, 100, "login ok");
|
|
login_log(ip, sd->userid, 100, "login ok");
|
|
ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
|
|
ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
|
|
|
|
|
|
- WFIFOHEAD(fd,header+size*server_num);
|
|
|
|
- WFIFOW(fd,0) = cmd;
|
|
|
|
- WFIFOW(fd,2) = header+size*server_num;
|
|
|
|
- WFIFOL(fd,4) = sd->login_id1;
|
|
|
|
- WFIFOL(fd,8) = sd->account_id;
|
|
|
|
- WFIFOL(fd,12) = sd->login_id2;
|
|
|
|
- WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
|
|
|
|
- //memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
|
|
|
|
- memset(WFIFOP(fd,20), 0, 24);
|
|
|
|
- WFIFOW(fd,44) = 0; // unknown
|
|
|
|
- WFIFOB(fd,46) = sex_str2num(sd->sex);
|
|
|
|
|
|
+ PACKET_AC_ACCEPT_LOGIN* p = (PACKET_AC_ACCEPT_LOGIN*)packet_buffer;
|
|
|
|
+
|
|
|
|
+ p->packetType = HEADER_AC_ACCEPT_LOGIN;
|
|
|
|
+ p->packetLength = sizeof( *p );
|
|
|
|
+ p->login_id1 = sd->login_id1;
|
|
|
|
+ p->AID = sd->account_id;
|
|
|
|
+ p->login_id2 = sd->login_id2;
|
|
|
|
+ // in old version, that was for ip (not more used)
|
|
|
|
+ p->last_ip = 0;
|
|
|
|
+ // in old version, that was for last login time (not more used)
|
|
|
|
+ safestrncpy( p->last_login, "", sizeof( p->last_login ) );
|
|
|
|
+ p->sex = sex_str2num( sd->sex );
|
|
#if PACKETVER >= 20170315
|
|
#if PACKETVER >= 20170315
|
|
- safestrncpy( WFIFOCP( fd, 47 ), sd->web_auth_token, WEB_AUTH_TOKEN_LENGTH ); // web authentication token
|
|
|
|
|
|
+ safestrncpy( p->token, sd->web_auth_token, WEB_AUTH_TOKEN_LENGTH ); // web authentication token
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
for( i = 0, n = 0; i < ARRAYLENGTH(ch_server); ++i ) {
|
|
for( i = 0, n = 0; i < ARRAYLENGTH(ch_server); ++i ) {
|
|
if( !session_isValid(ch_server[i].fd) )
|
|
if( !session_isValid(ch_server[i].fd) )
|
|
continue;
|
|
continue;
|
|
subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
|
|
subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
|
|
- WFIFOL(fd,header+n*size) = htonl((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip);
|
|
|
|
- WFIFOW(fd,header+n*size+4) = ntows(htons(ch_server[i].port)); // [!] LE byte order here [!]
|
|
|
|
- memcpy(WFIFOP(fd,header+n*size+6), ch_server[i].name, 20);
|
|
|
|
- WFIFOW(fd,header+n*size+26) = login_get_usercount( ch_server[i].users );
|
|
|
|
- WFIFOW(fd,header+n*size+28) = ch_server[i].type;
|
|
|
|
- WFIFOW(fd,header+n*size+30) = ch_server[i].new_;
|
|
|
|
|
|
+
|
|
|
|
+ PACKET_AC_ACCEPT_LOGIN_sub& char_server = p->char_servers[n];
|
|
|
|
+
|
|
|
|
+ char_server.ip = htonl( ( subnet_char_ip ) ? subnet_char_ip : ch_server[i].ip );
|
|
|
|
+ char_server.port = ntows( htons( ch_server[i].port ) ); // [!] LE byte order here [!]
|
|
|
|
+ safestrncpy( char_server.name, ch_server[i].name, sizeof( char_server.name ) );
|
|
|
|
+ char_server.users = login_get_usercount( ch_server[i].users );
|
|
|
|
+ char_server.type = ch_server[i].type;
|
|
|
|
+ char_server.new_ = ch_server[i].new_;
|
|
#if PACKETVER >= 20170315
|
|
#if PACKETVER >= 20170315
|
|
- memset(WFIFOP(fd, header+n*size+32), 0, 128); // Unknown
|
|
|
|
|
|
+ memset( &char_server.unknown, 0, sizeof( char_server.unknown ) );
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
ShowDebug(
|
|
ShowDebug(
|
|
"Sending the client (%d %d.%d.%d.%d) to char-server %s with ip %d.%d.%d.%d and port "
|
|
"Sending the client (%d %d.%d.%d.%d) to char-server %s with ip %d.%d.%d.%d and port "
|
|
@@ -152,9 +151,12 @@ static void logclif_auth_ok(struct login_session_data* sd) {
|
|
sd->account_id, CONVIP(ip), ch_server[i].name,
|
|
sd->account_id, CONVIP(ip), ch_server[i].name,
|
|
CONVIP((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip), ch_server[i].port);
|
|
CONVIP((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip), ch_server[i].port);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
n++;
|
|
n++;
|
|
|
|
+ p->packetLength += sizeof( char_server );
|
|
}
|
|
}
|
|
- WFIFOSET(fd,header+size*server_num);
|
|
|
|
|
|
+
|
|
|
|
+ socket_send( fd, p );
|
|
|
|
|
|
// create temporary auth entry
|
|
// create temporary auth entry
|
|
login_add_auth_node( sd, ip );
|
|
login_add_auth_node( sd, ip );
|
|
@@ -165,6 +167,16 @@ static void logclif_auth_ok(struct login_session_data* sd) {
|
|
data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
|
|
data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void logclif_auth_failed( int fd, int result, const char* unblock_time = "" ){
|
|
|
|
+ PACKET_AC_REFUSE_LOGIN p = {};
|
|
|
|
+
|
|
|
|
+ p.packetType = HEADER_AC_REFUSE_LOGIN;
|
|
|
|
+ p.error = result;
|
|
|
|
+ safestrncpy( p.unblock_time, "", sizeof( p.unblock_time ) );
|
|
|
|
+
|
|
|
|
+ socket_send( fd, p );
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Inform client that auth has failed.
|
|
* Inform client that auth has failed.
|
|
* @param sd: player session
|
|
* @param sd: player session
|
|
@@ -210,33 +222,18 @@ static void logclif_auth_failed(struct login_session_data* sd, int result) {
|
|
if( (result == 0 || result == 1) && login_config.dynamic_pass_failure_ban )
|
|
if( (result == 0 || result == 1) && login_config.dynamic_pass_failure_ban )
|
|
ipban_log(ip); // log failed password attempt
|
|
ipban_log(ip); // log failed password attempt
|
|
|
|
|
|
-#if PACKETVER >= 20120000 /* not sure when this started */
|
|
|
|
- WFIFOHEAD(fd,26);
|
|
|
|
- WFIFOW(fd,0) = 0x83e;
|
|
|
|
- WFIFOL(fd,2) = result;
|
|
|
|
- if( result != 6 )
|
|
|
|
- memset(WFIFOP(fd,6), '\0', 20);
|
|
|
|
- else { // 6 = You are prohibited to log in until %s
|
|
|
|
- struct mmo_account acc;
|
|
|
|
- AccountDB* accounts = login_get_accounts_db();
|
|
|
|
- time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
|
|
|
|
- timestamp2string(WFIFOCP(fd,6), 20, unban_time, login_config.date_format);
|
|
|
|
- }
|
|
|
|
- WFIFOSET(fd,26);
|
|
|
|
-#else
|
|
|
|
- WFIFOHEAD(fd,23);
|
|
|
|
- WFIFOW(fd,0) = 0x6a;
|
|
|
|
- WFIFOB(fd,2) = (uint8)result;
|
|
|
|
- if( result != 6 )
|
|
|
|
- memset(WFIFOP(fd,3), '\0', 20);
|
|
|
|
- else { // 6 = You are prohibited to log in until %s
|
|
|
|
|
|
+ // 6 = You are prohibited to log in until %s
|
|
|
|
+ if( result == 6 ){
|
|
|
|
+ char unblock_time[20];
|
|
struct mmo_account acc;
|
|
struct mmo_account acc;
|
|
AccountDB* accounts = login_get_accounts_db();
|
|
AccountDB* accounts = login_get_accounts_db();
|
|
- time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
|
|
|
|
- timestamp2string(WFIFOCP(fd,3), 20, unban_time, login_config.date_format);
|
|
|
|
|
|
+ time_t unban_time = ( accounts->load_str( accounts, &acc, sd->userid ) ) ? acc.unban_time : 0;
|
|
|
|
+ timestamp2string( unblock_time, sizeof( unblock_time ), unban_time, login_config.date_format );
|
|
|
|
+
|
|
|
|
+ logclif_auth_failed( fd, result, unblock_time );
|
|
|
|
+ }else{
|
|
|
|
+ logclif_auth_failed( fd, result );
|
|
}
|
|
}
|
|
- WFIFOSET(fd,23);
|
|
|
|
-#endif
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -246,9 +243,14 @@ static void logclif_auth_failed(struct login_session_data* sd, int result) {
|
|
* @return 0 not enough info transmitted, 1 success
|
|
* @return 0 not enough info transmitted, 1 success
|
|
*/
|
|
*/
|
|
static int logclif_parse_keepalive(int fd){
|
|
static int logclif_parse_keepalive(int fd){
|
|
- if (RFIFOREST(fd) < 26)
|
|
|
|
|
|
+ PACKET_CA_CONNECT_INFO_CHANGED* p = (PACKET_CA_CONNECT_INFO_CHANGED*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p ) ){
|
|
return 0;
|
|
return 0;
|
|
- RFIFOSKIP(fd,26);
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p ) );
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -259,112 +261,124 @@ static int logclif_parse_keepalive(int fd){
|
|
* @return 0 not enough info transmitted, 1 success
|
|
* @return 0 not enough info transmitted, 1 success
|
|
*/
|
|
*/
|
|
static int logclif_parse_updclhash(int fd, struct login_session_data *sd){
|
|
static int logclif_parse_updclhash(int fd, struct login_session_data *sd){
|
|
- if (RFIFOREST(fd) < 18)
|
|
|
|
|
|
+ PACKET_CA_EXE_HASHCHECK* p = (PACKET_CA_EXE_HASHCHECK*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p ) ){
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
sd->has_client_hash = 1;
|
|
sd->has_client_hash = 1;
|
|
- memcpy(sd->client_hash, RFIFOP(fd, 2), 16);
|
|
|
|
- RFIFOSKIP(fd,18);
|
|
|
|
|
|
+ memcpy( sd->client_hash, p->hash, sizeof( sd->client_hash ) );
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p ) );
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * Received a connection request.
|
|
|
|
- * @param fd: file descriptor to parse from (client)
|
|
|
|
- * @param sd: client session
|
|
|
|
- * @param command: packet type sent
|
|
|
|
- * @param ip: ipv4 address (client)
|
|
|
|
- * S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
|
|
|
|
- * S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
|
|
|
|
- * S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
|
|
|
|
- * S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
|
|
|
|
- * S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
|
|
|
|
- * S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
|
|
|
|
- * S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
|
|
|
|
- * @param fd: fd to parse from (client fd)
|
|
|
|
- * @return 0 failure, 1 success
|
|
|
|
- */
|
|
|
|
-static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int command, char* ip){
|
|
|
|
- size_t packet_len = RFIFOREST(fd);
|
|
|
|
-
|
|
|
|
- if( (command == 0x0064 && packet_len < 55)
|
|
|
|
- || (command == 0x0277 && packet_len < 84)
|
|
|
|
- || (command == 0x02b0 && packet_len < 85)
|
|
|
|
- || (command == 0x01dd && packet_len < 47)
|
|
|
|
- || (command == 0x01fa && packet_len < 48)
|
|
|
|
- || (command == 0x027c && packet_len < 60)
|
|
|
|
- || (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) )
|
|
|
|
|
|
+template <typename P>
|
|
|
|
+int logclif_parse_reqauth_raw( int fd, login_session_data& sd, char* ip ){
|
|
|
|
+ P* p = (P*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p ) ){
|
|
return 0;
|
|
return 0;
|
|
- else {
|
|
|
|
- int result;
|
|
|
|
- char username[NAME_LENGTH];
|
|
|
|
- char password[PASSWD_LENGTH];
|
|
|
|
- unsigned char passhash[16];
|
|
|
|
- uint8 clienttype;
|
|
|
|
- bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825);
|
|
|
|
-
|
|
|
|
- // Shinryo: For the time being, just use token as password.
|
|
|
|
- if(command == 0x0825) {
|
|
|
|
- char *accname = RFIFOCP(fd, 9);
|
|
|
|
- char *token = RFIFOCP(fd, 0x5C);
|
|
|
|
- size_t uAccLen = strlen(accname);
|
|
|
|
- size_t uTokenLen = RFIFOREST(fd) - 0x5C;
|
|
|
|
-
|
|
|
|
- if(uAccLen > NAME_LENGTH - 1 || uAccLen == 0 || uTokenLen > NAME_LENGTH - 1 || uTokenLen == 0)
|
|
|
|
- {
|
|
|
|
- logclif_auth_failed(sd, 3);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- safestrncpy(username, accname, uAccLen + 1);
|
|
|
|
- safestrncpy(password, token, uTokenLen + 1);
|
|
|
|
- clienttype = RFIFOB(fd, 8);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- safestrncpy(username, RFIFOCP(fd,6), NAME_LENGTH);
|
|
|
|
- if( israwpass )
|
|
|
|
- {
|
|
|
|
- safestrncpy(password, RFIFOCP(fd,30), PASSWD_LENGTH);
|
|
|
|
- clienttype = RFIFOB(fd,54);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- memcpy(passhash, RFIFOP(fd,30), 16);
|
|
|
|
- clienttype = RFIFOB(fd,46);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent
|
|
|
|
|
|
+ safestrncpy( sd.userid, p->username, sizeof( sd.userid ) );
|
|
|
|
+ sd.clienttype = p->clienttype;
|
|
|
|
|
|
- sd->clienttype = clienttype;
|
|
|
|
- safestrncpy(sd->userid, username, NAME_LENGTH);
|
|
|
|
- if( israwpass )
|
|
|
|
- {
|
|
|
|
- ShowStatus("Request for connection of %s (ip: %s)\n", sd->userid, ip);
|
|
|
|
- safestrncpy(sd->passwd, password, PASSWD_LENGTH);
|
|
|
|
- if( login_config.use_md5_passwds )
|
|
|
|
- MD5_String(sd->passwd, sd->passwd);
|
|
|
|
- sd->passwdenc = 0;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s)\n", sd->userid, ip);
|
|
|
|
- bin2hex(sd->passwd, passhash, 16); // raw binary data here!
|
|
|
|
- sd->passwdenc = PASSWORDENC;
|
|
|
|
- }
|
|
|
|
|
|
+ ShowStatus( "Request for connection of %s (ip: %s)\n", sd.userid, ip );
|
|
|
|
+ safestrncpy( sd.passwd, p->password, PASSWD_LENGTH );
|
|
|
|
|
|
- if( sd->passwdenc != 0 && login_config.use_md5_passwds )
|
|
|
|
- {
|
|
|
|
- logclif_auth_failed(sd, 3); // send "rejected from server"
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ if( login_config.use_md5_passwds ){
|
|
|
|
+ MD5_String( sd.passwd, sd.passwd );
|
|
|
|
+ }
|
|
|
|
|
|
- result = login_mmo_auth(sd, false);
|
|
|
|
|
|
+ sd.passwdenc = 0;
|
|
|
|
|
|
- if( result == -1 )
|
|
|
|
- logclif_auth_ok(sd);
|
|
|
|
- else
|
|
|
|
- logclif_auth_failed(sd, result);
|
|
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p ) );
|
|
|
|
+
|
|
|
|
+ int result = login_mmo_auth( &sd, false );
|
|
|
|
+
|
|
|
|
+ if( result == -1 ){
|
|
|
|
+ logclif_auth_ok( &sd );
|
|
|
|
+ }else{
|
|
|
|
+ logclif_auth_failed( &sd, result );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <typename P>
|
|
|
|
+int logclif_parse_reqauth_md5( int fd, login_session_data& sd, char* ip ){
|
|
|
|
+ P* p = (P*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p ) ){
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ safestrncpy( sd.userid, p->username, sizeof( sd.userid ) );
|
|
|
|
+ sd.clienttype = p->clienttype;
|
|
|
|
+
|
|
|
|
+ ShowStatus( "Request for connection (passwdenc mode) of %s (ip: %s)\n", sd.userid, ip );
|
|
|
|
+ bin2hex( sd.passwd, p->passwordMD5, sizeof( p->passwordMD5 ) ); // raw binary data here!
|
|
|
|
+
|
|
|
|
+ sd.passwdenc = PASSWORDENC;
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p ) );
|
|
|
|
+
|
|
|
|
+ if( login_config.use_md5_passwds ){
|
|
|
|
+ logclif_auth_failed( &sd, 3 ); // send "rejected from server"
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int result = login_mmo_auth( &sd, false );
|
|
|
|
+
|
|
|
|
+ if( result == -1 ){
|
|
|
|
+ logclif_auth_ok( &sd );
|
|
|
|
+ }else{
|
|
|
|
+ logclif_auth_failed( &sd, result );
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <typename P>
|
|
|
|
+int logclif_parse_reqauth_sso( int fd, login_session_data& sd, char* ip ){
|
|
|
|
+ P* p = (P*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p ) ){
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < p->packetLength ){
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ size_t token_length = p->packetLength - sizeof( *p );
|
|
|
|
+
|
|
|
|
+ safestrncpy( sd.userid, p->username, sizeof( sd.userid ) );
|
|
|
|
+ sd.clienttype = p->clienttype;
|
|
|
|
+
|
|
|
|
+ ShowStatus( "Request for connection (SSO mode) of %s (ip: %s)\n", sd.userid, ip );
|
|
|
|
+ // Shinryo: For the time being, just use token as password.
|
|
|
|
+ safestrncpy( sd.passwd, p->token, token_length );
|
|
|
|
+
|
|
|
|
+ if( login_config.use_md5_passwds ){
|
|
|
|
+ MD5_String( sd.passwd, sd.passwd );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sd.passwdenc = 0;
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p ) );
|
|
|
|
+
|
|
|
|
+ int result = login_mmo_auth( &sd, false );
|
|
|
|
+
|
|
|
|
+ if( result == -1 ){
|
|
|
|
+ logclif_auth_ok( &sd );
|
|
|
|
+ }else{
|
|
|
|
+ logclif_auth_failed( &sd, result );
|
|
|
|
+ }
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -375,17 +389,25 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
|
|
* @return 1 success
|
|
* @return 1 success
|
|
*/
|
|
*/
|
|
static int logclif_parse_reqkey(int fd, struct login_session_data *sd){
|
|
static int logclif_parse_reqkey(int fd, struct login_session_data *sd){
|
|
- RFIFOSKIP(fd,2);
|
|
|
|
- {
|
|
|
|
- sd->md5keylen = sizeof( sd->md5key );
|
|
|
|
- MD5_Salt(sd->md5keylen, sd->md5key);
|
|
|
|
-
|
|
|
|
- WFIFOHEAD(fd,4 + sd->md5keylen);
|
|
|
|
- WFIFOW(fd,0) = 0x01dc;
|
|
|
|
- WFIFOW(fd,2) = 4 + sd->md5keylen;
|
|
|
|
- memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen);
|
|
|
|
- WFIFOSET(fd,WFIFOW(fd,2));
|
|
|
|
|
|
+ PACKET_CA_REQ_HASH* p_in = (PACKET_CA_REQ_HASH*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p_in ) ){
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p_in ) );
|
|
|
|
+
|
|
|
|
+ sd->md5keylen = sizeof( sd->md5key );
|
|
|
|
+ MD5_Salt( sd->md5keylen, sd->md5key );
|
|
|
|
+
|
|
|
|
+ PACKET_AC_ACK_HASH* p_out = (PACKET_AC_ACK_HASH*)packet_buffer;
|
|
|
|
+
|
|
|
|
+ p_out->packetType = HEADER_AC_ACK_HASH;
|
|
|
|
+ p_out->packetLength = sizeof( *p_out ) + sd->md5keylen;
|
|
|
|
+ strncpy( p_out->salt, sd->md5key, sd->md5keylen );
|
|
|
|
+
|
|
|
|
+ socket_send( fd, p_out );
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -464,15 +486,23 @@ static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, ch
|
|
}
|
|
}
|
|
|
|
|
|
int logclif_parse_otp_login( int fd, struct login_session_data* sd ){
|
|
int logclif_parse_otp_login( int fd, struct login_session_data* sd ){
|
|
- RFIFOSKIP( fd, 68 );
|
|
|
|
|
|
+ PACKET_CT_AUTH* p_in = (PACKET_CT_AUTH*)RFIFOP( fd, 0 );
|
|
|
|
+
|
|
|
|
+ if( RFIFOREST( fd ) < sizeof( *p_in ) ){
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ RFIFOSKIP( fd, sizeof( *p_in ) );
|
|
|
|
+
|
|
|
|
+ PACKET_TC_RESULT p_out = {};
|
|
|
|
+
|
|
|
|
+ p_out.packetType = HEADER_TC_RESULT;
|
|
|
|
+ p_out.packetLength = sizeof( p_out );
|
|
|
|
+ p_out.type = 0; // normal login
|
|
|
|
+ safestrncpy( p_out.unknown1, "S1000", sizeof( p_out.unknown1 ) );
|
|
|
|
+ safestrncpy( p_out.unknown2, "token", sizeof( p_out.unknown2 ) );
|
|
|
|
|
|
- WFIFOHEAD( fd, 34 );
|
|
|
|
- WFIFOW( fd, 0 ) = 0xae3;
|
|
|
|
- WFIFOW( fd, 2 ) = 34;
|
|
|
|
- WFIFOL( fd, 4 ) = 0; // normal login
|
|
|
|
- safestrncpy( WFIFOCP( fd, 8 ), "S1000", 6 );
|
|
|
|
- safestrncpy( WFIFOCP( fd, 28 ), "token", 6 );
|
|
|
|
- WFIFOSET( fd, 34 );
|
|
|
|
|
|
+ socket_send( fd, p_out );
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -497,17 +527,15 @@ int logclif_parse(int fd) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if( sd == NULL )
|
|
|
|
- {
|
|
|
|
|
|
+ if( sd == nullptr ){
|
|
// Perform ip-ban check
|
|
// Perform ip-ban check
|
|
if( login_config.ipban && ipban_check(ipl) )
|
|
if( login_config.ipban && ipban_check(ipl) )
|
|
{
|
|
{
|
|
ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
|
|
ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
|
|
login_log(ipl, "unknown", -3, "ip banned");
|
|
login_log(ipl, "unknown", -3, "ip banned");
|
|
- WFIFOHEAD(fd,23);
|
|
|
|
- WFIFOW(fd,0) = 0x6a;
|
|
|
|
- WFIFOB(fd,2) = 3; // 3 = Rejected from Server
|
|
|
|
- WFIFOSET(fd,23);
|
|
|
|
|
|
+
|
|
|
|
+ logclif_auth_failed( fd, 3 ); // 3 = Rejected from Server
|
|
|
|
+
|
|
set_eof(fd);
|
|
set_eof(fd);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -522,35 +550,59 @@ int logclif_parse(int fd) {
|
|
uint16 command = RFIFOW(fd,0);
|
|
uint16 command = RFIFOW(fd,0);
|
|
int next=1;
|
|
int next=1;
|
|
|
|
|
|
- switch( command )
|
|
|
|
- {
|
|
|
|
- // New alive packet: used to verify if client is always alive.
|
|
|
|
- case 0x0200: next = logclif_parse_keepalive(fd); break;
|
|
|
|
- // client md5 hash (binary)
|
|
|
|
- case 0x0204: next = logclif_parse_updclhash(fd,sd); break;
|
|
|
|
- // request client login (raw password)
|
|
|
|
- case 0x0064: // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
|
|
|
|
- case 0x0277: // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
|
|
|
|
- case 0x02b0: // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
|
|
|
|
- // request client login (md5-hashed password)
|
|
|
|
- case 0x01dd: // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
|
|
|
|
- case 0x01fa: // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
|
|
|
|
- case 0x027c: // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
|
|
|
|
- case 0x0825: // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
|
|
|
|
- next = logclif_parse_reqauth(fd, sd, command, ip);
|
|
|
|
- break;
|
|
|
|
- // Sending request of the coding key
|
|
|
|
- case 0x01db: next = logclif_parse_reqkey(fd, sd); break;
|
|
|
|
- // OTP token login
|
|
|
|
- case 0x0acf:
|
|
|
|
- next = logclif_parse_otp_login( fd, sd );
|
|
|
|
- break;
|
|
|
|
- // Connection request of a char-server
|
|
|
|
- case 0x2710: logclif_parse_reqcharconnec(fd,sd, ip); return 0; // processing will continue elsewhere
|
|
|
|
- default:
|
|
|
|
- ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
|
|
|
|
- set_eof(fd);
|
|
|
|
- return 0;
|
|
|
|
|
|
+ switch( command ){
|
|
|
|
+ // New alive packet: used to verify if client is always alive.
|
|
|
|
+ case HEADER_CA_CONNECT_INFO_CHANGED:
|
|
|
|
+ next = logclif_parse_keepalive( fd );
|
|
|
|
+ break;
|
|
|
|
+ // client md5 hash (binary)
|
|
|
|
+ case HEADER_CA_EXE_HASHCHECK:
|
|
|
|
+ next = logclif_parse_updclhash( fd, sd );
|
|
|
|
+ break;
|
|
|
|
+ // request client login (raw password)
|
|
|
|
+ case HEADER_CA_LOGIN:
|
|
|
|
+ // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
|
|
|
|
+ next = logclif_parse_reqauth_raw<PACKET_CA_LOGIN>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ case HEADER_CA_LOGIN_PCBANG:
|
|
|
|
+ // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
|
|
|
|
+ next = logclif_parse_reqauth_raw<PACKET_CA_LOGIN_PCBANG>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ case HEADER_CA_LOGIN_CHANNEL:
|
|
|
|
+ // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
|
|
|
|
+ next = logclif_parse_reqauth_raw<PACKET_CA_LOGIN_CHANNEL>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ // request client login (md5-hashed password)
|
|
|
|
+ case HEADER_CA_LOGIN2:
|
|
|
|
+ // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
|
|
|
|
+ next = logclif_parse_reqauth_md5<PACKET_CA_LOGIN2>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ case HEADER_CA_LOGIN3:
|
|
|
|
+ // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
|
|
|
|
+ next = logclif_parse_reqauth_md5<PACKET_CA_LOGIN3>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ case HEADER_CA_LOGIN4:
|
|
|
|
+ // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <adapter address>.13B
|
|
|
|
+ next = logclif_parse_reqauth_md5<PACKET_CA_LOGIN4>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ case HEADER_CA_SSO_LOGIN_REQ:
|
|
|
|
+ // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.?B
|
|
|
|
+ next = logclif_parse_reqauth_sso<PACKET_CA_SSO_LOGIN_REQ>( fd, *sd, ip );
|
|
|
|
+ break;
|
|
|
|
+ // Sending request of the coding key
|
|
|
|
+ case HEADER_CA_REQ_HASH:
|
|
|
|
+ next = logclif_parse_reqkey( fd, sd );
|
|
|
|
+ break;
|
|
|
|
+ // OTP token login
|
|
|
|
+ case HEADER_CT_AUTH:
|
|
|
|
+ next = logclif_parse_otp_login( fd, sd );
|
|
|
|
+ break;
|
|
|
|
+ // Connection request of a char-server
|
|
|
|
+ case 0x2710: logclif_parse_reqcharconnec(fd,sd, ip); return 0; // processing will continue elsewhere
|
|
|
|
+ default:
|
|
|
|
+ ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
|
|
|
|
+ set_eof(fd);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete)
|
|
if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete)
|
|
}
|
|
}
|