/**
* 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))) )
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
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, NAME_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;
}
if( sd->passwdenc != 0 && login_config.use_md5_passwds )
{
logclif_auth_failed(sd, 3); // send "rejected from server"
return 0;
}
result = login_mmo_auth(sd, false);
if( result == -1 )
logclif_auth_ok(sd);
else
logclif_auth_failed(sd, result);
}
return 1;
}