4

私は、コマンドラインを使用するにはあまりにも恐れているユーザーのグループのSSHトンネルを生成および監視するためのGUIプログラムを作成しています。

残念ながら、問題のサーバーは非常に厳格です。RSA SecurIDトークンを介した2要素認証は、SSH接続を開くための唯一の公式に承認された方法です。パスワードなしのRSA公開/秘密鍵認証は許可されていません。

したがって、私のプログラムでは、テキスト入力ボックスからパスワードを読み取り、それを子SSHプロセスに送信する必要があります。残念ながら、sshパスワードが実際のキーボードからのみ取得されるようにするには、かなりの時間がかかります。

サードパーティのモジュールは使用しないことを強くお勧めします。私はparamikoとpexpect(どちらも同様の問題の可能な解決策として提案されています)を知っていますが、ソースからPythonモジュールをインストールする方法をユーザーに説明しようとするのは非常に頭痛の種です。

だから:標準のPythonモジュールのみを使用してsshサブプロセスにパスワードを送信するにはどうすればよいですか?subprocessサブプロセスをだまして、TTYを使用していると思わせる方法はありますか?SSH_ASKPASSを使用してプログラムから読み取ることはできますか?

他の標準ライブラリモジュール(たとえば、モジュールを使用した低レベルのコマンドos)も許可されます。

4

1 に答える 1

5

結局、私はptyモジュールを使用して、疑似端末を介してsshを制御することができました。でソリューションをコーディングしpexpect、pexpectのソースコードを見て、このStackOverflowの回答を参考にして、何をすべきかを理解することができました。関連するコードの抜粋を次に示します(オブジェクトのメソッドの一部として実行されるため、への参照self)。

command = [
        '/usr/bin/ssh',
        '{0}@{1}'.format(username, hostname),
        '-L', '{0}:localhost:{1}'.format(local_port, foreign_port),
        '-o', 'NumberOfPasswordPrompts=1',
        'sleep {0}'.format(SLEEP_TIME),
]

# PID = 0 for child, and the PID of the child for the parent    
self.pid, child_fd = pty.fork()

if not self.pid: # Child process
    # Replace child process with our SSH process
    os.execv(command[0], command)

while True:
    output = os.read(child_fd, 1024).strip()
    lower = output.lower()
    # Write the password
    if lower.endswith('password:'):
        os.write(child_fd, self.password_var.get() + '\n')
        break
    elif 'are you sure you want to continue connecting' in lower:
        # Adding key to known_hosts
        os.write(child_fd, 'yes\n')
    elif 'company privacy warning' in lower:
        pass # This is an understood message
    else:
        tkMessageBox.showerror("SSH Connection Failed",
            "Encountered unrecognized message when spawning "
            "the SSH tunnel: '{0}'".format(output))
        self.disconnect()
于 2012-10-30T23:08:24.933 に答える