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."))
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)
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)
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.'))
def _handle_continuation(self, request): _ = request.getText oidstage = request.values.get('oidstage') if oidstage == '1': logging.debug('OpenID: handle verify continuation') return self._handle_verify_continuation(request) elif oidstage == '2': logging.debug('OpenID: handle name continuation') return self._handle_name_continuation(request) elif oidstage == '3': logging.debug('OpenID: handle associate continuation') return self._handle_associate_continuation(request) logging.debug('OpenID error: unknown continuation stage') return CancelLogin(_('OpenID error: unknown continuation stage'))
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.'))
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)
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."))
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)
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.'))