Exemplo n.º 1
0
 def checkAccess(self, required):
     if 'level' in required:
         rlevel = self._string_to_level(required['level'])
         if rlevel > self._user_level:
             raise AccessError('%s access is not sufficient, %s access '
                               'is required' %
                               (ACCESS_LEVELS.get(self._user_level,
                                                  str(self._user_level)),
                                ACCESS_LEVELS.get(rlevel, str(rlevel))))
     return Session.checkAccess(self, required)
Exemplo n.º 2
0
def UserPassLevelAuthEntry(val=None):
    """Provide a 3-tuple of user, level and password

        * user: string
        * level: oneof(ACCESS_LEVELS)
           currently: GUEST, USER, ADMIN
        * password: string
    """
    val = list(val)
    if len(val) != 3:
        raise ValueError('UserPassLevelAuthEntry entry needs to be '
                         'a 3-tuple (name, password, accesslevel)')
    if not isinstance(val[0], string_types):
        raise ValueError('user name must be a string')
    val[0] = val[0].strip()
    if not isinstance(val[1], string_types):
        raise ValueError('user password must be a string')
    val[1] = val[1].strip()
    if isinstance(val[2], string_types):
        for i, name in ACCESS_LEVELS.items():
            if name == val[2].strip():
                val[2] = i
                break
        else:
            raise ValueError('access level must be one of %s' % _access_level_list())
    elif not isinstance(val[2], int):
        # for backwards compatibility: allow integer values as well
        raise ValueError('access level must be one of %s' % _access_level_list())
    else:
        if val[2] not in ACCESS_LEVELS:
            raise ValueError('access level must be one of %s' % _access_level_list())
    return tuple(val)
Exemplo n.º 3
0
 def _string_to_level(self, level):
     if isinstance(level, string_types):
         for k, v in ACCESS_LEVELS.items():
             if v == level:
                 return k
         raise ValueError('invalid access level name: %r' % level)
     return level
Exemplo n.º 4
0
 def checkAccess(self, required):
     if 'level' in required:
         script = self.daemon_device.current_script()
         rlevel = required['level']
         if isinstance(rlevel, str):
             for k, v in ACCESS_LEVELS.items():
                 if v == rlevel:
                     rlevel = k
                     break
             else:
                 raise AccessError('invalid access level name: %r' % rlevel)
         if script and rlevel > script.user.level:
             raise AccessError('%s access is not sufficient, %s access '
                               'is required' %
                               (ACCESS_LEVELS.get(script.user.level,
                                                  str(script.user.level)),
                                ACCESS_LEVELS.get(rlevel, str(rlevel))))
     return NoninteractiveSession.checkAccess(self, required)
Exemplo n.º 5
0
class Authenticator(BaseAuthenticator):
    """Authenticates against the configured LDAP server.

    Basically it tries to bind on the server with the given userdn.
    Per default, all ldap users are rejected when there is no user level
    definition inside the 'roles' dictionary.
    """

    BIND_METHODS = {
        'none': ldap3.AUTO_BIND_NONE,
        'no_tls': ldap3.AUTO_BIND_NO_TLS,
        'tls_before_bind': ldap3.AUTO_BIND_TLS_BEFORE_BIND,
        'tls_after_bind': ldap3.AUTO_BIND_TLS_AFTER_BIND,
    }

    parameters = {
        'uri':
        Param('LDAP connection URI', type=str, mandatory=True),
        'bindmethod':
        Param('LDAP port', type=oneof(*BIND_METHODS), default='no_tls'),
        'userbasedn':
        Param('Base dn to query users.', type=str, mandatory=True),
        'userfilter':
        Param('Filter for querying users. Must contain '
              '"%(username)s"',
              type=str,
              default='(&(uid=%(username)s)'
              '(objectClass=posixAccount))'),
        'groupbasedn':
        Param('Base dn to query groups', type=str, mandatory=True),
        'groupfilter':
        Param(
            'Filter for querying groups. '
            'Must contain "%(gidnumber)s"',
            type=str,
            default='(&(gidNumber=%(gidnumber)s)'
            '(objectClass=posixGroup))'),
        'usergroupfilter':
        Param(
            'Filter groups of a specific user. '
            'Must contain "%(username)s"',
            type=str,
            default='(&(memberUid=%(username)s)'
            '(objectClass=posixGroup))'),
        'userroles':
        Param('Dictionary of allowed users with their '
              'associated role',
              type=dictof(str, oneof(*ACCESS_LEVELS.values()))),
        'grouproles':
        Param('Dictionary of allowed groups with their '
              'associated role',
              type=dictof(str, oneof(*ACCESS_LEVELS.values()))),
    }

    def doInit(self, mode):
        self._access_levels = {
            value: key
            for key, value in iteritems(ACCESS_LEVELS)
        }

    def authenticate(self, username, password):
        userdn = self._get_user_dn(username)

        # first of all: try a bind to check user existence and password
        try:
            connection = ldap3.Connection(
                self.uri,
                user=userdn,
                password=password,
                auto_bind=self.BIND_METHODS[self.bindmethod])
        except ldap3.core.exceptions.LDAPException as e:
            raise AuthenticationError('LDAP connection failed (%s)' % e)

        userlevel = -1

        # check if the user has explicit rights
        if username in self.userroles:
            userlevel = self._access_levels[self.userroles[username]]
            return User(username, userlevel)

        # if no explicit user right was given, check group rights
        groups = self._get_user_groups(connection, username)

        for group in groups:
            if group in self.grouproles:
                userlevel = max(userlevel,
                                self._access_levels[self.grouproles[group]])

        if userlevel >= 0:
            return User(username, userlevel)

        raise AuthenticationError('Login not permitted for the given user')

    def _get_user_groups(self, connection, username):
        # start with the users default group
        groups = [self._get_default_group(connection, username)]

        # find additional groups of the user
        filter_str = self.usergroupfilter % {'username': username}
        connection.search(self.groupbasedn,
                          filter_str,
                          ldap3.LEVEL,
                          attributes=ldap3.ALL_ATTRIBUTES)

        for group in connection.response:
            groups.append(group['attributes']['cn'][0])

        return groups

    def _get_default_group(self, connection, username):
        filter_str = self.userfilter % {'username': username}

        if not connection.search(self.userbasedn,
                                 filter_str,
                                 ldap3.LEVEL,
                                 attributes=ldap3.ALL_ATTRIBUTES):
            raise AuthenticationError('User not found in LDAP directory')

        return self._get_group_name(
            connection, connection.response[0]['attributes']['gidNumber'])

    def _get_group_name(self, connection, gid):
        filter_str = self.groupfilter % {'gidnumber': gid}
        if not connection.search(self.groupbasedn,
                                 filter_str,
                                 ldap3.LEVEL,
                                 attributes=ldap3.ALL_ATTRIBUTES):
            raise AuthenticationError('Group %s not found' % gid)
        return connection.response[0]['attributes']['cn'][0]

    def _get_user_dn(self, username):
        return 'uid=%s,%s' % (username, self.userbasedn)
Exemplo n.º 6
0
 def doInit(self, mode):
     self._access_levels = {
         value: key
         for key, value in ACCESS_LEVELS.items()
     }
Exemplo n.º 7
0
def _access_level_list():
    return ', '.join(repr(l) for l in ACCESS_LEVELS.values())