Exemple #1
0
void handle_D9( Network::Client* client, PKTIN_D9* msg )
{
  PKTIN_D9 _msg;  // got crashes here under *nix -> modify a new local instance
  // Transform Little-Endian <-> Big-Endian
  _msg.instance = cfBEu32( msg->instance );              // Unique Instance ID of UO
  _msg.os_major = cfBEu32( msg->os_major );              // OS Major
  _msg.os_minor = cfBEu32( msg->os_minor );              // OS Minor
  _msg.os_revision = cfBEu32( msg->os_revision );        // OS Revision
  _msg.cpu_family = cfBEu32( msg->cpu_family );          // CPU Family
  _msg.cpu_model = cfBEu32( msg->cpu_model );            // CPU Model
  _msg.cpu_clockspeed = cfBEu32( msg->cpu_clockspeed );  // CPU Clock Speed [Mhz]
  _msg.memory = cfBEu32( msg->memory );                  // Memory [MB]
  _msg.screen_width = cfBEu32( msg->screen_width );      // Screen Width
  _msg.screen_height = cfBEu32( msg->screen_height );    // Screen Height
  _msg.screen_depth = cfBEu32( msg->screen_depth );      // Screen Depth [Bit]
  _msg.directx_major = cfBEu16( msg->directx_major );    // DirectX Major
  _msg.directx_minor = cfBEu16( msg->directx_minor );    // DirectX Minor

  for ( unsigned i = 0; i < sizeof( msg->video_description ) / sizeof( msg->video_description[0] );
        ++i )
    _msg.video_description[i] =
        cfBEu16( msg->video_description[i] );  // Video Card Description [wide-character]

  _msg.video_vendor = cfBEu32( msg->video_vendor );  // Video Card Vendor ID
  _msg.video_device = cfBEu32( msg->video_device );  // Video Card Device ID
  _msg.video_memory = cfBEu32( msg->video_memory );  // Video Card Memory [MB]

  for ( unsigned i = 0; i < sizeof( msg->langcode ) / sizeof( msg->langcode[0] ); ++i )
    _msg.langcode[i] = cfBEu16( msg->langcode[i] );  // Language Code [wide-character]

  client->setclientinfo( &_msg );
}
	void handle_menu_selection( Network::Client *client, PKTIN_7D *msg )
	{
	  if ( client->chr->menu == NULL )
	  {
        POLLOG.Format( "{}/{} tried to use a menu, but none was active.\n" )
          << client->acct->name()
          << client->chr->name();
		return;
	  }

	  u16 menu_id = cfBEu16( msg->menu_id );
	  if ( client->chr->menu->menu_id != menu_id )
	  {
        INFO_PRINT << "Client tried to use a menu he wasn't entitled to\n";
		// LOGME illegal menu selection
		client->chr->cancel_menu();
		return;
	  }

	  Menu* menu = client->chr->menu;

	  client->chr->menu = NULL;

	  if ( msg->choice == 0 )	// client cancelled menu
	  {
		client->chr->cancel_menu();
		return;
	  }

	  u16 choice = cfBEu16( msg->choice );
	  if ( choice == 0 || choice > menu->menuitems_.size() )
	  {
        INFO_PRINT << "Client menu choice out of range\n";
		client->chr->cancel_menu();
		return;
	  }
	  // Wow, client chose something valid from the menu, even.
	  // Note, the incoming message specified object type, color, and used_item_serial.
	  // Since we'd just have to verify these anyway, I'm just going
	  // to ignore them, and use the information in the MenuItem.
	  // If this turns out not to be workable, we'll have to validate those 
	  // input fields, too.

	  MenuItem* mi = &menu->menuitems_[choice - 1];
	  if ( mi->submenu_id )
	  {
		client->chr->menu = Menu::find_menu( mi->submenu_id );
		send_menu( client, client->chr->menu );
	  }
	  else
	  {

		passert( client->chr->on_menu_selection );

		client->chr->on_menu_selection( client, mi, msg );
	  }
	}
Exemple #3
0
void handle_prompt( Network::Client* client, PKTBI_9A* msg )
{
  Module::UOExecutorModule* uoemod = client->gd->prompt_uoemod;
  if ( uoemod == nullptr )
    return;
  int textlen = cfBEu16( msg->msglen ) - offsetof( PKTBI_9A, text );
  if ( msg->type )
  {
    if ( textlen <= 120 && msg->text[textlen - 1] == '\0' )
    {
      bool ok = true;
      --textlen;  // don't include null terminator (already checked)
      for ( int i = 0; i < textlen; ++i )
      {
        if ( !isprint( msg->text[i] ) )
        {
          ok = false;
          break;
        }
      }
      if ( ok )
      {
        Bscript::String* str = new Bscript::String( msg->text, textlen );
        uoemod->uoexec.ValueStack.back().set( new Bscript::BObject( str ) );
      }
    }
  }
  uoemod->uoexec.revive();
  uoemod->prompt_chr = nullptr;
  client->gd->prompt_uoemod = nullptr;
}
void handle_client_version( Client* client, PKTBI_BD* msg )
{
	u16 len = cfBEu16(msg->msglen)-3;
	if (len < 100)
	{
		int c=0;
		char ch;
		string ver2 ="";
		while (c<len)
		{
			ch = msg->version[c];
			if (ch==0) break; // seems to be null-terminated
			ver2+=ch;
			++c;
		} 
		client->setversion( ver2 );

		VersionDetailStruct vers_det;
		client->itemizeclientversion(ver2, vers_det);
		client->setversiondetail(vers_det);

        if (client->compareVersion(CLIENT_VER_7000))
            client->setClientType(CLIENTTYPE_7000);
		else if (client->compareVersion(CLIENT_VER_60142))
			client->setClientType(CLIENTTYPE_60142);
		else if (client->compareVersion(CLIENT_VER_6017)) //Grid-loc support
			client->setClientType(CLIENTTYPE_6017);
        else if (client->compareVersion(CLIENT_VER_5020))
			client->setClientType(CLIENTTYPE_5020);
		else if (client->compareVersion(CLIENT_VER_5000))
			client->setClientType(CLIENTTYPE_5000);
        else if (client->compareVersion(CLIENT_VER_4070))
            client->setClientType(CLIENTTYPE_4070);
        else if (client->compareVersion(CLIENT_VER_4000))
            client->setClientType(CLIENTTYPE_4000);

		if (ssopt.core_sends_season)
			send_season_info( client );	// Scott 10/11/2007 added for login fixes and handling 1.x clients.
										// Season info needs to check client version to keep from crashing 1.x
										// version not set until shortly after login complete.
		//send_feature_enable(client); //dave commented out 8/21/03, unexpected problems with people sending B9 via script with this too.
		if( (client->UOExpansionFlag & AOS) )
		{
		send_object_cache(client, dynamic_cast<const UObject*>(client->chr));
		}
	}
	else
	{
		Log2( "Suspect string length in PKTBI_BD packet: %u\n", (unsigned) len );
	}
}
Exemple #5
0
	bool convertUCtoArray( const u16* in_wtext, Bscript::ObjArray*& out_text,
						   size_t textlen, bool ConvFromBE /*false*/ )
	{
	  u16 value;
	  out_text = new Bscript::ObjArray( );
	  for( size_t i = 0; i < textlen; i++ )
	  {
		value = ConvFromBE ? cfBEu16( in_wtext[i] ) : in_wtext[i];
		// Jump out on a NULL (EOS) value (should stop exploits, too?)
		if( value == 0L )
		  return true;
		out_text->addElement( new Bscript::BLong( value ) );
	  }
	  return true;
	}
void handle_se_object_list( Client* client, PKTBI_D6_IN* msgin )
{
	UObject* obj = NULL;
	int length=cfBEu16(msgin->msglen)-3;
	if ( length < 0 || (length%4) != 0 )
		return;
	int count = length/4;
	
	for( int i = 0; i < count; ++i )
	{
		obj = system_find_object(cfBEu32( msgin->serials[i].serial ));
		if (obj != NULL)
			SendAOSTooltip(client,obj);
	}
}
Exemple #7
0
void handle_skill_lock( Network::Client* client, PKTBI_3A_LOCKS* msg )
{
  if ( settingsManager.ssopt.core_handled_locks )
  {
    unsigned int skillid = cfBEu16( msg->skillid );
    if ( skillid > networkManager.uoclient_general.maxskills )
      return;

    const UOSkill& uoskill = GetUOSkill( skillid );
    if ( !uoskill.pAttr )  // tried to set lockstate for a skill that isn't defined
      return;

    if ( msg->lock_mode < 3 )
      client->chr->attribute( uoskill.pAttr->attrid ).lock( msg->lock_mode );
    else
      INFO_PRINT << "Client " << client->chr->name() << " tried to set an illegal lock state.\n";
  }
}
Exemple #8
0
void handle_get_tip( Client* client, PKTIN_A7* msg )
{
	u16 tipnum = cfBEu16( msg->lasttip );
    if (tipfilenames.size())
    {
        if (msg->prevnext)
        {
            ++tipnum;
            if (tipnum >= tipfilenames.size())
                tipnum = 0;
        }
        else
        {
            --tipnum;
            if (tipnum >= tipfilenames.size())
                tipnum = static_cast<u16>(tipfilenames.size()) - 1;
        }

        send_tip( client, tipfilenames[tipnum].c_str(), tipnum );
    }
}
Exemple #9
0
void select_server( Network::Client* client, PKTIN_A0* msg )  // Relay player to a certain IP
{
  unsigned servernum = cfBEu16( msg->servernum ) - 1;

  if ( servernum >= networkManager.servers.size() )
  {
    client->forceDisconnect();
    return;
  }

  ServerDescription* svr = networkManager.servers[servernum];

  Network::PktHelper::PacketOut<Network::PktOut_8C> rsp;
  rsp->Write<u8>( svr->ip[3] );
  rsp->Write<u8>( svr->ip[2] );
  rsp->Write<u8>( svr->ip[1] );
  rsp->Write<u8>( svr->ip[0] );

  if ( client->listen_port != 0 )
    rsp->WriteFlipped<u16>( client->listen_port );
  else
    rsp->WriteFlipped<u16>( svr->port );
  // MuadDib Added new seed system. This is for transferring KR/6017/Normal client detection from
  // loginserver
  // to the gameserver. Allows keeping client flags from remote loginserver to gameserver for 6017
  // and kr
  // packets.

  unsigned int nseed = 0xFEFE0000 | client->ClientType;
  rsp->WriteFlipped<u32>( nseed );  // This was set to 0xffffffff in the past but this will conflict
                                    // with UO:KR detection

  rsp.Send( client );

  client->cryptengine->Init( &nseed, Crypt::CCryptBase::typeGame );
}
Exemple #10
0
void login2( Network::Client* client, PKTIN_91* msg )  // Gameserver login and character listing
{
  client->encrypt_server_stream = true;

  if ( Network::is_banned_ip( client ) )
  {
    send_login_error( client, LOGIN_ERROR_ACCOUNT_BLOCKED );
    client->Disconnect();
    return;
  }

  /* Hmm, might have to re-search for account.
     For now, we already have the account in client->acct.
     Might work different if real loginservers were used. */
  Accounts::Account* acct = Accounts::find_account( msg->name );
  if ( acct == nullptr )
  {
    send_login_error( client, LOGIN_ERROR_NO_ACCOUNT );
    client->Disconnect();
    return;
  }

  // First check the password - if wrong, you can't find out anything else.
  bool correct_password = false;

  // dave changed 6/5/3, always authenticate with hashed user+pass
  std::string msgpass = msg->password;
  std::string acctname = acct->name();
  std::string temp;
  Clib::MD5_Encrypt( acctname + msgpass, temp );  // MD5
  correct_password = Clib::MD5_Compare( acct->passwordhash(), temp );

  if ( !correct_password )
  {
    send_login_error( client, LOGIN_ERROR_WRONG_PASSWORD );
    client->Disconnect();
    POLLOG.Format( "Incorrect password for account {} from {}\n" )
        << acct->name() << client->ipaddrAsString();
    return;
  }
  else
  {
    // write out cleartext if necessary
    if ( Plib::systemstate.config.retain_cleartext_passwords )
    {
      if ( acct->password().empty() )
        acct->set_password( msgpass );
    }
  }

  if ( !acct->enabled() || acct->banned() )
  {
    send_login_error( client, LOGIN_ERROR_ACCOUNT_BLOCKED );
    client->Disconnect();
    return;
  }

  //
  // Dave moved the max_clients check to pol.cpp so character cmdlevel could be checked.
  //

  POLLOG.Format( "Account {} logged in from {}\n" )
      << acct->name() << client->ipaddrAsString();

  // ENHANCEMENT: could authenticate with real loginservers.

  client->acct = acct;
  /* NOTE: acct->client is not set here.  It is possible that another client
     is still connected, or a connection is stuck open, or similar.  When
     a character is selected, if another client is connected, measures will
     be taken. */

  // Tell the client about the starting locations and his characters (up to 5).

  // MuadDib Added new seed system. This is for transferring KR/6017/Normal client detection from
  // loginserver
  // to the gameserver. Allows keeping client flags from remote loginserver to gameserver for 6017
  // and kr
  // packets.
  client->ClientType = cfBEu16( msg->unk3_4_ClientType );

  send_start( client );
}
Exemple #11
0
// This is for legacy up to 5.0(?). Cuz ML added new bytes in the middle of the packet.
void send_full_statmsg_std( Client *client, Character *chr )
{
	PKTOUT_11_V1 msg;
	msg.msgtype = PKTOUT_11_V1_ID;

	if( (client->UOExpansionFlag & AOS) )
	{
		msg.msglen = ctBEu16(sizeof msg);
		msg.moreinfo = 04;  // Set to AOS level statbar for full info
	}
	else
	{
		unsigned short msglen = offsetof( PKTOUT_11_V1, statcap );
		msg.msglen = ctBEu16(msglen);
		msg.moreinfo = 01;  // Set to oldschool statbar info.
	}
	msg.serial = chr->serial_ext;
	strzcpy( msg.name, chr->name().c_str(), sizeof msg.name );
	
    if (uoclient_general.hits.any)
    {
        long v = chr->vital(uoclient_general.hits.id).current_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;
        msg.hits = ctBEu16( static_cast<u16>(v) );

        v = chr->vital(uoclient_general.hits.id).maximum_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;
        msg.max_hits = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.hits = 0;
        msg.max_hits = 0;
    }
	
	msg.renameable = 0; // (client->chr->can_rename( chr ) ? 0xFF : 0);

	//if (chr->race == RACE_ELF)
	//	msg.gender = static_cast<u8>(chr->gender | FLAG_RACE);
	//else
		msg.gender = static_cast<u8>(chr->gender);
	
    if (uoclient_general.strength.any)
    {
        long v = chr->attribute(uoclient_general.strength.id).effective();
        if (v > 0xFFFF)
            v = 0xFFFF;
       
        msg.str = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.str = 0;
    }

    if (uoclient_general.dexterity.any)
    {
        long v = chr->attribute(uoclient_general.dexterity.id).effective();
        if (v > 0xFFFF)
            v = 0xFFFF;
       
        msg.dex = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.dex = 0;
    }
    
    if (uoclient_general.intelligence.any)
    {
        long v = chr->attribute(uoclient_general.intelligence.id).effective();
        if (v > 0xFFFF)
            v = 0xFFFF;
       
        msg.intel = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.intel = 0;
    }
	
    if (uoclient_general.stamina.any)
    {
        long v = chr->vital(uoclient_general.stamina.id).current_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;
        msg.stamina = ctBEu16( static_cast<u16>(v) );

        v = chr->vital( uoclient_general.stamina.id ).maximum_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;

	    msg.max_stamina = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.stamina = 0;
	    msg.max_stamina = 0;
    }
	
    if (uoclient_general.mana.any)
    {
        long v = chr->vital(uoclient_general.mana.id).current_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;
        msg.mana = ctBEu16( static_cast<u16>(v) );

        v = chr->vital(uoclient_general.mana.id).maximum_ones();
        if (v > 0xFFFF)
            v = 0xFFFF;
	    msg.max_mana = ctBEu16( static_cast<u16>(v) );
    }
    else
    {
        msg.mana = 0;
	    msg.max_mana = 0;
    }

	
    msg.gold = ctBEu32( chr->gold_carried() );
	// Adjusted to work with Physical Resist if AOS client, and AOS Resistances enabled.
	if( (client->UOExpansionFlag & AOS) && client->aosresist )
		msg.AR = (chr->element_resist.physical < 0)?ctBEu16(0x10000+chr->element_resist.physical):ctBEu16(chr->element_resist.physical);
	else
		msg.AR = ctBEu16( chr->ar() );

	msg.weight = ctBEu16( static_cast<u16>(chr->weight()) );

	if ( msg.moreinfo >= 4 )
	{
		msg.statcap = ctBEu16( chr->expanded_statbar.statcap );
		msg.followers = chr->expanded_statbar.followers;
		msg.followers_max = chr->expanded_statbar.followers_max;
		msg.fireresist = (chr->element_resist.fire < 0)?ctBEu16(0x10000+chr->element_resist.fire):ctBEu16(chr->element_resist.fire);
		msg.coldresist = (chr->element_resist.cold < 0)?ctBEu16(0x10000+chr->element_resist.cold):ctBEu16(chr->element_resist.cold);
		msg.poisonresist = (chr->element_resist.poison < 0)?ctBEu16(0x10000+chr->element_resist.poison):ctBEu16(chr->element_resist.poison);
		msg.energyresist = (chr->element_resist.energy < 0)?ctBEu16(0x10000+chr->element_resist.energy):ctBEu16(chr->element_resist.energy);
		msg.luck = ctBEu16( chr->expanded_statbar.luck );
		msg.damage_min = ctBEu16( chr->min_weapon_damage() );
		msg.damage_max = ctBEu16( chr->max_weapon_damage() );
		msg.titching = ctBEu32( chr->expanded_statbar.tithing );
	}

	transmit(client, &msg, cfBEu16(msg.msglen) );
}
Exemple #12
0
void handle_aos_commands (Client *client, PKTBI_D7* msg)
{
	//cout <<" Sizeof: " << sizeof(PKTBI_D7) << endl;
	//cout << "Received AOS command: " << cfBEu16(msg->msglen) << " " << cfBEu16(msg->subcmd) << endl;
	//fdump (stdout, client->buffer, client->bytes_received);

	//should check if serial is valid? client->chr->serial == msg->serial?

	switch (cfBEu16(msg->subcmd)) {
		case PKTBI_D7::CUSTOM_HOUSE_BACKUP:
			CustomHousesBackup(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_RESTORE:
			CustomHousesRestore(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_COMMIT:
			CustomHousesCommit(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_ERASE:
			CustomHousesErase(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_ADD:
			CustomHousesAdd(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_QUIT:
			CustomHousesQuit(msg);
			break;

		case PKTBI_D7::CUSTOM_HOUSE_ADD_MULTI:
			CustomHousesAddMulti(msg);
			break;
		
		case PKTBI_D7::CUSTOM_HOUSE_SYNCH:
			CustomHousesSynch(msg);
			break;

		case PKTBI_D7::CUSTOM_HOUSE_CLEAR:
			CustomHousesClear(msg);
			break;

		case PKTBI_D7::CUSTOM_HOUSE_SELECT_FLOOR:
			CustomHousesSelectFloor(msg);
			break;

		case PKTBI_D7::CUSTOM_HOUSE_REVERT:
			CustomHousesRevert(msg);
			break;
		case PKTBI_D7::GUILD_BUTTON:
			OnGuildButton(client);
			break;
		case PKTBI_D7::QUEST_BUTTON:
			OnQuestButton(client);
			break;
			//missing combat book abilities
		default:
			handle_unknown_packet(client);
	}
}
Exemple #13
0
void handle_msg_BF( Client* client, PKTBI_BF* msg )
	{
	UObject* obj = NULL;
	UMulti* multi = NULL;
	UHouse* house = NULL;
	switch(cfBEu16(msg->subcmd))
		{
		case PKTBI_BF::TYPE_CLIENT_LANGUAGE:
			client->chr->uclang = strlower(msg->client_lang);
			break;
		case PKTBI_BF::TYPE_REQ_FULL_CUSTOM_HOUSE:
			if( (client->UOExpansionFlag & AOS) == 0 )
				return;
			multi = system_find_multi(cfBEu32(msg->reqfullcustomhouse.house_serial));
			if(multi != NULL)
				{
				house = multi->as_house();
				if(house != NULL)
					{
					if(client->UOExpansionFlag & AOS)
						{
						send_object_cache(client, (UObject*)(house));
						}
					//consider sending working design to certain players, to assist building, or GM help
					CustomHousesSendFull( house, client, HOUSE_DESIGN_CURRENT );
					}
				}
			break;
		case PKTBI_BF::TYPE_OBJECT_CACHE:
			if( (client->UOExpansionFlag & AOS) == 0)
				return;
			obj = system_find_object(cfBEu32(msg->objectcache.serial));
			if(obj != NULL)
				{
				SendAOSTooltip(client,obj);
				}
			break;
		case PKTBI_BF::TYPE_SESPAM:
			return;
			break;
		case PKTBI_BF::TYPE_SPELL_SELECT:
			do_cast(client, cfBEu16(msg->spellselect.selected_spell) );
			break;
		case PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER:
			character_race_changer_handler( client, msg );
			break;
		case PKTBI_BF::TYPE_PARTY_SYSTEM:
			party_cmd_handler( client, msg );
			break;
		case PKTBI_BF::TYPE_EXTENDED_STATS_IN:
			ext_stats_in(client, msg);
			break;
		case PKTBI_BF::TYPE_CLOSED_STATUS_GUMP:
			return;
			break;
		case PKTBI_BF::TYPE_SCREEN_SIZE:
			return;
			break;
		case PKTBI_BF::TYPE_TOGGLE_FLYING:
			if (client->chr->race==RACE_GARGOYLE)
				{
				// FIXME: add checks if its possible to stand with new movemode
				client->chr->movemode = (MOVEMODE)(client->chr->movemode ^ MOVEMODE_FLY);
				send_move_mobile_to_nearby_cansee( client->chr );
				send_goxyz( client, client->chr );
				}
			break;
		case PKTBI_BF::TYPE_CLIENTTYPE:
			client->UOExpansionFlagClient = ctBEu32( msg->clienttype.clientflag );
			break;
		default:
			handle_unknown_packet( client );
		}
	}