示例#1
0
 def ssh_KEX_DH_GEX_REQUEST(self, packet):
     if self.ignoreNextPacket:
         self.ignoreNextPacket = 0
         return
     self.min, self.ideal, self.max = struct.unpack('>3L', packet)
     self.g, self.p = self.factory.getDHPrime(self.ideal)
     self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p) + MP(self.g))
示例#2
0
 def ssh_KEX_DH_GEX_REQUEST_OLD(self, packet):
     if self.ignoreNextPacket:
         self.ignoreNextPacket = 0
         return
     if self.kexAlg == 'diffie-hellman-group1-sha1':  # this is really KEXDH_INIT
         clientDHPubKey, foo = getMP(packet)
         y = Util.number.getRandomNumber(16, entropy.get_bytes)
         f = pow(DH_GENERATOR, y, DH_PRIME)
         sharedSecret = _MPpow(clientDHPubKey, y, DH_PRIME)
         h = sha.new()
         h.update(NS(self.otherVersionString))
         h.update(NS(self.ourVersionString))
         h.update(NS(self.clientKexInitPayload))
         h.update(NS(self.ourKexInitPayload))
         h.update(NS(self.factory.publicKeys[self.keyAlg]))
         h.update(MP(clientDHPubKey))
         h.update(MP(f))
         h.update(sharedSecret)
         exchangeHash = h.digest()
         self.sendPacket(MSG_KEXDH_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \
                        MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash)))
         self._keySetup(sharedSecret, exchangeHash)
     elif self.kexAlg == 'diffie-hellman-group-exchange-sha1':
         self.kexAlg = 'diffie-hellman-group-exchange-sha1-old'
         self.ideal = struct.unpack('>L', packet)[0]
         self.g, self.p = self.factory.getDHPrime(self.ideal)
         self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p) + MP(self.g))
     else:
         raise error.ConchError('bad kexalg: %s' % self.kexAlg)
示例#3
0
    def ssh_KEX_DH_GEX_INIT(self, packet):
        clientDHPubKey, foo = getMP(packet)

        # if y < 1024, openssh will reject us: "bad server public DH value".
        # y<1024 means f will be short, and of the form 2^y, so an observer
        # could trivially derive our secret y from f. Openssh detects this
        # and complains, so avoid creating such values by requiring y to be
        # larger than ln2(self.p)

        # TODO: we should also look at the value they send to us and reject
        # insecure values of f (if g==2 and f has a single '1' bit while the
        # rest are '0's, then they must have used a small y also).

        # TODO: This could be computed when self.p is set up
        #  or do as openssh does and scan f for a single '1' bit instead

        minimum = long(math.floor(math.log(self.p) / math.log(2)) + 1)
        tries = 0
        pSize = Util.number.size(self.p)
        y = Util.number.getRandomNumber(pSize, entropy.get_bytes)
        while tries < 10 and y < minimum:
            tries += 1
            y = Util.number.getRandomNumber(pSize, entropy.get_bytes)
        assert (y >= minimum)  # TODO: test_conch just hangs if this is hit
        # the chance of it being hit are really really low

        f = pow(self.g, y, self.p)
        sharedSecret = _MPpow(clientDHPubKey, y, self.p)
        h = sha.new()
        h.update(NS(self.otherVersionString))
        h.update(NS(self.ourVersionString))
        h.update(NS(self.clientKexInitPayload))
        h.update(NS(self.ourKexInitPayload))
        h.update(NS(self.factory.publicKeys[self.keyAlg]))
        if self.kexAlg == 'diffie-hellman-group-exchange-sha1':
            h.update(struct.pack('>3L', self.min, self.ideal, self.max))
        else:
            h.update(struct.pack('>L', self.ideal))
        h.update(MP(self.p))
        h.update(MP(self.g))
        h.update(MP(clientDHPubKey))
        h.update(MP(f))
        h.update(sharedSecret)
        exchangeHash = h.digest()
        self.sendPacket(MSG_KEX_DH_GEX_REPLY, NS(self.factory.publicKeys[self.keyAlg])+ \
                       MP(f)+NS(keys.signData(self.factory.privateKeys[self.keyAlg], exchangeHash)))
        self._keySetup(sharedSecret, exchangeHash)
示例#4
0
 def _continueGEX_GROUP(self, ignored, pubKey, f, signature):
     serverKey = keys.getPublicKeyObject(pubKey)
     sharedSecret = _MPpow(f, self.x, DH_PRIME)
     h = sha.new()
     h.update(NS(self.ourVersionString))
     h.update(NS(self.otherVersionString))
     h.update(NS(self.ourKexInitPayload))
     h.update(NS(self.serverKexInitPayload))
     h.update(NS(pubKey))
     h.update(MP(self.DHpubKey))
     h.update(MP(f))
     h.update(sharedSecret)
     exchangeHash = h.digest()
     if not keys.verifySignature(serverKey, signature, exchangeHash):
         self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, 'bad signature')
         return
     self._keySetup(sharedSecret, exchangeHash)
示例#5
0
 def ssh_KEX_DH_GEX_GROUP(self, packet):
     if self.kexAlg == 'diffie-hellman-group1-sha1':
         pubKey, packet = getNS(packet)
         f, packet = getMP(packet)
         signature, packet = getNS(packet)
         fingerprint = ':'.join(map(lambda c: '%02x'%ord(c), md5.new(pubKey).digest()))
         d = self.verifyHostKey(pubKey, fingerprint)
         d.addCallback(self._continueGEX_GROUP, pubKey, f, signature)
         d.addErrback(lambda unused,self=self:self.sendDisconnect(DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 'bad host key'))
     else:
         self.p, rest = getMP(packet)
         self.g, rest = getMP(rest)
         self.x = getMP('\x00\x00\x00\x40'+entropy.get_bytes(64))[0]
         self.DHpubKey = pow(self.g, self.x, self.p)
         self.sendPacket(MSG_KEX_DH_GEX_INIT, MP(self.DHpubKey))
示例#6
0
    def ssh_KEXINIT(self, packet):
        self.serverKexInitPayload = chr(MSG_KEXINIT) + packet
        #cookie = packet[: 16] # taking this is unimportant
        k = getNS(packet[16:], 10)
        strings, rest = k[:-1], k[-1]
        kexAlgs, keyAlgs, encCS, encSC, macCS, macSC, compCS, compSC, langCS, langSC =  \
           [s.split(',')for s in strings]
        self.kexAlg = ffs(self.supportedKeyExchanges, kexAlgs)
        self.keyAlg = ffs(self.supportedPublicKeys, keyAlgs)
        self.nextEncryptions = SSHCiphers(
            ffs(self.supportedCiphers, encCS),
            ffs(self.supportedCiphers, encSC),
            ffs(self.supportedMACs, macCS),
            ffs(self.supportedMACs, macSC),
        )
        self.outgoingCompressionType = ffs(self.supportedCompressions, compCS)
        self.incomingCompressionType = ffs(self.supportedCompressions, compSC)
        if None in (self.kexAlg, self.keyAlg, self.outgoingCompressionType,
                    self.incomingCompressionType):
            self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED,
                                "couldn't match all kex parts")
            return
        if None in self.nextEncryptions.__dict__.values():
            self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED,
                                "couldn't match all kex parts")
            return
        log.msg('kex alg, key alg: %s %s' % (self.kexAlg, self.keyAlg))
        log.msg(
            'client->server: %s %s %s' %
            (self.nextEncryptions.outCipType, self.nextEncryptions.outMacType,
             self.outgoingCompressionType))
        log.msg('server->client: %s %s %s' %
                (self.nextEncryptions.inCipType,
                 self.nextEncryptions.inMacType, self.incomingCompressionType))

        if self.kexAlg == 'diffie-hellman-group1-sha1':
            self.x = Util.number.getRandomNumber(512, entropy.get_bytes)
            self.DHpubKey = pow(DH_GENERATOR, self.x, DH_PRIME)
            self.sendPacket(MSG_KEXDH_INIT, MP(self.DHpubKey))
        else:
            self.sendPacket(MSG_KEX_DH_GEX_REQUEST_OLD, '\x00\x00\x08\x00')