summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/char/char-server.conf27
-rw-r--r--src/char/char.c4
-rw-r--r--src/char/pincode.c241
-rw-r--r--src/char/pincode.h40
4 files changed, 266 insertions, 46 deletions
diff --git a/conf/char/char-server.conf b/conf/char/char-server.conf
index 47506e324..7cdcc7bdb 100644
--- a/conf/char/char-server.conf
+++ b/conf/char/char-server.conf
@@ -228,8 +228,33 @@ char_configuration: {
// Default: 3
// Maximum allowed by clientside: 3
max_tries: 3
- }
+ // Whether or not to refuse pincodes that are blacklisted
+ // Default: true
+ check_blacklisted: true
+
+ // Blacklisted pincodes
+ blacklist: [
+ "0000",
+ "1111",
+ "2222",
+ "3333",
+ "4444",
+ "5555",
+ "6666",
+ "7777",
+ "8888",
+ "9999",
+ "0123",
+ "1234",
+ "2345",
+ "3456",
+ "4567",
+ "5678",
+ "6789",
+ "7890"
+ ]
+ }
}
import: "conf/import/char-server.conf"
diff --git a/src/char/char.c b/src/char/char.c
index 0069e7f1d..f370cf5a8 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -5009,7 +5009,7 @@ void char_parse_char_pincode_window(int fd, struct char_session_data* sd) __attr
void char_parse_char_pincode_window(int fd, struct char_session_data* sd)
{
if (RFIFOL(fd,2) == sd->account_id)
- pincode->sendstate(fd, sd, PINCODE_NOTSET);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_NOTSET);
RFIFOSKIP(fd, 6);
}
@@ -6156,6 +6156,7 @@ int do_final(void) {
do_final_mapif();
loginif->final();
+ pincode->final();
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s`", ragsrvinfo_db) )
Sql_ShowDebug(inter->sql_handle);
@@ -6302,6 +6303,7 @@ int do_init(int argc, char **argv) {
//Read map indexes
mapindex->init();
+ pincode->init();
#ifdef RENEWAL
start_point.map = mapindex->name2id("iz_int");
diff --git a/src/char/pincode.c b/src/char/pincode.c
index bca1b4394..8f3df4584 100644
--- a/src/char/pincode.c
+++ b/src/char/pincode.c
@@ -26,6 +26,7 @@
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/db.h"
+#include "common/memmgr.h"
#include "common/mmo.h"
#include "common/nullpo.h"
#include "common/random.h"
@@ -39,56 +40,95 @@
struct pincode_interface pincode_s;
struct pincode_interface *pincode;
-void pincode_handle (int fd, struct char_session_data* sd) {
+void pincode_handle (int fd, struct char_session_data* sd)
+{
struct online_char_data* character;
nullpo_retv(sd);
+
character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id);
- if( character && character->pincode_enable > pincode->charselect ){
+
+ if (character && character->pincode_enable > pincode->charselect) {
character->pincode_enable = pincode->charselect * 2;
- }else{
- pincode->sendstate( fd, sd, PINCODE_OK );
+ } else {
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_OK);
return;
}
- if( strlen(sd->pincode) == 4 ){
- if( pincode->changetime && time(NULL) > (sd->pincode_change+pincode->changetime) ){ // User hasn't changed his PIN code for a long time
- pincode->sendstate( fd, sd, PINCODE_EXPIRED );
+ if (strlen(sd->pincode) == 4) {
+ if (pincode->check_blacklist && pincode->isBlacklisted(sd->pincode)) {
+ // Ask player to change pincode to be able to connect
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_EXPIRED);
+ } else if (pincode->changetime && time(NULL) > (sd->pincode_change + pincode->changetime)) {
+ // User hasn't changed his PIN code for a long time
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_EXPIRED);
} else { // Ask user for his PIN code
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
}
} else // No PIN code has been set yet
- pincode->sendstate( fd, sd, PINCODE_NOTSET );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_NOTSET);
- if( character )
+ if (character)
character->pincode_enable = -1;
}
-void pincode_check(int fd, struct char_session_data* sd) {
+void pincode_check(int fd, struct char_session_data* sd)
+{
char pin[5] = "\0\0\0\0";
nullpo_retv(sd);
+
if (strlen(sd->pincode) != 4)
return;
+
safestrncpy(pin, RFIFOP(fd, 6), sizeof(pin));
- pincode->decrypt(sd->pincode_seed, pin);
- if( pincode->compare( fd, sd, pin ) ){
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(pin)) {
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_RESTRICT_PW);
+ return;
+ }
+
+ if (pincode->compare(fd, sd, pin)) {
struct online_char_data* character;
- if( (character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id)) )
+ if ((character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id)))
character->pincode_enable = pincode->charselect * 2;
- pincode->sendstate( fd, sd, PINCODE_OK );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_OK);
+ } else {
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_WRONG);
+ }
+}
+
+/**
+* Check if this pincode is blacklisted or not
+*
+* @param (const char *) pin The pin to be verified
+* @return bool
+*/
+bool pincode_isBlacklisted(const char *pin)
+{
+ int i;
+
+ nullpo_retr(false, pin);
+
+ ARR_FIND(0, VECTOR_LENGTH(pincode->blacklist), i, strcmp(VECTOR_INDEX(pincode->blacklist, i), pin) == 0);
+
+ if (i < VECTOR_LENGTH(pincode->blacklist)) {
+ return true;
}
+
+ return false;
}
-int pincode_compare(int fd, struct char_session_data* sd, char* pin) {
+int pincode_compare(int fd, struct char_session_data* sd, char* pin)
+{
nullpo_ret(sd);
nullpo_ret(pin);
- if( strcmp( sd->pincode, pin ) == 0 ){
+
+ 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 ){
+ if (pincode->maxtry && ++sd->pincode_try >= pincode->maxtry) {
pincode->error(sd->account_id);
chr->authfail_fd(fd, 0);
chr->disconnect_player(sd->account_id);
@@ -97,35 +137,94 @@ int pincode_compare(int fd, struct char_session_data* sd, char* pin) {
}
}
-void pincode_change(int fd, struct char_session_data* sd) {
+void pincode_change(int fd, struct char_session_data* sd)
+{
char oldpin[5] = "\0\0\0\0", newpin[5] = "\0\0\0\0";
nullpo_retv(sd);
+
if (strlen(sd->pincode) != 4)
return;
+
safestrncpy(oldpin, RFIFOP(fd,6), sizeof(oldpin));
- pincode->decrypt(sd->pincode_seed,oldpin);
- if( !pincode->compare( fd, sd, oldpin ) )
+ pincode->decrypt(sd->pincode_seed, oldpin);
+
+ if (!pincode->compare(fd, sd, oldpin)) {
+ pincode->editstate(fd, sd, PINCODE_EDIT_FAILED);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
return;
+ }
- safestrncpy(newpin, RFIFOP(fd,10), sizeof(newpin));
- pincode->decrypt(sd->pincode_seed,newpin);
- pincode->update( sd->account_id, newpin );
- safestrncpy(sd->pincode, newpin, sizeof(sd->pincode));
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ safestrncpy(newpin, RFIFOP(fd, 10), sizeof(newpin));
+ pincode->decrypt(sd->pincode_seed, newpin);
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(newpin)) {
+ pincode->editstate(fd, sd, PINCODE_EDIT_RESTRICT_PW);
+ } else {
+ pincode->update(sd->account_id, newpin);
+ safestrncpy(sd->pincode, newpin, sizeof(sd->pincode));
+ pincode->editstate(fd, sd, PINCODE_EDIT_SUCCESS);
+ }
+
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
}
-void pincode_setnew(int fd, struct char_session_data* sd) {
+void pincode_setnew(int fd, struct char_session_data* sd)
+{
char newpin[5] = "\0\0\0\0";
nullpo_retv(sd);
+
if (strlen(sd->pincode) == 4)
return;
+
safestrncpy(newpin, RFIFOP(fd,6), sizeof(newpin));
- pincode->decrypt(sd->pincode_seed,newpin);
- pincode->update( sd->account_id, newpin );
+ pincode->decrypt(sd->pincode_seed, newpin);
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(newpin)) {
+ pincode->makestate(fd, sd, PINCODE_MAKE_RESTRICT_PW);
+ return;
+ }
+
+ pincode->update(sd->account_id, newpin);
safestrncpy(sd->pincode, newpin, sizeof(sd->pincode));
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ pincode->makestate(fd, sd, PINCODE_MAKE_SUCCESS);
+}
+
+/**
+* Send state of making new pincode
+*
+* @param[in] fd
+* @param[in, out] sd Session Data
+* @param[in] state Pincode Edit State
+*/
+void pincode_makestate(int fd, struct char_session_data *sd, enum pincode_make_response state)
+{
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, 8);
+ WFIFOW(fd, 0) = 0x8bb;
+ WFIFOW(fd, 2) = state;
+ WFIFOW(fd, 4) = 0;
+ WFIFOSET(fd, 8);
+}
+
+/**
+* Send state of editing pincode
+*
+* @param[in] fd
+* @param[in, out] sd Session Data
+* @param[in] state Pincode Edit State
+*/
+void pincode_editstate(int fd, struct char_session_data *sd, enum pincode_edit_response state)
+{
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, 8);
+ WFIFOW(fd, 0) = 0x8bf;
+ WFIFOW(fd, 2) = state;
+ WFIFOW(fd, 4) = sd->pincode_seed = rnd() % 0xFFFF;
+ WFIFOSET(fd, 8);
}
// 0 = pin is correct
@@ -137,7 +236,8 @@ void pincode_setnew(int fd, struct char_session_data* sd) {
// 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) {
+void pincode_loginstate(int fd, struct char_session_data* sd, enum pincode_login_response state)
+{
nullpo_retv(sd);
WFIFOHEAD(fd, 12);
WFIFOW(fd, 0) = 0x8b9;
@@ -180,7 +280,7 @@ void pincode_decrypt(unsigned int userSeed, char* pin) {
}
}
- for (i = 0; i < 4; i++ ) {
+ for (i = 0; i < 4; i++) {
if (pin[i] < '0' || pin[i] > '9')
pin[i] = '0';
else
@@ -202,6 +302,8 @@ void pincode_decrypt(unsigned int userSeed, char* pin) {
bool pincode_config_read(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
+ const struct config_setting_t *temp = NULL;
+
nullpo_retr(false, filename);
nullpo_retr(false, config);
@@ -238,26 +340,93 @@ bool pincode_config_read(const char *filename, const struct config_t *config, bo
}
}
+ if (libconfig->setting_lookup_bool_real(setting, "check_blacklisted", &pincode->check_blacklist) == CONFIG_FALSE) {
+ if (!imported) {
+ ShowWarning("pincode 'check_blaclisted' not found, defaulting to false...\n");
+ pincode->check_blacklist = false;
+ }
+ }
+
+ if (pincode->check_blacklist) {
+ if ((temp = libconfig->setting_get_member(setting, "blacklist")) != NULL) {
+ VECTOR_DECL(char *) duplicate;
+ int i, j, size = libconfig->setting_length(temp);
+ VECTOR_INIT(duplicate);
+ VECTOR_ENSURE(duplicate, size, 1);
+ for (i = 0; i < size; i++) {
+ const char *pin = libconfig->setting_get_string_elem(temp, i);
+
+ if (pin == NULL)
+ continue;
+
+ if (strlen(pin) != 4) {
+ ShowError("Wrong size on element %d of blacklist. Desired size = 4, received = %d\n", i, (int)strlen(pin));
+ continue;
+ }
+
+ ARR_FIND(0, VECTOR_LENGTH(duplicate), j, strcmp(VECTOR_INDEX(duplicate, j), pin) == 0);
+
+ if (j < VECTOR_LENGTH(duplicate)) {
+ ShowWarning("Duplicate pin on pincode blacklist. Item #%d\n", i);
+ continue;
+ }
+
+ VECTOR_ENSURE(pincode->blacklist, 1, 1);
+ VECTOR_PUSH(pincode->blacklist, aStrdup(pin));
+ VECTOR_PUSH(duplicate, aStrdup(pin));
+ }
+ while (VECTOR_LENGTH(duplicate) > 0) {
+ aFree(VECTOR_POP(duplicate));
+ }
+ VECTOR_CLEAR(duplicate);
+ }
+ else if (!imported) {
+ ShowError("Pincode Blacklist Check is enabled but there's no blacklist setting! Disabling check.\n");
+ pincode->check_blacklist = false;
+ }
+ }
+
return true;
}
-void pincode_defaults(void) {
+void do_pincode_init(void)
+{
+ VECTOR_INIT(pincode->blacklist);
+}
+
+void do_pincode_final(void)
+{
+ while (VECTOR_LENGTH(pincode->blacklist) > 0) {
+ aFree(VECTOR_POP(pincode->blacklist));
+ }
+ VECTOR_CLEAR(pincode->blacklist);
+}
+
+void pincode_defaults(void)
+{
pincode = &pincode_s;
- pincode->enabled = PINCODE_OK;
+ pincode->enabled = 0;
pincode->changetime = 0;
pincode->maxtry = 3;
pincode->charselect = 0;
+ pincode->check_blacklist = false;
pincode->multiplier = 0x3498;
pincode->baseSeed = 0x881234;
+ pincode->init = do_pincode_init;
+ pincode->final = do_pincode_final;
+
pincode->handle = pincode_handle;
pincode->decrypt = pincode_decrypt;
pincode->error = pincode_notifyLoginPinError;
pincode->update = pincode_notifyLoginPinUpdate;
- pincode->sendstate = pincode_sendstate;
+ pincode->makestate = pincode_makestate;
+ pincode->editstate = pincode_editstate;
+ pincode->loginstate = pincode_loginstate;
pincode->setnew = pincode_setnew;
pincode->change = pincode_change;
+ pincode->isBlacklisted = pincode_isBlacklisted;
pincode->compare = pincode_compare;
pincode->check = pincode_check;
pincode->config_read = pincode_config_read;
diff --git a/src/char/pincode.h b/src/char/pincode.h
index cffaa3054..8e4f67c2d 100644
--- a/src/char/pincode.h
+++ b/src/char/pincode.h
@@ -22,18 +22,35 @@
#define CHAR_PINCODE_H
#include "common/hercules.h"
+#include "common/db.h"
/* Forward Declarations */
struct char_session_data;
struct config_t; // common/conf.h
-enum PincodeResponseCode {
- PINCODE_OK = 0,
- PINCODE_ASK = 1,
- PINCODE_NOTSET = 2,
- PINCODE_EXPIRED = 3,
- PINCODE_UNUSED = 7,
- PINCODE_WRONG = 8,
+enum pincode_make_response {
+ PINCODE_MAKE_SUCCESS = 0,
+ PINCODE_MAKE_DUPLICATED = 1,
+ PINCODE_MAKE_RESTRICT_PW = 2,
+ PINCODE_MAKE_PERSONALNUM_PW = 3,
+ PINCODE_MAKE_FAILED = 4,
+};
+
+enum pincode_edit_response {
+ PINCODE_EDIT_SUCCESS = 0x0,
+ PINCODE_EDIT_FAILED = 0x1,
+ PINCODE_EDIT_RESTRICT_PW = 0x2,
+ PINCODE_EDIT_PERSONALNUM_PW = 0x3,
+};
+
+enum pincode_login_response {
+ PINCODE_LOGIN_OK = 0,
+ PINCODE_LOGIN_ASK = 1,
+ PINCODE_LOGIN_NOTSET = 2,
+ PINCODE_LOGIN_EXPIRED = 3,
+ PINCODE_LOGIN_RESTRICT_PW = 5,
+ PINCODE_LOGIN_UNUSED = 7,
+ PINCODE_LOGIN_WRONG = 8,
};
/**
@@ -45,6 +62,8 @@ struct pincode_interface {
int changetime;
int maxtry;
int charselect;
+ bool check_blacklist;
+ VECTOR_DECL(char *) blacklist;
unsigned int multiplier;
unsigned int baseSeed;
/* handler */
@@ -52,12 +71,17 @@ struct pincode_interface {
void (*decrypt) (unsigned int userSeed, char* pin);
void (*error) (int account_id);
void (*update) (int account_id, char* pin);
- void (*sendstate) (int fd, struct char_session_data* sd, uint16 state);
+ void (*makestate) (int fd, struct char_session_data *sd, enum pincode_make_response state);
+ void (*editstate) (int fd, struct char_session_data *sd, enum pincode_edit_response state);
+ void (*loginstate) (int fd, struct char_session_data *sd, enum pincode_login_response state);
void (*setnew) (int fd, struct char_session_data* sd);
void (*change) (int fd, struct char_session_data* sd);
+ bool (*isBlacklisted) (const char *pin);
int (*compare) (int fd, struct char_session_data* sd, char* pin);
void (*check) (int fd, struct char_session_data* sd);
bool (*config_read) (const char *filename, const struct config_t *config, bool imported);
+ void (*init) (void);
+ void (*final) (void);
};
#ifdef HERCULES_CORE