twisted conch,重写认证

3 投票
2 回答
803 浏览
提问于 2025-04-16 13:06

我一直在尝试在一个叫做 twisted conch 的模块中覆盖默认的身份验证方式。我原以为我已经搞明白了怎么做。这个脚本其实是对 这个问题的回答。我正在以以下方式创建一个 SSHUserAuthClient 的子类:

class ClientUserAuth(SSHUserAuthClient):
    def getPassword(self, prompt = None):
        return defer.succeed("*****")

显然,我在脚本中把 SSHUserAuthClient 的调用替换成了我自己创建的类。但是我不明白的是,脚本并没有执行我类中的 getPassword 方法,而是执行了父类的 getPassword 方法。有没有人知道我哪里做错了?我对脚本做的唯一其他修改是添加了以下模块导入:

from twisted.internet import defer

谢谢!

补充:奇怪的是,子类中的 getPublicKey 方法被正确调用了。只有 getPassword 方法表现得很奇怪。

2 个回答

3

这里有一些关于如何实现键盘交互式认证的额外细节。

我以为第一次就能搞定,但我的服务器发送了两个交互请求。第一个请求包含一个提示信息 = [('密码: ', False)]
第二个请求则是一个空的提示 = []

下面的代码在我测试过的所有服务器上都能正常工作(包括Redhat、Ubuntu和OpenSUSE)

from twisted.conch.ssh import keys, userauth

class ClientUserAuth(userauth.SSHUserAuthClient):
    def getPassword(self, prompt = None):
        #normal password authentication
        print "PASSWORD AUTH"
        return defer.succeed('*****') # <-- YOUR PASSWORD

    def getGenericAnswers(self, name, instruction, prompts):
        #interactive password authentication
        print "INTERACTIVE AUTH"
        response = ['']*len(prompts)
        for i, p in enumerate(prompts):
            try:
                if('password' in p[0].lower()):
                    response[i] = '*****' # <-- YOUR PASSWORD
            except:
                pass
        #The response is always a sequence, and the length of it is always
        #identical to the length of prompts
        return defer.succeed(response)

在Twisted中启用日志记录对调试Conch的内部工作也很有帮助。

from twisted.python import log
log.msg('Started Logging for A Conch Program')
log.startLogging(sys.stdout)
3

你可能实际上看到的是键盘交互式认证。这种认证方式和密码认证有点像,但又是分开的。你在Linux和OS X上看到的不同表现,其实只是因为这两个系统的SSH服务器设置不同。

你可以重写getGenericAnswers这个函数来处理这个问题。

撰写回答