mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
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
This commit is contained in:
parent
10414145b2
commit
1e672a0fec
4 changed files with 20 additions and 6 deletions
|
@ -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):
|
||||||
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 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
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):
|
||||||
|
|
||||||
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):
|
||||||
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:
|
||||||
|
|
|
@ -952,9 +952,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 @@
|
||||||
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):
|
||||||
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):
|
||||||
|
|
Loading…
Reference in a new issue