From d2d734ce0983fbed72e69f555f57f29de04f30b3 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sat, 9 Mar 2013 00:04:28 -0300 Subject: Hercules Renewal'd Pin Code Feature is not, I repeat, NOT complete. the decryption is not fully functional which leads to dial values different from the ones the player used. Credits: lemongrass3110 for the base yommy for the packets LightFighter for the decrypt function (altho its not stable :P) Signed-off-by: shennetsind --- src/login/account.h | 26 ++++++++++++++------------ src/login/account_sql.c | 14 ++++++++++---- src/login/login.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 18 deletions(-) (limited to 'src/login') diff --git a/src/login/account.h b/src/login/account.h index 56708d5e9..be5bad988 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -38,18 +38,20 @@ struct mmo_account { int account_id; char userid[NAME_LENGTH]; - char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords - char sex; // gender (M/F/S) - char email[40]; // e-mail (by default: a@a.com) - int group_id; // player group id - uint8 char_slots; // this accounts maximum character slots (maximum is limited to MAX_CHARS define in char server) - unsigned int state; // packet 0x006a value + 1 (0: compte OK) - time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban) - time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited) - unsigned int logincount;// number of successful auth attempts - char lastlogin[24]; // date+time of last successful login - char last_ip[16]; // save of last IP of connection - char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00) + char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords + char sex; // gender (M/F/S) + char email[40]; // e-mail (by default: a@a.com) + int group_id; // player group id + uint8 char_slots; // this accounts maximum character slots (maximum is limited to MAX_CHARS define in char server) + unsigned int state; // packet 0x006a value + 1 (0: compte OK) + time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban) + time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited) + unsigned int logincount; // number of successful auth attempts + unsigned int pincode_change;// (timestamp): last time of pincode change + char pincode[4+1]; // pincode value + char lastlogin[24]; // date+time of last successful login + char last_ip[16]; // save of last IP of connection + char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00) int account_reg2_num; struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server) }; diff --git a/src/login/account_sql.c b/src/login/account_sql.c index f8c39efc9..6f21cbb6c 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -522,7 +522,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc // retrieve login entry for the specified account if( SQL_ERROR == Sql_Query(sql_handle, - "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots` FROM `%s` WHERE `account_id` = %d", + "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`,`pincode_change` FROM `%s` WHERE `account_id` = %d", db->account_db, account_id ) ) { Sql_ShowDebug(sql_handle); @@ -549,7 +549,9 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip)); Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate)); Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data); - + Sql_GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode)); + Sql_GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data); + Sql_FreeResult(sql_handle); @@ -597,7 +599,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo if( is_new ) {// insert into account table if( SQL_SUCCESS != SqlStmt_Prepare(stmt, - "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", db->account_db) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) @@ -613,6 +615,8 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_STRING, (void*)&acc->pincode, sizeof(acc->pincode)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); @@ -621,7 +625,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo } else {// update account table - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?,`pincode_change`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) @@ -635,6 +639,8 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); diff --git a/src/login/login.c b/src/login/login.c index e174672cc..c16cce342 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -559,6 +559,7 @@ int parse_fromchar(int fd) int group_id = 0; uint8 char_slots = 0; char birthdate[10+1] = ""; + char pincode[4+1] = "\0\0\0\0\0"; int account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); @@ -570,10 +571,13 @@ int parse_fromchar(int fd) expiration_time = acc.expiration_time; group_id = acc.group_id; char_slots = acc.char_slots; + safestrncpy(pincode, acc.pincode, sizeof(pincode)); safestrncpy(birthdate, acc.birthdate, sizeof(birthdate)); + if( strlen(pincode) == 0 ) + memset(pincode,'\0',sizeof(pincode)); } - WFIFOHEAD(fd,63); + WFIFOHEAD(fd,72); WFIFOW(fd,0) = 0x2717; WFIFOL(fd,2) = account_id; safestrncpy((char*)WFIFOP(fd,6), email, 40); @@ -581,7 +585,9 @@ int parse_fromchar(int fd) WFIFOB(fd,50) = (unsigned char)group_id; WFIFOB(fd,51) = char_slots; safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1); - WFIFOSET(fd,63); + safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 ); + WFIFOL(fd,68) = acc.pincode_change; + WFIFOSET(fd,72); } break; @@ -907,6 +913,41 @@ int parse_fromchar(int fd) RFIFOSKIP(fd,2); break; + case 0x2738: //Change PIN Code for a account + if( RFIFOREST(fd) < 11 ) + return 0; + else { + struct mmo_account acc; + + if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ) { + strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 ); + acc.pincode_change = time( NULL ); + accounts->save(accounts, &acc); + } + RFIFOSKIP(fd,11); + } + break; + + case 0x2739: // PIN Code was entered wrong too often + if( RFIFOREST(fd) < 6 ) + return 0; + else { + struct mmo_account acc; + + if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ) { + struct online_login_data* ld; + + if( ( ld = (struct online_login_data*)idb_get(online_db,acc.account_id) ) == NULL ) + return 0; + + login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" ); + } + + remove_online_user(acc.account_id); + RFIFOSKIP(fd,6); + } + break; + default: ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command); set_eof(fd); @@ -958,6 +999,8 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha safestrncpy(acc.lastlogin, "0000-00-00 00:00:00", sizeof(acc.lastlogin)); safestrncpy(acc.last_ip, last_ip, sizeof(acc.last_ip)); safestrncpy(acc.birthdate, "0000-00-00", sizeof(acc.birthdate)); + safestrncpy(acc.pincode, "\0", sizeof(acc.pincode)); + acc.pincode_change = 0; acc.char_slots = 0; if( !accounts->create(accounts, &acc) ) -- cgit v1.2.3-70-g09d2