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/char/pincode.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/char/pincode.c (limited to 'src/char/pincode.c') diff --git a/src/char/pincode.c b/src/char/pincode.c new file mode 100644 index 000000000..610f9b12f --- /dev/null +++ b/src/char/pincode.c @@ -0,0 +1,191 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" +#include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/strlib.h" +#include "char.h" +#include "pincode.h" + +#include + +int enabled = PINCODE_OK; +int changetime = 0; +int maxtry = 3; +unsigned long multiplier = 0x3498, baseSeed = 0x881234; + +void pincode_handle ( int fd, struct char_session_data* sd ) { + if( pincode->enabled ){ + // PIN code system enabled + if( sd->pincode[0] == '\0' ){ + // No PIN code has been set yet + pincode->state( fd, sd, PINCODE_NOTSET ); + } else { + if( !pincode->changetime || !( time(NULL) > (sd->pincode_change+*pincode->changetime) ) ){ + // Ask user for his PIN code + pincode->state( fd, sd, PINCODE_ASK ); + } else { + // User hasnt changed his PIN code too long + pincode->state( fd, sd, PINCODE_EXPIRED ); + } + } + } else { + // PIN code system, disabled + pincode->state( fd, sd, PINCODE_OK ); + } +} + +void pincode_check(int fd, struct char_session_data* sd) { + char pin[5]; + + safestrncpy((char*)pin, (char*)RFIFOP(fd, 6), 4+1); + + pincode->decrypt(sd->pincode_seed, pin); + + if( pincode->compare( fd, sd, pin ) ){ + pincode->state( 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->state( fd, sd, PINCODE_WRONG ); + + if( pincode->maxtry && ++sd->pincode_try >= *pincode->maxtry ){ + pincode->error( sd->account_id ); + } + + return 0; + } +} + +void pincode_change(int fd, struct char_session_data* sd) { + char oldpin[5], newpin[5]; + + safestrncpy(oldpin, (char*)RFIFOP(fd,6), 4+1); + pincode->decrypt(sd->pincode_seed,oldpin); + if( !pincode->compare( fd, sd, oldpin ) ) + return; + + safestrncpy(newpin, (char*)RFIFOP(fd,10), 4+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]; + + safestrncpy(newpin, (char*)RFIFOP(fd,6), 4+1); + pincode->decrypt(sd->pincode_seed,newpin); + + pincode->update( sd->account_id, newpin ); + + pincode->state( 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 = rnd() % 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,11); + WFIFOW(login_fd,0) = 0x2738; + WFIFOL(login_fd,2) = account_id; + strncpy( (char*)WFIFOP(login_fd,6), pin, 5 ); + WFIFOSET(login_fd,11); +} + +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}; + + for( i = 1; i < 10; i++ ){ + userSeed = *pincode->baseSeed + userSeed * *pincode->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]); +} + +bool pincode_config_read(char *w1, char *w2) { + + while ( true ) { + + if ( strcmpi(w1, "pincode_enabled") == 0 ) { + enabled = atoi(w2); + } else if ( strcmpi(w1, "pincode_changetime") == 0 ) { + changetime = atoi(w2)*60; + } else if ( strcmpi(w1, "pincode_maxtry") == 0 ) { + maxtry = atoi(w2); + if( maxtry > 3 ) { + ShowWarning("pincode_maxtry is too high (%d); maximum allowed: 3! capping to 3...\n",maxtry); + maxtry = 3; + } + } else + return false; + + break; + } + + return true; +} + +void pincode_defaults(void) { + pincode = &pincode_s; + + pincode->enabled = &enabled; + pincode->changetime = &changetime; + pincode->maxtry = &maxtry; + pincode->multiplier = &multiplier; + pincode->baseSeed = &baseSeed; + + pincode->handle = pincode_handle; + pincode->decrypt = pincode_decrypt; + pincode->error = pincode_notifyLoginPinError; + pincode->update = pincode_notifyLoginPinUpdate; + pincode->state = pincode_sendstate; + pincode->new = pincode_setnew; + pincode->change = pincode_change; + pincode->compare = pincode_compare; + pincode->check = pincode_check; + pincode->config_read = pincode_config_read; + +} \ No newline at end of file -- cgit v1.2.3-60-g2f50