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 commit a0aa53d1a1)

* Ignore user module use of subprocess.

(cherry picked from commit 8d00afc013)

* Fix python3 problem in user module cve fix

(cherry picked from commit 9088671c4e)

* Fix changelog entry for user module CVE fix

(cherry picked from commit 210a43ebeb)
(cherry picked from commit b618339c32)

* zap ignore entry
This commit is contained in:
Martin Krizek 2018-10-24 20:04:14 +02:00 committed by Matt Davis
parent 97826dc970
commit 77928e6c3a
3 changed files with 82 additions and 4 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- user module - do not pass ssh_key_passphrase on cmdline (CVE-2018-16837)

View file

@ -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.

View file

@ -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