summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-03-14 20:15:07 -0300
committershennetsind <ind@henn.et>2013-03-14 20:15:07 -0300
commit84e8f1872f0f00d6f82d6fe85974bb1f37247c53 (patch)
tree758980ea103f740ea98f2527a48869737f5f4f30
parent54b5ec95ca29216dcdac7e913f8a0c959a6c14a4 (diff)
downloadhercules-84e8f1872f0f00d6f82d6fe85974bb1f37247c53.tar.gz
hercules-84e8f1872f0f00d6f82d6fe85974bb1f37247c53.tar.bz2
hercules-84e8f1872f0f00d6f82d6fe85974bb1f37247c53.tar.xz
hercules-84e8f1872f0f00d6f82d6fe85974bb1f37247c53.zip
Fixed Pin Code Feature
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>
-rw-r--r--conf/char-server.conf7
-rw-r--r--src/char/char.c33
-rw-r--r--src/char/char.h15
-rw-r--r--src/char/pincode.c62
-rw-r--r--src/char/pincode.h8
-rw-r--r--src/login/login.c2
6 files changed, 85 insertions, 42 deletions
diff --git a/conf/char-server.conf b/conf/char-server.conf
index 26503f468..c573a5339 100644
--- a/conf/char-server.conf
+++ b/conf/char-server.conf
@@ -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
diff --git a/src/char/char.c b/src/char/char.c
index 4223fdded..3436860d0 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -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);
@@ -4176,9 +4167,11 @@ 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;
@@ -4186,7 +4179,6 @@ int parse_char(int fd)
case 0x8c5:
if( RFIFOREST(fd) < 6 )
return 0;
-
if( RFIFOL(fd,2) == sd->account_id )
pincode->state( fd, sd, PINCODE_NOTSET );
@@ -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;
@@ -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;
diff --git a/src/char/char.h b/src/char/char.h
index d75dc21f9..934c26f45 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -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,
@@ -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
diff --git a/src/char/pincode.c b/src/char/pincode.c
index 610f9b12f..c7d7bce4c 100644
--- a/src/char/pincode.c
+++ b/src/char/pincode.c
@@ -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
@@ -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 );
}
@@ -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 );
}
@@ -66,14 +85,14 @@ 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 );
@@ -81,14 +100,15 @@ void pincode_change(int fd, struct char_session_data* sd) {
}
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
@@ -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);
@@ -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};
@@ -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]);
@@ -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 ) {
@@ -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;
@@ -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;
@@ -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;
diff --git a/src/char/pincode.h b/src/char/pincode.h
index 209817c78..1856e4baa 100644
--- a/src/char/pincode.h
+++ b/src/char/pincode.h
@@ -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;
diff --git a/src/login/login.c b/src/login/login.c
index c16cce342..dfa67d932 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -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);