summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSam Doran <sdoran@redhat.com>2019-04-22 15:24:10 -0400
committerToshio Kuratomi <a.badger@gmail.com>2019-04-24 14:45:52 -0600
commit76f6d21ff3e7bb5118cb078b6924905ce012e9e6 (patch)
treeb72682451b3e9013645d71a10d15a2a239010381 /lib
parent0cfbc1feb888e99d62ea5655f19bdeced39ee3d4 (diff)
downloadansible-76f6d21ff3e7bb5118cb078b6924905ce012e9e6.tar.gz
[stable-2.8] User - Fix shadow file parsing on AIX (#55230)
Implement a new method for shadow file parsing so it can be subclassed. (cherry picked from commit f27eccabbd) Co-authored-by: Sam Doran <sdoran@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/ansible/modules/system/user.py65
1 files changed, 58 insertions, 7 deletions
diff --git a/lib/ansible/modules/system/user.py b/lib/ansible/modules/system/user.py
index 31757389a0..cc1ab81190 100644
--- a/lib/ansible/modules/system/user.py
+++ b/lib/ansible/modules/system/user.py
@@ -907,13 +907,19 @@ class User(object):
if not self.user_exists():
return passwd, expires
elif self.SHADOWFILE:
- # Read shadow file for user's encrypted password string
- if os.path.exists(self.SHADOWFILE) and os.access(self.SHADOWFILE, os.R_OK):
- with open(self.SHADOWFILE, 'r') as f:
- for line in f:
- if line.startswith('%s:' % self.name):
- passwd = line.split(':')[1]
- expires = line.split(':')[self.SHADOWFILE_EXPIRE_INDEX] or -1
+ passwd, expires = self.parse_shadow_file()
+
+ return passwd, expires
+
+ def parse_shadow_file(self):
+ passwd = ''
+ expires = ''
+ if os.path.exists(self.SHADOWFILE) and os.access(self.SHADOWFILE, os.R_OK):
+ with open(self.SHADOWFILE, 'r') as f:
+ for line in f:
+ if line.startswith('%s:' % self.name):
+ passwd = line.split(':')[1]
+ expires = line.split(':')[self.SHADOWFILE_EXPIRE_INDEX] or -1
return passwd, expires
def get_ssh_key_path(self):
@@ -2326,6 +2332,7 @@ class AIX(User):
- create_user()
- remove_user()
- modify_user()
+ - parse_shadow_file()
"""
platform = 'AIX'
@@ -2467,6 +2474,50 @@ class AIX(User):
else:
return (rc2, out + out2, err + err2)
+ def parse_shadow_file(self):
+ """Example AIX shadowfile data:
+ nobody:
+ password = *
+
+ operator1:
+ password = {ssha512}06$xxxxxxxxxxxx....
+ lastupdate = 1549558094
+
+ test1:
+ password = *
+ lastupdate = 1553695126
+
+ """
+
+ b_name = to_bytes(self.name)
+ if os.path.exists(self.SHADOWFILE) and os.access(self.SHADOWFILE, os.R_OK):
+ with open(self.SHADOWFILE, 'rb') as bf:
+ b_lines = bf.readlines()
+
+ b_passwd_line = b''
+ b_expires_line = b''
+ for index, b_line in enumerate(b_lines):
+ # Get password and lastupdate lines which come after the username
+ if b_line.startswith(b'%s:' % b_name):
+ b_passwd_line = b_lines[index + 1]
+ b_expires_line = b_lines[index + 2]
+ break
+
+ # Sanity check the lines because sometimes both are not present
+ if b' = ' in b_passwd_line:
+ b_passwd = b_passwd_line.split(b' = ', 1)[-1].strip()
+ else:
+ b_passwd = b''
+
+ if b' = ' in b_expires_line:
+ b_expires = b_expires_line.split(b' = ', 1)[-1].strip()
+ else:
+ b_expires = b''
+
+ passwd = to_native(b_passwd)
+ expires = to_native(b_expires) or -1
+ return passwd, expires
+
class HPUX(User):
"""