Fix an exception when passlib library is used with a wrapped algo (#75527)

* Test a passlib wrapped algo with a password lookup

* Fix error when passlib is used with a wrapped algo

The exception was:

     An unhandled exception occurred while running the lookup plugin 'password'.
     Error was a <class 'TypeError'>, original message: issubclass() arg 1 must be a class

and can be reproduced using the following command:

    ansible localhost -i localhost, -mdebug -amsg="{{ lookup('password', '/dev/null encrypt=ldap_sha512_crypt') }}"

The concerned algo are: bsd_nthash, django_argon2, django_bcrypt, ldap_bcrypt,
ldap_bsdi_crypt, ldap_des_crypt, ldap_hex_md5, ldap_hex_sha1, ldap_md5_crypt,
ldap_pbkdf2_sha1, ldap_pbkdf2_sha256, ldap_pbkdf2_sha512, ldap_sha1_crypt,
ldap_sha256_crypt, ldap_sha512_crypt, roundup_plaintext
pull/75638/head
Pilou 4 years ago committed by GitHub
parent baa20fba2f
commit 3d7f2a1366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
bugfixes:
- password - Handle passlib wrapped algos bsd_nthash, django_argon2, django_bcrypt, ldap_bcrypt, ldap_bsdi_crypt,
ldap_des_crypt, ldap_hex_md5, ldap_hex_sha1, ldap_md5_crypt, ldap_pbkdf2_sha1, ldap_pbkdf2_sha256,
ldap_pbkdf2_sha512, ldap_sha1_crypt, ldap_sha256_crypt, ldap_sha512_crypt, roundup_plaintext
(https://github.com/ansible/ansible/pull/75527).

@ -23,7 +23,7 @@ HAS_CRYPT = PASSLIB_AVAILABLE = False
try:
import passlib
import passlib.hash
from passlib.utils.handlers import HasRawSalt
from passlib.utils.handlers import HasRawSalt, PrefixWrapper
try:
from passlib.utils.binary import bcrypt64
except ImportError:
@ -194,7 +194,7 @@ class PasslibHash(BaseHash):
def _clean_salt(self, salt):
if not salt:
return None
elif issubclass(self.crypt_algo, HasRawSalt):
elif issubclass(self.crypt_algo.wrapped if isinstance(self.crypt_algo, PrefixWrapper) else self.crypt_algo, HasRawSalt):
ret = to_bytes(salt, encoding='ascii', errors='strict')
else:
ret = to_text(salt, encoding='ascii', errors='strict')

@ -521,3 +521,48 @@ class TestLookupModuleWithPasslib(BaseTestLookupModule):
results = self.password_lookup.run([u'/path/to/somewhere chars=anything encrypt=pbkdf2_sha256'], None)
for result in results:
self.assertEqual(result, u'$pbkdf2-sha256$20000$ODc2NTQzMjE$Uikde0cv0BKaRaAXMrUQB.zvG4GmnjClwjghwIRf2gU')
@pytest.mark.skipif(passlib is None, reason='passlib must be installed to run these tests')
class TestLookupModuleWithPasslibWrappedAlgo(BaseTestLookupModule):
def setUp(self):
super(TestLookupModuleWithPasslibWrappedAlgo, self).setUp()
self.os_path_exists = password.os.path.exists
def tearDown(self):
super(TestLookupModuleWithPasslibWrappedAlgo, self).tearDown()
password.os.path.exists = self.os_path_exists
@patch('ansible.plugins.lookup.password._write_password_file')
def test_encrypt_wrapped_crypt_algo(self, mock_write_file):
password.os.path.exists = self.password_lookup._loader.path_exists
with patch.object(builtins, 'open', mock_open(read_data=self.password_lookup._loader._get_file_contents('/path/to/somewhere')[0])) as m:
results = self.password_lookup.run([u'/path/to/somewhere encrypt=ldap_sha256_crypt'], None)
wrapper = getattr(passlib.hash, 'ldap_sha256_crypt')
self.assertEqual(len(results), 1)
result = results[0]
self.assertIsInstance(result, text_type)
expected_password_length = 76
self.assertEqual(len(result), expected_password_length)
# result should have 5 parts split by '$'
str_parts = result.split('$')
self.assertEqual(len(str_parts), 5)
# verify the string and passlib agree on the number of rounds
self.assertEqual(str_parts[2], "rounds=%s" % wrapper.default_rounds)
# verify it used the right algo type
self.assertEqual(str_parts[0], '{CRYPT}')
# verify it used the right algo type
self.assertTrue(wrapper.verify(self.password_lookup._loader._get_file_contents('/path/to/somewhere')[0], result))
# verify a password with a non default rounds value
# generated with: echo test | mkpasswd -s --rounds 660000 -m sha-256 --salt testansiblepass.
hashpw = '{CRYPT}$5$rounds=660000$testansiblepass.$KlRSdA3iFXoPI.dEwh7AixiXW3EtCkLrlQvlYA2sluD'
self.assertTrue(wrapper.verify('test', hashpw))

Loading…
Cancel
Save