Fixes to handle non-ascii become passwords
Fixes for non-ascii passwords on
* both python2 and python3,
* local and paramiko_ssh (ssh tested working with these changes)
* sudo and su
Fixes #16557
(cherry picked from commit f24c10c32b
)
This commit is contained in:
parent
3d3ebbf98e
commit
e1101f78bd
3 changed files with 42 additions and 41 deletions
|
@ -31,6 +31,7 @@ import string
|
||||||
from ansible.compat.six import iteritems, string_types
|
from ansible.compat.six import iteritems, string_types
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
|
from ansible.module_utils._text import to_bytes
|
||||||
from ansible.playbook.attribute import FieldAttribute
|
from ansible.playbook.attribute import FieldAttribute
|
||||||
from ansible.playbook.base import Base
|
from ansible.playbook.base import Base
|
||||||
from ansible.utils.boolean import boolean
|
from ansible.utils.boolean import boolean
|
||||||
|
@ -84,38 +85,38 @@ MAGIC_VARIABLE_MAPPING = dict(
|
||||||
module_compression = ('ansible_module_compression',),
|
module_compression = ('ansible_module_compression',),
|
||||||
)
|
)
|
||||||
|
|
||||||
SU_PROMPT_LOCALIZATIONS = [
|
b_SU_PROMPT_LOCALIZATIONS = [
|
||||||
'Password',
|
to_bytes('Password'),
|
||||||
'암호',
|
to_bytes('암호'),
|
||||||
'パスワード',
|
to_bytes('パスワード'),
|
||||||
'Adgangskode',
|
to_bytes('Adgangskode'),
|
||||||
'Contraseña',
|
to_bytes('Contraseña'),
|
||||||
'Contrasenya',
|
to_bytes('Contrasenya'),
|
||||||
'Hasło',
|
to_bytes('Hasło'),
|
||||||
'Heslo',
|
to_bytes('Heslo'),
|
||||||
'Jelszó',
|
to_bytes('Jelszó'),
|
||||||
'Lösenord',
|
to_bytes('Lösenord'),
|
||||||
'Mật khẩu',
|
to_bytes('Mật khẩu'),
|
||||||
'Mot de passe',
|
to_bytes('Mot de passe'),
|
||||||
'Parola',
|
to_bytes('Parola'),
|
||||||
'Parool',
|
to_bytes('Parool'),
|
||||||
'Pasahitza',
|
to_bytes('Pasahitza'),
|
||||||
'Passord',
|
to_bytes('Passord'),
|
||||||
'Passwort',
|
to_bytes('Passwort'),
|
||||||
'Salasana',
|
to_bytes('Salasana'),
|
||||||
'Sandi',
|
to_bytes('Sandi'),
|
||||||
'Senha',
|
to_bytes('Senha'),
|
||||||
'Wachtwoord',
|
to_bytes('Wachtwoord'),
|
||||||
'ססמה',
|
to_bytes('ססמה'),
|
||||||
'Лозинка',
|
to_bytes('Лозинка'),
|
||||||
'Парола',
|
to_bytes('Парола'),
|
||||||
'Пароль',
|
to_bytes('Пароль'),
|
||||||
'गुप्तशब्द',
|
to_bytes('गुप्तशब्द'),
|
||||||
'शब्दकूट',
|
to_bytes('शब्दकूट'),
|
||||||
'సంకేతపదము',
|
to_bytes('సంకేతపదము'),
|
||||||
'හස්පදය',
|
to_bytes('හස්පදය'),
|
||||||
'密码',
|
to_bytes('密码'),
|
||||||
'密碼',
|
to_bytes('密碼'),
|
||||||
]
|
]
|
||||||
|
|
||||||
TASK_ATTRIBUTE_OVERRIDES = (
|
TASK_ATTRIBUTE_OVERRIDES = (
|
||||||
|
@ -515,9 +516,9 @@ class PlayContext(Base):
|
||||||
elif self.become_method == 'su':
|
elif self.become_method == 'su':
|
||||||
|
|
||||||
# passing code ref to examine prompt as simple string comparisson isn't good enough with su
|
# passing code ref to examine prompt as simple string comparisson isn't good enough with su
|
||||||
def detect_su_prompt(data):
|
def detect_su_prompt(b_data):
|
||||||
SU_PROMPT_LOCALIZATIONS_RE = re.compile("|".join(['(\w+\'s )?' + x + ' ?: ?' for x in SU_PROMPT_LOCALIZATIONS]), flags=re.IGNORECASE)
|
b_SU_PROMPT_LOCALIZATIONS_RE = re.compile(b"|".join([b'(\w+\'s )?' + x + b' ?: ?' for x in b_SU_PROMPT_LOCALIZATIONS]), flags=re.IGNORECASE)
|
||||||
return bool(SU_PROMPT_LOCALIZATIONS_RE.match(data))
|
return bool(b_SU_PROMPT_LOCALIZATIONS_RE.match(b_data))
|
||||||
prompt = detect_su_prompt
|
prompt = detect_su_prompt
|
||||||
|
|
||||||
becomecmd = '%s %s %s -c %s' % (exe, flags, self.become_user, pipes.quote(command))
|
becomecmd = '%s %s %s -c %s' % (exe, flags, self.become_user, pipes.quote(command))
|
||||||
|
@ -528,8 +529,8 @@ class PlayContext(Base):
|
||||||
becomecmd = '%s -b %s -u %s %s' % (exe, flags, self.become_user, success_cmd)
|
becomecmd = '%s -b %s -u %s %s' % (exe, flags, self.become_user, success_cmd)
|
||||||
|
|
||||||
elif self.become_method == 'ksu':
|
elif self.become_method == 'ksu':
|
||||||
def detect_ksu_prompt(data):
|
def detect_ksu_prompt(b_data):
|
||||||
return re.match("Kerberos password for .*@.*:", data)
|
return re.match(b"Kerberos password for .*@.*:", b_data)
|
||||||
|
|
||||||
prompt = detect_ksu_prompt
|
prompt = detect_ksu_prompt
|
||||||
becomecmd = '%s %s %s -e %s' % (exe, self.become_user, flags, command)
|
becomecmd = '%s %s %s -e %s' % (exe, self.become_user, flags, command)
|
||||||
|
|
|
@ -90,7 +90,7 @@ class Connection(ConnectionBase):
|
||||||
if self._play_context.prompt and sudoable:
|
if self._play_context.prompt and sudoable:
|
||||||
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||||
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||||
become_output = ''
|
become_output = b''
|
||||||
while not self.check_become_success(become_output) and not self.check_password_prompt(become_output):
|
while not self.check_become_success(become_output) and not self.check_password_prompt(become_output):
|
||||||
|
|
||||||
rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stdout, p.stderr], self._play_context.timeout)
|
rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stdout, p.stderr], self._play_context.timeout)
|
||||||
|
@ -100,10 +100,10 @@ class Connection(ConnectionBase):
|
||||||
chunk = p.stderr.read()
|
chunk = p.stderr.read()
|
||||||
else:
|
else:
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + become_output)
|
raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + to_native(become_output))
|
||||||
if not chunk:
|
if not chunk:
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
raise AnsibleError('privilege output closed while waiting for password prompt:\n' + become_output)
|
raise AnsibleError('privilege output closed while waiting for password prompt:\n' + to_native(become_output))
|
||||||
become_output += chunk
|
become_output += chunk
|
||||||
if not self.check_become_success(become_output):
|
if not self.check_become_success(become_output):
|
||||||
p.stdin.write(to_bytes(self._play_context.become_pass, errors='surrogate_or_strict') + b'\n')
|
p.stdin.write(to_bytes(self._play_context.become_pass, errors='surrogate_or_strict') + b'\n')
|
||||||
|
|
|
@ -310,7 +310,7 @@ class Connection(ConnectionBase):
|
||||||
|
|
||||||
if passprompt:
|
if passprompt:
|
||||||
if self._play_context.become and self._play_context.become_pass:
|
if self._play_context.become and self._play_context.become_pass:
|
||||||
chan.sendall(self._play_context.become_pass + '\n')
|
chan.sendall(to_bytes(self._play_context.become_pass) + b'\n')
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("A password is reqired but none was supplied")
|
raise AnsibleError("A password is reqired but none was supplied")
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in a new issue