Python hashlib.md5 and ejabberd
Question: I am using a python script as an external auth option in ejabberd 2.1.6.

I wanted to start encrypting the clear text passwords that come across in the
auth verification, so that they are not being stored in plain text in the
backend database. When I add the following code to my python script and
restart ejabberd, it hangs:

    
    
    import hashlib
    
    clear = "barfoo"
    salt = "foobar"
    hash = hashlib.md5( salt + clear ).hexdigest()
    

Does hashlib require specific priviledges to run?

When I run it as a normal user (ejabberd) it works without issue. When the
python script is run within the external auth of ejabberd it hangs.

I've attempted to have it write out the 'hash' to a file and it never gets
there ... if i run it as the 'ejabberd' user, it writes out to file fine.

I've tried to find information about restrictions for using this library on
ubuntu without any success. Any ideas?

-sd

** 22.02.2011: Here is the full script adapted from <https://git.process-
one.net/ejabberd/mainline/blobs/raw/2.1.x/doc/dev.html#htoc8> :

    
    
    #!/usr/bin/python
    
    import sys
    from struct import *
    
    import hashlib  
    
    def from_ejabberd():
        input_length = sys.stdin.read(2)
        (size,) = unpack('>h', input_length)
        return sys.stdin.read(size).split(':')
    
    def to_ejabberd(bool):
        answer = 0
        if bool:
            answer = 1
        token = pack('>hh', 2, answer)
        sys.stdout.write(token)
        sys.stdout.flush()
    
    def auth(username, server, password):
        clear = "barfoo"
        salt = "foobar"
        hash = hashlib.md5( salt + clear ).hexdigest()
        if (password == hash): return True
        else: return False
    
    def isuser(username, server):
        return True
    
    def setpass(username, server, password):
        return True
    
    while True:
        data = from_ejabberd()
        success = False
        if data[0] == "auth":
            success = auth(data[1], data[2], data[3])
        elif data[0] == "isuser":
            success = isuser(data[1], data[2])
        elif data[0] == "setpass":
            success = setpass(data[1], data[2], data[3])
        to_ejabberd(success)
    


Answer: I looked into the hashlib
[source](http://svn.python.org/view/python/trunk/Modules/_hashopenssl.c?view=markup)
and while it does not seem to require too much, it does import .so files as
modules and one of them hits openssl. It all looks pretty safe but if ejabberd
tries to fence itself against calls to 3rd party code (or if you have SELinux
or something else to that effect running), stuff can conceivably get weird. I
got this in a REPL:

    
    
    >>> import _md5
    >>> _md5.__file__
    '/usr/lib/python2.7/lib-dynload/_md5module.so'
    

Try this on your box and then try putting

    
    
    _md5 = imp.load_dynamic('_md5', '/usr/lib/python2.7/lib-dynload/_md5module.so')
    

Or just

    
    
    import _md5
    

(with the appropriate path updated to yours) in your code before the offending
line and with some trace statement afterwards. Try the same with _hashlib
instead of _md5 (hashlib defaults to _hashlib which wraps openssl, but if it
doesn't load or doesn't have the needed hash it falls back to _md5, _sha
etc.). If it's not the imports that fail/hang then you can try calling
_md5.new(salt + clear) and _hashlib.openssl_md5(salt + clear) and see if it's
one of them.

If it is the import at fault, then possibly a similar problem was tackled
[here](http://stackoverflow.com/questions/4236045/django-apache-mod-wsgi-
hangs-on-importing-a-python-module-from-so-file) I don't know ejabberd, so I
can't relate their solution to your problem, unfortunately.

I do have to say it, though: in all python implementations I know, = instead
of == in a condition would raise a SyntaxError and that's that - the program
would never even enter the main while loop.

