Beta Release of PIN Code system.
Thanks to Yommy for his help with the basic packet information and LightFighter for the PIN decrypt function. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17183 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
3f28476cd2
commit
0fc28289b5
@ -159,4 +159,22 @@ char_del_delay: 86400
|
||||
// What folder the DB files are in (item_db.txt, etc.)
|
||||
db_path: db
|
||||
|
||||
// Pincode system
|
||||
// A window is opened before you can select your character and you will have to enter a pincode by using only your mouse
|
||||
// NOTE: Requires client 2011-03-09aragexeRE or newer.
|
||||
// 0: disabled
|
||||
// 1: enabled
|
||||
pincode_enabled: 1
|
||||
|
||||
// How often does a user have to change his pincode?
|
||||
// Default: 0
|
||||
// 0: never
|
||||
// X: every X seconds
|
||||
pincode_changetime: 0
|
||||
|
||||
// How often can a user enter the wrong password?
|
||||
// Default: 3
|
||||
// NOTE: The maximum on clientside is 3
|
||||
pincode_maxtry: 3
|
||||
|
||||
import: conf/import/char_conf.txt
|
||||
|
2
sql-files/upgrades/upgrade_svn17183.sql
Normal file
2
sql-files/upgrades/upgrade_svn17183.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE `login` ADD COLUMN `pincode` varchar(4) NOT NULL DEFAULT '';
|
||||
ALTER TABLE `login` ADD COLUMN `pincode_change` int(11) unsigned NOT NULL DEFAULT '0';
|
229
src/char/char.c
229
src/char/char.c
@ -131,6 +131,10 @@ struct char_session_data {
|
||||
uint8 clienttype;
|
||||
char new_name[NAME_LENGTH];
|
||||
char birthdate[10+1]; // YYYY-MM-DD
|
||||
char pincode[4+1];
|
||||
uint16 pincode_seed;
|
||||
time_t pincode_change;
|
||||
uint16 pincode_try;
|
||||
};
|
||||
|
||||
int max_connect_user = -1;
|
||||
@ -141,6 +145,27 @@ int start_weapon = 1201;
|
||||
int start_armor = 2301;
|
||||
int guild_exp_rate = 100;
|
||||
|
||||
// Pincode system
|
||||
#define PINCODE_OK 0
|
||||
#define PINCODE_ASK 1
|
||||
#define PINCODE_NOTSET 2
|
||||
#define PINCODE_EXPIRED 3
|
||||
#define PINCODE_UNUSED 7
|
||||
#define PINCODE_WRONG 8
|
||||
|
||||
int pincode_enabled = PINCODE_OK; // PINCODE_OK = off, PINCODE_ASK = on
|
||||
int pincode_changetime = 0;
|
||||
int pincode_maxtry = 3;
|
||||
|
||||
void pincode_check( int fd, struct char_session_data* sd );
|
||||
void pincode_change( int fd, struct char_session_data* sd );
|
||||
void pincode_setnew( int fd, struct char_session_data* sd );
|
||||
void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
|
||||
void pincode_notifyLoginPinUpdate( int account_id, char* pin );
|
||||
void pincode_notifyLoginPinError( int account_id );
|
||||
void pincode_decrypt( unsigned long userSeed, char* pin );
|
||||
int pincode_compare( int fd, struct char_session_data* sd, char* pin );
|
||||
|
||||
//Custom limits for the fame lists. [Skotlex]
|
||||
int fame_list_size_chemist = MAX_FAME_LIST;
|
||||
int fame_list_size_smith = MAX_FAME_LIST;
|
||||
@ -2147,7 +2172,7 @@ int parse_fromlogin(int fd) {
|
||||
break;
|
||||
|
||||
case 0x2717: // account data
|
||||
if (RFIFOREST(fd) < 63)
|
||||
if (RFIFOREST(fd) < 72)
|
||||
return 0;
|
||||
|
||||
// find the authenticated session with this account id
|
||||
@ -2165,6 +2190,8 @@ int parse_fromlogin(int fd) {
|
||||
} else if ( !sd->char_slots )/* no value aka 0 in sql */
|
||||
sd->char_slots = MAX_CHARS;/* cap to maximum */
|
||||
safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
|
||||
safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode));
|
||||
sd->pincode_change = (time_t)RFIFOL(fd,68);
|
||||
ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
|
||||
// continued from char_auth_ok...
|
||||
if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
|
||||
@ -2179,18 +2206,28 @@ int parse_fromlogin(int fd) {
|
||||
// send characters to player
|
||||
mmo_char_send006b(i, sd);
|
||||
#if PACKETVER >= 20110309
|
||||
// PIN code system, disabled
|
||||
WFIFOHEAD(i, 12);
|
||||
WFIFOW(i, 0) = 0x08B9;
|
||||
WFIFOW(i, 2) = 0;
|
||||
WFIFOW(i, 4) = 0;
|
||||
WFIFOL(i, 6) = sd->account_id;
|
||||
WFIFOW(i, 10) = 0;
|
||||
WFIFOSET(i, 12);
|
||||
if( pincode_enabled ){
|
||||
// PIN code system enabled
|
||||
if( strlen( sd->pincode ) <= 0 ){
|
||||
// No PIN code has been set yet
|
||||
pincode_sendstate( i, sd, PINCODE_UNUSED );
|
||||
}else{
|
||||
if( !pincode_changetime || sd->pincode_change > time(NULL) ){
|
||||
// Ask user for his PIN code
|
||||
pincode_sendstate( i, sd, PINCODE_ASK );
|
||||
}else{
|
||||
// User hasnt changed his PIN code too long
|
||||
pincode_sendstate( i, sd, PINCODE_EXPIRED );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// PIN code system, disabled
|
||||
pincode_sendstate( i, sd, PINCODE_OK );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
RFIFOSKIP(fd,63);
|
||||
RFIFOSKIP(fd,72);
|
||||
break;
|
||||
|
||||
// login-server alive packet
|
||||
@ -4188,6 +4225,58 @@ int parse_char(int fd)
|
||||
}
|
||||
return 0; // avoid processing of followup packets here
|
||||
|
||||
// checks the entered pin
|
||||
case 0x8b8:
|
||||
if( RFIFOREST(fd) < 10 )
|
||||
return 0;
|
||||
|
||||
if( RFIFOL(fd,2) != sd->account_id )
|
||||
break;
|
||||
|
||||
pincode_check( fd, sd );
|
||||
|
||||
RFIFOSKIP(fd,10);
|
||||
break;
|
||||
|
||||
// request for PIN window
|
||||
case 0x8c5:
|
||||
if( RFIFOREST(fd) < 6 )
|
||||
return 0;
|
||||
|
||||
if( RFIFOL(fd,2) != sd->account_id )
|
||||
break;
|
||||
|
||||
pincode_sendstate( fd, sd, PINCODE_NOTSET );
|
||||
|
||||
RFIFOSKIP(fd,6);
|
||||
break;
|
||||
|
||||
// pincode change request
|
||||
case 0x8be:
|
||||
if( RFIFOREST(fd) < 14 )
|
||||
return 0;
|
||||
|
||||
if( RFIFOL(fd,2) != sd->account_id )
|
||||
break;
|
||||
|
||||
pincode_change( fd, sd );
|
||||
|
||||
RFIFOSKIP(fd,14);
|
||||
break;
|
||||
|
||||
// activate PIN system and set first PIN
|
||||
case 0x8ba:
|
||||
if( RFIFOREST(fd) < 10 )
|
||||
return 0;
|
||||
|
||||
if( RFIFOL(fd,2) != sd->account_id )
|
||||
break;
|
||||
|
||||
pincode_setnew( fd, sd );
|
||||
|
||||
RFIFOSKIP(fd,10);
|
||||
break;
|
||||
|
||||
// unknown packet received
|
||||
default:
|
||||
ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));
|
||||
@ -4368,6 +4457,120 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//Pincode system
|
||||
//------------------------------------------------
|
||||
void pincode_check( int fd, struct char_session_data* sd ){
|
||||
char pin[5] = "\0\0\0\0";
|
||||
strncpy((char*)pin, (char*)RFIFOP(fd, 6), 4+1);
|
||||
|
||||
pincode_decrypt(sd->pincode_seed, pin );
|
||||
|
||||
if( pincode_compare( fd, sd, pin ) ){
|
||||
pincode_sendstate( fd, sd, PINCODE_OK );
|
||||
}
|
||||
}
|
||||
|
||||
int pincode_compare( int fd, struct char_session_data* sd, char* pin ){
|
||||
if( strcmp( sd->pincode, pin ) == 0 ){
|
||||
sd->pincode_try = 0;
|
||||
return 1;
|
||||
}else{
|
||||
pincode_sendstate( fd, sd, PINCODE_WRONG );
|
||||
|
||||
if( pincode_maxtry && ++sd->pincode_try >= pincode_maxtry ){
|
||||
pincode_notifyLoginPinError( sd->account_id );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void pincode_change( int fd, struct char_session_data* sd ){
|
||||
char oldpin[5] = "\0\0\0\0";
|
||||
char newpin[5] = "\0\0\0\0";
|
||||
|
||||
strncpy(oldpin, (char*)RFIFOP(fd,6), 4+1);
|
||||
pincode_decrypt(sd->pincode_seed,oldpin);
|
||||
|
||||
if( !pincode_compare( fd, sd, oldpin ) )
|
||||
return;
|
||||
|
||||
strncpy(newpin, (char*)RFIFOP(fd,10), 4+1);
|
||||
pincode_decrypt(sd->pincode_seed,newpin);
|
||||
|
||||
pincode_notifyLoginPinUpdate( sd->account_id, newpin );
|
||||
|
||||
pincode_sendstate( fd, sd, PINCODE_OK );
|
||||
}
|
||||
|
||||
void pincode_setnew( int fd, struct char_session_data* sd ){
|
||||
char newpin[5] = "\0\0\0\0";
|
||||
|
||||
strncpy(newpin, (char*)RFIFOP(fd,6), 4+1);
|
||||
pincode_decrypt(sd->pincode_seed,newpin);
|
||||
|
||||
pincode_notifyLoginPinUpdate( sd->account_id, newpin );
|
||||
|
||||
pincode_sendstate( fd, sd, PINCODE_OK );
|
||||
}
|
||||
|
||||
// 0 = disabled / pin is correct
|
||||
// 1 = ask for pin - client sends 0x8b8
|
||||
// 2 = create new pin - client sends 0x8ba
|
||||
// 3 = pin must be changed - client 0x8be
|
||||
// 4 = create new pin ?? - client sends 0x8ba
|
||||
// 5 = client shows msgstr(1896)
|
||||
// 6 = client shows msgstr(1897) Unable to use your KSSN number
|
||||
// 7 = char select window shows a button - client sends 0x8c5
|
||||
// 8 = pincode was incorrect
|
||||
void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state ){
|
||||
WFIFOHEAD(fd, 12);
|
||||
WFIFOW(fd, 0) = 0x8b9;
|
||||
WFIFOL(fd, 2) = sd->pincode_seed = rand() % 0xFFFF;
|
||||
WFIFOL(fd, 6) = sd->account_id;
|
||||
WFIFOW(fd,10) = state;
|
||||
WFIFOSET(fd,12);
|
||||
}
|
||||
|
||||
void pincode_notifyLoginPinUpdate( int account_id, char* pin ){
|
||||
WFIFOHEAD(login_fd,15);
|
||||
WFIFOW(login_fd,0) = 0x2738;
|
||||
WFIFOL(login_fd,2) = account_id;
|
||||
strncpy( (char*)WFIFOP(login_fd,6), pin, 5 );
|
||||
WFIFOL(login_fd,11) = pincode_changetime;
|
||||
WFIFOSET(login_fd,15);
|
||||
}
|
||||
|
||||
void pincode_notifyLoginPinError( int account_id ){
|
||||
WFIFOHEAD(login_fd,6);
|
||||
WFIFOW(login_fd,0) = 0x2739;
|
||||
WFIFOL(login_fd,2) = account_id;
|
||||
WFIFOSET(login_fd,6);
|
||||
}
|
||||
|
||||
void pincode_decrypt( unsigned long userSeed, char* pin ){
|
||||
int i, pos;
|
||||
char tab[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
unsigned long multiplier = 0x3498, baseSeed = 0x881234;
|
||||
|
||||
for( i = 1; i < 10; i++ ){
|
||||
userSeed = baseSeed + userSeed * multiplier;
|
||||
pos = userSeed % (i + 1);
|
||||
if( i != pos ){
|
||||
tab[i] ^= tab[pos];
|
||||
tab[pos] ^= tab[i];
|
||||
tab[i] ^= tab[pos];
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < 4; i++ ){
|
||||
pin[i] = tab[pin[i]- '0'];
|
||||
}
|
||||
|
||||
sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
//Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't
|
||||
//replies/disconnect the player we tried to kick. [Skotlex]
|
||||
@ -4691,6 +4894,12 @@ int char_config_read(const char* cfgName)
|
||||
}
|
||||
} else if (strcmpi(w1, "guild_exp_rate") == 0) {
|
||||
guild_exp_rate = atoi(w2);
|
||||
} else if (strcmpi(w1, "pincode_enabled") == 0) {
|
||||
pincode_enabled = atoi(w2);
|
||||
} else if (strcmpi(w1, "pincode_changetime") == 0) {
|
||||
pincode_changetime = atoi(w2);
|
||||
} else if (strcmpi(w1, "pincode_maxtry") == 0) {
|
||||
pincode_maxtry = atoi(w2);
|
||||
} else if (strcmpi(w1, "import") == 0) {
|
||||
char_config_read(w2);
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ void mapif_parse_accinfo(int fd) {
|
||||
account_id = atoi(query);
|
||||
|
||||
if (account_id < START_ACCOUNT_NUM) { // is string
|
||||
if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `char` WHERE `name` LIKE '%s' LIMIT 10", query_esq)
|
||||
if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", char_db, query_esq)
|
||||
|| Sql_NumRows(sql_handle) == 0 ) {
|
||||
if( Sql_NumRows(sql_handle) == 0 ) {
|
||||
inter_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query);
|
||||
|
@ -50,6 +50,8 @@ struct mmo_account
|
||||
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 pincode[4+1]; // pincode system
|
||||
time_t pincode_change; // (timestamp): last time of pincode change
|
||||
int account_reg2_num;
|
||||
struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
|
||||
};
|
||||
|
@ -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,6 +549,8 @@ 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);
|
||||
|
@ -562,6 +562,7 @@ int parse_fromchar(int fd)
|
||||
uint8 char_slots = 0;
|
||||
int group_id = 0;
|
||||
char birthdate[10+1] = "";
|
||||
char pincode[4+1] = "";
|
||||
|
||||
int account_id = RFIFOL(fd,2);
|
||||
RFIFOSKIP(fd,6);
|
||||
@ -574,9 +575,10 @@ int parse_fromchar(int fd)
|
||||
group_id = acc.group_id;
|
||||
char_slots = acc.char_slots;
|
||||
safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
|
||||
safestrncpy(pincode, acc.pincode, sizeof(pincode));
|
||||
}
|
||||
|
||||
WFIFOHEAD(fd,63);
|
||||
WFIFOHEAD(fd,72);
|
||||
WFIFOW(fd,0) = 0x2717;
|
||||
WFIFOL(fd,2) = account_id;
|
||||
safestrncpy((char*)WFIFOP(fd,6), email, 40);
|
||||
@ -584,7 +586,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) = (uint32)acc.pincode_change;
|
||||
WFIFOSET(fd,72);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -910,6 +914,54 @@ int parse_fromchar(int fd)
|
||||
RFIFOSKIP(fd,2);
|
||||
break;
|
||||
|
||||
case 0x2738: //Change PIN Code for a account
|
||||
if( RFIFOREST(fd) < 15 )
|
||||
return 0;
|
||||
|
||||
{
|
||||
struct mmo_account acc;
|
||||
|
||||
if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) )
|
||||
{
|
||||
strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 );
|
||||
acc.pincode_change = RFIFOL(fd,11);
|
||||
if( acc.pincode_change > 0 ){
|
||||
acc.pincode_change += time( NULL );
|
||||
}
|
||||
accounts->save(accounts, &acc);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
RFIFOSKIP(fd,15);
|
||||
break;
|
||||
|
||||
case 0x2739: // PIN Code was entered wrong too often
|
||||
if( RFIFOREST(fd) < 6 )
|
||||
return 0;
|
||||
|
||||
{
|
||||
|
||||
struct mmo_account acc;
|
||||
|
||||
if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) )
|
||||
{
|
||||
struct online_login_data* ld;
|
||||
|
||||
ld = (struct online_login_data*)idb_get(online_db,acc.account_id);
|
||||
|
||||
if( ld == 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);
|
||||
@ -961,6 +1013,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, "", sizeof(acc.pincode));
|
||||
acc.pincode_change = 0;
|
||||
|
||||
acc.char_slots = 0;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user