2

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)
sdolgy
  • 6,963
  • 3
  • 41
  • 61
  • 4
    One issue is the script pasted above contains a typo: should be `if (password == hash): return True`, since assignment is not allowed within a conditional. – samplebias Apr 22 '11 at 15:05
  • if i've been waiting 3 months because of a missing = i'll go mental. will check it out ... ! – sdolgy Apr 22 '11 at 15:13
  • 3
    that whole condition could be written `return password == hash` – SpliFF Apr 28 '11 at 00:38

4 Answers4

1

I looked into the hashlib source 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 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.

Community
  • 1
  • 1
t.dubrownik
  • 12,464
  • 1
  • 17
  • 6
1

I have been messing with the same problem. I Can't really track down the problem with openssl binings in _hashlib. Whatever the problem is, i will have to patch python distribution sources. Not really an feasible solution. So i ended up using a pycrypto wrapper for the crypto functions which don't block in this case.

pip install pycrypto
from Crypto.Hash import MD5
m = MD5.new()
m.update("%s%s" % (salt ,clear))
h.hexdigest()
optixx
  • 2,110
  • 3
  • 16
  • 16
0

hashlib does not require anything special. What means hangs? Where does it hang? Use pdb.set_trace() to step trough the code or use 'strace' or 'ltrace' to investigate API calls.

  • Thanks Andreas. I'll take a look into pdb.set_trace() .. Maybe it can output everything into a file to give me more hints. – sdolgy Feb 22 '11 at 09:08
  • after reading about pdb more, i realize this wont help. when i run the python script as a user, it has no issues. it's only when it's run from ejabberd does this problem happen. – sdolgy Feb 22 '11 at 09:33
  • It's more likely that your read statements are hanging as a result of the ejabberd output not being formatted as nicely as you'd like. I'd suggest non-blocking IO. – Clarus Apr 28 '11 at 22:36
-1

Try to use logging module, it can help you to watch input and output data, also check scripts permissions, let executing by user which is ejabberd, or for debug just set chmod 777 external.py.

Anatolij
  • 597
  • 3
  • 11
  • so although this is a nice bit of feedback, it's not all that helpful in determinig the root cause of the issues. i suspect the issue IS because of a = instead of a == – sdolgy Apr 28 '11 at 13:49