# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /home/lighta/Documents/Myscript/RO/Servs/ramerge # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: conf/atcommand_athena.conf --- conf/atcommand_athena.conf Base (BASE) +++ conf/atcommand_athena.conf Locally Modified (Based On LOCAL) Index: conf/channels.conf --- conf/channels.conf Base (BASE) +++ conf/channels.conf Locally Modified (Based On LOCAL) @@ -2,19 +2,19 @@ chsys: ( { - /* Default channels (available to all players) */ + /* Default channels (available on boot) */ default_channels: { /* channel_name : channel_messages_color */ - main: "Orange" - support: "Blue" - trade: "Red" - offtopic: "Cyan" - /* Add as many channels as you'd like. */ + main: "Orange" /* available as #main */ + support: "Blue" /* available as #support */ + trade: "Red" /* available as #trade */ + offtopic: "Cyan" /* available as #offtopic */ + /* Add as many channels as you'd like */ } /* Colors available */ colors: { - Default: "0xffffff" /* Custom channels will use the first in the list unless a font is selected through @channel. */ + Default: "0xffffff" /* Custom channels will use the first in the list unless a font is selected through @channel */ Red: "0xff0000" Blue: "0x83cfe9" Orange: "0xe57c00" @@ -22,22 +22,22 @@ Yellow: "0xffff90" Green: "0x28bf00" Normal: "0x00ff00" - /* Add as many channels as you'd like. */ + /* Add as many channels as you'd like */ } /* Allow users to create their own (private) channels through @channels command? */ /* (must also allow players to use @channels in groups.conf) */ allow_user_channel_creation: true - /* "map_local_channel" is an instanced channel unique to each map. */ + /* "map_local_channel" is a instanced channel unique to each map */ map_local_channel: true - map_local_channel_name: "map" + map_local_channel_name: "map" /* available as #map */ map_local_channel_color: "Yellow" - map_local_channel_autojoin: true /* Disable autojoin in specific maps through mapflag 'nomapchannelautojoin'. */ + map_local_channel_autojoin: true /* can disable autojoin in specific maps through a mapflag or zone */ - /* "ally_channel" is a channel shared by all your guild allies. */ + /* "ally_channel" is a channel shared by all your guild allies */ ally_channel_enabled: true - ally_channel_name: "ally" + ally_channel_name: "ally" /* available as #ally */ ally_channel_color: "Green" ally_channel_autojoin: true } Index: doc/permissions.txt --- doc/permissions.txt Base (BASE) +++ doc/permissions.txt Locally Modified (Based On LOCAL) Index: src/char/Makefile.in --- src/char/Makefile.in Base (BASE) +++ src/char/Makefile.in Locally Modified (Based On LOCAL) @@ -15,9 +15,9 @@ COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h -CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \ +CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o obj_sql/pincode.o \ obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o -CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h +CHAR_H = char.h inter.h int_party.h int_guild.h pincode.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) Index: src/char/char.c --- src/char/char.c Base (BASE) +++ src/char/char.c Locally Modified (Based On LOCAL) @@ -21,6 +21,7 @@ #include "int_storage.h" #include "char.h" #include "inter.h" +#include "pincode.h" #include #include @@ -81,7 +82,7 @@ unsigned short map[MAX_MAP_PER_SERVER]; } server[MAX_MAP_SERVERS]; -int login_fd=-1, char_fd=-1; +int char_fd=-1; char userid[24]; char passwd[24]; char server_name[20]; @@ -119,27 +120,6 @@ } subnet[16]; int subnet_count = 0; -struct char_session_data { - bool auth; // whether the session is authed or not - int account_id, login_id1, login_id2, sex; - int found_char[MAX_CHARS]; // ids of chars on this account - char email[40]; // e-mail (default: a@a.com) by [Yor] - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int group_id; // permission - uint8 char_slots; - uint32 version; - uint8 clienttype; - char new_name[NAME_LENGTH]; - char birthdate[10+1]; // YYYY-MM-DD - // Pincode system - char pincode[4+1]; - uint16 pincode_seed; - time_t pincode_change; - uint16 pincode_try; - // Addon system - unsigned int char_moves[MAX_CHARS]; // character moves left -}; - int max_connect_user = -1; int gm_allow_group = -1; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; @@ -148,29 +128,6 @@ 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_NEW 4 -#define PINCODE_PASSED 7 -#define PINCODE_WRONG 8 - -bool pincode_enabled = true; -int pincode_changetime = 0; -int pincode_maxtry = 3; -bool pincode_force = true; - -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 ); - // Addon system bool char_move_enabled = true; bool char_movetoused = true; @@ -222,16 +179,8 @@ // 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 - bool pincode_success; -}; - static DBMap* online_char_db; // int account_id -> struct online_char_data* +DBMap* char_get_online_char_db(void) { return online_char_db; } static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); int delete_char_sql(int char_id); @@ -245,6 +194,7 @@ character->account_id = key.i; character->char_id = -1; character->server = -1; + character->pincode_enable = -1; character->fd = -1; character->waiting_disconnect = INVALID_TIMER; return db_ptr2data(character); @@ -262,6 +212,8 @@ character->char_id = -1; character->server = -1; + if(character->pincode_enable == -1) + character->pincode_enable = pincode_charselect + pincode_enabled; if(character->waiting_disconnect != INVALID_TIMER) { delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); @@ -358,8 +310,7 @@ { character->char_id = -1; character->server = -1; - // needed if player disconnects completely since Skotlex did not want to free the session - character->pincode_success = false; + character->pincode_enable = -1; } //FIXME? Why Kevin free'd the online information when the char was effectively in the map-server? @@ -1044,8 +995,7 @@ char last_map[MAP_NAME_LENGTH_EXT]; stmt = SqlStmt_Malloc(sql_handle); - if( stmt == NULL ) - { + if( stmt == NULL ) { SqlStmt_ShowDebug(stmt); return 0; } @@ -1109,8 +1059,7 @@ sd->char_moves[i] = 0; } - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) - { + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) { p.last_point.map = mapindex_name2id(last_map); sd->found_char[p.slot] = p.char_id; j += mmo_char_tobuf(WBUFP(buf, j), &p); @@ -2209,8 +2158,7 @@ // find the authenticated session with this account id ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); - if( i < fd_max ) - { + if( i < fd_max ) { int server_id; memcpy(sd->email, RFIFOP(fd,6), 40); sd->expiration_time = (time_t)RFIFOL(fd,46); @@ -2237,39 +2185,9 @@ } else { // send characters to player mmo_char_send006b(i, sd); -#if PACKETVER >= 20110309 - if( pincode_enabled ){ - // PIN code system enabled - if( strlen( sd->pincode ) <= 0 ){ - // No PIN code has been set yet - if( pincode_force ){ - pincode_sendstate( i, sd, PINCODE_NEW ); - }else{ - pincode_sendstate( i, sd, PINCODE_PASSED ); + pincode_handle(fd,sd); } - }else{ - if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){ - struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id ); - - if( node != NULL && node->pincode_success ){ - // User has already passed the check - pincode_sendstate( i, sd, PINCODE_PASSED ); - }else{ - // 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,72); break; @@ -2934,6 +2852,7 @@ WFIFOSET(fd,7); }else{ struct auth_node* node; + struct online_char_data* character; // create temporary auth entry CREATE(node, struct auth_node, 1); @@ -2950,14 +2869,12 @@ //Set char to "@ char select" in online db [Kevin] set_char_charselect(account_id); - { - struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id); - + character = (struct online_char_data*)idb_get(online_char_db, account_id); if( character != NULL ){ character->pincode_success = true; } - } + WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x2b03; WFIFOL(fd,2) = account_id; @@ -3744,14 +3661,12 @@ return 0; } - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } cmd = RFIFOW(fd,0); - switch( cmd ) - { + switch( cmd ) { // request to connect // 0065 .L .L .L .W .B @@ -3844,6 +3759,7 @@ int slot = RFIFOB(fd,2); RFIFOSKIP(fd,3); + if(pincode_hack_check(fd,sd)==1) break; if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot) || SQL_SUCCESS != Sql_NextRow(sql_handle) @@ -4040,6 +3956,8 @@ { int cid = RFIFOL(fd,2); + if(pincode_hack_check(fd,sd)==1) break; + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); memcpy(email, RFIFOP(fd,6), 40); RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); @@ -4274,12 +4192,10 @@ case 0x8b8: if( RFIFOREST(fd) < 10 ) return 0; - - if( RFIFOL(fd,2) != sd->account_id ) + if(RFIFOL(fd,2) != sd->account_id ) break; - + if( pincode_enabled) pincode_check( fd, sd ); - RFIFOSKIP(fd,10); break; @@ -4291,11 +4207,13 @@ if( RFIFOL(fd,2) != sd->account_id ) break; + if( pincode_enabled){ if( strlen( sd->pincode ) <= 0 ){ pincode_sendstate( fd, sd, PINCODE_NEW ); }else{ pincode_sendstate( fd, sd, PINCODE_ASK ); } + } RFIFOSKIP(fd,6); break; @@ -4307,7 +4225,7 @@ if( RFIFOL(fd,2) != sd->account_id ) break; - + if(pincode_enabled) pincode_change( fd, sd ); RFIFOSKIP(fd,14); @@ -4321,6 +4239,7 @@ if( RFIFOL(fd,2) != sd->account_id ) break; + if( pincode_enabled) pincode_setnew( fd, sd ); RFIFOSKIP(fd,10); @@ -4517,120 +4436,6 @@ } //------------------------------------------------ -//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_PASSED ); - } -} - -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_PASSED ); -} - -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 ); - strncpy( sd->pincode, newpin, strlen( newpin ) ); - - pincode_sendstate( fd, sd, PINCODE_PASSED ); -} - -// 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,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}; - 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]); -} - -//------------------------------------------------ //Add On system //------------------------------------------------ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ){ @@ -4939,7 +4744,7 @@ } else if (strcmpi(w1, "max_connect_user") == 0) { max_connect_user = atoi(w2); if (max_connect_user < -1) - max_connect_user = -1; + max_connect_user = -1; // unlimited online players } else if(strcmpi(w1, "gm_allow_group") == 0) { gm_allow_group = atoi(w2); } else if (strcmpi(w1, "autosave_time") == 0) { @@ -5018,6 +4823,12 @@ guild_exp_rate = atoi(w2); } else if (strcmpi(w1, "pincode_enabled") == 0) { pincode_enabled = config_switch(w2); + #if PACKETVER < 20110309 + if( pincode_enabled ) { + ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. Disabling...\n"); + pincode_enabled = false; + } + #endif } else if (strcmpi(w1, "pincode_changetime") == 0) { pincode_changetime = atoi(w2)*60*60*24; } else if (strcmpi(w1, "pincode_maxtry") == 0) { @@ -5137,8 +4948,7 @@ mmo_char_sql_init(); char_read_fame_list(); //Read fame lists. - if ((naddr_ != 0) && (!login_ip || !char_ip)) - { + if ((naddr_ != 0) && (!login_ip || !char_ip)) { char ip_str[16]; ip2str(addr_[0], ip_str); Index: src/char/char.h --- src/char/char.h Base (BASE) +++ src/char/char.h Locally Modified (Based On LOCAL) @@ -7,9 +7,9 @@ #include "../config/core.h" #include "../common/core.h" // CORE_ST_LAST #include "../common/msg_conf.h" +#include "../common/cbasetypes.h" -enum E_CHARSERVER_ST -{ +enum E_CHARSERVER_ST { CHARSERVER_ST_RUNNING = CORE_ST_LAST, CHARSERVER_ST_SHUTDOWN, CHARSERVER_ST_LAST @@ -28,6 +28,46 @@ const char* char_msg_txt(int msg_number); void char_do_final_msg(void); +struct char_session_data { + bool auth; // whether the session is authed or not + int account_id, login_id1, login_id2, sex; + int found_char[MAX_CHARS]; // ids of chars on this account + char email[40]; // e-mail (default: a@a.com) by [Yor] + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + int group_id; // permission + uint8 char_slots; + uint32 version; + uint8 clienttype; + char new_name[NAME_LENGTH]; + char birthdate[10+1]; // YYYY-MM-DD + // Pincode system + char pincode[PINCODE_LENGTH+1]; + uint32 pincode_seed; + time_t pincode_change; + uint16 pincode_try; + // Addon system + unsigned int char_moves[MAX_CHARS]; // character moves left +}; + +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_success; + int pincode_enable; +}; +DBMap* char_get_online_char_db(void); + +typedef struct char_session_data char_sd; +typedef struct online_char_data online_cd; +extern int pincode_charselect; +extern bool pincode_enabled; +extern int pincode_changetime; +extern int pincode_maxtry; +extern bool pincode_force; + enum { TABLE_INVENTORY, TABLE_CART, @@ -47,7 +87,7 @@ int request_accreg2(int account_id, int char_id); int save_accreg2(unsigned char* buf, int len); - +int login_fd; extern int char_name_option; extern char char_name_letters[]; extern bool char_gm_read; Index: src/char/pincode.c --- src/char/pincode.c No Base Revision +++ src/char/pincode.c Locally New @@ -0,0 +1,221 @@ + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" +#include "../common/random.h" +#include "../common/socket.h" +#include "../common/strlib.h" +#include "pincode.h" + +#include + +bool pincode_enabled = true; +int pincode_changetime = 0; +int pincode_maxtry = 3; +bool pincode_force = true; +int pincode_charselect = 0; + +void pincode_handle(int fd, char_sd *sd) { +#if PACKETVER >= 20110309 + DBMap* online_char_db = char_get_online_char_db(); + online_cd *character = (online_cd *)idb_get( online_char_db, sd->account_id ); + + if( pincode_enabled ){ + // PIN code system enabled + if( strlen( sd->pincode ) <= 0 ){ + // No PIN code has been set yet + if( pincode_force ){ + pincode_sendstate( fd, sd, PINCODE_NEW ); + }else{ + pincode_sendstate( fd, sd, PINCODE_OK ); + } + }else{ + if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){ + if( character != NULL && character->pincode_success ){ + // User has already passed the check + pincode_sendstate( fd, sd, PINCODE_PASSED ); + }else{ + // Ask user for his PIN code + pincode_sendstate( fd, sd, PINCODE_ASK ); + } + }else{ + // User hasnt changed his PIN code too long + pincode_sendstate( fd, sd, PINCODE_EXPIRED ); + } + } + }else{ + // PIN code system disabled + pincode_sendstate( fd, sd, PINCODE_OK ); //PINCODE_NOTSET + } + + if( character ) + character->pincode_enable = -1; +#endif +} + +void pincode_handle2 ( int fd, struct char_session_data* sd ) { + DBMap* online_char_db = char_get_online_char_db(); + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + + if( character && character->pincode_enable > pincode_charselect ){ + character->pincode_enable = pincode_charselect * 2; + }else{ + pincode_sendstate( fd, sd, PINCODE_OK ); + return; + } + + if( strlen(sd->pincode) == 4 ){ + if( pincode_changetime && time(NULL) > (sd->pincode_change+pincode_changetime) ){ // User hasnt changed his PIN code for a long time + pincode_sendstate( fd, sd, PINCODE_EXPIRED ); + } else { // Ask user for his PIN code + pincode_sendstate( fd, sd, PINCODE_ASK ); + } + } else // No PIN code has been set yet + pincode_sendstate( fd, sd, PINCODE_NOTSET ); + + if( character ) + character->pincode_enable = -1; +} + +/* + * Checking if trying to bypass pincode + * return + * 1 : yes must close session + * 0 : no + */ +int pincode_hack_check(int fd, char_sd *sd ) { +#if PACKETVER >= 20110309 + DBMap* online_char_db = char_get_online_char_db(); + if( pincode_enabled ){ // hack check + struct online_char_data* character; + character = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + if( character && character->pincode_enable == -1){ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + return 1; + } + } +#endif + return 0; +} + +void pincode_check( int fd, char_sd *sd ){ + char pin[PINCODE_LENGTH+1]; + DBMap* online_char_db = char_get_online_char_db(); + + memset(pin,0,sizeof(pin)); + strncpy((char*)pin, (char*)RFIFOP(fd, 6), sizeof(pin)); + + pincode_decrypt(sd->pincode_seed, pin ); + + if( pincode_compare( fd, sd, pin ) ){ + struct online_char_data* character; + if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) ) + character->pincode_enable = pincode_charselect * 2; + pincode_sendstate( fd, sd, PINCODE_PASSED ); + } +} + +int pincode_compare( int fd, char_sd *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, char_sd *sd ){ + char oldpin[PINCODE_LENGTH+1]; + char newpin[PINCODE_LENGTH+1]; + + memset(oldpin,0,sizeof(oldpin)); + memset(newpin,0,sizeof(newpin)); + + strncpy(oldpin, (char*)RFIFOP(fd,6), sizeof(oldpin)); + pincode_decrypt(sd->pincode_seed,oldpin); + + if( !pincode_compare( fd, sd, oldpin ) ) + return; + + strncpy(newpin, (char*)RFIFOP(fd,10), sizeof(newpin)); + pincode_decrypt(sd->pincode_seed,newpin); + + pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy(sd->pincode, newpin, sizeof(sd->pincode)); + pincode_sendstate( fd, sd, PINCODE_PASSED ); +} + +void pincode_setnew( int fd, char_sd *sd ){ + char newpin[PINCODE_LENGTH+1]; + + memset(newpin,0,sizeof(newpin)); + + strncpy( newpin, (char*)RFIFOP(fd,6), sizeof(newpin) ); + pincode_decrypt( sd->pincode_seed, newpin ); + + pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy( sd->pincode, newpin, strlen( newpin ) ); + + pincode_sendstate( fd, sd, PINCODE_ASK ); +} + +// 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, char_sd * 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, strlen(pin) ); + 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( uint32 userSeed, char* pin ){ + int i, pos; + char tab[10] = {0,1,2,3,4,5,6,7,8,9}; +// uint32 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 < PINCODE_LENGTH; i++ ){ + sprintf( pin+i, "%d", tab[pin[i]- '0'] ); + } +} Index: src/char/pincode.h --- src/char/pincode.h No Base Revision +++ src/char/pincode.h Locally New @@ -0,0 +1,51 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef PINCODE_H +#define PINCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "char.h" + +// Pincode system +typedef enum pin_state { + PINCODE_OK, + PINCODE_ASK, + PINCODE_NOTSET, + PINCODE_EXPIRED, + PINCODE_NEW, + PINCODE_PASSED, + PINCODE_WRONG +} pin_state; + +void pincode_handle(int fd, char_sd *sd); +int pincode_hack_check(int fd, char_sd *sd ); +void pincode_check( int fd, char_sd *sd ); +int pincode_compare( int fd, char_sd *sd, char* pin ); +void pincode_change( int fd, char_sd *sd ); +void pincode_setnew( int fd, char_sd *sd ); + +// 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 ); + +void pincode_notifyLoginPinUpdate( int account_id, char* pin ); +void pincode_notifyLoginPinError( int account_id ); +void pincode_decrypt( uint32 userSeed, char* pin ); + +#ifdef __cplusplus +} +#endif + +#endif /* PINCODE_H */ + Index: src/common/mmo.h --- src/common/mmo.h Base (BASE) +++ src/common/mmo.h Locally Modified (Based On LOCAL) @@ -122,6 +122,8 @@ //For Map Names, which the client considers to be 16 in length including the .gat extension #define MAP_NAME_LENGTH (11 + 1) #define MAP_NAME_LENGTH_EXT (MAP_NAME_LENGTH + 4) +//Pincode Length +#define PINCODE_LENGTH 4 #define MAX_FRIENDS 40 #define MAX_MEMOPOINTS 3 Index: src/login/account.h --- src/login/account.h Base (BASE) +++ src/login/account.h Locally Modified (Based On LOCAL) @@ -50,7 +50,7 @@ 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 + char pincode[PINCODE_LENGTH+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) Index: src/login/login.c --- src/login/login.c Base (BASE) +++ src/login/login.c Locally Modified (Based On LOCAL) @@ -552,8 +552,10 @@ uint8 char_slots = 0; int group_id = 0; char birthdate[10+1] = ""; - char pincode[4+1] = ""; + char pincode[PINCODE_LENGTH+1]; + memset(pincode,0,PINCODE_LENGTH+1); + int account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); Index: src/map/map.c --- src/map/map.c Base (BASE) +++ src/map/map.c Locally Modified (Based On LOCAL)