【问题标题】:heisenbug: pexpect and changing passwords on Mac OS X over sshheisenbug:在 Mac OS X 上通过 ssh 预测和更改密码
【发布时间】:2015-06-03 17:54:10
【问题描述】:

在我的组织中,我们有许多运行 OS X Yosemite 的 Mac。每台机器都有一个默认帐户,我们的 IT 团队可以使用该帐户访问机器以提供 IT 帮助。我们希望定期更改此帐户的密码,并且随着组织中 mac 数量的增长,我们希望找到一种方法来自动执行此任务。

我已经使用pexpect 编写了一个 Python 脚本,它将 SSH 进入每台机器并执行 dscl 以更改登录密码,然后 SSH 进入每台机器以运行 security 以更改登录钥匙串密码。

这些方法是类的一部分,新旧密码存储在 old_passwordnew_password 属性中:

def _change_login_password(self, host):
    """Change the login password of a machine.

    Returns True on success, False on failure.
    """

    try:
        child = pexpect.spawn(
            "ssh default@{} dscl . passwd /Users/default".format(host))
        child.expect("Password:")
        child.sendline(self.old_password)
        child.expect("New Password: ")
        child.sendline(self.new_password)
        child.expect(
            "Permission denied. Please enter user's old password:")
        child.sendline(self.old_password)
        child.close()

        return not child.exitstatus

    except pexpect.TIMEOUT:
        return False

def _change_keychain_password(self, host, login_password):
    """Change the keychain password of a machine.

    Changes the keychain password to match the login password.

    Returns True on success, False on failure.
    """

    try:
        child = pexpect.spawn(
            "ssh default@{} security set-keychain-password"
            " login.keychain".format(host))
        child.expect("Password:")
        child.sendline(login_password)
        child.expect("Old Password: ")
        child.sendline(self.old_password)
        child.expect("New Password: ")
        child.sendline(login_password)
        child.expect("Retype New Password: ")
        child.sendline(login_password)
        child.close()

        return not child.exitstatus

    except pexpect.TIMEOUT:
        return False

这些方法都无法针对我的 OS X Yosemite 工作笔记本电脑进行测试。通过 ssh 执行的每个命令都会返回非零退出状态,并且笔记本电脑上的密码不会更改。

...但是,当我在任一方法的顶部插入一个pdb 断点,然后在调试器中单步执行该方法而不进行任何更改时,退出状态变为 0,并且笔记本电脑上的密码更改.

海森堡。

pexpect 调用周围插入打印语句有时也会导致方法成功。

我已经尝试过pexepectdelaybeforesend 属性,它在sendline 将其有效负载发送到子进程之前添加了延迟,认为调试器中的时间延迟可能是问题所在,但这并没有解决问题。

有人知道我接下来会去哪里吗?我的一些同事怀疑这可能是tty 问题。有谁知道pdb 可能如何影响环境并导致这些命令成功,或者 OS X 导致它们失败的原因是什么?

【问题讨论】:

  • 您是否尝试过使用ssh -t
  • 我刚试过-ttt。没有骰子

标签: python ssh osx-yosemite pexpect dscl


【解决方案1】:

啊,所以这是一件事。经过仔细检查,两个进程都以状态码 130 退出,对应于 Ctrl+C。我需要在close 之前将expect(pexpect.EOF) 添加到这两个方法中,以便它们有机会在被关闭之前完成。

def _change_login_password(self, host):
    """Change the login password of a machine.

    Returns True on success, False on failure.
    """

    try:
        child = pexpect.spawn(
            "ssh -ttt default@{} dscl . passwd /Users/default".format(host))
        child.expect("Password:")
        child.sendline(self.old_password)
        child.expect("New Password: ")
        child.sendline(self.new_password)
        child.expect(
            "Permission denied. Please enter user's old password:")
        child.sendline(self.old_password)
        child.expect(pexpect.EOF)  # Wait for EOF.
        child.close()

        return not child.exitstatus

    except pexpect.TIMEOUT:
        return False

    def _change_keychain_password(self, host, login_password):
    """Change the keychain password of a machine.

    Changes the keychain password to match the login password.

    Returns True on success, False on failure.
    """

    try:
        child = pexpect.spawn(
            "ssh -ttt default@{} security set-keychain-password"
            " login.keychain".format(host))
        child.expect("Password:")
        child.sendline(login_password)
        child.expect("Old Password: ")
        child.sendline(self.old_password)
        child.expect("New Password: ")
        child.sendline(login_password)
        child.expect("Retype New Password: ")
        child.sendline(login_password)
        child.expect(pexpect.EOF)  # Wait for EOF.
        child.close()

        return not child.exitstatus

    except pexpect.TIMEOUT:
        return False

按照 robertklep 的建议,我也使用了 ssh -t(实际上是 ssh -ttt,所以我很想得到那个 tty)。这两者的结合解决了这个问题,我现在很高兴通过 ssh 更改密码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 2011-10-25
    • 1970-01-01
    • 2019-04-26
    • 2011-10-31
    • 1970-01-01
    • 2013-08-26
    • 2019-08-15
    相关资源
    最近更新 更多