def test_add(self): stream = streams.StreamOut(settings.default()) stream.add(common.ResultRange()) assert stream.get() == bytes.fromhex("000000000a000000") stream = streams.StreamOut(settings.load("switch")) stream.add(common.ResultRange()) assert stream.get() == bytes.fromhex("0008000000000000000a000000")
def test_pid(self): stream = streams.StreamOut(settings.default()) stream.pid(12345) assert stream.get() == bytes.fromhex("39300000") stream = streams.StreamOut(settings.load("switch")) stream.pid(12345) assert stream.get() == bytes.fromhex("3930000000000000")
def test_anydata(self): stream = streams.StreamOut(settings.default()) stream.anydata(common.NullData()) assert stream.get() == b"\x09\0NullData\0\x04\0\0\0\0\0\0\0" stream = streams.StreamOut(settings.load("switch")) stream.anydata(common.NullData()) assert stream.get( ) == b"\x09\0NullData\0\x0E\0\0\0\x0A\0\0\0\0\0\0\0\0\0\0\0\0\0"
def build_connection_request(self, ticket, check_value): stream = streams.StreamOut(self.settings) stream.buffer(ticket.internal) substream = streams.StreamOut(self.settings) substream.pid(ticket.source_pid) substream.u32(ticket.target_cid) substream.u32(check_value) kerb = kerberos.KerberosEncryption(ticket.session_key) stream.buffer(kerb.encrypt(substream.get())) return stream.get()
def build_connection_request(self): if self.credentials is None: return b"" stream = streams_nex.StreamOut(self.settings) stream.buffer(self.credentials.ticket.internal) substream = streams_nex.StreamOut(self.settings) substream.pid(self.credentials.pid) substream.u32(self.credentials.cid) substream.u32(self.connection_check) kerb = kerberos.KerberosEncryption(self.credentials.ticket.session_key) stream.buffer(kerb.encrypt(substream.get())) return stream.get()
async def validate_and_request_ticket_with_custom_data( self, username, extra_data): logger.info( "AuthenticationClientNX.validate_and_request_ticket_with_custom_data()" ) #--- request --- stream = streams.StreamOut(self.settings) stream.string(username) stream.anydata(extra_data) data = await self.client.request( self.PROTOCOL_ID, self.METHOD_VALIDATE_AND_REQUEST_TICKET_WITH_CUSTOM_DATA, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) obj = rmc.RMCResponse() obj.result = stream.result() obj.pid = stream.pid() obj.ticket = stream.buffer() obj.connection_data = stream.extract(RVConnectionData) obj.server_name = stream.string() obj.source_key = stream.string() if not stream.eof(): raise ValueError( "Response is bigger than expected (got %i bytes, but only %i were read)" % (stream.size(), stream.tell())) logger.info( "AuthenticationClientNX.validate_and_request_ticket_with_custom_data -> done" ) return obj
def encode(self): stream = streams.StreamOut(self.settings) flag = 0x80 if self.mode == self.REQUEST else 0 if self.protocol < 0x80: stream.u8(self.protocol | flag) else: stream.u8(0x7F | flag) stream.u16(self.protocol) if self.mode == self.REQUEST: stream.u32(self.call_id) stream.u32(self.method) stream.write(self.body) else: if self.error != -1 and self.error & 0x80000000: stream.bool(False) stream.u32(self.error) stream.u32(self.call_id) else: stream.bool(True) stream.u32(self.call_id) stream.u32(self.method | 0x8000) stream.write(self.body) return struct.pack("I", stream.size()) + stream.get()
def init_request(self, protocol_id, method_id): self.call_id += 1 stream = streams.StreamOut(self.settings) stream.u8(protocol_id | 0x80) stream.u32(self.call_id) stream.u32(method_id) return stream, self.call_id
def get_all_information(self, nna_info, presence, birthday): logger.info("FriendsClient.get_all_information()") #--- request --- stream = streams.StreamOut(self.settings) stream.add(nna_info) stream.add(presence) stream.datetime(birthday) data = self.client.send_request(self.PROTOCOL_ID, self.METHOD_GET_ALL_INFORMATION, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) obj = common.RMCResponse() obj.principal_preference = stream.extract(PrincipalPreference) obj.comment = stream.extract(Comment) obj.friends = stream.list(FriendInfo) obj.sent_requests = stream.list(FriendRequest) obj.received_requests = stream.list(FriendRequest) obj.blacklist = stream.list(BlacklistedPrincipal) obj.unk1 = stream.bool() obj.notifications = stream.list(PersistentNotification) obj.unk2 = stream.bool() if not stream.eof(): raise ValueError( "Response is bigger than expected (got %i bytes, but only %i were read)" % (stream.size(), stream.tell())) logger.info("FriendsClient.get_all_information -> done") return obj
async def process_notification_event(self, event): logger.info("NotificationClient.process_notification_event()") #--- request --- stream = streams.StreamOut(self.settings) stream.add(event) await self.client.request(self.PROTOCOL_ID, self.METHOD_PROCESS_NOTIFICATION_EVENT, stream.get(), True)
def build_connection_request(self): if not self.client_ticket: return b"" self.check_value = random.randint(0, 0xFFFFFFFF) stream = streams.StreamOut(self.settings) stream.buffer(self.client_ticket.internal) substream = streams.StreamOut(self.settings) substream.pid(self.client_ticket.source_pid) substream.u32(self.client_ticket.target_cid) substream.u32(self.check_value) kerb = kerberos.KerberosEncryption(self.client_ticket.session_key) stream.buffer(kerb.encrypt(substream.get())) return stream.get()
def encode(self, stream): stream.string(self.data.get_name()) substream = streams.StreamOut(stream.settings) substream.add(self.data) stream.u32(len(substream.data) + 4) stream.buffer(substream.data)
def encode(self, stream): stream.string(self.data.__class__.__name__) substream = streams.StreamOut(stream.settings) substream.add(self.data) stream.u32(len(substream.get()) + 4) stream.buffer(substream.get())
def test_variant(self): stream = streams.StreamOut(settings.default()) stream.variant(None) assert stream.get() == b"\0" stream = streams.StreamOut(settings.default()) stream.variant(-12345) assert stream.get() == bytes.fromhex("01c7cfffffffffffff") stream = streams.StreamOut(settings.default()) stream.variant(123.45) assert stream.get() == bytes.fromhex("02cdccccccccdc5e40") stream = streams.StreamOut(settings.default()) stream.variant(True) stream.variant(False) assert stream.get() == bytes.fromhex("03010300") stream = streams.StreamOut(settings.default()) stream.variant("hello") assert stream.get() == b"\x04\x06\0hello\0" stream = streams.StreamOut(settings.default()) stream.variant(common.DateTime.never()) assert stream.get() == bytes.fromhex("050000000000000000") stream = streams.StreamOut(settings.default()) stream.variant(12345) assert stream.get() == bytes.fromhex("063930000000000000")
def connect(self, host, port): stream = streams.StreamOut(self.backend.settings) stream.buffer(self.ticket.data) check_value = random.randint(0, 0xFFFFFFFF) substream = streams.StreamOut(self.backend.settings) substream.uint(self.auth_client.pid) substream.u32(self.connection_id) substream.u32(check_value) #Used to check connection response stream.buffer(self.kerberos_encryption.encrypt(substream.get())) response = super().connect(host, port, stream.get()) stream = streams.StreamIn(response, self.backend.settings) if stream.u32() != 4: raise ConnectionError("Invalid connection response size") if stream.u32() != (check_value + 1) & 0xFFFFFFFF: raise ConnectionError("Connection response check failed") self.client.set_secure_key(self.ticket.key)
def encrypt(self, key, settings): stream = streams.StreamOut(settings) if settings.get("kerberos.key_size") != len(self.session_key): raise ValueError("Incorrect session_key size") stream.write(self.session_key) stream.pid(self.target_pid) stream.buffer(self.internal) data = stream.get() kerberos = KerberosEncryption(key) return kerberos.encrypt(data)
def encode(self, stream): self.init_version(-1) #self.init_version(stream.settings.get("server.version")) if self.version == -1: self.streamin(stream) else: substream = streams.StreamOut(stream.settings) self.streamin(substream) stream.u8(self.version) stream.buffer(substream.data)
async def test_connectivity(self): logger.info("SecureConnectionClient.test_connectivity()") #--- request --- stream = streams.StreamOut(self.settings) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_TEST_CONNECTIVITY, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("SecureConnectionClient.test_connectivity -> done")
async def mark_friend_requests_as_received(self, ids): logger.info("FriendsClientV2.mark_friend_requests_as_received()") #--- request --- stream = streams.StreamOut(self.settings) stream.list(ids, stream.u64) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_MARK_FRIEND_REQUESTS_AS_RECEIVED, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("FriendsClientV2.mark_friend_requests_as_received -> done")
async def update_preference(self, preference): logger.info("FriendsClientV2.update_preference()") #--- request --- stream = streams.StreamOut(self.settings) stream.add(preference) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_UPDATE_PREFERENCE, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("FriendsClientV2.update_preference -> done")
def encode(self, stream): hierarchy = self.get_hierarchy() for cls in hierarchy: version = self.init_version(cls, stream.settings) if version == -1: cls.save(self, stream) else: substream = streams.StreamOut(stream.settings) cls.save(self, substream) stream.u8(version) stream.buffer(substream.get())
async def delete_persistent_notification(self, notifications): logger.info("FriendsClientV2.delete_persistent_notification()") #--- request --- stream = streams.StreamOut(self.settings) stream.list(notifications, stream.add) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_DELETE_PERSISTENT_NOTIFICATION, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("FriendsClientV2.delete_persistent_notification -> done")
async def delete_common_data(self, unique_id): logger.info("Ranking2Client.delete_common_data()") #--- request --- stream = streams.StreamOut(self.settings) stream.u64(unique_id) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_DELETE_COMMON_DATA, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("Ranking2Client.delete_common_data -> done")
def init_response(self, protocol_id, call_id, method_id, error=None): stream = streams.StreamOut(self.settings) stream.u8(protocol_id) if error: stream.u8(0) stream.result(error) stream.u32(call_id) else: stream.u8(1) stream.u32(call_id) stream.u32(method_id | 0x8000) return stream
def encrypt(self, key, settings): ticket_key = secrets.token_bytes(16) stream = streams.StreamOut(settings) stream.datetime(self.expiration) stream.pid(self.source_pid) if len(self.session_key) != settings.get("kerberos.key_size"): raise ValueError("Incorrect session_key length") stream.write(self.session_key) ticket_body = stream.get() final_key = hashlib.md5(key + ticket_key).digest() kerberos = KerberosEncryption(final_key) encrypted = kerberos.encrypt(ticket_body) stream = streams.StreamOut(settings) stream.buffer(ticket_key) stream.buffer(encrypted) return stream.get()
async def get_course_record(param): #--- request --- stream = streams.StreamOut(datastore_smm_client.settings) stream.add(param) data = await datastore_smm_client.client.request(datastore_smm_client.PROTOCOL_ID, 72, stream.get()) #--- response --- stream = streams.StreamIn(data, datastore_smm_client.settings) result = stream.extract(DataStoreGetCourseRecordResult) return result
async def request_probe_initiation(self, target_urls): logger.info("NATTraversalClient.request_probe_initiation()") #--- request --- stream = streams.StreamOut(self.settings) stream.list(target_urls, stream.stationurl) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_REQUEST_PROBE_INITIATION, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("NATTraversalClient.request_probe_initiation -> done")
async def initiate_probe(self, station_to_probe): logger.info("NATTraversalClient.initiate_probe()") #--- request --- stream = streams.StreamOut(self.settings) stream.stationurl(station_to_probe) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_INITIATE_PROBE, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("NATTraversalClient.initiate_probe -> done")
def encrypt(self, key, settings): stream = streams.StreamOut(settings) stream.datetime(self.timestamp) stream.pid(self.source) if len(self.session_key) != settings["kerberos.key_size"]: raise ValueError("Incorrect session_key length") stream.write(self.session_key) data = stream.get() if settings["kerberos.ticket_version"] == 1: ticket_key = secrets.token_bytes(16) final_key = hashlib.md5(key + ticket_key).digest() kerberos = KerberosEncryption(final_key) encrypted = kerberos.encrypt(data) stream = streams.StreamOut(settings) stream.buffer(ticket_key) stream.buffer(encrypted) return stream.get() return data
async def remove_black_list(self, pid): logger.info("FriendsClientV2.remove_black_list()") #--- request --- stream = streams.StreamOut(self.settings) stream.pid(pid) data = await self.client.request(self.PROTOCOL_ID, self.METHOD_REMOVE_BLACK_LIST, stream.get()) #--- response --- stream = streams.StreamIn(data, self.settings) if not stream.eof(): raise ValueError("Response is bigger than expected (got %i bytes, but only %i were read)" %(stream.size(), stream.tell())) logger.info("FriendsClientV2.remove_black_list -> done")