Repository: ansible/ansible

Issue:
Jinja filter password_hash does not work correctly
Hi!

I have tried to generate encrypted password hash with password_hash filter. But it gives me wrong results.

Test playbook:

```
- hosts: default
  connection: local
  tasks:
    - debug: msg="Pass {{ 'exampletext' | password_hash('sha512')  }}"
```

I got result:
debug msg="Pass $6FTpWXL4Wvg."

When encrypted string should be something like:
$6$djcPQAXy$EQkcQoFE9LjCJrUfF2mC9adJU.4HLvhx0.I4iSGbSinuhmj/F88l/QYFfcC73qcjOhGKH4UCAjqqiVqbH/jSE/

I have got same kind result with sha1, sha256 filters also.

My Ansible version is 1.9.1, on osx yosemite.

Any help would be appreciate!

Br,
Sami Niemi 



Discussion:
I don't have OS X, but cannot reproduce this on any version of linux or bsd.

this does depend on the underlying python supporting the hash methods, can you try:
`python -c 'import crypt; print crypt.crypt("exampletext", "$6$mysalt$")'`

it seems like crypt in osx  uses 'des' https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/crypt.3.html

using passlib if installed on the machine might be the way to go here

we avoided passlib due to other compatibility issues and it not being universally installed, we might need to do some conditional magic for the OS X case, I would also open a bug with Apple as DES has been outdated for so long even the mention of it being outdated seems outdated.

Thanks for nice answers. I could reproduce problem with a line bcoca gave: 
~% python -c 'import crypt; print crypt.crypt("exampletext", "$6$mysalt$")'
$6FTpWXL4Wvg.

On same time on our Debian production enviroment command gives us a proper result. So we can live with this but sure it would be nice to get it work on OS X. Compared to earlier solutions for password encrypting on Ansible, password_hash filter seems to be very convient way.

Br,
Sami


Resolving patch:
diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py
--- a/lib/ansible/plugins/filter/core.py
+++ b/lib/ansible/plugins/filter/core.py
@@ -42,6 +42,12 @@
 from ansible.utils.hashing import md5s, checksum_s
 from ansible.utils.unicode import unicode_wrap, to_unicode
 
+try:
+    import passlib.hash
+    HAS_PASSLIB = True
+except:
+    HAS_PASSLIB = False
+
 
 UUID_NAMESPACE_ANSIBLE = uuid.UUID('361E6D51-FAEC-444A-9079-341386DA8E2E')
 
@@ -266,8 +272,15 @@ def get_encrypted_password(password, hashtype='sha512', salt=None):
             r = SystemRandom()
             salt = ''.join([r.choice(string.ascii_letters + string.digits) for _ in range(16)])
 
-        saltstring =  "$%s$%s" % (cryptmethod[hashtype],salt)
-        encrypted = crypt.crypt(password,saltstring)
+        if not HAS_PASSLIB:
+            if sys.platform.startswith('darwin'):
+                raise errors.AnsibleFilterError('|password_hash requires the passlib python module to generate password hashes on Mac OS X/Darwin')
+            saltstring =  "$%s$%s" % (cryptmethod[hashtype],salt)
+            encrypted = crypt.crypt(password, saltstring)
+        else:
+            cls = getattr(passlib.hash, '%s_crypt' % hashtype)
+            encrypted = cls.encrypt(password, salt=salt)
+
         return encrypted
 
     return None


Test patch: