Revert "Actually wait for password prompt in remote sudo execution. Totally breaks stderr debugging

and various modules.

This reverts commit 6341a9547f.
pull/271/head
Michael DeHaan 13 years ago
parent f939f3fdaf
commit e16114034c

@ -26,8 +26,6 @@ import re
import shutil import shutil
import subprocess import subprocess
import pipes import pipes
import socket
import random
from ansible import errors from ansible import errors
# prevent paramiko warning noise # prevent paramiko warning noise
@ -39,7 +37,6 @@ with warnings.catch_warnings():
################################################ ################################################
RANDOM_PROMPT_LEN = 32 # 32 random chars in [a-z] gives > 128 bits of entropy
class Connection(object): class Connection(object):
@ -145,53 +142,19 @@ class ParamikoConnection(object):
quoted_command = '"$SHELL" -c ' + pipes.quote(cmd) quoted_command = '"$SHELL" -c ' + pipes.quote(cmd)
chan.exec_command(quoted_command) chan.exec_command(quoted_command)
else: else:
""" # Rather than detect if sudo wants a password this time, -k makes
Sudo strategy: # sudo always ask for a password if one is required. The "--"
# tells sudo that this is the end of sudo options and the command
First, if sudo doesn't need a password, it's easy: just run the # follows. Passing a quoted compound command to sudo (or sudo -s)
command. # directly doesn't work, so we shellquote it with pipes.quote()
# and pass the quoted string to the user's shell.
If we need a password, we want to read everything up to and sudocmd = 'sudo -k -- "$SHELL" -c ' + pipes.quote(cmd)
including the prompt before sending the password. This is so sudo chan.exec_command(sudocmd)
doesn't block sending the prompt, to catch any errors running sudo if self.runner.sudo_pass:
itself, and so sudo's output doesn't gunk up the command's output. while not chan.recv_ready():
Some systems have large login banners and slow networks, so the time.sleep(0.25)
prompt isn't guaranteed to be in the first chunk we read. So, we sudo_output = chan.recv(bufsize) # Pull prompt, catch errors, eat sudo output
have to keep reading until we find the password prompt, or timeout chan.sendall(self.runner.sudo_pass + '\n')
trying.
In order to detect the password prompt, we set it ourselves with
the sudo -p switch. We use a random prompt so that a) it's
exceedingly unlikely anyone's login material contains it and b) you
can't forge it. This can fail if passprompt_override is set in
/etc/sudoers.
Some systems are set to remember your sudo credentials for a set
period across terminals and won't prompt for a password. We use
sudo -k so it always asks for the password every time (if one is
required) to avoid dealing with both cases.
The "--" tells sudo that this is the end of sudo options and the
command follows.
We shell quote the command for safety, and since we can't run a quoted
command directly with sudo (or sudo -s), we actually run the user's
shell and pass the quoted command string to the shell's -c option.
"""
prompt = '[sudo via ansible, key=%s] password: ' % ''.join(chr(random.randint(ord('a'), ord('z'))) for _ in xrange(RANDOM_PROMPT_LEN))
sudocmd = 'sudo -k -p "%s" -- "$SHELL" -c %s' % (prompt, pipes.quote(cmd))
sudo_output = ''
try:
chan.exec_command(sudocmd)
if self.runner.sudo_pass:
while not sudo_output.endswith(prompt):
chunk = chan.recv(bufsize)
if not chunk:
raise errors.AnsibleError('ssh connection closed waiting for sudo password prompt')
sudo_output += chunk
chan.sendall(self.runner.sudo_pass + '\n')
except socket.timeout:
raise errors.AnsibleError('ssh timed out waiting for sudo.\n' + sudo_output)
stdin = chan.makefile('wb', bufsize) stdin = chan.makefile('wb', bufsize)
stdout = chan.makefile('rb', bufsize) stdout = chan.makefile('rb', bufsize)

Loading…
Cancel
Save