Skip to content

Commit 01ff717

Browse files
committed
- single quotes for create .. identified by values
- implemented check for password change for hashes - implemented check for plaintext password against S: pw hash
1 parent f3a07f1 commit 01ff717

File tree

1 file changed

+39
-40
lines changed

1 file changed

+39
-40
lines changed

library/oracle_user

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ oracle_user: hostname=localhost service_name=orcl user=system password=manager s
110110
111111
'''
112112

113+
import hashlib
114+
from binascii import unhexlify
115+
113116
try:
114117
import cx_Oracle
115118
except ImportError:
@@ -160,7 +163,7 @@ def create_user(module, cursor, schema, schema_password, schema_password_hash, d
160163

161164
if authentication_type == 'password':
162165
if (schema_password_hash):
163-
sql = 'create user %s identified by values \"%s\" ' % (schema, schema_password_hash)
166+
sql = 'create user %s identified by values \'%s\' ' % (schema, schema_password_hash)
164167
else:
165168
sql = 'create user %s identified by \"%s\" '% (schema, schema_password)
166169
elif authentication_type == 'global':
@@ -205,7 +208,7 @@ def create_user(module, cursor, schema, schema_password, schema_password_hash, d
205208

206209
# Get the current password hash for the user
207210
def get_user_password_hash(module, cursor, schema):
208-
sql = 'select password from sys.user$ where name = upper(\'%s\')' % schema
211+
sql = 'select spare4 from sys.user$ where name = upper(\'%s\')' % schema
209212
try:
210213
cursor.execute(sql)
211214
pwhashresult = cursor.fetchone()[0]
@@ -216,18 +219,40 @@ def get_user_password_hash(module, cursor, schema):
216219

217220
return pwhashresult
218221

222+
# Check plaintext password against retrieved hash
223+
# currently works with S: hashes only, returns true otherwise
224+
def password_matches_hash(password,password_hash):
225+
# S: style hash
226+
if ('S:' in password_hash):
227+
for ch in password_hash.split('S:')[1][:60].upper():
228+
if((ch < '0' or ch > '9') and (ch < 'A' or ch > 'F')):
229+
return False # not a valid hex string character found, should not happen
230+
hash=password_hash.split('S:')[1][:40]
231+
salt=password_hash.split('S:')[1][40:60]
232+
sha1 = hashlib.sha1()
233+
sha1.update(password.encode('utf-8'))
234+
sha1.update(unhexlify(salt))
235+
return hash.upper() == sha1.hexdigest().upper()
236+
237+
# no supported hashes found
238+
return False
239+
219240
# Modify the user/schema
220241
def modify_user(module, cursor, schema, schema_password, schema_password_hash, default_tablespace, default_temp_tablespace, update_password, profile, authentication_type, state, container_data):
221242

222243
sql_get_curr_def = 'select lower(account_status)'
223244
sql = 'alter user %s' % schema
245+
pw_change_needed = False
224246

225247
if update_password == 'always':
226248
if authentication_type == 'password':
227-
if schema_password_hash:
249+
old_pw_hash = get_user_password_hash(module, cursor, schema)
250+
if (schema_password_hash and (old_pw_hash != schema_password_hash)):
251+
pw_change_needed = True
228252
sql += ' identified by values \'%s\'' % (schema_password_hash)
229-
elif schema_password:
230-
sql += ' identified by %s ' % (schema_password)
253+
elif schema_password and not password_matches_hash(schema_password,old_pw_hash):
254+
pw_change_needed = True
255+
sql += ' identified by \"%s\" ' % (schema_password)
231256
elif authentication_type == 'external':
232257
sql += ' identified externally '
233258
sql_get_curr_def += ' ,lower(authentication_type)'
@@ -283,47 +308,21 @@ def modify_user(module, cursor, schema, schema_password, schema_password_hash, d
283308

284309
sql_get_curr_def += ' from dba_users where username = upper(\'%s\')' % schema
285310

286-
if update_password == 'always':
287-
old_pw_hash = get_user_password_hash(module, cursor, schema)
288-
289311
wanted_list = [x.lower() for x in wanted_list]
290312
curr_defaults = execute_sql_get(module, cursor, sql_get_curr_def)
291313
curr_defaults = [list(t) for t in curr_defaults]
292314

293-
if (schema_password_hash):
294-
if update_password == 'always':
295-
# if (wanted_list in curr_defaults) and (old_pw_hash == schema_password_hash):
296-
# # Everything is kosher, exit changed=False
297-
# module.exit_json(msg='The schema (%s) is in the intented state' % (schema), changed=False)
298-
# else:
299-
# # Make the change and exit changed=True
300-
execute_sql(module, cursor, sql)
301-
module.exit_json(msg='Successfully altered the user (%s)' % (schema), changed=True)
315+
if (wanted_list in curr_defaults):
316+
if (update_password == 'always' and pw_change_needed):
317+
execute_sql(module, cursor, sql)
318+
module.exit_json(msg='Successfully altered the user password (%s)' % (schema), changed=True)
302319
else:
303-
if (wanted_list in curr_defaults):
304-
module.exit_json(msg='The schema (%s) is in the intented state' % (schema), changed=False)
305-
else:
306-
# Make the change and exit changed=Truecontainer = module.params["container"]
307-
execute_sql(module, cursor, sql)
308-
module.exit_json(msg='Successfully altered the user (%s)' % (schema), changed=True)
320+
module.exit_json(msg='The schema (%s) is in the intented state' % (schema), changed=False)
309321
else:
310-
if (wanted_list in curr_defaults):
311-
if update_password == 'always':
312-
## DISABLING THE PRE/POST-CHECK
313-
# change everything and compare hash pre/post. If same => exit change=False else exit change=True
314-
execute_sql(module, cursor, sql)
315-
# new_pw_hash = get_user_password_hash(module, cursor, schema)
316-
# if new_pw_hash == old_pw_hash:
317-
# module.exit_json(msg='The schema (%s) is in the intented state' % (schema), changed=False)
318-
# else:
319-
module.exit_json(msg='Successfully altered the user (%s)' % (schema), changed=True)
320-
else:
321-
module.exit_json(msg='The schema (%s) is in the intented state' % (schema), changed=False)
322-
else:
323-
# do the complete change -> exit with change=True
324-
# module.exit_json(msg=sql)
325-
execute_sql(module, cursor, sql)
326-
module.exit_json(msg='Successfully altered the user (%s, %s)' % (schema, sql), changed=True)
322+
# do the complete change -> exit with change=True
323+
# module.exit_json(msg=sql)
324+
execute_sql(module, cursor, sql)
325+
module.exit_json(msg='Successfully altered the user (%s, %s)' % (schema, sql), changed=True)
327326

328327
return True
329328

0 commit comments

Comments
 (0)