Esempio n. 1
0
    def authenticate(self, req):
        """authenticate user using connection information found in the request,
        and return corresponding a :class:`~cubicweb.dbapi.Connection` instance,
        as well as login used to open the connection.

        raise :exc:`cubicweb.AuthenticationError` if authentication failed
        (no authentication info found or wrong user/password)
        """
        has_auth = False
        for retriever in self.authinforetrievers:
            try:
                login, authinfo = retriever.authentication_information(req)
            except NoAuthInfo:
                continue
            has_auth = True
            try:
                session = self._authenticate(login, authinfo)
            except AuthenticationError:
                retriever.cleanup_authentication_information(req)
                continue  # the next one may succeed
            for retriever_ in self.authinforetrievers:
                retriever_.authenticated(retriever, req, session, login,
                                         authinfo)
            return session, login
        # false if no authentication info found, i.e. this is not an
        # authentication failure
        if has_auth:
            req.set_message(req._('authentication failure'))
        login, authinfo = self.anoninfo
        if login:
            session = self._authenticate(login, authinfo)
            return session, login
        raise AuthenticationError()
Esempio n. 2
0
 def publish(self, rset=None):
     """log in the instance"""
     if self._cw.vreg.config['auth-mode'] == 'http':
         # HTTP authentication
         raise AuthenticationError()
     else:
         # Cookie authentication
         self._cw.status_out = http.client.FORBIDDEN
         return self.appli.need_login_content(self._cw)
Esempio n. 3
0
    def authenticate(self, cnx, login, password=None, **kwargs):
        """return CWUser eid for the given login/password if this account is
        defined in this source, else raise `AuthenticationError`

        two queries are needed since passwords are stored crypted, so we have
        to fetch the salt first
        """
        self.info('ldap authenticate %s', login)
        if not password:
            # On Windows + ADAM this would have succeeded (!!!)
            # You get Authenticated as: 'NT AUTHORITY\ANONYMOUS LOGON'.
            # we really really don't want that
            raise AuthenticationError()
        searchfilter = [
            '(%s=%s)' %
            (replace_filter(self.user_login_attr), replace_filter(login))
        ]
        searchfilter.extend(self.base_filters)
        searchstr = '(&%s)' % ''.join(searchfilter)
        # first search the user
        try:
            user = self._search(cnx, self.user_base_dn, self.user_base_scope,
                                searchstr)[0]
        except IndexError:
            # no such user
            raise AuthenticationError()
        # check password by establishing a (unused) connection
        try:
            self._connect(user, password)
        except ldap3.LDAPException as ex:
            # Something went wrong, most likely bad credentials
            self.info('while trying to authenticate %s: %s', user, ex)
            raise AuthenticationError()
        except Exception:
            self.error('while trying to authenticate %s', user, exc_info=True)
            raise AuthenticationError()
        rset = cnx.execute(
            'Any X,SN WHERE X cwuri %(extid)s, X is CWUser, '
            'X cw_source S, S name SN', {'extid': user['dn']})
        if not rset or rset[0][1] != self.uri:
            # user is not known or has been moved away from this source
            raise AuthenticationError()
        return rset[0][0]
Esempio n. 4
0
 def authenticate_user(self, cnx, login, **authinfo):
     """validate login / password, raise AuthenticationError on failure
     return associated CWUser instance on success
     """
     eid = self.check_auth_info(cnx, login, authinfo)
     cwuser = self._build_user(cnx, eid)
     if self.config.consider_user_state and \
        not cwuser.cw_adapt_to('IWorkflowable').state in cwuser.AUTHENTICABLE_STATES:
         raise AuthenticationError('user is not in authenticable state')
     return cwuser
Esempio n. 5
0
def anonymous_cnx(repo):
    """return a Connection for Anonymous user.

    raises an AuthenticationError if anonymous usage is not allowed
    """
    anoninfo = getattr(repo.config, 'anonymous_user', lambda: None)()
    if anoninfo is None:  # no anonymous user
        raise AuthenticationError('anonymous access is not authorized')
    anon_login, anon_password = anoninfo
    # use vreg's repository cache
    return connect(repo, anon_login, password=anon_password)
Esempio n. 6
0
 def check_auth_info(self, cnx, login, authinfo):
     """validate authentication, raise AuthenticationError on failure, return
     associated CWUser's eid on success.
     """
     # iter on sources_by_uri then check enabled source since sources doesn't
     # contain copy based sources
     for source in self.sources_by_uri.values():
         if self.config.source_enabled(source):
             try:
                 return source.authenticate(cnx, login, **authinfo)
             except (NotImplementedError, AuthenticationError):
                 continue
     else:
         raise AuthenticationError('authentication failed with all sources')
Esempio n. 7
0
 def _connect(self, user=None, userpwd=None):
     protocol, host, port = self.connection_info()
     self.info('connecting %s://%s:%s as %s', protocol, host, port,
               user and user['dn'] or 'anonymous')
     server = ldap3.Server(host, port=int(port))
     conn = ldap3.Connection(
         server,
         user=user and user['dn'],
         client_strategy=ldap3.STRATEGY_SYNC_RESTARTABLE,
         auto_referrals=False)
     # Now bind with the credentials given. Let exceptions propagate out.
     if user is None:
         # XXX always use simple bind for data connection
         if not self.cnx_dn:
             conn.bind()
         else:
             self._authenticate(conn, {'dn': self.cnx_dn}, self.cnx_pwd)
     else:
         # user specified, we want to check user/password, no need to return
         # the connection which will be thrown out
         if not self._authenticate(conn, user, userpwd):
             raise AuthenticationError()
     return conn
Esempio n. 8
0
    def main_handle_request(self, req):
        """Process an HTTP request `req`

        :type req: `web.Request`
        :param req: the request object

        It returns the content of the http response. HTTP header and status are
        set on the Request object.
        """
        if req.authmode == 'http':
            # activate realm-based auth
            realm = self.vreg.config['realm']
            req.set_header('WWW-Authenticate', [('Basic', {
                'realm': realm
            })],
                           raw=False)
        content = b''
        try:
            try:
                session = self.get_session(req)
                cnx = session.new_cnx()
                with cnx:  # may need an open connection to access to e.g. properties
                    req.set_cnx(cnx)
                cnx._open = None  # XXX needed to reuse it a few line later :'(
            except AuthenticationError:
                # Keep the dummy session set at initialisation.  such session will work to some
                # extend but raise an AuthenticationError on any database access.
                # XXX We want to clean up this approach in the future. But several cubes like
                # registration or forgotten password rely on this principle.
                @contextlib.contextmanager
                def dummy():
                    yield

                cnx = dummy()
            # nested try to allow LogOut to delegate logic to AuthenticationError
            # handler
            try:
                # Try to generate the actual request content
                with cnx:
                    content = self.core_handle(req)
            # Handle user log-out
            except LogOut as ex:
                # When authentification is handled by cookie the code that
                # raised LogOut must has invalidated the cookie. We can just
                # reload the original url without authentification
                if self.vreg.config['auth-mode'] == 'cookie' and ex.url:
                    req.headers_out.setHeader('location', str(ex.url))
                if ex.status is not None:
                    req.status_out = http_client.SEE_OTHER
                # When the authentification is handled by http we must
                # explicitly ask for authentification to flush current http
                # authentification information
                else:
                    # Render "logged out" content.
                    # assignement to ``content`` prevent standard
                    # AuthenticationError code to overwrite it.
                    content = self.loggedout_content(req)
                    # let the explicitly reset http credential
                    raise AuthenticationError()
        except Redirect as ex:
            # authentication needs redirection (eg openid)
            content = self.redirect_handler(req, ex)
        # Wrong, absent or Reseted credential
        except AuthenticationError:
            # We assume here that in http auth mode the user *May* provide
            # Authentification Credential if asked kindly.
            if self.vreg.config['auth-mode'] == 'http':
                req.status_out = http_client.UNAUTHORIZED
            # In the other case (coky auth) we assume that there is no way
            # for the user to provide them...
            # XXX But WHY ?
            else:
                req.status_out = http_client.FORBIDDEN
            # If previous error handling already generated a custom content
            # do not overwrite it. This is used by LogOut Except
            # XXX ensure we don't actually serve content
            if not content:
                content = self.need_login_content(req)
        assert isinstance(content, bytes)
        return content
Esempio n. 9
0
 def __getattribute__(self, attr):
     raise AuthenticationError()