def set(self, key, value):
     with self.pool.reserve() as mc:
         try:
             if not mc.set(key, value):
                 raise BackendError()
         except MemcachedError, err:
             raise BackendError(str(err))
    def update_password(self, user_id, new_password, old_password):
        """Change the user password.

        Uses the admin bind or the user bind if the old password is provided.

        Args:
            user_id: user id
            new_password: new password
            old_password: old password of the user (optional)

        Returns:
            True if the change was successful, False otherwise
        """
        user_dn = self._userid2dn(user_id)
        if user_dn is None:
            raise BackendError('Unknown user "%s"' % user_id)

        password_hash = ssha(new_password)

        user = [(ldap.MOD_REPLACE, 'userPassword', [password_hash])]

        try:
            with self._conn(user_dn, old_password) as conn:
                try:
                    res, __ = conn.modify_s(user_dn, user)
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    self.logger.debug('Could not update the password in ldap.')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        self._purge_conn(user_dn, new_password)
        return res == ldap.RES_MODIFY
Beispiel #3
0
    def create_user(self, user_name, password, email):
        """Creates a user. Returns a user object on success."""
        if not self.allow_new_users:
            raise BackendError("Creation of new users is disabled")

        # no unicode
        user_name = user_name.encode('utf8')
        password = password.encode('utf8')
        email = email.encode('utf8')

        #First make sure the username isn't taken. There'll still be a race
        #condition, but it's pretty small
        test_user = User()
        test_user['username'] = user_name
        dn = self._get_dn(test_user)
        if dn is not None:
            return False

        user_id = self._get_next_user_id()
        password_hash = ssha(password)
        key = '%s%s' % (random.randint(0, 9999999), user_name)
        key = sha1(key).hexdigest()

        user = {
            'cn': user_name,
            'sn': user_name,
            'uid': user_name,
            'uidNumber': str(user_id),
            'userPassword': password_hash,
            'primaryNode': 'weave:',
            'accountStatus': '1',
            'account-enabled': 'Yes',
            'mail': email,
            'mail-verified': key,
            'objectClass': ['dataStore', 'inetOrgPerson']
        }

        dn = "uidNumber=%i,%s" % (user_id, self.users_root)

        #need a copy with some of the info for the return value
        userobj = User()
        userobj['username'] = user['uid']
        userobj['userid'] = user['uidNumber']
        userobj['mail'] = email
        userobj['dn'] = dn

        #need to turn the user hash into tuples
        user = user.items()

        with self._conn() as conn:
            try:
                res, __ = conn.add_s(dn, user)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                self.logger.debug('Could not create the user.')
                raise BackendError(str(e))
Beispiel #4
0
    def delete_user(self, user, credentials=None):
        """
        Deletes a user.

        Args:
            user: the user object

        Returns:
            True if the deletion was successful, False otherwise
        """

        if credentials is not None:
            if not self.authenticate_user(user, credentials):
                return False

        dn = self._get_dn(user)
        if dn is None:
            return True

        try:
            with self._conn() as conn:
                try:
                    res, __ = conn.delete_s(dn)
                except ldap.NO_SUCH_OBJECT:
                    return False
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    self.logger.debug('Could not delete the user in ldap')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        self._purge_conn(dn)
        return res == ldap.RES_DELETE
Beispiel #5
0
    def get_user_info(self, user, attrs):
        """Returns user info

        Args:
            user_id: user id

        Returns:
            user object populated with attrs
        """

        need = [attr for attr in attrs if not user.get(attr)]
        if need == []:
            return user

        dn = self._get_dn(user)
        if not dn:
            return user

        scope = ldap.SCOPE_BASE

        with self._conn() as conn:
            try:
                res = conn.search_st(dn,
                                     scope,
                                     attrlist=need,
                                     timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                self.logger.debug('Could not get the user info in ldap.')
                raise BackendError(str(e))
            except ldap.NO_SUCH_OBJECT:
                return user
 def get(self, key):
     with self.pool.reserve() as mc:
         try:
             return mc.get(key)
         except MemcachedError, err:
             # memcache seems down
             raise BackendError(str(err))
Beispiel #7
0
    def _set_reset_code(self, user_id):
        code = self._generate_reset_code()
        key = self._generate_key(user_id)
        if not self._engine.set(key, code, self.expiration):
            raise BackendError()

        return code
    def create_user(self, user_name, password, email):
        """Creates a user. Returns True on success."""
        user_name = str(user_name)  # XXX only ASCII
        user_id = self._get_next_user_id()
        password_hash = ssha(password)
        key = '%s%s' % (random.randint(0, 9999999), user_name)
        key = sha1(key).hexdigest()

        user = {
            'cn': user_name,
            'sn': user_name,
            'uid': user_name,
            'uidNumber': str(user_id),
            'primaryNode': 'weave:',
            'userPassword': password_hash,
            'account-enabled': 'Yes',
            'mail': email,
            'mail-verified': key,
            'objectClass': ['dataStore', 'inetOrgPerson']
        }

        user = user.items()
        dn = "uidNumber=%i,%s" % (user_id, self.users_root)

        with self._conn(self.admin_user, self.admin_password) as conn:
            try:
                res, __ = conn.add_s(dn, user)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                logger.debug('Could not create the user.')
                raise BackendError(str(e))
    def update_email(self, user_id, email, password=None):
        """Change the user e-mail

        Args:
            user_id: user id
            email: new email

        Returns:
            True if the change was successful, False otherwise
        """
        if password is None:
            return False  # we need a password

        user = [(ldap.MOD_REPLACE, 'mail', [email])]
        #not going to change this behavior yet
        #user = [(ldap.MOD_REPLACE, 'mail', [email]),
        #        (ldap.MOD_REPLACE, 'uid', [extract_username(email)])
        #       ]
        user_name = self._get_username(user_id)
        dn = self._get_dn(user_name)

        with self._conn(dn, password) as conn:
            try:
                res, __ = conn.modify_s(dn, user)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                logger.debug('Could not update the email field in ldap.')
                raise BackendError(str(e))
    def delete_user(self, user_id, password=None):
        """Deletes a user

        Args:
            user_id: user id
            password: user password

        Returns:
            True if the deletion was successful, False otherwise
        """
        user_name = self._get_username(user_id)
        dn = self._get_dn(user_name)
        if password is None:
            return False  # we need a password

        try:
            with self._conn(dn, password) as conn:
                try:
                    res, __ = conn.delete_s(dn)
                except ldap.NO_SUCH_OBJECT:
                    return False
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    logger.debug('Could not delete the user in ldap')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        self._purge_conn(dn)
        return res == ldap.RES_DELETE
    def authenticate_user(self, user_name, password, host=None):
        """Authenticates a user given a user_name and password.

        Returns the user id in case of success. Returns None otherwise."""
        if password is None or password == '':
            return None

        dn = self._username2dn(user_name)
        if dn is None:
            # unknown user, we can return immediatly
            return None

        attrs = ['uidNumber']
        if self.check_account_state:
            attrs.append('account-enabled')
        if self.check_node:
            attrs.append('primaryNode')

        try:
            with self._conn(dn, password) as conn:
                user = conn.search_st(dn,
                                      ldap.SCOPE_BASE,
                                      attrlist=attrs,
                                      timeout=self.ldap_timeout)
        except (ldap.NO_SUCH_OBJECT, ldap.INVALID_CREDENTIALS):
            return None
        except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
            self.logger.debug('Could not authenticate the user.')
            raise BackendError(str(e))
 def incr(self, key, size=1):
     size = int(size)
     with self.pool.reserve() as mc:
         try:
             return mc.incr(key, size)
         except NotFound:
             return mc.set(key, size)
         except MemcachedError, err:
             raise BackendError(str(err))
 def delete(self, key):
     with self.pool.reserve() as mc:
         try:
             return mc.delete(key)
         except NotFound:
             return False
         except MemcachedError, err:
             # memcache seems down
             raise BackendError(str(err))
Beispiel #14
0
    def create_user(self, username, password, email):
        """Creates a user. Returns True on success."""
        payload = {'password': password, 'email': email}
        url = self.generate_url(username)
        status, body = self._proxy('PUT', url, payload)
        if status != 200:
            raise BackendError()

        # the result is the username on success
        return body == username
Beispiel #15
0
    def __init__(self, config):
        if _NO_CAPTCHA_LIB:
            raise ImportError('Recaptcha lib is not installed')
        self.use = config.get('use', False)
        self.private_key = config.get('private_key')
        self.public_key = config.get('public_key')
        self.use_ssl = config.get('use_ssl', True)

        if self.use and (self.private_key is None or self.public_key is None):
            logger.error("No key defined for captcha!")
            raise BackendError()
    def update_password(self,
                        user_id,
                        new_password,
                        old_password=None,
                        key=None):
        """Change the user password.

        Uses the admin bind or the user bind if the old password is provided.

        Args:
            user_id: user id
            new_password: new password
            old_password: old password of the user (optional)

        Returns:
            True if the change was successful, False otherwise
        """
        user_name = self._get_username(user_id)
        user_dn = self._get_dn(user_name)

        if old_password is None:
            if key:
                #using a key, therefore we should check it
                if self.verify_reset_code(user_id, key):
                    self.clear_reset_code(user_id)
                else:
                    logger.error("bad key used for update password")
                    return False
            # we will use admin auth
            dn = self.admin_user
            ldap_password = self.admin_password
        else:
            # user auth
            dn = user_dn
            ldap_password = old_password
            # we need a password

        password_hash = ssha(new_password)
        user = [(ldap.MOD_REPLACE, 'userPassword', [password_hash])]

        try:
            with self._conn(dn, ldap_password) as conn:
                try:
                    res, __ = conn.modify_s(user_dn, user)
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    logger.debug('Could not update the password in ldap.')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        self._purge_conn(user_dn, new_password)
        return res == ldap.RES_MODIFY
    def admin_update_password(self, user_id, new_password, key):
        """Change the user password.

        Uses the admin bind or the user bind if the old password is provided.

        Args:
            user_id: user id
            new_password: new password
            key: password reset key

        Returns:
            True if the change was successful, False otherwise
        """
        user_dn = self._userid2dn(user_id)
        if user_dn is None:
            raise BackendError('Unknown user "%s"' % user_id)

        # using a key, therefore we should check it
        if self.verify_reset_code(user_id, key):
            self.clear_reset_code(user_id)
        else:
            self.logger.error("bad key used for update password")
            return False

        password_hash = ssha(new_password)
        user = [(ldap.MOD_REPLACE, 'userPassword', [password_hash])]

        try:
            with self._conn(self.admin_user, self.admin_password) as conn:
                try:
                    res, __ = conn.modify_s(user_dn, user)
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    self.logger.debug('Could not update the password in ldap.')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        self._purge_conn(user_dn, new_password)
        return res == ldap.RES_MODIFY
Beispiel #18
0
    def get_user_node(self, user_id, assign=True):
        if self.single_box:
            return None

        node = super(MozillaAuth, self).get_user_node(user_id, assign=False)
        if node is not None or assign is False:
            return node

        username = self._get_username(user_id)
        url = self.generate_url(username, 'node/weave')
        status, body = self._proxy('GET', url)
        if status != 200:
            raise BackendError()

        return body
 def _get_dn_by_filter(self, filter):
     dn = self.users_root
     scope = ldap.SCOPE_SUBTREE
     with self._conn() as conn:
         try:
             user = conn.search_st(dn,
                                   scope,
                                   filterstr=filter,
                                   attrlist=[],
                                   timeout=self.ldap_timeout)
         except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
             self.logger.debug('Could not get the user info from ldap')
             raise BackendError(str(e))
         except ldap.NO_SUCH_OBJECT:
             return None
    def get_user_node(self, user_id, assign=True):
        if self.single_box:
            return None

        user_name = self._get_username(user_id)
        dn = self._get_dn(user_name)

        # getting the list of primary nodes
        with self._conn() as conn:
            try:
                res = conn.search_st(dn,
                                     ldap.SCOPE_BASE,
                                     attrlist=['primaryNode'],
                                     timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                logger.debug('Could not get the user node in ldap')
                raise BackendError(str(e))
Beispiel #21
0
    def clear_reset_code(self, user_id):
        """Clears the reset code

        Args:
            user_id: user id

        Returns:
            True if the change was successful, False otherwise
        """
        # handled by sreg
        username = self._get_username(user_id)
        status, body = self._proxy(
            'DELETE', self.generate_url(username, 'password_reset_code'))
        if status != 200:
            raise BackendError()

        return body == 0
    def get_user_id(self, user_name):
        """Returns the id for a user name"""
        dn = self.users_root
        scope = ldap.SCOPE_SUBTREE
        filter = '(uid=%s)' % user_name

        with self._conn() as conn:
            try:
                user = conn.search_st(dn,
                                      scope,
                                      filterstr=filter,
                                      attrlist=['uidNumber'],
                                      timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.OTHER), e:
                self.logger.debug('Could not get the user id from ldap.')
                raise BackendError(str(e))
            except ldap.NO_SUCH_OBJECT:
                return None
    def authenticate_user(self, user_name, passwd):
        """Authenticates a user given a user_name and password.

        Returns the user id in case of success. Returns None otherwise."""
        dn = self._get_dn(user_name)
        attrs = ['uidNumber']
        if self.check_account_state:
            attrs.append('account-enabled')

        try:
            with self._conn(dn, passwd) as conn:
                user = conn.search_st(dn,
                                      ldap.SCOPE_BASE,
                                      attrlist=attrs,
                                      timeout=self.ldap_timeout)
        except (ldap.NO_SUCH_OBJECT, ldap.INVALID_CREDENTIALS):
            return None
        except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
            logger.debug('Could not authenticate the user.')
            raise BackendError(str(e))
    def _get_username(self, user_id):
        """Returns the name for a user id"""
        dn = self.users_root
        if dn == 'md5':
            dn = self.users_base_dn
        scope = ldap.SCOPE_SUBTREE
        filter = '(uidNumber=%s)' % user_id

        with self._conn() as conn:
            try:
                user = conn.search_st(dn,
                                      scope,
                                      filterstr=filter,
                                      attrlist=['uid'],
                                      timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                logger.debug('Could not get the user info from ldap')
                raise BackendError(str(e))
            except ldap.NO_SUCH_OBJECT:
                return None
    def _get_dn(self, user_name=None, user_id=None):
        dn = self.users_root

        #if we already have the uid, just build it
        if user_id:
            return "uidNumber=%i,%s" % (user_id, dn)
        scope = ldap.SCOPE_SUBTREE
        filter = '(uid=%s)' % user_name

        with self._conn() as conn:
            try:
                user = conn.search_st(dn,
                                      scope,
                                      filterstr=filter,
                                      attrlist=[],
                                      timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                logger.debug('Could not get the user info from ldap')
                raise BackendError(str(e))
            except ldap.NO_SUCH_OBJECT:
                return None
Beispiel #26
0
    def generate_reset_code(self, user_id, overwrite=True):
        """Sends a reset code by e-mail

        Args:
            user_id: user id
            overwrite: if True, overwrites an existing code

        Returns:
            True if reset code was generated and sent to user, False otherwise
        """
        username = self._get_username(user_id)
        status, body = self._proxy(
            'GET', self.generate_url(username, 'password_reset_code'))
        if status == 200:
            return body == 0

        if status == 400:
            if body == WEAVE_NO_EMAIL_ADRESS:
                raise NoEmailError()

        raise BackendError()
Beispiel #27
0
    def _get_dn(self, user):
        """
        Gets the user's dn from either their id or username

        Args:
            user: user object (may be updated as a side effect)
        Returns:
            user's dn or None if the user cannot be found
        """
        if user.get('dn'):
            return user['dn']

        user_id = user.get('userid')
        if user_id:
            #build it from the user id
            user['dn'] = "uidNumber=%s,%s" % (user_id, self.users_root)
            return user['dn']

        user_name = user.get('username')
        if not user_name:
            #we have nothing to do a search on
            return None

        dn = self.search_root
        scope = ldap.SCOPE_SUBTREE
        filter = '(uid=%s)' % user_name
        attrs = ['uidNumber']

        with self._conn() as conn:
            try:
                res = conn.search_st(dn,
                                     scope,
                                     filterstr=filter,
                                     attrlist=attrs,
                                     timeout=self.ldap_timeout)
            except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                self.logger.debug('Could not get the user info from ldap')
                raise BackendError(str(e))
            except ldap.NO_SUCH_OBJECT:
                return None
Beispiel #28
0
    def update_password(self,
                        user_id,
                        new_password,
                        old_password=None,
                        key=None):
        """Change the user password.

        Uses the admin bind or the user bind if the old password is provided.

        Args:
            user_id: user id
            password: new password
            old_password: old password of the user (optional)
            key: the reset code

        Returns:
            True if the change was successful, False otherwise
        """
        if old_password is not None:
            return super(MozillaAuth,
                         self).update_password(user_id,
                                               new_password,
                                               old_password=old_password)

        if not key:
            logger.error("Calling update password without password or key")
            return False

        payload = {'reset_code': key, 'password': new_password}
        username = self._get_username(user_id)
        url = self.generate_url(username, 'password')
        status, body = self._proxy('POST', url, payload)
        if status == 200:
            return body == 0
        elif status == 400:
            if body == WEAVE_INVALID_RESET_CODE:
                raise InvalidCodeError()

        raise BackendError()
Beispiel #29
0
    def authenticate_user(self, user, credentials, attrs=None):
        """Authenticates a user given a user_name and credentials.

        Returns the user id in case of success. Returns None otherwise.
        """

        username = credentials.get("username")
        if username is None:
            return None
        if user.get("username") is None:
            user["username"] = username
        elif user.get("username") != username:
            return None

        password = credentials.get("password")
        if not password:
            return None

        dn = self._get_dn(user)
        if not dn:
            return None

        if attrs is None:
            attrs = []

        if self.check_account_state and 'account-enabled' not in attrs:
            attrs.append('account-enabled')

        try:
            with self._conn(dn, password) as conn:
                result = conn.search_st(dn,
                                        ldap.SCOPE_BASE,
                                        attrlist=attrs,
                                        timeout=self.ldap_timeout)
        except (ldap.NO_SUCH_OBJECT, ldap.INVALID_CREDENTIALS):
            return None
        except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
            self.logger.debug('Could not authenticate the user.')
            raise BackendError(str(e))
Beispiel #30
0
    def _modify_record(self, user, key, value, ldap_user=None, ldap_pass=None):
        """
        Change a value in the user's account.
        Uses the account passed in with ldap_user and ldap_pass.

        Args:
            user: user object
            key: field in ldap to be changed
            value: value to change the field to
            ldap_user, ldap_pass: bind information (admin or user)

        Returns:
            True if the change was successful, False otherwise
        """
        if ldap_user is not None and ldap_pass is None:
            return False

        dn = self._get_dn(user)
        if dn is None:
            return False

        action = [(ldap.MOD_REPLACE, key, value)]

        try:
            with self._conn(ldap_user, ldap_pass) as conn:
                try:
                    res, __ = conn.modify_s(dn, action)
                except (ldap.TIMEOUT, ldap.SERVER_DOWN, ldap.OTHER), e:
                    self.logger.debug('Could not update the password in ldap.')
                    raise BackendError(str(e))
        except ldap.INVALID_CREDENTIALS:
            return False

        if res != ldap.RES_MODIFY:
            return False

        user[key] = value
        return True