def _send_kexinit(self): """_send_kexinit(self) -> None Sets self2remote.kexinit_packet. Separate function to help with unittests. """ cookie = random.get_random_data(16) server_keys = [x.name for x in self.self2remote.supported_server_keys] server_keys.reverse() packet = ssh_packet.pack_payload( ssh_packet.PAYLOAD_MSG_KEXINIT, ( SSH_MSG_KEXINIT, cookie, [x.name for x in self.self2remote.supported_key_exchanges], # [x.name for x in self.self2remote.supported_server_keys], server_keys, [x.name for x in self.c2s.supported_ciphers], [x.name for x in self.s2c.supported_ciphers], [x.name for x in self.c2s.supported_macs], [x.name for x in self.s2c.supported_macs], [x.name for x in self.c2s.supported_compressions], [x.name for x in self.s2c.supported_compressions], [x.name for x in self.c2s.supported_languages], [x.name for x in self.s2c.supported_languages], self.self2remote.proactive_kex, # first_kex_packet_follows 0 # reserved )) self.self2remote.kexinit_packet = packet return packet
def _send_packet(self, data): # Packet is: # uint32 packet_length # byte padding_length # byte[n1] payload # byte[n2] random padding # byte[m] MAC self.debug.write(ssh_debug.DEBUG_3, 'send_packet( len(data)=%i )', (len(data), )) data = self.self2remote.compression.compress(data) # packet_len + padding_length + payload + random_padding # must be multiple of cipher block size. block_size = max(8, self.self2remote.cipher.block_size) padding_length = block_size - ((5 + len(data)) % block_size) if padding_length < 4: padding_length += block_size # Total packet size must also be at least 16 bytes. base_size = 5 + len(data) + padding_length minimum_size = max(16, block_size) if base_size < minimum_size: self.debug.write(ssh_debug.DEBUG_2, 'send_packet: base size too small') # Add enough padding to make it big enough. # Make a first guess of the padding length. padding_length_guess = minimum_size - base_size # See how much larger it should be to make it a multiple of the # block size. additional_padding_length = block_size - ( (5 + len(data) + padding_length_guess) % block_size) padding_length = padding_length_guess + additional_padding_length self.debug.write(ssh_debug.DEBUG_2, 'send_packet: padding_length=%i', (padding_length, )) self.debug.write(ssh_debug.DEBUG_2, 'send_packet: cipher=%s', (self.self2remote.cipher.name, )) packet_length = 1 + len(data) + padding_length self.debug.write(ssh_debug.DEBUG_2, 'send_packet: packet_length=%i', (packet_length, )) random_padding = random.get_random_data(padding_length) chunk = struct.pack('>Ic', packet_length, chr(padding_length)) + data + random_padding self.debug.write(ssh_debug.DEBUG_2, 'send_packet: chunk_length=%i', (len(chunk), )) mac = self.self2remote.mac.digest( self.self2remote.packet_sequence_number, chunk) self.self2remote.inc_packet_sequence_number() self.debug.write(ssh_debug.DEBUG_2, 'send_packet: mac=%r', (mac, )) # self.debug.write(ssh_debug.DEBUG_2, 'send_packet: chunk=%r', (chunk,)) encrypted_chunk = self.self2remote.cipher.encrypt(chunk) # self.debug.write(ssh_debug.DEBUG_2, 'send_packet: encrypted_chunk=%r', (encrypted_chunk,)) self.transport.write(encrypted_chunk + mac)