Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP authenticator: number_attr - use hash(username_attr) instead #10

Open
stumbaumr opened this issue May 13, 2015 · 4 comments
Open

Comments

@stumbaumr
Copy link

Hi,
instead of using a possibly unused field in LDAP why do you not just use a hash function to generate a unique number from the unique username_attr instead.

This would also save time when creating user accounts.

Thanks
Rainer

@hacst
Copy link
Contributor

hacst commented May 14, 2015

The mumble user ID is a signed 32 bit Integer. The negative space is reserved for unregistered users and 0 is superuser. That leaves you with 2^31-1 numbers minus whatever you exclude for the offset you configure. Imho this is not really enough for collision resistant hashing of usernames in a long living server. With a thousand accounts over the server life-time you are already at p > 10^-4 for a collision.

@IronSavior
Copy link

Are you sure it's 32 bits wide? I was given to believe it was 64. Been working on something like the following:

@lru_cache(maxsize=1000)
def dn_to_uid(dn, max_bits=64, make_hash=hashlib.sha1):
    """
    This function maps LDAP distinguished names to Murmur user IDs. It works by computing a hash of the given DN, taking
    the unsigned integer value of the least significant 8 bytes of the hash, and then mapping that value into the signed
    integer space of the same bit width. SQLite integer columns can hold signed integers up to 8 bytes wide.

    Yeah, there's faster ways to do this, but this implementation is portable--which is desirable when you consider the
    UIDs returned to Murmur are saved in an external database.
    """

    def hash_integer_value():
        h = make_hash()
        h.update(dn)
        return int(h.hexdigest(), 16)

    bitmask = 2 ** max_bits - 1
    return (hash_integer_value() & bitmask) - (bitmask >> 1)

Don't have the thing working yet because I can't get Ice to load the slice file. Complains: ImportError: No module named Ice_SliceChecksumDict_ice even though I'm passing it the correct include directory in Ice.loadSlice("-I/usr/share/Ice/slice {}".format(slice_name)).

@IronSavior
Copy link

Did more testing and found that the UID value must be an unsigned integer less than 31-bits wide. I'm guessing it has to be 31 bits unsigned because the value at a low level is 32 bits signed, but negative UIDs are not valid. Correct DN-to-UID mapping function with decently low risk of collisions:

@lru_cache(maxsize=1000)
def dn_to_uid(dn, max_bits=31, make_hash=hashlib.sha1):
    """
    This function maps LDAP distinguished names to Murmur user IDs. It works by computing a hash of the given DN, taking
    the unsigned integer value of the least significant 31-bits of the hash.
    """

    def hash_integer_value():
        h = make_hash()
        h.update(dn)
        return int(h.hexdigest(), 16)

    bitmask = 2 ** max_bits - 1
    return hash_integer_value() & bitmask

@IronSavior
Copy link

By the way, the authenticator process would sometimes get killed if we returned a value out of range. When that happens, it allows any user to connect unauthenticated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants