예제 #1
0
    def login(self, request, user_obj, **kw):
        _ = request.getText

        logging.debug("got: user_obj=%r" % user_obj)

        if not (user_obj and user_obj.valid):
            # No other method succeeded, so we cannot authorize
            # but maybe some following auth methods can still "fix" that.
            logging.debug("did not get valid user from previous auth method")
            return ContinueLogin(user_obj)

        # Got a valid user object - we can do stuff!
        logging.debug("got valid user (name=%r) from previous auth method" % user_obj.auth_username)

        # XXX Check auth_username for dodgy chars (should be none as it is authenticated, but...)
        # shouldn't really be necessary since execute() quotes them all...

        # OK, now check mysql!
        try:
            m = MySQLdb.connect(host=self.host, user=self.user,
                                passwd=self.passwd, db=self.dbname)
        except:
            logging.exception("authorization failed due to exception when connecting to DB, traceback follows...")
            return CancelLogin(_('Failed to connect to database.'))

        c = m.cursor()
        c.execute(self.mysql_group_query, user_obj.auth_username)
        results = c.fetchall()
        if results:
            # Checked out OK
            logging.debug("got %d results -- authorized!" % len(results))
            return ContinueLogin(user_obj)
        else:
            logging.debug("did not get match from DB -- not authorized")
            return CancelLogin(_("Invalid username or password."))
예제 #2
0
    def login(self, userobj, **kw):
        """
        Handles an login request and continues to multistage continuation
        if necessary.
        """
        continuation = kw.get('multistage')
        # process another subsequent step
        if continuation:
            return self._handleContinuation()

        openid = kw.get('openid')
        # no openid entered
        if not openid:
            return ContinueLogin(userobj)

        # we make a consumer object with an in-memory storage
        oid_consumer = consumer.Consumer(session, self.store)

        # we catch any possible openid-related exceptions
        try:
            oid_response = oid_consumer.begin(openid)
        except HTTPFetchingError:
            return ContinueLogin(None, _('Failed to resolve OpenID.'))
        except DiscoveryFailure:
            return ContinueLogin(
                None, _('OpenID discovery failure, not a valid OpenID.'))
        else:
            # we got no response from the service
            if oid_response is None:
                return ContinueLogin(None, _('No OpenID service at this URL.'))

            # site root and where to return after the redirect
            site_root = url_for('frontend.show_root', _external=True)
            return_to = get_multistage_continuation_url(
                self.name, {'oidstage': '1'})

            # should we redirect the user?
            if oid_response.shouldSendRedirect():
                redirect_url = oid_response.redirectURL(site_root, return_to)
                return MultistageRedirectLogin(redirect_url)
            else:
                # send a form
                form_html = oid_response.htmlMarkup(
                    site_root,
                    return_to,
                    form_tag_attrs={'id': 'openid_message'})

                # returns a MultistageFormLogin
                return MultistageFormLogin(form_html)
예제 #3
0
    def _handle_name_continuation(self, request):
        _ = request.getText
        logging.debug('openid %s' % request.session)
        logging.debug('openid %s' % request.form.get('openid_identifier'))

        if not 'openid.id' in request.session:
            return CancelLogin(_('No OpenID found in session.'))

        newname = request.form.get('username', '')
        if not newname:
            return MultistageFormLogin(self._get_account_name)
        if not user.isValidName(request, newname):
            return MultistageFormLogin(self._get_account_name_inval_user)
        uid = None
        if newname:
            uid = user.getUserId(request, newname)
        if not uid:
            # we can create a new user with this name :)
            u = user.User(request,
                          auth_method=self.name,
                          auth_username=request.session['openid.id'],
                          auth_attribs=self.auth_attribs)
            u.name = newname
            u = self._handle_user_data(request, u)
            return ContinueLogin(u)
        # requested username already exists. if they know the password,
        # they can associate that account with the openid.
        assoc = lambda req, form: self._associate_account(req, form, newname)
        return MultistageFormLogin(assoc)
예제 #4
0
    def login(self, request, user_obj, **kw):
        if kw.get('multistage'):
            uid = request.session.get('botbouncer.uid', None)
            if not uid:
                return CancelLogin(None)
            openid = request.session['botbouncer.id']
            del request.session['botbouncer.id']
            del request.session['botbouncer.uid']
            user_obj = user.User(request,
                                 uid,
                                 auth_method='openid',
                                 auth_username=openid)

        if not user_obj or not user_obj.valid:
            return ContinueLogin(user_obj)

        if user_obj.auth_method != 'openid':
            return ContinueLogin(user_obj)

        openid_id = user_obj.auth_username

        _ = request.getText

        try:
            url = "http://botbouncer.com/api/info?openid=%s&api_key=%s" % (
                quote_plus(openid_id), self.apikey)
            data = urlopen(url).read().strip()
        except IOError:
            return CancelLogin(_('Could not contact botbouncer.com.'))

        data = data.split(':')
        if len(data) != 2 or data[0] != 'verified':
            return CancelLogin(
                'botbouncer.com verification failed, probably invalid API key.'
            )

        if data[1].lower() == 'true':
            # they proved they are human already
            return ContinueLogin(user_obj)

        # tell them to verify at bot bouncer first
        request.session['botbouncer.id'] = openid_id
        request.session['botbouncer.uid'] = user_obj.id

        goto = "http://botbouncer.com/captcha/queryuser?return_to=%%return_form&openid=%s" % (
            quote_plus(request.session['botbouncer.id']))
        return MultistageRedirectLogin(goto)
예제 #5
0
    def login(self, request, user_obj, **kw):

        open_id = kw.get('openid_identifier')
        oidstage = request.form.get('oidstage')

        logging.info('stage %s' % oidstage)
        logging.info('params: %s' % kw)
        if open_id or oidstage:
            return self._handle_continuation(request)
        else:
            return ContinueLogin(user_obj)
예제 #6
0
    def _handle_verify_continuation(self, request):
        _ = request.getText
        oidconsumer = consumer.Consumer(request.session,
                                        MoinOpenIDStore(request))
        query = {}
        for key in request.values.keys():
            query[key] = request.values.get(key)
        current_url = get_multistage_continuation_url(request, self.name,
                                                      {'oidstage': '1'})
        info = oidconsumer.complete(query, current_url)
        if info.status == consumer.FAILURE:
            logging.debug(_("OpenID error: %s.") % info.message)
            return CancelLogin(_('OpenID error: %s.') % info.message)
        elif info.status == consumer.CANCEL:
            logging.debug(_("OpenID verification canceled."))
            return CancelLogin(_('Verification canceled.'))
        elif info.status == consumer.SUCCESS:
            logging.debug(_("OpenID success. id: %s") % info.identity_url)
            request.session['openid.id'] = info.identity_url
            request.session['openid.info'] = info

            # try to find user object
            uid = user.getUserIdByOpenId(request, info.identity_url)
            if uid:
                u = user.User(request,
                              id=uid,
                              auth_method=self.name,
                              auth_username=info.identity_url,
                              auth_attribs=self.auth_attribs)
            else:
                u = None

            # create or update the user according to the registration data
            u = self._handle_user_data(request, u)
            if u:
                return ContinueLogin(u)

            # if no user found, then we need to ask for a username,
            # possibly associating an existing account.
            logging.debug("OpenID: No user found, prompting for username")
            #request.session['openid.id'] = info.identity_url
            return MultistageFormLogin(self._get_account_name)
        else:
            logging.debug(_("OpenID failure"))
            return CancelLogin(_('OpenID failure.'))
예제 #7
0
    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')

        if not username or not password:
            return ContinueLogin(user_obj)

        logging.debug("trying to authenticate %r" % username)
        wikiname, username = username.split(' ', 1) # XXX Hack because ':' is not allowed in name field
        wikitag, wikiurl, name, err = wikiutil.resolve_interwiki(request, wikiname, username)

        logging.debug("resolve wiki returned: %r %r %r %r" % (wikitag, wikiurl, name, err))
        if err or wikitag not in self.trusted_wikis:
            return ContinueLogin(user_obj)

        homewiki = xmlrpclib.ServerProxy(wikiurl + "?action=xmlrpc2")
        auth_token = homewiki.getAuthToken(name, password)
        if not auth_token:
            logging.debug("%r wiki did not return an auth token." % wikitag)
            return ContinueLogin(user_obj)

        logging.debug("successfully got an auth token for %r. trying to get user profile data..." % name)

        mc = xmlrpclib.MultiCall(homewiki)
        mc.applyAuthToken(auth_token)
        mc.getUserProfile()
        result, account_data = mc()

        if result != "SUCCESS":
            logging.debug("%r wiki did not accept auth token." % wikitag)
            return ContinueLogin(None)

        if not account_data:
            logging.debug("%r wiki did not return a user profile." % wikitag)
            return ContinueLogin(None)

        logging.debug("%r wiki returned a user profile." % wikitag)

        # TODO: check remote auth_attribs
        u = user.User(request, name=name, auth_method=self.name, auth_attribs=('name', 'aliasname', 'password', 'email', ))
        for key, value in account_data.iteritems():
            if key not in request.cfg.user_transient_fields:
                setattr(u, key, value)
        u.valid = True
        if self.autocreate:
            u.create_or_update(True)
        logging.debug("successful interwiki auth for %r" % name)
        return ContinueLogin(u)
예제 #8
0
    def _handle_verify_continuation(self, request):
        _ = request.getText
        info = {}  #Response()
        #info.status = 'success'
        openid = request.form.get('openid_identifier')

        if openid:
            logging.debug(_("OpenID success. id: %s") % openid)
            request.session['openid.id'] = openid
            request.session['openid.info'] = info

            # try to find user object
            uid = user.getUserIdByOpenId(request, openid)
            logging.debug('openid %s' % request.session['openid.id'])
            logging.debug('uid %s' % uid)
            if uid:
                u = user.User(request,
                              id=uid,
                              auth_method=self.name,
                              auth_username=openid,
                              auth_attribs=self.auth_attribs)
            else:
                u = None

            # create or update the user according to the registration data
            u = self._handle_user_data(request, u)
            if u:
                return ContinueLogin(u)

            # if no user found, then we need to ask for a username,
            # possibly associating an existing account.
            logging.debug("OpenID: No user found, prompting for username")
            #request.session['openid.id'] = info.identity_url
            return MultistageFormLogin(self._get_account_name)
        else:
            logging.debug(_("OpenID failure"))
            return CancelLogin(_('Unable to get OpenID.'))
예제 #9
0
    def _handle_associate_continuation(self, request):
        if not 'openid.id' in request.session:
            return CancelLogin(_('No OpenID found in session.'))

        _ = request.getText
        username = request.form.get('username', '')
        password = request.form.get('password', '')
        if not password:
            return self._handle_name_continuation(request)
        u = user.User(request,
                      name=username,
                      password=password,
                      auth_method=self.name,
                      auth_username=request.session['openid.id'],
                      auth_attribs=self.auth_attribs)
        if u.valid:
            self._handle_user_data(request, u)
            return ContinueLogin(
                u, _('Your account is now associated to your OpenID.'))
        else:
            msg = _('The password you entered is not valid.')
            assoc = lambda req, form: self._associate_account(
                req, form, username, msg=msg)
            return MultistageFormLogin(assoc)
예제 #10
0
    def login(self, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')

        # we require non-empty password as ldap bind does a anon (not password
        # protected) bind if the password is empty and SUCCEEDS!
        if not password:
            return ContinueLogin(user_obj, _('Missing password. Please enter user name and password.'))

        try:
            try:
                u = None
                dn = None
                server = self.server_uri
                coding = self.coding
                logging.debug("Setting misc. ldap options...")
                ldap.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)  # ldap v2 is outdated
                ldap.set_option(ldap.OPT_REFERRALS, self.referrals)
                ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)

                if hasattr(ldap, 'TLS_AVAIL') and ldap.TLS_AVAIL:
                    for option, value in (
                        (ldap.OPT_X_TLS_CACERTDIR, self.tls_cacertdir),
                        (ldap.OPT_X_TLS_CACERTFILE, self.tls_cacertfile),
                        (ldap.OPT_X_TLS_CERTFILE, self.tls_certfile),
                        (ldap.OPT_X_TLS_KEYFILE, self.tls_keyfile),
                        (ldap.OPT_X_TLS_REQUIRE_CERT, self.tls_require_cert),
                        (ldap.OPT_X_TLS, self.start_tls),
                        # (ldap.OPT_X_TLS_ALLOW, 1),
                    ):
                        if value is not None:
                            ldap.set_option(option, value)

                logging.debug("Trying to initialize {0!r}.".format(server))
                l = ldap.initialize(server)
                logging.debug("Connected to LDAP server {0!r}.".format(server))

                if self.start_tls and server.startswith('ldap:'):
                    logging.debug("Trying to start TLS to {0!r}.".format(server))
                    try:
                        l.start_tls_s()
                        logging.debug("Using TLS to {0!r}.".format(server))
                    except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR) as err:
                        logging.warning("Couldn't establish TLS to {0!r} (err: {1!s}).".format(server, err))
                        raise

                # you can use %(username)s and %(password)s here to get the stuff entered in the form:
                binddn = self.bind_dn % locals()
                bindpw = self.bind_pw % locals()
                l.simple_bind_s(binddn.encode(coding), bindpw.encode(coding))
                logging.debug("Bound with binddn {0!r}".format(binddn))

                # you can use %(username)s here to get the stuff entered in the form:
                filterstr = self.search_filter % locals()
                logging.debug("Searching {0!r}".format(filterstr))
                attrs = [getattr(self, attr) for attr in [
                    'email_attribute',
                    'displayname_attribute',
                    'surname_attribute',
                    'givenname_attribute',
                ] if getattr(self, attr) is not None]
                lusers = l.search_st(self.base_dn, self.scope, filterstr.encode(coding),
                                     attrlist=attrs, timeout=self.timeout)
                # we remove entries with dn == None to get the real result list:
                lusers = [(dn, ldap_dict) for dn, ldap_dict in lusers if dn is not None]
                for dn, ldap_dict in lusers:
                    logging.debug("dn:{0!r}".format(dn))
                    for key, val in ldap_dict.items():
                        logging.debug("    {0!r}: {1!r}".format(key, val))

                result_length = len(lusers)
                if result_length != 1:
                    if result_length > 1:
                        logging.warning("Search found more than one ({0}) matches for {1!r}.".format(
                            result_length, filterstr))
                    if result_length == 0:
                        logging.debug("Search found no matches for {0!r}.".format(filterstr, ))
                    if self.report_invalid_credentials:
                        return ContinueLogin(user_obj, _("Invalid username or password."))
                    else:
                        return ContinueLogin(user_obj)

                dn, ldap_dict = lusers[0]
                if not self.bind_once:
                    logging.debug("DN found is {0!r}, trying to bind with pw".format(dn))
                    l.simple_bind_s(dn, password.encode(coding))
                    logging.debug("Bound with dn {0!r} (username: {1!r})".format(dn, username))

                if self.email_callback is None:
                    if self.email_attribute:
                        email = ldap_dict.get(self.email_attribute, [''])[0].decode(coding)
                    else:
                        email = None
                else:
                    email = self.email_callback(ldap_dict)

                display_name = ''
                try:
                    display_name = ldap_dict[self.displayname_attribute][0]
                except (KeyError, IndexError):
                    pass
                if not display_name:
                    sn = ldap_dict.get(self.surname_attribute, [''])[0]
                    gn = ldap_dict.get(self.givenname_attribute, [''])[0]
                    if sn and gn:
                        display_name = "{0}, {1}".format(sn, gn)
                    elif sn:
                        display_name = sn
                display_name = display_name.decode(coding)

                if self.name_callback:
                    username = self.name_callback(ldap_dict)

                if email:
                    u = user.User(auth_username=username, auth_method=self.name,
                                  auth_attribs=('name', 'password', 'email', 'mailto_author', ),
                                  trusted=self.trusted)
                    u.email = email
                else:
                    u = user.User(auth_username=username, auth_method=self.name,
                                  auth_attribs=('name', 'password', 'mailto_author', ),
                                  trusted=self.trusted)
                u.name = username
                u.display_name = display_name
                logging.debug("creating user object with name {0!r} email {1!r} display name {2!r}".format(
                    username, email, display_name))

            except ldap.INVALID_CREDENTIALS as err:
                logging.debug("invalid credentials (wrong password?) for dn {0!r} (username: {1!r})".format(
                    dn, username))
                return CancelLogin(_("Invalid username or password."))

            if u and self.autocreate:
                logging.debug("calling create_or_update to autocreate user {0!r}".format(u.name))
                u.create_or_update(True)
            return ContinueLogin(u)

        except ldap.SERVER_DOWN as err:
            # looks like this LDAP server isn't working, so we just try the next
            # authenticator object in cfg.auth list (there could be some second
            # ldap authenticator that queries a backup server or any other auth
            # method).
            logging.error("LDAP server {0} failed ({1!s}). "
                          "Trying to authenticate with next auth list entry.".format(server, err))
            return ContinueLogin(user_obj, _("LDAP server %(server)s failed.", server=server))

        except:
            logging.exception("caught an exception, traceback follows...")
            return ContinueLogin(user_obj)
예제 #11
0
 def login(self, request, user_obj, **kw):
     username = kw.get('username')
     password = kw.get('password')
     if user_obj and user_obj.valid:
         self.do_smb(request, username, password, True)
     return ContinueLogin(user_obj)
예제 #12
0
class LDAPAuth(BaseAuth):
    """ get authentication data from form, authenticate against LDAP (or Active
        Directory), fetch some user infos from LDAP and create a user object
        for that user. The session is kept by moin automatically.
    """

    login_inputs = ['username', 'password']
    logout_possible = True
    name = 'ldap'

    def __init__(
        self,
        server_uri='ldap://localhost',  # ldap / active directory server URI
        # use ldaps://server:636 url for ldaps,
        # use  ldap://server for ldap without tls (and set start_tls to 0),
        # use  ldap://server for ldap with tls (and set start_tls to 1 or 2).
        bind_dn='',  # We can either use some fixed user and password for binding to LDAP.
        # Be careful if you need a % char in those strings - as they are used as
        # a format string, you have to write %% to get a single % in the end.
        #bind_dn = '*****@*****.**' # (AD)
        #bind_dn = 'cn=admin,dc=example,dc=org' # (OpenLDAP)
        #bind_pw = 'secret'
        # or we can use the username and password we got from the user:
        #bind_dn = '%(username)[email protected]' # DN we use for first bind (AD)
        #bind_pw = '%(password)s' # password we use for first bind
        # or we can bind anonymously (if that is supported by your directory).
        # In any case, bind_dn and bind_pw must be defined.
        bind_pw='',
        base_dn='',  # base DN we use for searching
        #base_dn = 'ou=SOMEUNIT,dc=example,dc=org'
        scope=ldap.
        SCOPE_SUBTREE,  # scope of the search we do (2 == ldap.SCOPE_SUBTREE)
        referrals=0,  # LDAP REFERRALS (0 needed for AD)
        search_filter='(uid=%(username)s)',  # ldap filter used for searching:
        #search_filter = '(sAMAccountName=%(username)s)' # (AD)
        #search_filter = '(uid=%(username)s)' # (OpenLDAP)
        # you can also do more complex filtering like:
        # "(&(cn=%(username)s)(memberOf=CN=WikiUsers,OU=Groups,DC=example,DC=org))"
        # some attribute names we use to extract information from LDAP:
        givenname_attribute=None,  # ('givenName') ldap attribute we get the first name from
        surname_attribute=None,  # ('sn') ldap attribute we get the family name from
        aliasname_attribute=None,  # ('displayName') ldap attribute we get the aliasname from
        email_attribute=None,  # ('mail') ldap attribute we get the email address from
        email_callback=None,  # called to make up email address
        name_callback=None,  # called to use a Wiki name different from the login name
        coding='utf-8',  # coding used for ldap queries and result values
        timeout=10,  # how long we wait for the ldap server [s]
        start_tls=0,  # 0 = No, 1 = Try, 2 = Required
        tls_cacertdir=None,
        tls_cacertfile=None,
        tls_certfile=None,
        tls_keyfile=None,
        tls_require_cert=0,  # 0 == ldap.OPT_X_TLS_NEVER (needed for self-signed certs)
        bind_once=False,  # set to True to only do one bind - useful if configured to bind as the user on the first attempt
        autocreate=False,  # set to True if you want to autocreate user profiles
        name='ldap',  # use e.g. 'ldap_pdc' and 'ldap_bdc' (or 'ldap1' and 'ldap2') if you auth against 2 ldap servers
        report_invalid_credentials=True,  # whether to emit "invalid username or password" msg at login time or not
    ):
        self.server_uri = server_uri
        self.bind_dn = bind_dn
        self.bind_pw = bind_pw
        self.base_dn = base_dn
        self.scope = scope
        self.referrals = referrals
        self.search_filter = search_filter

        self.givenname_attribute = givenname_attribute
        self.surname_attribute = surname_attribute
        self.aliasname_attribute = aliasname_attribute
        self.email_attribute = email_attribute
        self.email_callback = email_callback
        self.name_callback = name_callback

        self.coding = coding
        self.timeout = timeout

        self.start_tls = start_tls
        self.tls_cacertdir = tls_cacertdir
        self.tls_cacertfile = tls_cacertfile
        self.tls_certfile = tls_certfile
        self.tls_keyfile = tls_keyfile
        self.tls_require_cert = tls_require_cert

        self.bind_once = bind_once
        self.autocreate = autocreate
        self.name = name

        self.report_invalid_credentials = report_invalid_credentials

    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')
        _ = request.getText

        # we require non-empty password as ldap bind does a anon (not password
        # protected) bind if the password is empty and SUCCEEDS!
        if not password:
            return ContinueLogin(
                user_obj,
                _('Missing password. Please enter user name and password.'))

        try:
            try:
                u = None
                dn = None
                coding = self.coding
                logging.debug("Setting misc. ldap options...")
                ldap.set_option(ldap.OPT_PROTOCOL_VERSION,
                                ldap.VERSION3)  # ldap v2 is outdated
                ldap.set_option(ldap.OPT_REFERRALS, self.referrals)
                ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)

                if hasattr(ldap, 'TLS_AVAIL') and ldap.TLS_AVAIL:
                    for option, value in (
                        (ldap.OPT_X_TLS_CACERTDIR, self.tls_cacertdir),
                        (ldap.OPT_X_TLS_CACERTFILE, self.tls_cacertfile),
                        (ldap.OPT_X_TLS_CERTFILE, self.tls_certfile),
                        (ldap.OPT_X_TLS_KEYFILE, self.tls_keyfile),
                        (ldap.OPT_X_TLS_REQUIRE_CERT, self.tls_require_cert),
                        (ldap.OPT_X_TLS, self.start_tls),
                            #(ldap.OPT_X_TLS_ALLOW, 1),
                    ):
                        if value is not None:
                            ldap.set_option(option, value)

                server = self.server_uri
                logging.debug("Trying to initialize %r." % server)
                l = ldap.initialize(server)
                logging.debug("Connected to LDAP server %r." % server)

                if self.start_tls and server.startswith('ldap:'):
                    logging.debug("Trying to start TLS to %r." % server)
                    try:
                        l.start_tls_s()
                        logging.debug("Using TLS to %r." % server)
                    except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR), err:
                        logging.warning(
                            "Couldn't establish TLS to %r (err: %s)." %
                            (server, str(err)))
                        raise

                # you can use %(username)s and %(password)s here to get the stuff entered in the form:
                binddn = self.bind_dn % locals()
                bindpw = self.bind_pw % locals()
                l.simple_bind_s(binddn.encode(coding), bindpw.encode(coding))
                logging.debug("Bound with binddn %r" % binddn)

                # you can use %(username)s here to get the stuff entered in the form:
                filterstr = self.search_filter % locals()
                logging.debug("Searching %r" % filterstr)
                attrs = [
                    getattr(self, attr) for attr in [
                        'email_attribute',
                        'aliasname_attribute',
                        'surname_attribute',
                        'givenname_attribute',
                    ] if getattr(self, attr) is not None
                ]
                lusers = l.search_st(self.base_dn,
                                     self.scope,
                                     filterstr.encode(coding),
                                     attrlist=attrs,
                                     timeout=self.timeout)
                # we remove entries with dn == None to get the real result list:
                lusers = [(dn, ldap_dict) for dn, ldap_dict in lusers
                          if dn is not None]
                for dn, ldap_dict in lusers:
                    logging.debug("dn:%r" % dn)
                    for key, val in ldap_dict.items():
                        logging.debug("    %r: %r" % (key, val))

                result_length = len(lusers)
                if result_length != 1:
                    if result_length > 1:
                        logging.warning(
                            "Search found more than one (%d) matches for %r." %
                            (result_length, filterstr))
                    if result_length == 0:
                        logging.debug("Search found no matches for %r." %
                                      (filterstr, ))
                    if self.report_invalid_credentials:
                        return ContinueLogin(
                            user_obj, _("Invalid username or password."))
                    else:
                        return ContinueLogin(user_obj)

                dn, ldap_dict = lusers[0]
                if not self.bind_once:
                    logging.debug("DN found is %r, trying to bind with pw" %
                                  dn)
                    l.simple_bind_s(dn, password.encode(coding))
                    logging.debug("Bound with dn %r (username: %r)" %
                                  (dn, username))

                if self.email_callback is None:
                    if self.email_attribute:
                        email = ldap_dict.get(self.email_attribute,
                                              [''])[0].decode(coding)
                    else:
                        email = None
                else:
                    email = self.email_callback(ldap_dict)

                aliasname = ''
                try:
                    aliasname = ldap_dict[self.aliasname_attribute][0]
                except (KeyError, IndexError):
                    pass
                if not aliasname:
                    sn = ldap_dict.get(self.surname_attribute, [''])[0]
                    gn = ldap_dict.get(self.givenname_attribute, [''])[0]
                    if sn and gn:
                        aliasname = "%s, %s" % (sn, gn)
                    elif sn:
                        aliasname = sn
                aliasname = aliasname.decode(coding)

                if self.name_callback:
                    username = self.name_callback(ldap_dict)

                if email:
                    u = user.User(request,
                                  auth_username=username,
                                  auth_method=self.name,
                                  auth_attribs=(
                                      'name',
                                      'password',
                                      'email',
                                      'mailto_author',
                                  ))
                    u.email = email
                else:
                    u = user.User(request,
                                  auth_username=username,
                                  auth_method=self.name,
                                  auth_attribs=(
                                      'name',
                                      'password',
                                      'mailto_author',
                                  ))
                u.name = username
                u.aliasname = aliasname
                u.remember_me = 0  # 0 enforces cookie_lifetime config param
                logging.debug(
                    "creating user object with name %r email %r alias %r" %
                    (username, email, aliasname))

            except ldap.INVALID_CREDENTIALS, err:
                logging.debug(
                    "invalid credentials (wrong password?) for dn %r (username: %r)"
                    % (dn, username))
                return CancelLogin(_("Invalid username or password."))

            if u and self.autocreate:
                logging.debug(
                    "calling create_or_update to autocreate user %r" % u.name)
                u.create_or_update(True)
            return ContinueLogin(u)
예제 #13
0
    def _handleContinuationVerify(self):
        """
        Handles the first stage continuation.
        """
        # the consumer object with an in-memory storage
        oid_consumer = consumer.Consumer(session, self.store)

        # a dict containing the parsed query string
        query = {}
        for key in request.values.keys():
            query[key] = request.values.get(key)
        # the current url (w/o query string)
        url = get_multistage_continuation_url(self.name, {'oidstage': '1'})

        # we get the info about the authentication
        oid_info = oid_consumer.complete(query, url)
        # the identity we've retrieved from the response
        if oid_info.status == consumer.FAILURE:
            # verification has failed
            # return an error message with description of error
            logging.debug("OpenIDError: {0}".format(oid_info.message))

            error_message = _('OpenID Error')
            return CancelLogin(error_message)
        elif oid_info.status == consumer.CANCEL:
            logging.debug("OpenID verification cancelled.")

            # verification was cancelled
            # return error
            return CancelLogin(_('OpenID verification cancelled.'))
        elif oid_info.status == consumer.SUCCESS:
            logging.debug('OpenID success. id: {0}'.format(
                oid_info.identity_url))

            # we get the provider's url
            # and the list of trusted providers
            trusted = self._trusted_providers
            server = oid_info.endpoint.server_url

            if server in trusted or not trusted:
                # the provider is trusted or all providers are trusted
                # we have successfully authenticated our openid
                # we get the user with this openid associated to him
                identity = oid_info.identity_url
                users = user.search_users(openid=identity)
                user_obj = users and user.User(users[0][ITEMID],
                                               trusted=self.trusted)

                # if the user actually exists
                if user_obj:
                    # we get the authenticated user object
                    # success!
                    user_obj.auth_method = self.name
                    return ContinueLogin(user_obj)

                # there is no user with this openid
                else:
                    # redirect the user to registration
                    return MultistageRedirectLogin(
                        url_for('frontend.register',
                                _external=True,
                                openid_openid=identity,
                                openid_submit='1'))

            # not trusted
            return ContinueLogin(None,
                                 _('This OpenID provider is not trusted.'))

        else:
            logging.debug("OpenID failure")
            # the auth failed miserably
            return CancelLogin(_('OpenID failure.'))
예제 #14
0
                    u = user.User(auth_username=username, auth_method=self.name, auth_attribs=('name', 'password', 'email', 'mailto_author', ))
                    u.email = email
                else:
                    u = user.User(auth_username=username, auth_method=self.name, auth_attribs=('name', 'password', 'mailto_author', ))
                u.name = username
                u.aliasname = aliasname
                logging.debug("creating user object with name %r email %r alias %r" % (username, email, aliasname))

            except ldap.INVALID_CREDENTIALS, err:
                logging.debug("invalid credentials (wrong password?) for dn %r (username: %r)" % (dn, username))
                return CancelLogin(_("Invalid username or password."))

            if u and self.autocreate:
                logging.debug("calling create_or_update to autocreate user %r" % u.name)
                u.create_or_update(True)
            return ContinueLogin(u)

        except ldap.SERVER_DOWN, err:
            # looks like this LDAP server isn't working, so we just try the next
            # authenticator object in cfg.auth list (there could be some second
            # ldap authenticator that queries a backup server or any other auth
            # method).
            logging.error("LDAP server %s failed (%s). "
                          "Trying to authenticate with next auth list entry." % (server, str(err)))
            return ContinueLogin(user_obj, _("LDAP server %(server)s failed.", server=server))

        except:
            logging.exception("caught an exception, traceback follows...")
            return ContinueLogin(user_obj)

예제 #15
0
 def login(self, request, user_obj, **kw):
     self.log(request, 'login', user_obj, kw)
     return ContinueLogin(user_obj)
예제 #16
0
                    "creating user object with name %r email %r alias %r" %
                    (username, email, aliasname))

            except ldap.INVALID_CREDENTIALS, err:
                logging.debug(
                    "invalid credentials (wrong password?) for dn %r (username: %r)"
                    % (dn, username))
                return CancelLogin(_("Invalid username or password."))

            if u and self.autocreate:
                logging.debug(
                    "calling create_or_update to autocreate user %r" % u.name)
                u.create_or_update(True)
            return ContinueLogin(u)

        except ldap.SERVER_DOWN, err:
            # looks like this LDAP server isn't working, so we just try the next
            # authenticator object in cfg.auth list (there could be some second
            # ldap authenticator that queries a backup server or any other auth
            # method).
            logging.error("LDAP server %s failed (%s). "
                          "Trying to authenticate with next auth list entry." %
                          (server, str(err)))
            return ContinueLogin(
                user_obj,
                _("LDAP server %(server)s failed.") % {'server': server})

        except:
            logging.exception("caught an exception, traceback follows...")
            return ContinueLogin(user_obj)
예제 #17
0
    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')
        _ = request.getText

        # we require non-empty password as ldap bind does a anon (not password
        # protected) bind if the password is empty and SUCCEEDS!
        if not password:
            return ContinueLogin(
                user_obj,
                _('Missing password. Please enter user name and password.'))

        try:
            try:
                u = None
                dn = None
                coding = self.coding
                logging.debug("Setting misc. ldap options...")
                ldap.set_option(ldap.OPT_PROTOCOL_VERSION,
                                ldap.VERSION3)  # ldap v2 is outdated
                ldap.set_option(ldap.OPT_REFERRALS, self.referrals)
                ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)

                if hasattr(ldap, 'TLS_AVAIL') and ldap.TLS_AVAIL:
                    for option, value in (
                        (ldap.OPT_X_TLS_CACERTDIR, self.tls_cacertdir),
                        (ldap.OPT_X_TLS_CACERTFILE, self.tls_cacertfile),
                        (ldap.OPT_X_TLS_CERTFILE, self.tls_certfile),
                        (ldap.OPT_X_TLS_KEYFILE, self.tls_keyfile),
                        (ldap.OPT_X_TLS_REQUIRE_CERT, self.tls_require_cert),
                        (ldap.OPT_X_TLS, self.start_tls),
                            #(ldap.OPT_X_TLS_ALLOW, 1),
                    ):
                        if value is not None:
                            ldap.set_option(option, value)

                server = self.server_uri
                logging.debug("Trying to initialize %r." % server)
                l = ldap.initialize(server)
                logging.debug("Connected to LDAP server %r." % server)

                if self.start_tls and server.startswith('ldap:'):
                    logging.debug("Trying to start TLS to %r." % server)
                    try:
                        l.start_tls_s()
                        logging.debug("Using TLS to %r." % server)
                    except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR), err:
                        logging.warning(
                            "Couldn't establish TLS to %r (err: %s)." %
                            (server, str(err)))
                        raise

                # you can use %(username)s and %(password)s here to get the stuff entered in the form:
                binddn = self.bind_dn % locals()
                bindpw = self.bind_pw % locals()
                l.simple_bind_s(binddn.encode(coding), bindpw.encode(coding))
                logging.debug("Bound with binddn %r" % binddn)

                # you can use %(username)s here to get the stuff entered in the form:
                filterstr = self.search_filter % locals()
                logging.debug("Searching %r" % filterstr)
                attrs = [
                    getattr(self, attr) for attr in [
                        'email_attribute',
                        'aliasname_attribute',
                        'surname_attribute',
                        'givenname_attribute',
                    ] if getattr(self, attr) is not None
                ]
                lusers = l.search_st(self.base_dn,
                                     self.scope,
                                     filterstr.encode(coding),
                                     attrlist=attrs,
                                     timeout=self.timeout)
                # we remove entries with dn == None to get the real result list:
                lusers = [(dn, ldap_dict) for dn, ldap_dict in lusers
                          if dn is not None]
                for dn, ldap_dict in lusers:
                    logging.debug("dn:%r" % dn)
                    for key, val in ldap_dict.items():
                        logging.debug("    %r: %r" % (key, val))

                result_length = len(lusers)
                if result_length != 1:
                    if result_length > 1:
                        logging.warning(
                            "Search found more than one (%d) matches for %r." %
                            (result_length, filterstr))
                    if result_length == 0:
                        logging.debug("Search found no matches for %r." %
                                      (filterstr, ))
                    if self.report_invalid_credentials:
                        return ContinueLogin(
                            user_obj, _("Invalid username or password."))
                    else:
                        return ContinueLogin(user_obj)

                dn, ldap_dict = lusers[0]
                if not self.bind_once:
                    logging.debug("DN found is %r, trying to bind with pw" %
                                  dn)
                    l.simple_bind_s(dn, password.encode(coding))
                    logging.debug("Bound with dn %r (username: %r)" %
                                  (dn, username))

                if self.email_callback is None:
                    if self.email_attribute:
                        email = ldap_dict.get(self.email_attribute,
                                              [''])[0].decode(coding)
                    else:
                        email = None
                else:
                    email = self.email_callback(ldap_dict)

                aliasname = ''
                try:
                    aliasname = ldap_dict[self.aliasname_attribute][0]
                except (KeyError, IndexError):
                    pass
                if not aliasname:
                    sn = ldap_dict.get(self.surname_attribute, [''])[0]
                    gn = ldap_dict.get(self.givenname_attribute, [''])[0]
                    if sn and gn:
                        aliasname = "%s, %s" % (sn, gn)
                    elif sn:
                        aliasname = sn
                aliasname = aliasname.decode(coding)

                if self.name_callback:
                    username = self.name_callback(ldap_dict)

                if email:
                    u = user.User(request,
                                  auth_username=username,
                                  auth_method=self.name,
                                  auth_attribs=(
                                      'name',
                                      'password',
                                      'email',
                                      'mailto_author',
                                  ))
                    u.email = email
                else:
                    u = user.User(request,
                                  auth_username=username,
                                  auth_method=self.name,
                                  auth_attribs=(
                                      'name',
                                      'password',
                                      'mailto_author',
                                  ))
                u.name = username
                u.aliasname = aliasname
                u.remember_me = 0  # 0 enforces cookie_lifetime config param
                logging.debug(
                    "creating user object with name %r email %r alias %r" %
                    (username, email, aliasname))

            except ldap.INVALID_CREDENTIALS, err:
                logging.debug(
                    "invalid credentials (wrong password?) for dn %r (username: %r)"
                    % (dn, username))
                return CancelLogin(_("Invalid username or password."))
예제 #18
0
    def login(self, request, user_obj, **kw):
        continuation = kw.get('multistage')

        if continuation:
            return self._handle_continuation(request)

        # openid is designed to work together with other auths
        if user_obj and user_obj.valid:
            return ContinueLogin(user_obj)

        openid_id = kw.get('openid_identifier')

        # nothing entered? continue...
        if not self._forced_service and not openid_id:
            return ContinueLogin(user_obj)

        _ = request.getText

        # user entered something but the session can't be stored
        if not request.cfg.cookie_lifetime[0]:
            return ContinueLogin(
                user_obj,
                _('Anonymous sessions need to be enabled for OpenID login.'))

        oidconsumer = consumer.Consumer(request.session,
                                        MoinOpenIDStore(request))

        try:
            fserv = self._forced_service
            if fserv:
                if isinstance(fserv, str) or isinstance(fserv, unicode):
                    oidreq = oidconsumer.begin(fserv)
                else:
                    oidreq = oidconsumer.beginWithoutDiscovery(fserv)
            else:
                oidreq = oidconsumer.begin(openid_id)
        except HTTPFetchingError:
            return ContinueLogin(None, _('Failed to resolve OpenID.'))
        except DiscoveryFailure:
            return ContinueLogin(
                None, _('OpenID discovery failure, not a valid OpenID.'))
        else:
            if oidreq is None:
                return ContinueLogin(None, _('No OpenID.'))

            self._modify_request(oidreq, request.cfg)

            return_to = get_multistage_continuation_url(
                request, self.name, {'oidstage': '1'})
            trust_root = request.url_root
            if oidreq.shouldSendRedirect():
                redirect_url = oidreq.redirectURL(trust_root, return_to)
                return MultistageRedirectLogin(redirect_url)
            else:
                form_html = oidreq.formMarkup(
                    trust_root,
                    return_to,
                    form_tag_attrs={'id': 'openid_message'})
                mcall = lambda request, form:\
                    self._openid_form(request, form, form_html)
                ret = MultistageFormLogin(mcall)
                return ret
예제 #19
0
파일: log.py 프로젝트: yask123/moin-2.0
 def login(self, user_obj, **kw):
     self.log('login', user_obj, kw)
     return ContinueLogin(user_obj)
예제 #20
0
    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')

        if self.dbconfig is None:
            logging.exception(
                "Please configure this authentication agent (mysql config missing)"
            )
            return None, None, None

        try:
            import MySQLdb
        except:
            logging.exception("Failed to import MySQL connector!")
            return None, None, None

        try:
            db = MySQLdb.connect(host=self.dbconfig['host'],
                                 user=self.dbconfig['user'],
                                 passwd=self.dbconfig['passwd'],
                                 db=self.dbconfig['dbname'])
        except:
            logging.exception(
                "authorization failed due to exception when connecting to DB, traceback follows..."
            )
            return None, None, None

        # Okay, let's start!
        query = """SELECT
                        Password, Name, Email
                FROM
                    GDN_User
                WHERE
                    GDN_User.Name = '%s';
        """ % username
        logging.debug("Executing query: " + query)
        c = db.cursor(MySQLdb.cursors.DictCursor)
        c.execute(query)
        vanilla_data = c.fetchone()
        # Hashed password is here. Compare it.
        valid = self.phpass.check_password(password, vanilla_data["Password"])
        logging.debug("Valid state: " + str(valid))
        if valid:
            u = user.User(request,
                          name=vanilla_data["Name"],
                          auth_username=vanilla_data["Name"],
                          auth_method=self.name)

            changed = False
            if u.aliasname != vanilla_data["Name"]:
                u.aliasname = vanilla_data["Name"]
                changed = True
            if u.email != vanilla_data["Email"]:
                u.email = vanilla_data["Email"]
                changed = True

            if u and self.autocreate:
                u.create_or_update(changed)
            if u and u.valid:
                return ContinueLogin(
                    u)  # True to get other methods called, too
            else:
                logging.debug(
                    "%s: could not authenticate user %r (not valid)" %
                    (self.name, username))
                return ContinueLogin(user_obj,
                                     _("Invalid username or password."))
        return user_obj, True  # continue with next method in auth list