Give warning if user inputs not encrypted password to user module (#43615)

* Check the password format

Check the password format and notify user if they
input unencrypted password.

* Fix sanity error

* Add integration test

* Missed a task name

* Hard code the testing password

Since some testing platfrom has no passlib installed

* Add changelog fragment

* Rework some English sentences

* Fix a grammar mistake
This commit is contained in:
Zhikang Zhang 2018-08-13 12:45:37 -04:00 committed by Sam Doran
commit b20d903cc4
3 changed files with 79 additions and 0 deletions

View file

@ -342,6 +342,7 @@ uid:
import errno
import grp
import os
import re
import platform
import pwd
import shutil
@ -358,6 +359,9 @@ except ImportError:
HAVE_SPWD = False
_HASH_RE = re.compile(r'[^a-zA-Z0-9./=]')
class User(object):
"""
This is a generic User manipulation class that is subclassed
@ -429,6 +433,37 @@ class User(object):
else:
self.ssh_file = os.path.join('.ssh', 'id_%s' % self.ssh_type)
def check_password_encrypted(self):
# darwin need cleartext password, so no check
if self.module.params['password'] and self.platform != 'Darwin':
maybe_invalid = False
# : for delimiter, * for disable user, ! for lock user
# these characters are invalid in the password
if any(char in self.module.params['password'] for char in ':*!'):
maybe_invalid = True
if '$' not in self.module.params['password']:
maybe_invalid = True
else:
fields = self.module.params['password'].split("$")
if len(fields) >= 3:
# contains character outside the crypto constraint
if bool(_HASH_RE.search(fields[-1])):
maybe_invalid = True
# md5
if fields[1] == '1' and len(fields[-1]) != 22:
maybe_invalid = True
# sha256
if fields[1] == '5' and len(fields[-1]) != 43:
maybe_invalid = True
# sha512
if fields[1] == '6' and len(fields[-1]) != 86:
maybe_invalid = True
else:
maybe_invalid = True
if maybe_invalid:
self.module.warn("The input password appears not to have been hashed. "
"The 'password' argument must be encrypted for this module to work properly.")
def execute_command(self, cmd, use_unsafe_shell=False, data=None, obey_checkmode=True):
if self.module.check_mode and obey_checkmode:
self.module.debug('In check mode, would have run: "%s"' % cmd)
@ -2392,6 +2427,7 @@ def main():
)
user = User(module)
user.check_password_encrypted()
module.debug('User instantiated - platform %s' % user.platform)
if user.distribution: