diff options
Diffstat (limited to 'src/leap/bitmask/bonafide')
-rw-r--r-- | src/leap/bitmask/bonafide/_protocol.py | 12 | ||||
-rw-r--r-- | src/leap/bitmask/bonafide/_srp.py | 23 | ||||
-rw-r--r-- | src/leap/bitmask/bonafide/service.py | 11 | ||||
-rw-r--r-- | src/leap/bitmask/bonafide/session.py | 14 |
4 files changed, 57 insertions, 3 deletions
diff --git a/src/leap/bitmask/bonafide/_protocol.py b/src/leap/bitmask/bonafide/_protocol.py index ff357a14..7917f383 100644 --- a/src/leap/bitmask/bonafide/_protocol.py +++ b/src/leap/bitmask/bonafide/_protocol.py @@ -147,6 +147,18 @@ class BonafideProtocol(object): d.addCallback(lambda _: '%s logged out' % full_id) return d + def do_change_password(self, full_id, current_password, new_password): + log.msg('Change password for %s' % full_id) + if (full_id not in self._sessions or + not self._sessions[full_id].is_authenticated): + return fail(RuntimeError("There is no session for such user")) + session = self._sessions[full_id] + + if current_password != session.password: + return fail(RuntimeError("The current password is not valid")) + + return session.change_password(new_password) + def do_get_provider(self, provider_id, autoconf=False): provider = config.Provider(provider_id, autoconf=autoconf) return provider.callWhenMainConfigReady(provider.config) diff --git a/src/leap/bitmask/bonafide/_srp.py b/src/leap/bitmask/bonafide/_srp.py index b0dd83ff..34a75a56 100644 --- a/src/leap/bitmask/bonafide/_srp.py +++ b/src/leap/bitmask/bonafide/_srp.py @@ -101,9 +101,7 @@ class SRPSignupMechanism(object): """ def get_signup_params(self, username, password): - salt, verifier = srp.create_salted_verification_key( - bytes(username), bytes(password), - srp.SHA256, srp.NG_1024) + salt, verifier = _get_salt_verifier(username, password) user_data = { 'user[login]': username, 'user[password_salt]': binascii.hexlify(salt), @@ -121,6 +119,25 @@ class SRPSignupMechanism(object): return username +class SRPPasswordChangeMechanism(object): + + """ + Implement a protocol-agnostic SRP passord change mechanism. + """ + + def get_password_params(self, username, password): + salt, verifier = _get_salt_verifier(username, password) + user_data = { + 'user[password_salt]': binascii.hexlify(salt), + 'user[password_verifier]': binascii.hexlify(verifier)} + return user_data + + +def _get_salt_verifier(username, password): + return srp.create_salted_verification_key(bytes(username), bytes(password), + srp.SHA256, srp.NG_1024) + + def _safe_unhexlify(val): return binascii.unhexlify(val) \ if (len(val) % 2 == 0) else binascii.unhexlify('0' + val) diff --git a/src/leap/bitmask/bonafide/service.py b/src/leap/bitmask/bonafide/service.py index 5e3b0f1c..797e6065 100644 --- a/src/leap/bitmask/bonafide/service.py +++ b/src/leap/bitmask/bonafide/service.py @@ -103,6 +103,17 @@ class BonafideService(HookableService): d.addCallback(lambda response: {'logout': 'ok'}) return d + def do_change_password(self, username, current_password, new_password): + def notify_passphrase_change(_): + data = dict(username=username, password=new_password) + self.trigger_hook('on_passphrase_change', **data) + + d = self._bonafide.do_change_password(username, current_password, + new_password) + d.addCallback(notify_passphrase_change) + d.addCallback(lambda _: {'update': 'ok'}) + return d + def do_provider_create(self, domain): return self._bonafide.do_get_provider(domain, autoconf=True) diff --git a/src/leap/bitmask/bonafide/session.py b/src/leap/bitmask/bonafide/session.py index f25fa05e..abb697ac 100644 --- a/src/leap/bitmask/bonafide/session.py +++ b/src/leap/bitmask/bonafide/session.py @@ -66,6 +66,7 @@ class Session(object): password = self.password or '' self._srp_auth = _srp.SRPAuthMechanism(username, password) self._srp_signup = _srp.SRPSignupMechanism() + self._srp_password = _srp.SRPPasswordChangeMechanism() self._token = None self._uuid = None @@ -123,6 +124,19 @@ class Session(object): self._initialize_session() defer.returnValue(OK) + @_auth_required + @defer.inlineCallbacks + def change_password(self, password): + uri = self._api.get_update_user_uri(uid=self._uuid) + met = self._api.get_update_user_method() + params = self._srp_password.get_password_params( + self.username, password) + update = yield self._request(self._agent, uri, values=params, + method=met) + self.password = password + self._srp_auth = _srp.SRPAuthMechanism(self.username, password) + defer.returnValue(OK) + # User certificates def get_vpn_cert(self): |