/** * Request of the map-server that a player claimed his achievement rewards. * @see inter_parse_frommap */ int mapif_parse_achievement_reward(int fd){ time_t current = time(NULL); uint32 char_id = RFIFOL(fd, 2); int32 achievement_id = RFIFOL(fd, 6); if( Sql_Query( sql_handle, "UPDATE `%s` SET `rewarded` = FROM_UNIXTIME('%u') WHERE `char_id`='%u' AND `id` = '%d' AND `completed` IS NOT NULL AND `rewarded` IS NULL", schema_config.achievement_table, (uint32)current, char_id, achievement_id ) == SQL_ERROR || Sql_NumRowsAffected(sql_handle) <= 0 ){ current = 0; }else if( RFIFOW(fd,10) > 0 ){ // Do not send a mail if no item reward char mail_sender[NAME_LENGTH]; char mail_receiver[NAME_LENGTH]; char mail_title[MAIL_TITLE_LENGTH]; char mail_text[MAIL_BODY_LENGTH]; struct item item; memset(&item, 0, sizeof(struct item)); item.nameid = RFIFOW(fd, 10); item.amount = RFIFOL(fd, 12); item.identify = 1; safesnprintf(mail_sender, NAME_LENGTH, char_msg_txt(227)); // 227: GM safestrncpy(mail_receiver, RFIFOCP(fd,16), NAME_LENGTH); safesnprintf(mail_title, MAIL_TITLE_LENGTH, char_msg_txt(228)); // 228: Achievement Reward Mail safesnprintf(mail_text, MAIL_BODY_LENGTH, char_msg_txt(229), RFIFOCP(fd,16+NAME_LENGTH) ); // 229: [%s] Achievement Reward. if( !mail_sendmail(0, mail_sender, char_id, mail_receiver, mail_title, mail_text, 0, &item, 1) ){ current = 0; } } mapif_achievement_reward(fd, char_id, achievement_id, current); return 0; }
/* * Client request to change pincode */ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 14 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char oldpin[PINCODE_LENGTH+1]; char newpin[PINCODE_LENGTH+1]; memset(oldpin,0,PINCODE_LENGTH+1); memset(newpin,0,PINCODE_LENGTH+1); strncpy(oldpin, RFIFOCP(fd,6), PINCODE_LENGTH); strncpy(newpin, RFIFOCP(fd,10), PINCODE_LENGTH); RFIFOSKIP(fd,14); char_pincode_decrypt(sd->pincode_seed,oldpin); if( !char_pincode_compare( fd, sd, oldpin ) ) return 1; char_pincode_decrypt(sd->pincode_seed,newpin); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy(sd->pincode, newpin, sizeof(newpin)); ShowInfo("Pincode changed for AID: %d\n", sd->account_id); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } return 1; }
/** * Map server send information to change an email of an account via char-server. * 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @param ip: char-serv ip (used for info) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_reqchangemail(int fd, int id, char* ip){ if (RFIFOREST(fd) < 86) return 0; else{ struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); char actual_email[40]; char new_email[40]; uint32 account_id = RFIFOL(fd,2); safestrncpy(actual_email, RFIFOCP(fd,6), 40); safestrncpy(new_email, RFIFOCP(fd,46), 40); RFIFOSKIP(fd, 86); if( e_mail_check(actual_email) == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( e_mail_check(new_email) == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( strcmpi(new_email, "*****@*****.**") == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( !accounts->load_num(accounts, &acc, account_id) ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip); else if( strcmpi(acc.email, actual_email) != 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, acc.email, actual_email, ip); else{ safestrncpy(acc.email, new_email, 40); ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, new_email, ip); // Save accounts->save(accounts, &acc); } } return 1; }
// Save account_reg into sql (type=2) int mapif_parse_Registry(int fd) { int account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8), count = RFIFOW(fd, 12); if( count ) { int cursor = 14, i; bool isLoginActive = session_isActive(login_fd); if( isLoginActive ) chlogif_upd_global_accreg(account_id,char_id); for(i = 0; i < count; i++) { size_t lenkey = RFIFOB( fd, cursor ); const char* src_key= RFIFOCP(fd, cursor + 1); std::string key( src_key, lenkey ); cursor += lenkey + 1; unsigned int index = RFIFOL(fd, cursor); cursor += 4; switch (RFIFOB(fd, cursor++)) { // int case 0: { intptr_t lVal = RFIFOL( fd, cursor ); inter_savereg( account_id, char_id, key.c_str(), index, lVal, false ); cursor += 4; break; } case 1: inter_savereg(account_id,char_id,key.c_str(),index,0,false); break; // str case 2: { size_t len_val = RFIFOB( fd, cursor ); const char* src_val= RFIFOCP(fd, cursor + 1); std::string sval( src_val, len_val ); cursor += len_val + 1; inter_savereg( account_id, char_id, key.c_str(), index, (intptr_t)sval.c_str(), true ); break; } case 3: inter_savereg(account_id,char_id,key.c_str(),index,0,true); break; default: ShowError("mapif_parse_Registry: unknown type %d\n",RFIFOB(fd, cursor - 1)); return 1; } } if (isLoginActive) chlogif_prepsend_global_accreg(); } return 0; }
int mapif_parse_NameChangeRequest(int fd) { uint32 account_id, char_id; int type; char* name; int i; account_id = RFIFOL(fd,2); char_id = RFIFOL(fd,6); type = RFIFOB(fd,10); name = RFIFOCP(fd,11); // Check Authorised letters/symbols in the name if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) { mapif_namechange_ack(fd, account_id, char_id, type, 0, name); return 0; } } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden for (i = 0; i < NAME_LENGTH && name[i]; i++) if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) { mapif_namechange_ack(fd, account_id, char_id, type, 0, name); return 0; } } //TODO: type holds the type of object to rename. //If it were a player, it needs to have the guild information and db information //updated here, because changing it on the map won't make it be saved [Skotlex] //name allowed. mapif_namechange_ack(fd, account_id, char_id, type, 1, name); return 0; }
/* * activate PIN system and set first PIN */ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char newpin[PINCODE_LENGTH+1]; memset(newpin,0,PINCODE_LENGTH+1); strncpy( newpin, RFIFOCP(fd,6), PINCODE_LENGTH ); RFIFOSKIP(fd,10); char_pincode_decrypt( sd->pincode_seed, newpin ); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy( sd->pincode, newpin, strlen( newpin ) ); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } return 1; }
void mmo_save_global_accreg(AccountDB* self, int fd, int account_id, int char_id) { Sql* sql_handle = ((AccountDB_SQL*)self)->accounts; AccountDB_SQL* db = (AccountDB_SQL*)self; int count = RFIFOW(fd, 12); if (count) { int cursor = 14, i; char key[32], sval[254]; for (i = 0; i < count; i++) { unsigned int index; safestrncpy(key, RFIFOCP(fd, cursor + 1), RFIFOB(fd, cursor)); cursor += RFIFOB(fd, cursor) + 1; index = RFIFOL(fd, cursor); cursor += 4; switch (RFIFOB(fd, cursor++)) { // int case 0: if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", db->global_acc_reg_num_table, account_id, key, index, RFIFOL(fd, cursor)) ) Sql_ShowDebug(sql_handle); cursor += 4; break; case 1: if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", db->global_acc_reg_num_table, account_id, key, index) ) Sql_ShowDebug(sql_handle); break; // str case 2: safestrncpy(sval, RFIFOCP(fd, cursor + 1), RFIFOB(fd, cursor)); cursor += RFIFOB(fd, cursor) + 1; if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", db->global_acc_reg_str_table, account_id, key, index, sval) ) Sql_ShowDebug(sql_handle); break; case 3: if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", db->global_acc_reg_str_table, account_id, key, index) ) Sql_ShowDebug(sql_handle); break; default: ShowError("mmo_save_global_accreg: unknown type %d\n",RFIFOB(fd, cursor - 1)); return; } } } }
/** * AH 0x2721 * Retrieve account info from login-server, ask inter-server to tell player */ int chlogif_parse_AccInfoAck(int fd) { if (RFIFOREST(fd) < 19) return 0; else { int8 type = RFIFOB(fd, 18); if (type == 0 || RFIFOREST(fd) < 122+NAME_LENGTH) { mapif_accinfo_ack(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), 0, -1, 0, 0, NULL, NULL, NULL, NULL, NULL); RFIFOSKIP(fd,19); return 1; } type>>=1; mapif_accinfo_ack(true, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), type, RFIFOL(fd,19), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOCP(fd,31), RFIFOCP(fd,71), RFIFOCP(fd,87), RFIFOCP(fd,111), RFIFOCP(fd,122)); RFIFOSKIP(fd,122+NAME_LENGTH); } return 1; }
/** * Receive account data from login-server * AH 0x2717 <aid>.L <email>.40B <expiration_time>.L <group_id>.B <birthdate>.11B <pincode>.5B <pincode_change>.L <isvip>.B <char_vip>.B <char_billing>.B **/ int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd){ int u_fd; //user fd if (RFIFOREST(fd) < 75) return 0; // find the authenticated session with this account id ARR_FIND( 0, fd_max, u_fd, session[u_fd] && (sd = (struct char_session_data*)session[u_fd]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); if( u_fd < fd_max ) { int server_id; memcpy(sd->email, RFIFOP(fd,6), 40); sd->expiration_time = (time_t)RFIFOL(fd,46); sd->group_id = RFIFOB(fd,50); sd->char_slots = RFIFOB(fd,51); if( sd->char_slots > MAX_CHARS ) { ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.hpp! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots); sd->char_slots = MAX_CHARS;/* cap to maximum */ } else if ( !sd->char_slots )/* no value aka 0 in sql */ sd->char_slots = MIN_CHARS;/* cap to minimum */ safestrncpy(sd->birthdate, RFIFOCP(fd,52), sizeof(sd->birthdate)); safestrncpy(sd->pincode, RFIFOCP(fd,63), sizeof(sd->pincode)); sd->pincode_change = (time_t)RFIFOL(fd,68); sd->isvip = RFIFOB(fd,72); sd->chars_vip = RFIFOB(fd,73); sd->chars_billing = RFIFOB(fd,74); ARR_FIND( 0, ARRAYLENGTH(map_server), server_id, map_server[server_id].fd > 0 && map_server[server_id].map[0] ); // continued from char_auth_ok... if( server_id == ARRAYLENGTH(map_server) || //server not online, bugreport:2359 (((charserv_config.max_connect_user == 0 || charserv_config.char_maintenance == 1) || (charserv_config.max_connect_user > 0 && char_count_users() >= charserv_config.max_connect_user)) && sd->group_id < charserv_config.gm_allow_group)) { // refuse connection (over populated) chclif_reject(u_fd,0); } else { // send characters to player chclif_mmo_char_send(u_fd, sd); #if PACKETVER_SUPPORTS_PINCODE chlogif_pincode_start(u_fd,sd); #endif } } RFIFOSKIP(fd,75); return 1; }
/** * Receive a account_info request from map-serv * @author : [Dekamaster/Nightroad] * @param fd : map-serv link */ void mapif_parse_accinfo(int fd) { int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10); char type= RFIFOB(fd,14); char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1]; uint32 account_id = 0; char *data; safestrncpy(query, RFIFOCP(fd,15), NAME_LENGTH); Sql_EscapeString(sql_handle, query_esq, query); account_id = atoi(query); if (account_id < START_ACCOUNT_NUM) { // is string if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", schema_config.char_db, query_esq) || Sql_NumRows(sql_handle) == 0 ) { if( Sql_NumRows(sql_handle) == 0 ) { inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(212) ,query); } else { Sql_ShowDebug(sql_handle); inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213)); } Sql_FreeResult(sql_handle); return; } else { if( Sql_NumRows(sql_handle) == 1 ) {//we found a perfect match Sql_NextRow(sql_handle); Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); Sql_FreeResult(sql_handle); } else {// more than one, listing... [Dekamaster/Nightroad] inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(214),(int)Sql_NumRows(sql_handle)); while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { int class_; short base_level, job_level, online; char name[NAME_LENGTH]; Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); Sql_GetData(sql_handle, 2, &data, NULL); class_ = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); base_level = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data); inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(215), account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline"); } Sql_FreeResult(sql_handle); return; } } } /* it will only get here if we have a single match then ask login-server to fetch the `login` record */ if (!account_id || chlogif_req_accinfo(fd, u_fd, u_aid, u_group, account_id, type) != 1) { inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213)); } return; }
// Communication from the map server //-Analysis that only one packet // Data packet length is set to inter.c that you // Do NOT go and check the packet length, RFIFOSKIP is done by the caller // Return : // 0 : error // 1 : ok int inter_party_parse_frommap(int fd) { RFIFOHEAD(fd); switch(RFIFOW(fd,0)) { case 0x3020: mapif_parse_CreateParty(fd, RFIFOCP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break; case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break; case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break; case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOCP(fd,14), (enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); break; case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOW(fd,14), RFIFOB(fd,16), RFIFOW(fd,17)); break; case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break; case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOCP(fd,12), RFIFOW(fd,2)-12); break; case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; case 0x302A: mapif_parse_PartyShareLevel(fd, RFIFOL(fd,2)); break; default: return 0; } return 1; }
void mapif_parse_Auction_bid(int fd) { uint32 char_id = RFIFOL(fd,4), auction_id = RFIFOL(fd,8); int bid = RFIFOL(fd,12); struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id ) { mapif_Auction_bid(fd, char_id, bid, 0); // You have failed to bid in the auction return; } if( auction_count(char_id, true) > 4 && bid < auction->buynow && auction->buyer_id != char_id ) { mapif_Auction_bid(fd, char_id, bid, 9); // You cannot place more than 5 bids at a time return; } if( auction->buyer_id > 0 ) { // Send Money back to the previous Buyer if( auction->buyer_id != char_id ) { mail_sendmail(0, msg_txt(200), auction->buyer_id, auction->buyer_name, msg_txt(201), msg_txt(208), auction->price, NULL, 0); mapif_Auction_message(auction->buyer_id, 7); // You have failed to win the auction } else mail_sendmail(0, msg_txt(200), auction->buyer_id, auction->buyer_name, msg_txt(201), msg_txt(209), auction->price, NULL, 0); } auction->buyer_id = char_id; safestrncpy(auction->buyer_name, RFIFOCP(fd,16), NAME_LENGTH); auction->price = bid; if( bid >= auction->buynow ) { // Automatic won the auction mapif_Auction_bid(fd, char_id, bid - auction->buynow, 1); // You have successfully bid in the auction mail_sendmail(0, msg_txt(200), auction->buyer_id, auction->buyer_name, msg_txt(201), msg_txt(210), 0, &auction->item, 1); mapif_Auction_message(char_id, 6); // You have won the auction mail_sendmail(0, msg_txt(200), auction->seller_id, auction->seller_name, msg_txt(201), msg_txt(211), auction->buynow, NULL, 0); auction_delete(auction); return; } auction_save(auction); mapif_Auction_bid(fd, char_id, 0, 1); // You have successfully bid in the auction }
/** * Request to change PIN Code for an account. * @param fd: fd to parse from (char-serv) * @return 0 fail (packet does not have enough data), 1 success */ int logchrif_parse_updpincode(int fd){ if( RFIFOREST(fd) < 8 + PINCODE_LENGTH+1 ) return 0; else{ struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); if( accounts->load_num(accounts, &acc, RFIFOL(fd,4) ) ){ strncpy( acc.pincode, RFIFOCP(fd,8), PINCODE_LENGTH+1 ); acc.pincode_change = time( NULL ); accounts->save(accounts, &acc); } RFIFOSKIP(fd,8 + PINCODE_LENGTH+1); } return 1; }
/* * Client as anwsered pincode questionning, checking if valid anwser */ int chclif_parse_pincode_check( int fd, struct char_session_data* sd ){ char pin[PINCODE_LENGTH+1]; if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; memset(pin,0,PINCODE_LENGTH+1); strncpy((char*)pin, RFIFOCP(fd, 6), PINCODE_LENGTH); RFIFOSKIP(fd,10); char_pincode_decrypt(sd->pincode_seed, pin ); if( char_pincode_compare( fd, sd, pin ) ){ chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); } return 1; }
void mapif_parse_Mail_receiver_check( int fd ){ char name[NAME_LENGTH], esc_name[NAME_LENGTH * 2 + 1]; uint32 char_id = 0; uint16 class_ = 0, base_level = 0; safestrncpy( name, RFIFOCP(fd, 6), NAME_LENGTH ); // Try to find the Dest Char by Name Sql_EscapeStringLen( sql_handle, esc_name, name, strnlen( name, NAME_LENGTH ) ); if( SQL_ERROR == Sql_Query( sql_handle, "SELECT `char_id`,`class`,`base_level` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name ) ){ Sql_ShowDebug(sql_handle); }else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ){ char *data; Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); class_ = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); base_level = atoi(data); } Sql_FreeResult(sql_handle); mapif_Mail_receiver_send( fd, RFIFOL(fd, 2), char_id, class_, base_level, name ); }
/** * Char-server request to connect to the login-server. * This is needed to exchange packets. * @param fd: file descriptor to parse from (client) * @param sd: client session * @param ip: ipv4 address (client) * @return 0 packet received too shirt, 1 success */ static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, char* ip){ if (RFIFOREST(fd) < 86) return 0; else { int result; char server_name[20]; char message[256]; uint32 server_ip; uint16 server_port; uint16 type; uint16 new_; safestrncpy(sd->userid, RFIFOCP(fd,2), NAME_LENGTH); safestrncpy(sd->passwd, RFIFOCP(fd,26), NAME_LENGTH); if( login_config.use_md5_passwds ) MD5_String(sd->passwd, sd->passwd); sd->passwdenc = 0; server_ip = ntohl(RFIFOL(fd,54)); server_port = ntohs(RFIFOW(fd,58)); safestrncpy(server_name, RFIFOCP(fd,60), 20); type = RFIFOW(fd,82); new_ = RFIFOW(fd,84); RFIFOSKIP(fd,86); ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, ip); sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port); login_log(session[fd]->client_addr, sd->userid, 100, message); result = login_mmo_auth(sd, true); if( runflag == LOGINSERVER_ST_RUNNING && result == -1 && sd->sex == 'S' && sd->account_id < ARRAYLENGTH(ch_server) && !session_isValid(ch_server[sd->account_id].fd) ) { ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); safestrncpy(ch_server[sd->account_id].name, server_name, sizeof(ch_server[sd->account_id].name)); ch_server[sd->account_id].fd = fd; ch_server[sd->account_id].ip = server_ip; ch_server[sd->account_id].port = server_port; ch_server[sd->account_id].users = 0; ch_server[sd->account_id].type = type; ch_server[sd->account_id].new_ = new_; session[fd]->func_parse = logchrif_parse; session[fd]->flag.server = 1; realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); // send connection success WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); } else { ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 3; WFIFOSET(fd,3); } } return 1; }
/** * Received a connection request. * @param fd: file descriptor to parse from (client) * @param sd: client session * @param command: packet type sent * @param ip: ipv4 address (client) * S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B * S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B * S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B * S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B * S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc")) * S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk) * S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B * @param fd: fd to parse from (client fd) * @return 0 failure, 1 success */ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int command, char* ip){ size_t packet_len = RFIFOREST(fd); if( (command == 0x0064 && packet_len < 55) || (command == 0x0277 && packet_len < 84) || (command == 0x02b0 && packet_len < 85) || (command == 0x01dd && packet_len < 47) || (command == 0x01fa && packet_len < 48) || (command == 0x027c && packet_len < 60) || (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) ) return 0; else { int result; char username[NAME_LENGTH]; char password[PASSWD_LENGTH]; unsigned char passhash[16]; uint8 clienttype; bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825); // Shinryo: For the time being, just use token as password. if(command == 0x0825) { char *accname = RFIFOCP(fd, 9); char *token = RFIFOCP(fd, 0x5C); size_t uAccLen = strlen(accname); size_t uTokenLen = RFIFOREST(fd) - 0x5C; if(uAccLen > NAME_LENGTH - 1 || uAccLen == 0 || uTokenLen > NAME_LENGTH - 1 || uTokenLen == 0) { logclif_auth_failed(sd, 3); return 0; } safestrncpy(username, accname, uAccLen + 1); safestrncpy(password, token, uTokenLen + 1); clienttype = RFIFOB(fd, 8); } else { safestrncpy(username, RFIFOCP(fd,6), NAME_LENGTH); if( israwpass ) { safestrncpy(password, RFIFOCP(fd,30), PASSWD_LENGTH); clienttype = RFIFOB(fd,54); } else { memcpy(passhash, RFIFOP(fd,30), 16); clienttype = RFIFOB(fd,46); } } RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent sd->clienttype = clienttype; safestrncpy(sd->userid, username, NAME_LENGTH); if( israwpass ) { ShowStatus("Request for connection of %s (ip: %s)\n", sd->userid, ip); safestrncpy(sd->passwd, password, NAME_LENGTH); if( login_config.use_md5_passwds ) MD5_String(sd->passwd, sd->passwd); sd->passwdenc = 0; } else { ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s)\n", sd->userid, ip); bin2hex(sd->passwd, passhash, 16); // raw binary data here! sd->passwdenc = PASSWORDENC; } if( sd->passwdenc != 0 && login_config.use_md5_passwds ) { logclif_auth_failed(sd, 3); // send "rejected from server" return 0; } result = login_mmo_auth(sd, false); if( result == -1 ) logclif_auth_ok(sd); else logclif_auth_failed(sd, result); } return 1; }
// Wisp/page request to send int mapif_parse_WisRequest(int fd) { struct WisData* wd; char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1];// escaped name char* data; size_t len; if ( fd <= 0 ) {return 0;} // check if we have a valid fd if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { ShowWarning("inter: Wis message size too long.\n"); return 0; } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... ShowError("inter: Wis message doesn't exist.\n"); return 0; } safestrncpy(name, RFIFOCP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", schema_config.char_db, esc_name) ) Sql_ShowDebug(sql_handle); // search if character exists before to ask all map-servers if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target chmapif_send(fd, buf, 27); } else {// Character exists. So, ask all map-servers // to be sure of the correct name, rewrite it Sql_GetData(sql_handle, 0, &data, &len); memset(name, 0, NAME_LENGTH); memcpy(name, data, zmin(len, NAME_LENGTH)); // if source is destination, don't ask other servers. if( strncmp(RFIFOCP(fd,4), name, NAME_LENGTH) == 0 ) { uint8 buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target chmapif_send(fd, buf, 27); } else { static int wisid = 0; CREATE(wd, struct WisData, 1); // Whether the failure of previous wisp/page transmission (timeout) check_ttl_wisdata(); wd->id = ++wisid; wd->fd = fd; wd->len= RFIFOW(fd,2)-52; memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); memcpy(wd->msg, RFIFOP(fd,52), wd->len); wd->tick = gettick(); idb_put(wis_db, wd->id, wd); mapif_wis_message(wd); } } Sql_FreeResult(sql_handle); return 0; }