def test_warnOpenFailed(self): """ L{ConsoleUI.warn} should log a traceback if the output can't be opened. """ def raiseIt(): 1 / 0 ui = ConsoleUI(raiseIt) ui.warn("This message never makes it.") self.assertEqual(len(self.flushLoggedErrors(ZeroDivisionError)), 1)
def test_promptOpenFailed(self): """ If the C{opener} passed to L{ConsoleUI} raises an exception, that exception will fail the L{Deferred} returned from L{ConsoleUI.prompt}. """ def raiseIt(): raise IOError() ui = ConsoleUI(raiseIt) d = ui.prompt("This is a test.") return self.assertFailure(d, IOError)
def test_promptOpenFailed(self): """ If the C{opener} passed to L{ConsoleUI} raises an exception, that exception will fail the L{Deferred} returned from L{ConsoleUI.prompt}. """ def raiseIt(): raise IOError() ui = ConsoleUI(raiseIt) l = [] ui.prompt("This is a test.").addErrback(l.append) l[0].trap(IOError)
def __init__(self, reactor, hostname, port, username, keys, password, agentEndpoint, knownHosts, ui, tty=FilePath(b"/dev/tty")): """ @param tty: The path of the tty device to use in case C{ui} is L{None}. @type tty: L{FilePath} @see: L{SSHCommandClientEndpoint.newConnection} """ self.reactor = reactor self.hostname = hostname if port is not None: self.port = port self.username = username self.keys = keys self.password = password self.agentEndpoint = agentEndpoint if knownHosts is None: knownHosts = self._knownHosts() self.knownHosts = knownHosts if ui is None: ui = ConsoleUI(self._opener) self.ui = ui self.tty = tty
def fromCommandLine(cls, reactor, argv): config = EchoOptions() config.parseOptions(argv) ui = ConsoleUI(lambda: open("/dev/tty", "r+")) keys = [] if config["identity"]: keyPath = os.path.expanduser(config["identity"]) if os.path.exists(keyPath): keys.append(readKey(keyPath)) knownHostsPath = FilePath(os.path.expanduser(config["knownhosts"])) if knownHostsPath.exists(): knownHosts = KnownHostsFile.fromPath(knownHostsPath) else: knownHosts = None if config["no-agent"] or "SSH_AUTH_SOCK" not in os.environ: agentEndpoint = None else: agentEndpoint = UNIXClientEndpoint(reactor, os.environ["SSH_AUTH_SOCK"]) return cls(reactor, ui, config["host"], config["port"], config["username"], config["password"], keys, knownHosts, agentEndpoint)
def verifyHostKey(transport, host, pubKey, fingerprint): """ Verify a host's key. This function is a gross vestige of some bad factoring in the client internals. The actual implementation, and a better signature of this logic is in L{KnownHostsFile.verifyHostKey}. This function is not deprecated yet because the callers have not yet been rehabilitated, but they should eventually be changed to call that method instead. However, this function does perform two functions not implemented by L{KnownHostsFile.verifyHostKey}. It determines the path to the user's known_hosts file based on the options (which should really be the options object's job), and it provides an opener to L{ConsoleUI} which opens '/dev/tty' so that the user will be prompted on the tty of the process even if the input and output of the process has been redirected. This latter part is, somewhat obviously, not portable, but I don't know of a portable equivalent that could be used. @param host: Due to a bug in L{SSHClientTransport.verifyHostKey}, this is always the dotted-quad IP address of the host being connected to. @type host: L{str} @param transport: the client transport which is attempting to connect to the given host. @type transport: L{SSHClientTransport} @param fingerprint: the fingerprint of the given public key, in xx:xx:xx:... format. This is ignored in favor of getting the fingerprint from the key itself. @type fingerprint: L{str} @param pubKey: The public key of the server being connected to. @type pubKey: L{str} @return: a L{Deferred} which fires with C{1} if the key was successfully verified, or fails if the key could not be successfully verified. Failure types may include L{HostKeyChanged}, L{UserRejectedKey}, L{IOError} or L{KeyboardInterrupt}. """ actualHost = transport.factory.options['host'] actualKey = keys.Key.fromString(pubKey) kh = KnownHostsFile.fromPath(FilePath( transport.factory.options['known-hosts'] or os.path.expanduser(_KNOWN_HOSTS) )) ui = ConsoleUI(lambda : _open("/dev/tty", "r+b", buffering=0)) return kh.verifyHostKey(ui, actualHost, host, actualKey)
def setUp(self): """ Create a L{ConsoleUI} pointed at a L{FakeFile}. """ self.fakeFile = FakeFile() self.ui = ConsoleUI(self.openFile)
class ConsoleUITests(TestCase): """ Test cases for L{ConsoleUI}. """ def setUp(self): """ Create a L{ConsoleUI} pointed at a L{FakeFile}. """ self.fakeFile = FakeFile() self.ui = ConsoleUI(self.openFile) def openFile(self): """ Return the current fake file. """ return self.fakeFile def newFile(self, lines): """ Create a new fake file (the next file that self.ui will open) with the given list of lines to be returned from readline(). """ self.fakeFile = FakeFile() self.fakeFile.inlines = lines def test_promptYes(self): """ L{ConsoleUI.prompt} writes a message to the console, then reads a line. If that line is 'yes', then it returns a L{Deferred} that fires with True. """ for okYes in ['yes', 'Yes', 'yes\n']: self.newFile([okYes]) l = [] self.ui.prompt("Hello, world!").addCallback(l.append) self.assertEqual(["Hello, world!"], self.fakeFile.outchunks) self.assertEqual([True], l) self.assertEqual(True, self.fakeFile.closed) def test_promptNo(self): """ L{ConsoleUI.prompt} writes a message to the console, then reads a line. If that line is 'no', then it returns a L{Deferred} that fires with False. """ for okNo in ['no', 'No', 'no\n']: self.newFile([okNo]) l = [] self.ui.prompt("Goodbye, world!").addCallback(l.append) self.assertEqual(["Goodbye, world!"], self.fakeFile.outchunks) self.assertEqual([False], l) self.assertEqual(True, self.fakeFile.closed) def test_promptRepeatedly(self): """ L{ConsoleUI.prompt} writes a message to the console, then reads a line. If that line is neither 'yes' nor 'no', then it says "Please enter 'yes' or 'no'" until it gets a 'yes' or a 'no', at which point it returns a Deferred that answers either True or False. """ self.newFile(['what', 'uh', 'okay', 'yes']) l = [] self.ui.prompt("Please say something useful.").addCallback(l.append) self.assertEqual([True], l) self.assertEqual(self.fakeFile.outchunks, ["Please say something useful."] + ["Please type 'yes' or 'no': "] * 3) self.assertEqual(True, self.fakeFile.closed) self.newFile(['blah', 'stuff', 'feh', 'no']) l = [] self.ui.prompt("Please say something negative.").addCallback(l.append) self.assertEqual([False], l) self.assertEqual(self.fakeFile.outchunks, ["Please say something negative."] + ["Please type 'yes' or 'no': "] * 3) self.assertEqual(True, self.fakeFile.closed) def test_promptOpenFailed(self): """ If the C{opener} passed to L{ConsoleUI} raises an exception, that exception will fail the L{Deferred} returned from L{ConsoleUI.prompt}. """ def raiseIt(): raise IOError() ui = ConsoleUI(raiseIt) d = ui.prompt("This is a test.") return self.assertFailure(d, IOError) def test_warn(self): """ L{ConsoleUI.warn} should output a message to the console object. """ self.ui.warn("Test message.") self.assertEqual(["Test message."], self.fakeFile.outchunks) self.assertEqual(True, self.fakeFile.closed) def test_warnOpenFailed(self): """ L{ConsoleUI.warn} should log a traceback if the output can't be opened. """ def raiseIt(): 1 / 0 ui = ConsoleUI(raiseIt) ui.warn("This message never makes it.") self.assertEqual(len(self.flushLoggedErrors(ZeroDivisionError)), 1)
def __init__(self, hostname, port): self.hostname = hostname self.port = port self.ui = ConsoleUI(lambda: open("/dev/tty", "r+b"))