User - Fix shadow file parsing on AIX (#55230)
Implement a new method for shadow file parsing so it can be subclassed.
This commit is contained in:
parent
d18beee641
commit
f27eccabbd
2 changed files with 60 additions and 7 deletions
2
changelogs/fragments/user-aix-shadow-file-parsing.yaml
Normal file
2
changelogs/fragments/user-aix-shadow-file-parsing.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- user - properly parse the shadow file on AIX (https://github.com/ansible/ansible/issues/54461)
|
|
@ -907,13 +907,19 @@ class User(object):
|
||||||
if not self.user_exists():
|
if not self.user_exists():
|
||||||
return passwd, expires
|
return passwd, expires
|
||||||
elif self.SHADOWFILE:
|
elif self.SHADOWFILE:
|
||||||
# Read shadow file for user's encrypted password string
|
passwd, expires = self.parse_shadow_file()
|
||||||
if os.path.exists(self.SHADOWFILE) and os.access(self.SHADOWFILE, os.R_OK):
|
|
||||||
with open(self.SHADOWFILE, 'r') as f:
|
return passwd, expires
|
||||||
for line in f:
|
|
||||||
if line.startswith('%s:' % self.name):
|
def parse_shadow_file(self):
|
||||||
passwd = line.split(':')[1]
|
passwd = ''
|
||||||
expires = line.split(':')[self.SHADOWFILE_EXPIRE_INDEX] or -1
|
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
|
return passwd, expires
|
||||||
|
|
||||||
def get_ssh_key_path(self):
|
def get_ssh_key_path(self):
|
||||||
|
@ -2326,6 +2332,7 @@ class AIX(User):
|
||||||
- create_user()
|
- create_user()
|
||||||
- remove_user()
|
- remove_user()
|
||||||
- modify_user()
|
- modify_user()
|
||||||
|
- parse_shadow_file()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
platform = 'AIX'
|
platform = 'AIX'
|
||||||
|
@ -2467,6 +2474,50 @@ class AIX(User):
|
||||||
else:
|
else:
|
||||||
return (rc2, out + out2, err + err2)
|
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):
|
class HPUX(User):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue