def _parse_kexdh_init(self, m): # server mode self.e = m.e if (self.e < 1) or (self.e > self.P - 1): raise SshException('Client kex "e" is out of range') K = pow(self.e, self.x, self.P) if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) key = self.protocol.server_key.asbytes() # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) hm = bytearray() hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(key) hm += sshtype.encodeMpint(self.e) hm += sshtype.encodeMpint(self.f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) # sign it sig = self.protocol.server_key.sign_ssh_data(H) # send reply m = mnetpacket.SshKexdhReplyMessage() m.host_key = key m.f = self.f m.signature = sig m.encode() self.protocol.write_packet(m)
def encode(self, obuf=None): self.buf = buf = obuf if obuf else bytearray() buf += struct.pack(">L", self.version) buf += sshtype.encodeBinary(self.sender_pubkey) buf += sshtype.encodeBinary(self.destination_addr) buf += sshtype.encodeString(self.subject) buf += sshtype.encodeString(self.date) buf += struct.pack(">H", len(self.parts)) for part in self.parts: part.encode(buf) self.signature_offset = len(buf) # Reserve space for signature, MorphisBlock and TargetedBlock header. max_size = consts.MAX_DATA_BLOCK_SIZE - 2768 if len(buf) > max_size: raise DmailException(\ "Dmail is [{}] bytes, yet cannot be larger than [{}] bytes."\ .format(len(buf), max_size)) # 512 byte RSA-4096 signature goes at the end. return buf
def _parse_kexdh_reply(self, m): # client mode host_key = m.host_key self.f = m.f if (self.f < 1) or (self.f > self.P - 1): raise SshException('Server kex "f" is out of range') sig = m.signature K = pow(self.f, self.x, self.P) if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K) hm = bytearray() hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(host_key) hm += sshtype.encodeMpint(self.e) hm += sshtype.encodeMpint(self.f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) log.info("Verifying signature...") r = yield from self.protocol.verify_server_key(host_key, sig) return r
def _parse_kexdh_reply(self, m): # The client runs this function. host_key = m.host_key server_f = self.dh.f = m.f if (server_f < 1) or (server_f > self.dh.P - 1): raise SshException('Server kex "f" is out of range') K = self.dh.calculate_k() if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) # H = (V_C || V_S || I_C || I_S || K_S || e || f || K). hm = bytearray() hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(host_key) hm += sshtype.encodeMpint(self.dh.e) hm += sshtype.encodeMpint(server_f) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) log.info("Verifying signature...") r = yield from self.protocol.verify_server_key(host_key, m.signature) return r
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.host_key) nbuf += sshtype.encodeMpint(self.f) nbuf += sshtype.encodeBinary(self.signature) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.data) nbuf += struct.pack("?", self.targeted) if self.pubkey: # Updateable keys. nbuf += sshtype.encodeBinary(self.pubkey) nbuf += sshtype.encodeBinary(self.path_hash) nbuf += sshtype.encodeMpint(self.version) nbuf += sshtype.encodeBinary(self.signature) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.data) nbuf += struct.pack(">L", self.original_size) if self.version is not None: nbuf += sshtype.encodeMpint(self.version) nbuf += sshtype.encodeBinary(self.signature) if self.epubkey: nbuf += sshtype.encodeBinary(self.epubkey) nbuf += struct.pack(">L", self.pubkeylen) return nbuf
def encode(self): nbuf = super().encode() nbuf += struct.pack(">L", len(self.peers)) for peer in self.peers: nbuf += sshtype.encodeString(peer.address) nbuf += sshtype.encodeBinary(peer.node_id) if type(peer) is mnpeer.Peer: nbuf += sshtype.encodeBinary(peer.node_key.asbytes()) else: assert type(peer) is Peer nbuf += sshtype.encodeBinary(peer.pubkey) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.node_id) nbuf += struct.pack("B", self.data_mode.value) nbuf += struct.pack("?", self.version is not None) if self.version is not None: nbuf += sshtype.encodeMpint(self.version) if self.significant_bits: nbuf += struct.pack(">H", self.significant_bits) if self.target_key: nbuf += sshtype.encodeBinary(self.target_key) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeString(self.algorithm_name) nbuf += sshtype.encodeBinary(self.public_key) return nbuf
def encode(self): nbuf = super().encode() if self.first_id is None: nbuf += struct.pack("?", self.data_present) else: nbuf += sshtype.encodeBinary(self.first_id) return nbuf
def encode(self): nbuf = super().encode() nbuf += struct.pack(">L", self.index) nbuf += struct.pack(">L", len(self.packets)) for packet in self.packets: nbuf += sshtype.encodeBinary(packet) return nbuf
def sign_ssh_data(self, data): digest = sha1(data).digest() rsa = self._private_key() sig = util.deflate_long(rsa.sign(self._pkcs1imify(digest), bytes())[0], 0) m = bytearray() m += sshtype.encodeString("ssh-rsa") m += sshtype.encodeBinary(sig) return m
def sign_ssh_data(self, data): digest = sha1(data).digest() rsa = self._private_key() sig = util.deflate_long(\ rsa.sign(self._pkcs1imify(digest), bytes())[0], 0) m = bytearray() m += sshtype.encodeString('ssh-rsa') m += sshtype.encodeBinary(sig) return m
def encode(self, obuf=None): buf = obuf if obuf else bytearray() buf += struct.pack(">L", self.version) buf += sshtype.encodeString(self.ssm) buf += sshtype.encodeMpint(self.sse) buf += sshtype.encodeMpint(self.ssf) buf += sshtype.encodeBinary(self.signature) buf += struct.pack(">L", self.data_len) buf += self.data_enc
def encode(self, obuf=None): buf = obuf if obuf else bytearray() buf += struct.pack(">L", self.version) buf += sshtype.encodeBinary(self.sender_pubkey) buf += sshtype.encodeString(self.subject) buf += sshtype.encodeString(self.date) for part in self.parts: part.encode(buf) return buf
def _parse_kexdh_init(self, m): # The server runs this function. client_e = self.dh.f = m.e if (client_e < 1) or (client_e > self.dh.P - 1): raise SshException("Client kex 'e' is out of range") K = self.dh.calculate_k() if log.isEnabledFor(logging.DEBUG): log.debug("K=[{}].".format(K)) key = self.protocol.server_key.asbytes() # H = (V_C || V_S || I_C || I_S || K_S || e || f || K). hm = bytearray() hm += sshtype.encodeString(self.protocol.remote_banner) hm += sshtype.encodeString(self.protocol.local_banner) hm += sshtype.encodeBinary(self.protocol.remote_kex_init_message) hm += sshtype.encodeBinary(self.protocol.local_kex_init_message) hm += sshtype.encodeBinary(key) hm += sshtype.encodeMpint(client_e) hm += sshtype.encodeMpint(self.dh.e) hm += sshtype.encodeMpint(K) H = sha1(hm).digest() self.protocol.set_K_H(K, H) # Sign it. sig = self.protocol.server_key.sign_ssh_data(H) # Send reply. m = mnp.SshKexdhReplyMessage() m.host_key = key m.f = self.dh.e m.signature = sig m.encode() self.protocol.write_packet(m)
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeString(self.user_name) nbuf += sshtype.encodeString(self.service_name) nbuf += sshtype.encodeString(self.method_name) if self.method_name == "publickey": nbuf += struct.pack("B", self.signature_present) nbuf += sshtype.encodeString(self.algorithm_name) nbuf += sshtype.encodeBinary(self.public_key) # Leave signature for caller to append, as they need this encoded # data to sign. return nbuf
def send_dmail(self, from_asymkey, destination_addr, subject, date,\ message_text): assert from_asymkey is None or type(from_asymkey) is rsakey.RsaKey assert type(destination_addr) in (list, tuple, bytes, bytearray, str),\ type(destination_addr) assert not date or type(date) is datetime addr, rsite =\ yield from self.fetch_recipient_dmail_site(destination_addr) if not rsite: return False if rsite.root["ssm"] != _dh_method_name: raise DmailException("Unsupported ss method [{}]."\ .format(rsite.root["ssm"])) if type(message_text) is str: message_text = message_text.encode() if not date: date = mutil.utc_datetime() dmail = Dmail() dmail.sender_pubkey = from_asymkey.asbytes() if from_asymkey else b"" dmail.destination_addr = addr dmail.subject = subject dmail.date = mutil.format_iso_datetime(date) if message_text: part = DmailPart() part.mime_type = "text/plain" part.data = message_text dmail.parts.append(part) dmail_bytes = dmail.encode() if from_asymkey: signature = from_asymkey.calc_rsassa_pss_sig(dmail_bytes) dmail_bytes += sshtype.encodeBinary(signature) storing_nodes = yield from\ self._send_dmail(from_asymkey, rsite, dmail_bytes, signature) return storing_nodes
def sign_ssh_data(self, data): digest = sha1(data).digest() dss = DSA.construct((int(self.y), int(self.g), int(self.p), int(self.q), int(self.x))) # generate a suitable k qsize = len(util.deflate_long(self.q, 0)) while True: k = util.inflate_long(os.urandom(qsize), 1) if (k > 2) and (k < self.q): break r, s = dss.sign(util.inflate_long(digest, 1), k) m = bytearray() m += sshtype.encodeString("ssh-dss") # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = zero_byte * (20 - len(sstr)) + sstr m += sshtype.encodeBinary(rstr + sstr) return m
def sign_ssh_data(self, data): digest = sha1(data).digest() dss = DSA.construct( (int(self.y), int(self.g), int(self.p), int(self.q), int(self.x))) # generate a suitable k qsize = len(util.deflate_long(self.q, 0)) while True: k = util.inflate_long(os.urandom(qsize), 1) if (k > 2) and (k < self.q): break r, s = dss.sign(util.inflate_long(digest, 1), k) m = bytearray() m += sshtype.encodeString("ssh-dss") # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = zero_byte * (20 - len(sstr)) + sstr m += sshtype.encodeBinary(rstr + sstr) return m
def encode(self): nbuf = bytearray() nbuf += sshtype.encodeBinary(self.value) return nbuf
def encode(self): nbuf = super().encode() nbuf += sshtype.encodeBinary(self.data) nbuf += struct.pack("?", self.targeted) return nbuf
def encode(self, obuf=None): buf = obuf if obuf else bytearray() buf += sshtype.encodeString(self.mime_type) buf += sshtype.encodeBinary(self.data) return buf
def connectTaskSecure(protocol, server_mode): # Send KexInit packet. opobj = mnetpacket.SshKexInitMessage() opobj.cookie = os.urandom(16) # opobj.kex_algorithms = "diffie-hellman-group-exchange-sha256" opobj.kex_algorithms = "diffie-hellman-group14-sha1" opobj.server_host_key_algorithms = "ssh-rsa" opobj.encryption_algorithms_client_to_server = "aes256-cbc" opobj.encryption_algorithms_server_to_client = "aes256-cbc" # opobj.mac_algorithms_client_to_server = "hmac-sha2-512" # opobj.mac_algorithms_server_to_client = "hmac-sha2-512" opobj.mac_algorithms_client_to_server = "hmac-sha1" opobj.mac_algorithms_server_to_client = "hmac-sha1" opobj.compression_algorithms_client_to_server = "none" opobj.compression_algorithms_server_to_client = "none" opobj.encode() protocol.local_kex_init_message = opobj.buf protocol.write_packet(opobj) # Read KexInit packet. packet = yield from protocol.read_packet() if not packet: return False if log.isEnabledFor(logging.DEBUG): log.debug("X: Received packet [{}].".format(hex_dump(packet))) packet_type = mnetpacket.SshPacket.parse_type(packet) if log.isEnabledFor(logging.INFO): log.info("packet_type=[{}].".format(packet_type)) if packet_type != 20: log.warning("Peer sent unexpected packet_type[{}], disconnecting.".format(packet_type)) protocol.close() return False protocol.remote_kex_init_message = packet pobj = mnetpacket.SshKexInitMessage(packet) if log.isEnabledFor(logging.DEBUG): log.debug("cookie=[{}].".format(pobj.cookie)) if log.isEnabledFor(logging.INFO): log.info("keyExchangeAlgorithms=[{}].".format(pobj.kex_algorithms)) protocol.waitingForNewKeys = True # ke = kex.KexGroup14(protocol) # log.info("Calling start_kex()...") # r = yield from ke.do_kex() ke = kexdhgroup14sha1.KexDhGroup14Sha1(protocol) log.info("Calling kex->run()...") r = yield from ke.run() if not r: # Client is rejected for some reason by higher level. protocol.close() return False # Setup encryption now that keys are exchanged. protocol.init_outbound_encryption() if not protocol.server_mode: """ Server gets done automatically since parameters are always there before NEWKEYS is received, but client the parameters and NEWKEYS message may come in the same tcppacket, so the auto part just turns off inbound processing and waits for us to call init_inbound_encryption when we have the parameters ready. """ protocol.init_inbound_encryption() protocol.set_inbound_enabled(True) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshNewKeysMessage(packet) log.debug("Received SSH_MSG_NEWKEYS.") if protocol.server_mode: packet = yield from protocol.read_packet() if not packet: return False # m = mnetpacket.SshPacket(None, packet) # log.info("X: Received packet (type={}) [{}].".format(m.packet_type, packet)) m = mnetpacket.SshServiceRequestMessage(packet) log.info("Service requested [{}].".format(m.service_name)) if m.service_name != "ssh-userauth": raise SshException("Remote end requested unexpected service (name=[{}]).".format(m.service_name)) mr = mnetpacket.SshServiceAcceptMessage() mr.service_name = "ssh-userauth" mr.encode() protocol.write_packet(mr) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshUserauthRequestMessage(packet) log.info("Userauth requested with method=[{}].".format(m.method_name)) if m.method_name == "none": mr = mnetpacket.SshUserauthFailureMessage() mr.auths = "publickey" mr.partial_success = False mr.encode() protocol.write_packet(mr) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshUserauthRequestMessage(packet) log.info("Userauth requested with method=[{}].".format(m.method_name)) if m.method_name != "publickey": raise SshException("Unhandled client auth method [{}].".format(m.method_name)) if m.algorithm_name != "ssh-rsa": raise SshException("Unhandled client auth algorithm [{}].".format(m.algorithm_name)) log.debug("m.signature_present()={}.".format(m.signature_present)) if not m.signature_present: mr = mnetpacket.SshUserauthPkOkMessage() mr.algorithm_name = m.algorithm_name mr.public_key = m.public_key mr.encode() protocol.write_packet(mr) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshUserauthRequestMessage(packet) log.info("Userauth requested with method=[{}].".format(m.method_name)) if m.method_name != "publickey": raise SshException("Unhandled client auth method [{}].".format(m.method_name)) if m.algorithm_name != "ssh-rsa": raise SshException("Unhandled client auth algorithm [{}].".format(m.algorithm_name)) if log.isEnabledFor(logging.DEBUG): log.debug("signature=[{}].".format(hex_dump(m.signature))) if protocol.client_key: if protocol.client_key.asbytes() != m.public_key: raise SshException("Key provided by client differs from that which we were expecting.") else: protocol.client_key = rsakey.RsaKey(m.public_key) buf = bytearray() buf += sshtype.encodeBinary(protocol.session_id) buf += packet[:-m.signature_length] r = protocol.client_key.verify_ssh_sig(buf, m.signature) log.info("Userauth signature check result: [{}].".format(r)) if not r: raise SshException("Signature and key provided by client did not match.") r = yield from protocol.connection_handler.peer_authenticated(protocol) if not r: # Client is rejected for some reason by higher level. protocol.close() return False mr = mnetpacket.SshUserauthSuccessMessage() mr.encode() protocol.write_packet(mr) else: # client mode. m = mnetpacket.SshServiceRequestMessage() m.service_name = "ssh-userauth" m.encode() protocol.write_packet(m) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshServiceAcceptMessage(packet) log.info("Service request accepted [{}].".format(m.service_name)) mr = mnetpacket.SshUserauthRequestMessage() mr.user_name = "dev" mr.service_name = "ssh-connection" mr.method_name = "publickey" mr.signature_present = True mr.algorithm_name = "ssh-rsa" ckey = protocol.client_key mr.public_key = ckey.asbytes() mr.encode() mrb = bytearray() mrb += sshtype.encodeBinary(protocol.session_id) mrb += mr.buf sig = sshtype.encodeBinary(ckey.sign_ssh_data(mrb)) mrb = mr.buf assert mr.buf == mrb mrb += sig protocol.write_packet(mr) packet = yield from protocol.read_packet() if not packet: return False m = mnetpacket.SshUserauthSuccessMessage(packet) log.info("Userauth accepted.") log.info("Connect task done (server={}).".format(server_mode)) # if not server_mode: # protocol.close() return True