Commit 92f16b3d by James Cammarata

Merge pull request #7539 from jimi-c/issue_7503_freebsd_su_fixes

Fixes for su on freebsd
parents b5e91f81 1e672a0f
...@@ -31,6 +31,7 @@ import random ...@@ -31,6 +31,7 @@ import random
import logging import logging
import traceback import traceback
import fcntl import fcntl
import re
import sys import sys
from termios import tcflush, TCIFLUSH from termios import tcflush, TCIFLUSH
from binascii import hexlify from binascii import hexlify
...@@ -210,12 +211,17 @@ class Connection(object): ...@@ -210,12 +211,17 @@ class Connection(object):
shcmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd) shcmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
elif self.runner.su or su: elif self.runner.su or su:
shcmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd) shcmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd)
prompt_re = re.compile(prompt)
vvv("EXEC %s" % shcmd, host=self.host) vvv("EXEC %s" % shcmd, host=self.host)
sudo_output = '' sudo_output = ''
try: try:
chan.exec_command(shcmd) chan.exec_command(shcmd)
if self.runner.sudo_pass or self.runner.su_pass: 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) chunk = chan.recv(bufsize)
if not chunk: if not chunk:
if 'unknown user' in sudo_output: if 'unknown user' in sudo_output:
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
# #
import os import os
import re
import subprocess import subprocess
import shlex import shlex
import pipes import pipes
...@@ -268,6 +269,7 @@ class Connection(object): ...@@ -268,6 +269,7 @@ class Connection(object):
if su and su_user: if su and su_user:
sudocmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd) sudocmd, prompt, success_key = utils.make_su_cmd(su_user, executable, cmd)
prompt_re = re.compile(prompt)
ssh_cmd.append(sudocmd) ssh_cmd.append(sudocmd)
elif not self.runner.sudo or not sudoable: elif not self.runner.sudo or not sudoable:
prompt = None prompt = None
...@@ -308,7 +310,12 @@ class Connection(object): ...@@ -308,7 +310,12 @@ class Connection(object):
sudo_output = '' sudo_output = ''
sudo_errput = '' 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], [], rfd, wfd, efd = select.select([p.stdout, p.stderr], [],
[p.stdout], self.runner.timeout) [p.stdout], self.runner.timeout)
if p.stderr in rfd: if p.stderr in rfd:
......
...@@ -950,9 +950,9 @@ def make_su_cmd(su_user, executable, cmd): ...@@ -950,9 +950,9 @@ def make_su_cmd(su_user, executable, cmd):
""" """
# TODO: work on this function # TODO: work on this function
randbits = ''.join(chr(random.randint(ord('a'), ord('z'))) for x in xrange(32)) 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 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', C.DEFAULT_SU_EXE, C.DEFAULT_SU_FLAGS, su_user, executable or '$SHELL',
pipes.quote('echo %s; %s' % (success_key, cmd)) pipes.quote('echo %s; %s' % (success_key, cmd))
) )
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import unittest import unittest
import os import os
import os.path import os.path
import re
import tempfile import tempfile
import yaml import yaml
import passlib.hash import passlib.hash
...@@ -511,8 +512,8 @@ class TestUtils(unittest.TestCase): ...@@ -511,8 +512,8 @@ class TestUtils(unittest.TestCase):
cmd = ansible.utils.make_su_cmd('root', '/bin/sh', '/bin/ls') cmd = ansible.utils.make_su_cmd('root', '/bin/sh', '/bin/ls')
self.assertTrue(isinstance(cmd, tuple)) self.assertTrue(isinstance(cmd, tuple))
self.assertEqual(len(cmd), 3) self.assertEqual(len(cmd), 3)
self.assertTrue(' root /bin/sh' in cmd[0]) self.assertTrue(' root -c "/bin/sh' in cmd[0])
self.assertTrue(cmd[1] == 'assword: ') self.assertTrue(re.compile(cmd[1]))
self.assertTrue('echo SUDO-SUCCESS-' in cmd[0] and cmd[2].startswith('SUDO-SUCCESS-')) self.assertTrue('echo SUDO-SUCCESS-' in cmd[0] and cmd[2].startswith('SUDO-SUCCESS-'))
def test_to_unicode(self): def test_to_unicode(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment