Skip to content

Commit

Permalink
Fixed Pin Code Feature
Browse files Browse the repository at this point in the history
Now cross-platform, and stable ( after fixing I tested it a couple dozen times ).
Special Thanks to Yommy for providing me with his packet list, without it I would have never figured what was wrong with it.
Special Thanks to Jeroen who reported a inconsistency on the feature when used on windows.

Signed-off-by: shennetsind <ind@henn.et>
  • Loading branch information
shennetsind committed Mar 14, 2013
1 parent 54b5ec9 commit 84e8f18
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 42 deletions.
7 changes: 6 additions & 1 deletion conf/char-server.conf
Expand Up @@ -167,7 +167,12 @@ db_path: db
// NOTE: Requires client 2011-03-09aragexeRE or newer.
// 0: disabled
// 1: enabled
pincode_enabled: 0
pincode_enabled: 1

// Request Pincode only on login or on everytime char select is accessed?
// 0: only on login (default)
// 1: everytime the char select window is accessed
pincode_charselect: 0

// How often does a user have to change his pincode?
// Default: 0
Expand Down
33 changes: 13 additions & 20 deletions src/char/char.c
Expand Up @@ -173,15 +173,6 @@ static DBMap* auth_db; // int account_id -> struct auth_node*
// Online User Database
//-----------------------------------------------------

struct online_char_data {
int account_id;
int char_id;
int fd;
int waiting_disconnect;
short server; // -2: unknown server, -1: not connected, 0+: id of server
};

static DBMap* online_char_db; // int account_id -> struct online_char_data*
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
int delete_char_sql(int char_id);

Expand Down Expand Up @@ -4176,17 +4167,18 @@ int parse_char(int fd)
if( RFIFOREST(fd) < 10 )
return 0;

if( RFIFOL(fd,2) == sd->account_id )
pincode->check( fd, sd );

if( !sd->pincode_pass ) {
if( RFIFOL(fd,2) == sd->account_id )
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 )
pincode->state( fd, sd, PINCODE_NOTSET );

Expand All @@ -4197,9 +4189,10 @@ int parse_char(int fd)
case 0x8be:
if( RFIFOREST(fd) < 14 )
return 0;

if( RFIFOL(fd,2) == sd->account_id )
pincode->change( fd, sd );
if( !sd->pincode_pass ) {
if( RFIFOL(fd,2) == sd->account_id )
pincode->change( fd, sd );
}

RFIFOSKIP(fd,14);
break;
Expand All @@ -4208,10 +4201,10 @@ int parse_char(int fd)
case 0x8ba:
if( RFIFOREST(fd) < 10 )
return 0;

if( RFIFOL(fd,2) == sd->account_id )
pincode->new( fd, sd );

if( !sd->pincode_pass ) {
if( RFIFOL(fd,2) == sd->account_id )
pincode->new( fd, sd );
}
RFIFOSKIP(fd,10);
break;

Expand Down
15 changes: 14 additions & 1 deletion src/char/char.h
Expand Up @@ -6,6 +6,7 @@

#include "../config/core.h"
#include "../common/core.h" // CORE_ST_LAST
#include "../common/db.h"

enum E_CHARSERVER_ST {
CHARSERVER_ST_RUNNING = CORE_ST_LAST,
Expand All @@ -26,13 +27,25 @@ struct char_session_data {
uint32 version;
uint8 clienttype;
char pincode[4+1];
uint16 pincode_seed;
uint32 pincode_seed;
uint16 pincode_try;
uint32 pincode_change;
bool pincode_pass;
char new_name[NAME_LENGTH];
char birthdate[10+1]; // YYYY-MM-DD
};

struct online_char_data {
int account_id;
int char_id;
int fd;
int waiting_disconnect;
short server; // -2: unknown server, -1: not connected, 0+: id of server
bool pincode_passed;
};

DBMap* online_char_db; // int account_id -> struct online_char_data*

#define MAX_MAP_SERVERS 30

#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
Expand Down
62 changes: 46 additions & 16 deletions src/char/pincode.c
Expand Up @@ -15,10 +15,23 @@
int enabled = PINCODE_OK;
int changetime = 0;
int maxtry = 3;
unsigned long multiplier = 0x3498, baseSeed = 0x881234;
int charselect = 0;
unsigned int multiplier = 0x3498, baseSeed = 0x881234;

void pincode_handle ( int fd, struct char_session_data* sd ) {
if( pincode->enabled ){
bool pass = true;

if( !*pincode->charselect ) {
struct online_char_data* character;
if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL ) {
if( character->pincode_passed )
pass = false;
}
}

if( *pincode->enabled && pass ) {

sd->pincode_pass = false;
// PIN code system enabled
if( sd->pincode[0] == '\0' ){
// No PIN code has been set yet
Expand All @@ -37,14 +50,19 @@ void pincode_handle ( int fd, struct char_session_data* sd ) {
pincode->state( fd, sd, PINCODE_OK );
}
}

void pincode_check(int fd, struct char_session_data* sd) {
char pin[5];
void pincode_pass(struct char_session_data *sd) {
struct online_char_data* character;

safestrncpy((char*)pin, (char*)RFIFOP(fd, 6), 4+1);
if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL ) {
character->pincode_passed = true;
}
sd->pincode_pass = true;
}
void pincode_check(int fd, struct char_session_data* sd) {
char pin[4] = "\0\0\0\0";

strncpy(pin, (char*)RFIFOP(fd, 6), 3+1);
pincode->decrypt(sd->pincode_seed, pin);

if( pincode->compare( fd, sd, pin ) ){
pincode->state( fd, sd, PINCODE_OK );
}
Expand All @@ -53,11 +71,12 @@ void pincode_check(int fd, struct char_session_data* sd) {
int pincode_compare(int fd, struct char_session_data* sd, char* pin) {
if( strcmp( sd->pincode, pin ) == 0 ){
sd->pincode_try = 0;
pincode->pass(sd);
return 1;
} else {
pincode->state( fd, sd, PINCODE_WRONG );

if( pincode->maxtry && ++sd->pincode_try >= *pincode->maxtry ){
if( *pincode->maxtry && ++sd->pincode_try >= *pincode->maxtry ){
pincode->error( sd->account_id );
}

Expand All @@ -66,29 +85,30 @@ int pincode_compare(int fd, struct char_session_data* sd, char* pin) {
}

void pincode_change(int fd, struct char_session_data* sd) {
char oldpin[5], newpin[5];
char oldpin[4] = "\0\0\0\0", newpin[4] = "\0\0\0\0";

safestrncpy(oldpin, (char*)RFIFOP(fd,6), 4+1);
strncpy(oldpin, (char*)RFIFOP(fd,6), 3+1);
pincode->decrypt(sd->pincode_seed,oldpin);
if( !pincode->compare( fd, sd, oldpin ) )
return;

safestrncpy(newpin, (char*)RFIFOP(fd,10), 4+1);
strncpy(newpin, (char*)RFIFOP(fd,10), 3+1);
pincode->decrypt(sd->pincode_seed,newpin);
pincode->update( sd->account_id, newpin );

pincode->state( fd, sd, PINCODE_OK );
}

void pincode_setnew(int fd, struct char_session_data* sd) {
char newpin[5];
char newpin[4] = "\0\0\0\0";

safestrncpy(newpin, (char*)RFIFOP(fd,6), 4+1);
strncpy(newpin, (char*)RFIFOP(fd,6), 3+1);
pincode->decrypt(sd->pincode_seed,newpin);

pincode->update( sd->account_id, newpin );

pincode->state( fd, sd, PINCODE_OK );
pincode->pass(sd);
}

// 0 = disabled / pin is correct
Expand All @@ -103,7 +123,7 @@ void pincode_setnew(int fd, struct char_session_data* sd) {
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 = rnd() % 0xFFFF;
WFIFOL(fd, 2) = sd->pincode_seed = rand() % 0xFFFF;
WFIFOL(fd, 6) = sd->account_id;
WFIFOW(fd,10) = state;
WFIFOSET(fd,12);
Expand All @@ -124,7 +144,7 @@ void pincode_notifyLoginPinError(int account_id) {
WFIFOSET(login_fd,6);
}

void pincode_decrypt(unsigned long userSeed, char* pin) {
void pincode_decrypt(unsigned int userSeed, char* pin) {
int i, pos;
char tab[10] = {0,1,2,3,4,5,6,7,8,9};

Expand All @@ -139,7 +159,7 @@ void pincode_decrypt(unsigned long userSeed, char* pin) {
}

for( i = 0; i < 4; i++ ){
pin[i] = tab[pin[i]- '0'];
pin[i] = tab[pin[i] - '0'];
}

sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]);
Expand All @@ -151,6 +171,12 @@ bool pincode_config_read(char *w1, char *w2) {

if ( strcmpi(w1, "pincode_enabled") == 0 ) {
enabled = atoi(w2);
#ifdef PACKETVER < 20110309
if( enabled ) {
ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. disabling...\n");
enabled = 0;
}
#endif
} else if ( strcmpi(w1, "pincode_changetime") == 0 ) {
changetime = atoi(w2)*60;
} else if ( strcmpi(w1, "pincode_maxtry") == 0 ) {
Expand All @@ -159,6 +185,8 @@ bool pincode_config_read(char *w1, char *w2) {
ShowWarning("pincode_maxtry is too high (%d); maximum allowed: 3! capping to 3...\n",maxtry);
maxtry = 3;
}
} else if ( strcmpi(w1, "pincode_charselect") == 0 ) {
charselect = atoi(w2);
} else
return false;

Expand All @@ -174,6 +202,7 @@ void pincode_defaults(void) {
pincode->enabled = &enabled;
pincode->changetime = &changetime;
pincode->maxtry = &maxtry;
pincode->charselect = &charselect;
pincode->multiplier = &multiplier;
pincode->baseSeed = &baseSeed;

Expand All @@ -185,6 +214,7 @@ void pincode_defaults(void) {
pincode->new = pincode_setnew;
pincode->change = pincode_change;
pincode->compare = pincode_compare;
pincode->pass = pincode_pass;
pincode->check = pincode_check;
pincode->config_read = pincode_config_read;

Expand Down
8 changes: 5 additions & 3 deletions src/char/pincode.h
Expand Up @@ -19,17 +19,19 @@ struct pincode_interface {
int *enabled;
int *changetime;
int *maxtry;
unsigned long *multiplier;
unsigned long *baseSeed;
int *charselect;
unsigned int *multiplier;
unsigned int *baseSeed;
/* handler */
void (*handle) (int fd, struct char_session_data* sd);
void (*decrypt) (unsigned long userSeed, char* pin);
void (*decrypt) (unsigned int userSeed, char* pin);
void (*error) (int account_id);
void (*update) (int account_id, char* pin);
void (*state) (int fd, struct char_session_data* sd, uint16 state);
void (*new) (int fd, struct char_session_data* sd);
void (*change) (int fd, struct char_session_data* sd);
int (*compare) (int fd, struct char_session_data* sd, char* pin);
void (*pass) (struct char_session_data *sd);
void (*check) (int fd, struct char_session_data* sd);
bool (*config_read) (char *w1, char *w2);
} pincode_s;
Expand Down
2 changes: 1 addition & 1 deletion src/login/login.c
Expand Up @@ -921,7 +921,7 @@ int parse_fromchar(int fd)

if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ) {
strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 );
acc.pincode_change = time( NULL );
acc.pincode_change = ((unsigned int)time( NULL ));
accounts->save(accounts, &acc);
}
RFIFOSKIP(fd,11);
Expand Down

0 comments on commit 84e8f18

Please sign in to comment.