2.5: user: do not pass ssh_key_passphrase on cmdline (#47486)
* user: do not pass ssh_key_passphrase on cmdline * user: do not pass ssh_key_passphrase on cmdline CVE-2018-16837 Co-authored-by: Toshio Kuratomi <a.badger@gmail.com> (cherry picked from commita0aa53d1a1
) * Ignore user module use of subprocess. (cherry picked from commit8d00afc013
) * Fix python3 problem in user module cve fix (cherry picked from commit9088671c4e
) * Fix changelog entry for user module CVE fix (cherry picked from commit210a43ebeb
) (cherry picked from commitb618339c32
) * zap ignore entry
This commit is contained in:
parent
97826dc970
commit
77928e6c3a
3 changed files with 82 additions and 4 deletions
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- user module - do not pass ssh_key_passphrase on cmdline (CVE-2018-16837)
|
|
@ -325,13 +325,16 @@ import errno
|
|||
import grp
|
||||
import os
|
||||
import platform
|
||||
import pty
|
||||
import pwd
|
||||
import select
|
||||
import shutil
|
||||
import socket
|
||||
import subprocess
|
||||
import time
|
||||
import re
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils._text import to_native, to_bytes, to_text
|
||||
from ansible.module_utils.basic import load_platform_subclass, AnsibleModule
|
||||
|
||||
try:
|
||||
|
@ -774,13 +777,58 @@ class User(object):
|
|||
cmd.append(self.ssh_comment)
|
||||
cmd.append('-f')
|
||||
cmd.append(ssh_key_file)
|
||||
cmd.append('-N')
|
||||
if self.ssh_passphrase is not None:
|
||||
cmd.append(self.ssh_passphrase)
|
||||
if self.module.check_mode:
|
||||
self.module.debug('In check mode, would have run: "%s"' % cmd)
|
||||
return (0, '', '')
|
||||
|
||||
master_in_fd, slave_in_fd = pty.openpty()
|
||||
master_out_fd, slave_out_fd = pty.openpty()
|
||||
master_err_fd, slave_err_fd = pty.openpty()
|
||||
env = os.environ.copy()
|
||||
env['LC_ALL'] = 'C'
|
||||
try:
|
||||
p = subprocess.Popen([to_bytes(c) for c in cmd],
|
||||
stdin=slave_in_fd,
|
||||
stdout=slave_out_fd,
|
||||
stderr=slave_err_fd,
|
||||
preexec_fn=os.setsid,
|
||||
env=env)
|
||||
out_buffer = b''
|
||||
err_buffer = b''
|
||||
while p.poll() is None:
|
||||
r, w, e = select.select([master_out_fd, master_err_fd], [], [], 1)
|
||||
first_prompt = b'Enter passphrase (empty for no passphrase):'
|
||||
second_prompt = b'Enter same passphrase again'
|
||||
prompt = first_prompt
|
||||
for fd in r:
|
||||
if fd == master_out_fd:
|
||||
chunk = os.read(master_out_fd, 10240)
|
||||
out_buffer += chunk
|
||||
if prompt in out_buffer:
|
||||
os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
|
||||
prompt = second_prompt
|
||||
else:
|
||||
chunk = os.read(master_err_fd, 10240)
|
||||
err_buffer += chunk
|
||||
if prompt in err_buffer:
|
||||
os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
|
||||
prompt = second_prompt
|
||||
if b'Overwrite (y/n)?' in out_buffer or b'Overwrite (y/n)?' in err_buffer:
|
||||
# The key was created between us checking for existence and now
|
||||
return (None, 'Key already exists', '')
|
||||
|
||||
rc = p.returncode
|
||||
out = to_native(out_buffer)
|
||||
err = to_native(err_buffer)
|
||||
except OSError as e:
|
||||
return (1, '', to_native(e))
|
||||
else:
|
||||
cmd.append('-N')
|
||||
cmd.append('')
|
||||
|
||||
(rc, out, err) = self.execute_command(cmd)
|
||||
(rc, out, err) = self.execute_command(cmd)
|
||||
|
||||
if rc == 0 and not self.module.check_mode:
|
||||
# If the keys were successfully created, we should be able
|
||||
# to tweak ownership.
|
||||
|
|
|
@ -246,3 +246,31 @@
|
|||
- name: Restore original timezone - {{ original_timezone.diff.before.name }}
|
||||
timezone:
|
||||
name: "{{ original_timezone.diff.before.name }}"
|
||||
|
||||
# Test creating ssh key with passphrase
|
||||
- name: Remove ansibulluser
|
||||
user:
|
||||
name: ansibulluser
|
||||
state: absent
|
||||
|
||||
- name: Create user with ssh key
|
||||
user:
|
||||
name: ansibulluser
|
||||
state: present
|
||||
generate_ssh_key: yes
|
||||
ssh_key_file: "{{ output_dir }}/test_id_rsa"
|
||||
ssh_key_passphrase: secret_passphrase
|
||||
|
||||
- name: Unlock ssh key
|
||||
command: "ssh-keygen -y -f {{ output_dir }}/test_id_rsa -P secret_passphrase"
|
||||
register: result
|
||||
|
||||
- name: Check that ssh key was unlocked successfully
|
||||
assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
|
||||
- name: Clean ssh key
|
||||
file:
|
||||
path: "{{ output_dir }}/test_id_rsa"
|
||||
state: absent
|
||||
|
|
Loading…
Reference in a new issue