def test_userRejectedHostKey(self):
        """
        If the L{KnownHostsFile} instance used to construct
        L{SSHCommandClientEndpoint} rejects the SSH public key presented by the
        server, the L{Deferred} returned by L{SSHCommandClientEndpoint.connect}
        fires with a L{Failure} wrapping L{UserRejectedKey}.
        """
        endpoint = SSHCommandClientEndpoint.newConnection(
            self.reactor,
            b"/bin/ls -l",
            b"dummy user",
            self.hostname,
            self.port,
            knownHosts=KnownHostsFile(self.mktemp()),
            ui=FixedResponseUI(False))

        factory = Factory()
        factory.protocol = Protocol
        connected = endpoint.connect(factory)

        server, client, pump = self.connectedServerAndClient(
            self.factory, self.reactor.tcpClients[0][2])

        f = self.failureResultOf(connected)
        f.trap(UserRejectedKey)
示例#2
0
 def test_defaultInitializerIgnoresExisting(self):
     """
     The default initializer for L{KnownHostsFile} disregards any existing
     contents in the save path.
     """
     hostsFile = KnownHostsFile(self.pathWithContent(sampleHashedLine))
     self.assertEqual([], list(hostsFile.iterentries()))
示例#3
0
 def test_iterentriesUnsaved(self):
     """
     If the save path for a L{KnownHostsFile} does not exist,
     L{KnownHostsFile.iterentries} still returns added but unsaved entries.
     """
     hostsFile = KnownHostsFile(FilePath(self.mktemp()))
     hostsFile.addHostKey("www.example.com", Key.fromString(sampleKey))
     self.assertEqual(1, len(list(hostsFile.iterentries())))
 def test_readOnlySavePath(self):
     """
     L{KnownHostsFile.savePath} is read-only; if an assignment is made to
     it, L{AttributeError} is raised and the value is unchanged.
     """
     path = FilePath(self.mktemp())
     new = FilePath(self.mktemp())
     hostsFile = KnownHostsFile(path)
     self.assertRaises(AttributeError, setattr, hostsFile, "savePath", new)
     self.assertEqual(path, hostsFile.savePath)
 def setUp(self):
     """
     Configure an SSH server with password authentication enabled for a
     well-known (to the tests) account.
     """
     SSHCommandClientEndpointTestsMixin.setUp(self)
     # Make the server's host key available to be verified by the client.
     self.hostKeyPath = FilePath(self.mktemp())
     self.knownHosts = KnownHostsFile(self.hostKeyPath)
     self.knownHosts.addHostKey(self.hostname,
                                self.factory.publicKeys['ssh-rsa'])
     self.knownHosts.addHostKey(self.serverAddress.host,
                                self.factory.publicKeys['ssh-rsa'])
     self.knownHosts.save()
示例#6
0
    def test_savingAvoidsDuplication(self):
        """
        L{KnownHostsFile.save} only writes new entries to the save path, not
        entries which were added and already written by a previous call to
        C{save}.
        """
        path = FilePath(self.mktemp())
        knownHosts = KnownHostsFile(path)
        entry = knownHosts.addHostKey("some.example.com",
                                      Key.fromString(sampleKey))
        knownHosts.save()
        knownHosts.save()

        knownHosts = KnownHostsFile.fromPath(path)
        self.assertEqual([entry], list(knownHosts.iterentries()))
示例#7
0
    def test_saveResetsClobberState(self):
        """
        After L{KnownHostsFile.save} is used once with an instance initialized
        by the default initializer, contents of the save path are respected and
        preserved.
        """
        hostsFile = KnownHostsFile(self.pathWithContent(sampleHashedLine))
        preSave = hostsFile.addHostKey("www.example.com",
                                       Key.fromString(otherSampleKey))
        hostsFile.save()
        postSave = hostsFile.addHostKey("another.example.com",
                                        Key.fromString(thirdSampleKey))
        hostsFile.save()

        self.assertEqual([preSave, postSave], list(hostsFile.iterentries()))
示例#8
0
 def test_defaultInitializerClobbersExisting(self):
     """
     After using the default initializer for L{KnownHostsFile}, the first use
     of L{KnownHostsFile.save} overwrites any existing contents in the save
     path.
     """
     path = self.pathWithContent(sampleHashedLine)
     hostsFile = KnownHostsFile(path)
     entry = hostsFile.addHostKey("www.example.com",
                                  Key.fromString(otherSampleKey))
     hostsFile.save()
     # Check KnownHostsFile to see what it thinks the state is
     self.assertEqual([entry], list(hostsFile.iterentries()))
     # And also directly check the underlying file itself
     self.assertEqual(entry.toString() + "\n", path.getContent())
示例#9
0
 def test_unsavedEntryHasKeyMismatch(self):
     """
     L{KnownHostsFile.hasHostKey} raises L{HostKeyChanged} if the host key is
     present in memory (but not yet saved), but different from the expected
     one.  The resulting exception has a C{offendingEntry} indicating the
     given entry, but no filename or line number information (reflecting the
     fact that the entry exists only in memory).
     """
     hostsFile = KnownHostsFile(FilePath(self.mktemp()))
     entry = hostsFile.addHostKey("www.example.com",
                                  Key.fromString(otherSampleKey))
     exception = self.assertRaises(HostKeyChanged, hostsFile.hasHostKey,
                                   "www.example.com",
                                   Key.fromString(thirdSampleKey))
     self.assertEqual(exception.offendingEntry, entry)
     self.assertEqual(exception.lineno, None)
     self.assertEqual(exception.path, None)
示例#10
0
 def setUp(self):
     """
     Patch 'open' in verifyHostKey.
     """
     self.fakeFile = FakeFile()
     self.patch(default, "_open", self.patchedOpen)
     self.hostsOption = self.mktemp()
     knownHostsFile = KnownHostsFile(FilePath(self.hostsOption))
     knownHostsFile.addHostKey("exists.example.com",
                               Key.fromString(sampleKey))
     knownHostsFile.addHostKey("4.3.2.1", Key.fromString(sampleKey))
     knownHostsFile.save()
     self.fakeTransport = FakeObject()
     self.fakeTransport.factory = FakeObject()
     self.options = self.fakeTransport.factory.options = {
         'host': "exists.example.com",
         'known-hosts': self.hostsOption
     }
示例#11
0
 def setUp(self):
     """
     Patch 'open' in verifyHostKey.
     """
     self.fakeFile = FakeFile()
     self.patch(default, "_open", self.patchedOpen)
     self.hostsOption = self.mktemp()
     self.hashedEntries = {}
     knownHostsFile = KnownHostsFile(FilePath(self.hostsOption))
     for host in (b"exists.example.com", b"4.3.2.1"):
         entry = knownHostsFile.addHostKey(host, Key.fromString(sampleKey))
         self.hashedEntries[host] = entry
     knownHostsFile.save()
     self.fakeTransport = FakeObject()
     self.fakeTransport.factory = FakeObject()
     self.options = self.fakeTransport.factory.options = {
         'host': b"exists.example.com",
         'known-hosts': self.hostsOption
     }
示例#12
0
    def test_readExisting(self):
        """
        Existing entries in the I{known_hosts} file are reflected by the
        L{KnownHostsFile} created by L{_NewConnectionHelper} when none is
        supplied to it.
        """
        key = CommandFactory().publicKeys['ssh-rsa']
        path = FilePath(self.mktemp())
        knownHosts = KnownHostsFile(path)
        knownHosts.addHostKey("127.0.0.1", key)
        knownHosts.save()

        msg("Created known_hosts file at %r" % (path.path, ))

        # Unexpand ${HOME} to make sure ~ syntax is respected.
        home = os.path.expanduser("~/")
        default = path.path.replace(home, "~/")
        self.patch(_NewConnectionHelper, "_KNOWN_HOSTS", default)
        msg("Patched _KNOWN_HOSTS with %r" % (default, ))

        loaded = _NewConnectionHelper._knownHosts()
        self.assertTrue(loaded.hasHostKey("127.0.0.1", key))
示例#13
0
    def setUp(self):
        """
        Configure an SSH server with password authentication enabled for a
        well-known (to the tests) account.
        """
        SSHCommandClientEndpointTestsMixin.setUp(self)

        knownHosts = KnownHostsFile(FilePath(self.mktemp()))
        knownHosts.addHostKey(self.hostname,
                              self.factory.publicKeys['ssh-rsa'])
        knownHosts.addHostKey(self.serverAddress.host,
                              self.factory.publicKeys['ssh-rsa'])

        self.endpoint = SSHCommandClientEndpoint.newConnection(
            self.reactor,
            b"/bin/ls -l",
            self.user,
            self.hostname,
            self.port,
            password=self.password,
            knownHosts=knownHosts,
            ui=FixedResponseUI(False))
示例#14
0
    def test_mismatchedHostKey(self):
        """
        If the SSH public key presented by the SSH server does not match the
        previously remembered key, as reported by the L{KnownHostsFile}
        instance use to construct the endpoint, for that server, the
        L{Deferred} returned by L{SSHCommandClientEndpoint.connect} fires with
        a L{Failure} wrapping L{HostKeyChanged}.
        """
        differentKey = Key.fromString(privateDSA_openssh).public()
        knownHosts = KnownHostsFile(self.mktemp())
        knownHosts.addHostKey(self.serverAddress.host, differentKey)
        knownHosts.addHostKey(self.hostname, differentKey)

        # The UI may answer true to any questions asked of it; they should
        # make no difference, since a *mismatched* key is not even optionally
        # allowed to complete a connection.
        ui = FixedResponseUI(True)

        endpoint = SSHCommandClientEndpoint.newConnection(
            self.reactor,
            b"/bin/ls -l",
            b"dummy user",
            self.hostname,
            self.port,
            password=b"dummy password",
            knownHosts=knownHosts,
            ui=ui)

        factory = Factory()
        factory.protocol = Protocol
        connected = endpoint.connect(factory)

        server, client, pump = self.connectedServerAndClient(
            self.factory, self.reactor.tcpClients[0][2])

        f = self.failureResultOf(connected)
        f.trap(HostKeyChanged)