# HG changeset patch # User souliane # Date 1437380170 -7200 # Node ID 8ac862f6e5b3bb65af1e96892871d5adfbcc8ecb # Parent 7168a9873ddeadc0cd8ca2c1c75338260644bb65 browser and server sides: allow to connect with a JID that is not registered on the local server diff -r 7168a9873dde -r 8ac862f6e5b3 src/browser/sat_browser/register.py --- a/src/browser/sat_browser/register.py Mon Nov 23 22:02:18 2015 +0100 +++ b/src/browser/sat_browser/register.py Mon Jul 20 10:16:10 2015 +0200 @@ -171,8 +171,8 @@ pass def onLogin(self, button): - if not re.match(r'^[a-z0-9_-]+$', self.login_box.getText(), re.IGNORECASE): - self.login_warning_msg.setText('Invalid login, valid characters are a-z A-Z 0-9 _ -') + if not re.match(r'^[a-z0-9_-]+(@[a-z0-9_-]+\.[a-z0-9_-]+)?$', self.login_box.getText(), re.IGNORECASE): + self.login_warning_msg.setHTML('Invalid login, valid characters
are a-z A-Z 0-9 _ - or a bare JID') else: self.submit_type.setValue('login') self.submit(None) @@ -182,7 +182,7 @@ self.register_login_box.setText(self.register_login_box.getText().lower()) if not re.match(r'^[a-z0-9_-]+$', self.register_login_box.getText(), re.IGNORECASE): self.register_warning_msg.setHTML(_('Invalid login, valid characters
are a-z A-Z 0-9 _ -')) - elif not re.match(r'^.+@.+\..+', self.email_box.getText(), re.IGNORECASE): + elif not re.match(r'^[a-z0-9_-]+@[a-z0-9_-]+\.[a-z0-9_-]+$', self.email_box.getText(), re.IGNORECASE): self.register_warning_msg.setHTML(_('Invalid email address')) elif len(self.register_pass_box.getText()) < C.PASSWORD_MIN_LENGTH: self.register_warning_msg.setHTML(_('Your password must contain
at least %d characters.') % C.PASSWORD_MIN_LENGTH) diff -r 7168a9873dde -r 8ac862f6e5b3 src/server/server.py --- a/src/server/server.py Mon Nov 23 22:02:18 2015 +0100 +++ b/src/server/server.py Mon Jul 20 10:16:10 2015 +0200 @@ -25,7 +25,7 @@ from twisted.web.util import Redirect, redirectTo from twisted.python.components import registerAdapter from twisted.python.failure import Failure -from twisted.words.protocols.jabber.jid import JID +from twisted.words.protocols.jabber import jid from txjsonrpc.web import jsonrpc from txjsonrpc import jsonrpclib @@ -484,8 +484,8 @@ sat_jid = sat_session.jid if not sat_jid: # we keep a session cache for jid to avoir jid spoofing - sat_jid = sat_session.jid = JID(self.sat_host.bridge.getParamA("JabberID", "Connection", profile_key=profile)) - if JID(from_jid).userhost() != sat_jid.userhost() and JID(to_jid).userhost() != sat_jid.userhost(): + sat_jid = sat_session.jid = jid.JID(self.sat_host.bridge.getParamA("JabberID", "Connection", profile_key=profile)) + if jid.JID(from_jid).userhost() != sat_jid.userhost() and jid.JID(to_jid).userhost() != sat_jid.userhost(): log.error(u"Trying to get history from a different jid (given (browser): {}, real (backend): {}), maybe a hack attempt ?".format(from_jid, sat_jid)) return {} d = self.asyncBridgeCall("getHistory", from_jid, to_jid, size, between, search, profile) @@ -526,7 +526,7 @@ """Quit a Multi-User Chat room""" profile = ISATSession(self.session).profile try: - room_jid = JID(room_jid) + room_jid = jid.JID(room_jid) except: log.warning('Invalid room jid') return @@ -785,43 +785,53 @@ value will be given by self._logged or auth_eb """ try: - login_ = request.args['login'][0] - password_ = request.args['login_password'][0] + login = request.args['login'][0] + password = request.args['login_password'][0] except KeyError: return C.BAD_REQUEST - if login_.startswith('@'): + if login.startswith('@'): # this is checked by javascript but also here for security reason raise Exception('No profile_key allowed') - profile_check = self.sat_host.bridge.getProfileName(login_) - if ((not profile_check or profile_check != login_) or - (not password_ and profile_check not in self.sat_host.empty_password_allowed_warning_dangerous_list)): - return C.PROFILE_AUTH_ERROR - # profiles with empty passwords are restricted to local frontends + try: + profile = self.sat_host.bridge.getProfileName(login) + except Exception as e: + try: # try to connect using XMPP credentials instead of SàT profile credentials + jid.JID(login) + except (RuntimeError, jid.InvalidFormat, AttributeError): + return C.PROFILE_AUTH_ERROR + profile = login + connect_method = "asyncConnectWithXMPPCredentials" + else: + if profile != login: + return C.PROFILE_AUTH_ERROR + if not password and profile not in self.sat_host.empty_password_allowed_warning_dangerous_list: + return C.PROFILE_AUTH_ERROR # profiles with empty passwords are restricted to local frontends + connect_method = "asyncConnect" - if self.waiting_profiles.getRequest(login_): + if self.waiting_profiles.getRequest(profile): return C.ALREADY_WAITING def auth_eb(failure): fault = failure.value.faultString - self.waiting_profiles.purgeRequest(login_) - if fault == 'PasswordError': - log.info(u"Profile %s doesn't exist or the submitted password is wrong" % login_) + self.waiting_profiles.purgeRequest(profile) + if fault in ('PasswordError', 'ProfileUnknownError'): + log.info(u"Profile %s doesn't exist or the submitted password is wrong" % profile) request.write(C.PROFILE_AUTH_ERROR) elif fault == 'SASLAuthError': - log.info(u"The XMPP password of profile %s is wrong" % login_) + log.info(u"The XMPP password of profile %s is wrong" % profile) request.write(C.XMPP_AUTH_ERROR) elif fault == 'NoReply': log.info(_("Did not receive a reply (the timeout expired or the connection is broken)")) request.write(C.NO_REPLY) else: - log.error(u'Unmanaged fault string %s in errback for the connection of profile %s' % (fault, login_)) + log.error(u'Unmanaged fault string %s in errback for the connection of profile %s' % (fault, profile)) request.write(C.UNKNOWN_ERROR % fault) request.finish() - self.waiting_profiles.setRequest(request, login_) - d = self.asyncBridgeCall("asyncConnect", login_, password_) - d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb) + self.waiting_profiles.setRequest(request, profile) + d = self.asyncBridgeCall(connect_method, profile, password) + d.addCallbacks(lambda connected: self._logged(profile, request) if connected else None, auth_eb) return server.NOT_DONE_YET