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()
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)
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)
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
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)
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)
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()
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)
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)
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)