Fixes for su on freebsd

Addresses multiple issues when using su on freebsd including
* su prompt differs between platforms, so turned that check into a
  regex comparison instead of a simple string comparison
* not using '-c' after su causes problems, so added that for all
  platforms
* fixed quoting issues due to multiple uses of '-c' introduced by
  the above fix

Fixes #7503
Fixes #7507
pull/7539/head
James Cammarata 11 years ago
parent 10414145b2
commit 1e672a0fec

@ -31,6 +31,7 @@ import random
import logging
import traceback
import fcntl
import re
import sys
from termios import tcflush, TCIFLUSH
from binascii import hexlify
@ -210,12 +211,17 @@ class Connection(object):
shcmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
elif self.runner.su or su:
shcmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd)
prompt_re = re.compile(prompt)
vvv("EXEC %s" % shcmd, host=self.host)
sudo_output = ''
try:
chan.exec_command(shcmd)
if self.runner.sudo_pass or self.runner.su_pass:
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
while True:
if success_key in sudo_output or \
(self.runner.sudo_pass and sudo_output.endswith(prompt)) or \
(self.runner.su_pass and prompt_re.match(sudo_output)):
break
chunk = chan.recv(bufsize)
if not chunk:
if 'unknown user' in sudo_output:

@ -17,6 +17,7 @@
#
import os
import re
import subprocess
import shlex
import pipes
@ -268,6 +269,7 @@ class Connection(object):
if su and su_user:
sudocmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd)
prompt_re = re.compile(prompt)
ssh_cmd.append(sudocmd)
elif not self.runner.sudo or not sudoable:
prompt = None
@ -308,7 +310,12 @@ class Connection(object):
sudo_output = ''
sudo_errput = ''
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
while True:
if success_key in sudo_output or \
(self.runner.sudo_pass and sudo_output.endswith(prompt)) or \
(self.runner.su_pass and prompt_re.match(sudo_output)):
break
rfd, wfd, efd = select.select([p.stdout, p.stderr], [],
[p.stdout], self.runner.timeout)
if p.stderr in rfd:

@ -952,9 +952,9 @@ def make_su_cmd(su_user, executable, cmd):
"""
# TODO: work on this function
randbits = ''.join(chr(random.randint(ord('a'), ord('z'))) for x in xrange(32))
prompt = 'assword: '
prompt = '[Pp]assword: ?$'
success_key = 'SUDO-SUCCESS-%s' % randbits
sudocmd = '%s %s %s %s -c %s' % (
sudocmd = '%s %s %s -c "%s -c %s"' % (
C.DEFAULT_SU_EXE, C.DEFAULT_SU_FLAGS, su_user, executable or '$SHELL',
pipes.quote('echo %s; %s' % (success_key, cmd))
)

@ -3,6 +3,7 @@
import unittest
import os
import os.path
import re
import tempfile
import yaml
import passlib.hash
@ -511,8 +512,8 @@ class TestUtils(unittest.TestCase):
cmd = ansible.utils.make_su_cmd('root', '/bin/sh', '/bin/ls')
self.assertTrue(isinstance(cmd, tuple))
self.assertEqual(len(cmd), 3)
self.assertTrue(' root /bin/sh' in cmd[0])
self.assertTrue(cmd[1] == 'assword: ')
self.assertTrue(' root -c "/bin/sh' in cmd[0])
self.assertTrue(re.compile(cmd[1]))
self.assertTrue('echo SUDO-SUCCESS-' in cmd[0] and cmd[2].startswith('SUDO-SUCCESS-'))
def test_to_unicode(self):

Loading…
Cancel
Save