예제 #1
0
    def encode(self):
        payload = self.encrypt(self.payload)

        stream = StreamOut(self.settings)
        stream.u32(0x32AB9864)

        header_version = self.settings.get("pia.header_version")
        crypto_enabled = self.settings.get("pia.crypto_enabled")
        if header_version > 0:
            stream.u8((crypto_enabled << 7) | header_version)
        else:
            stream.u8(crypto_enabled + 1)

        stream.u8(self.connection_id)
        stream.u16(self.sequence_id)

        if header_version == 0:
            stream.u16(self.session_timer)
            stream.u16(self.rtt_timer)

        if self.settings.get(
                "pia.encryption_method") == EncryptionMethod.AES_GCM:
            stream.u64(self.nonce)
            stream.write(self.signature)

        stream.write(payload)
        stream.write(self.calc_signature(stream.get()))

        return stream.get()
예제 #2
0
    def send_browse_request(self, search_criteria, key, challenge):
        stream = StreamOut(self.settings)
        stream.add(search_criteria)
        buffer = stream.get()

        stream = StreamOut(self.settings)
        stream.u8(0)  #Packet type
        stream.u32(len(buffer))
        stream.write(buffer)

        if self.settings.get("pia.lan_version") != 0:
            self.nonce_counter += 1

            stream.u8(self.settings.get("pia.lan_version"))
            stream.bool(self.settings.get("pia.crypto_enabled"))
            stream.u64(self.nonce_counter)
            stream.write(key)

            if self.settings.get("pia.crypto_enabled"):
                challenge = self.generate_challenge(key, challenge)
            else:
                challenge = secrets.token_bytes(16 + 256)
            stream.write(challenge)

        self.s.send(stream.get(), self.broadcast)
예제 #3
0
    def send_connection_request(self, station, inverse_id=None):
        logger.debug("Sending connection request")

        is_inverse = inverse_id is not None

        local = self.session.local_station()
        local_info = local.connection_info
        target_info = station.connection_info

        stream = StreamOut(self.settings)
        stream.u8(self.MESSAGE_CONNECTION_REQUEST)
        stream.u8(station.connection_id_out_temp)
        stream.u8(self.version)
        stream.bool(is_inverse)

        if self.version >= 7:
            stream.pid(target_info.local.pid)
        if self.version >= 8:
            stream.u32(target_info.local.cid)
            if is_inverse:
                stream.u8(inverse_id)
            else:
                stream.u8(0)

        if self.version == 8:
            stream.add(local_info)
        else:
            stream.add(local_info.local)

        message = PIAMessage()
        message.protocol_id = self.get_protocol_type()
        message.payload = stream.get()

        self.resender.send(station, message)
예제 #4
0
	def send_session_reply(self, station, session_info):
		logger.debug("Sending session reply")
		
		stream = StreamOut(self.settings)
		stream.add(session_info)
		data = stream.get()
		
		rand_value = random.randint(0, 0xFFFFFFFF)
		
		fragments = (len(data) - 1) // 800 + 1
		for i in range(fragments):
			stream = StreamOut(self.settings)
			stream.u8(self.MESSAGE_SESSION_REPLY)
			stream.pad(11)
			stream.u32(rand_value)
			stream.u16(self.session_reply_id)
			stream.u8(i)
			stream.u8(fragments)
			
			body = data[i * 800 : (i + 1) * 800]
			stream.u32(len(body))
			stream.write(body)
			
			message = PIAMessage()
			message.protocol_id = self.get_protocol_type()
			message.payload = stream.get()
			self.transport.send(station, message)
			
		self.session_reply_id += 1
예제 #5
0
    def send_ack(self, station, ack_id):
        logger.debug("Acknowledging packet %i", ack_id)

        stream = StreamOut(self.settings)
        stream.u8(self.MESSAGE_ACK)
        stream.pad(3)
        stream.u32(ack_id)

        message = PIAMessage()
        message.protocol_id = self.get_protocol_type()
        message.payload = stream.get()

        self.transport.send(station, message)
예제 #6
0
	def send_session_request(self, session_id):
		logger.debug("Sending host request")
		
		stream = StreamOut(self.settings)
		stream.u8(self.MESSAGE_SESSION_REQUEST)
		stream.pad(11)
		stream.u32(session_id)
		
		message = PIAMessage()
		message.protocol_id = self.get_protocol_type()
		message.payload = stream.get()
		
		for port in range(0xC000, 0xC004):
			self.transport.broadcast(port, message)
예제 #7
0
    def generate_browse_reply(self, challenge):
        stream = StreamOut(self.settings)
        stream.add(self.session_info)
        buffer = stream.get()

        stream = StreamOut(self.settings)
        stream.u8(1)  #Packet type
        stream.u32(len(buffer))
        stream.write(buffer)

        if self.settings.get("pia.lan_version") != 0:
            stream.u8(self.settings.get("pia.lan_version"))
            stream.bool(self.settings.get("pia.crypto_enabled"))
            stream.write(challenge)

        return stream.get()
예제 #8
0
    def send_connection_response(self, station):
        logger.debug("Sending connection response")

        stream = StreamOut(self.settings)
        stream.u8(self.MESSAGE_CONNECTION_RESPONSE)
        stream.u8(0)
        stream.u8(self.version)
        stream.u8(self.platform)

        identification = self.session.local_station().identification_info

        if self.version < 7:
            stream.chars(identification.token.ljust(32, "\0"))

            player = identification.players[0]
            stream.wchars(player.name.ljust(16, "\0"))
            stream.u8(len(player.name))
            stream.u8(player.language)
        else:
            stream.u8(0)
            stream.u64(station.connection_info.local.pid)
            stream.u32(station.connection_info.local.cid)
            stream.chars(identification.token.ljust(32, "\0"))
            stream.u32(self.session.get_session_id())
            stream.u8(len(identification.players))
            stream.u8(identification.participants)
            stream.u8(len(identification.players))

            for player in identification.players:
                stream.write(player.name.encode("utf8").ljust(80, b"\0"))
                stream.u8(1)
                stream.write(player.nickname.encode("utf8").ljust(40, b"\0"))
                stream.u8(1)
                stream.u8(player.language)
                stream.write(player.play_history_key)
                stream.u64(player.info)

            stream.pad(0xC3 * (4 - len(identification.players)))

        message = PIAMessage()
        message.protocol_id = self.get_protocol_type()
        message.payload = stream.get()

        self.resender.send(station, message)
예제 #9
0
	def send_host_reply(self, station, session_info):
		logger.debug("Sending host reply")
		
		stream = StreamOut(self.settings)
		stream.u8(self.MESSAGE_HOST_REPLY)
		stream.pad(11)
		stream.u32(session_info.session_id)
		
		host = self.session.host_station()
		if self.settings.get("pia.version") < 51000:
			stream.add(host.connection_info)
		else:
			stream.add(host.connection_info.local)
		
		message = PIAMessage()
		message.protocol_id = self.get_protocol_type()
		message.payload = stream.get()
		
		for i in range(3):
			self.transport.send(station, message)
예제 #10
0
    def send_denying_connection_response(self, station, reason):
        logger.debug("Sending denying connection response")

        target_location = station.connection_info.local

        stream = StreamOut(self.settings)
        stream.u8(self.MESSAGE_CONNECTION_RESPONSE)
        stream.u8(reason)
        stream.u8(self.version)
        stream.u8(0)
        if self.version >= 8:
            stream.u8(0)
            stream.u64(target_location.pid)
            stream.u32(target_location.cid)

        message = PIAMessage()
        message.protocol_id = self.get_protocol_type()
        message.payload = stream.get()

        self.transport.send(station, message)