diff options
Diffstat (limited to 'mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login')
12 files changed, 0 insertions, 860 deletions
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/BaseRequestDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/BaseRequestDelegate.java deleted file mode 100644 index 5d3e71ece..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/BaseRequestDelegate.java +++ /dev/null @@ -1,49 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.background.fxa.FxAccountClient20; -import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException; -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.AccountNeedsVerification; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LocalError; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.RemoteError; - -public abstract class BaseRequestDelegate<T> implements FxAccountClient20.RequestDelegate<T> { - protected final ExecuteDelegate delegate; - protected final State state; - - public BaseRequestDelegate(State state, ExecuteDelegate delegate) { - this.delegate = delegate; - this.state = state; - } - - @Override - public void handleFailure(FxAccountClientRemoteException e) { - // Order matters here: we don't want to ignore upgrade required responses - // even if the server tells us something else as well. We don't go directly - // to the Doghouse on upgrade required; we want the user to try to update - // their credentials, and then display UI telling them they need to upgrade. - // Then they go to the Doghouse. - if (e.isUpgradeRequired()) { - delegate.handleTransition(new RemoteError(e), new Separated(state.email, state.uid, state.verified)); - return; - } - if (e.isInvalidAuthentication()) { - delegate.handleTransition(new RemoteError(e), new Separated(state.email, state.uid, state.verified)); - return; - } - if (e.isUnverified()) { - delegate.handleTransition(new AccountNeedsVerification(), state); - return; - } - delegate.handleTransition(new RemoteError(e), state); - } - - @Override - public void handleError(Exception e) { - delegate.handleTransition(new LocalError(e), state); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Cohabiting.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Cohabiting.java deleted file mode 100644 index dd3477a79..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Cohabiting.java +++ /dev/null @@ -1,50 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.background.fxa.FxAccountUtils; -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.browserid.JSONWebTokenUtils; -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LogMessage; -import org.mozilla.gecko.sync.ExtendedJSONObject; - -public class Cohabiting extends TokensAndKeysState { - private static final String LOG_TAG = Cohabiting.class.getSimpleName(); - - public Cohabiting(String email, String uid, byte[] sessionToken, byte[] kA, byte[] kB, BrowserIDKeyPair keyPair) { - super(StateLabel.Cohabiting, email, uid, sessionToken, kA, kB, keyPair); - } - - public Married withCertificate(String certificate) { - return new Married(email, uid, sessionToken, kA, kB, keyPair, certificate); - } - - @Override - public void execute(final ExecuteDelegate delegate) { - delegate.getClient().sign(sessionToken, keyPair.getPublic().toJSONObject(), delegate.getCertificateDurationInMilliseconds(), - new BaseRequestDelegate<String>(this, delegate) { - @Override - public void handleSuccess(String certificate) { - if (FxAccountUtils.LOG_PERSONAL_INFORMATION) { - try { - FxAccountUtils.pii(LOG_TAG, "Fetched certificate: " + certificate); - ExtendedJSONObject c = JSONWebTokenUtils.parseCertificate(certificate); - if (c != null) { - FxAccountUtils.pii(LOG_TAG, "Header : " + c.getObject("header")); - FxAccountUtils.pii(LOG_TAG, "Payload : " + c.getObject("payload")); - FxAccountUtils.pii(LOG_TAG, "Signature: " + c.getString("signature")); - } else { - FxAccountUtils.pii(LOG_TAG, "Could not parse certificate!"); - } - } catch (Exception e) { - FxAccountUtils.pii(LOG_TAG, "Could not parse certificate!"); - } - } - delegate.handleTransition(new LogMessage("sign succeeded"), withCertificate(certificate)); - } - }); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Doghouse.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Doghouse.java deleted file mode 100644 index 57600577d..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Doghouse.java +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LogMessage; - - -public class Doghouse extends State { - public Doghouse(String email, String uid, boolean verified) { - super(StateLabel.Doghouse, email, uid, verified); - } - - @Override - public void execute(final ExecuteDelegate delegate) { - delegate.handleTransition(new LogMessage("Upgraded Firefox clients might know what to do here."), this); - } - - @Override - public Action getNeededAction() { - return Action.NeedsUpgrade; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Engaged.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Engaged.java deleted file mode 100644 index f192cb58b..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Engaged.java +++ /dev/null @@ -1,91 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import java.security.NoSuchAlgorithmException; - -import org.mozilla.gecko.background.fxa.FxAccountClient20.TwoKeys; -import org.mozilla.gecko.background.fxa.FxAccountUtils; -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.AccountVerified; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LocalError; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LogMessage; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.RemoteError; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.Transition; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.Utils; - -public class Engaged extends State { - private static final String LOG_TAG = Engaged.class.getSimpleName(); - - protected final byte[] sessionToken; - protected final byte[] keyFetchToken; - protected final byte[] unwrapkB; - - public Engaged(String email, String uid, boolean verified, byte[] unwrapkB, byte[] sessionToken, byte[] keyFetchToken) { - super(StateLabel.Engaged, email, uid, verified); - Utils.throwIfNull(unwrapkB, sessionToken, keyFetchToken); - this.unwrapkB = unwrapkB; - this.sessionToken = sessionToken; - this.keyFetchToken = keyFetchToken; - } - - @Override - public ExtendedJSONObject toJSONObject() { - ExtendedJSONObject o = super.toJSONObject(); - // Fields are non-null by constructor. - o.put("unwrapkB", Utils.byte2Hex(unwrapkB)); - o.put("sessionToken", Utils.byte2Hex(sessionToken)); - o.put("keyFetchToken", Utils.byte2Hex(keyFetchToken)); - return o; - } - - @Override - public void execute(final ExecuteDelegate delegate) { - BrowserIDKeyPair theKeyPair; - try { - theKeyPair = delegate.generateKeyPair(); - } catch (NoSuchAlgorithmException e) { - delegate.handleTransition(new LocalError(e), new Doghouse(email, uid, verified)); - return; - } - final BrowserIDKeyPair keyPair = theKeyPair; - - delegate.getClient().keys(keyFetchToken, new BaseRequestDelegate<TwoKeys>(this, delegate) { - @Override - public void handleSuccess(TwoKeys result) { - byte[] kB; - try { - kB = FxAccountUtils.unwrapkB(unwrapkB, result.wrapkB); - if (FxAccountUtils.LOG_PERSONAL_INFORMATION) { - FxAccountUtils.pii(LOG_TAG, "Fetched kA: " + Utils.byte2Hex(result.kA)); - FxAccountUtils.pii(LOG_TAG, "And wrapkB: " + Utils.byte2Hex(result.wrapkB)); - FxAccountUtils.pii(LOG_TAG, "Giving kB : " + Utils.byte2Hex(kB)); - } - } catch (Exception e) { - delegate.handleTransition(new RemoteError(e), new Separated(email, uid, verified)); - return; - } - Transition transition = verified - ? new LogMessage("keys succeeded") - : new AccountVerified(); - delegate.handleTransition(transition, new Cohabiting(email, uid, sessionToken, result.kA, kB, keyPair)); - } - }); - } - - @Override - public Action getNeededAction() { - if (!verified) { - return Action.NeedsVerification; - } - return Action.None; - } - - public byte[] getSessionToken() { - return sessionToken; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginStateMachine.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginStateMachine.java deleted file mode 100644 index 34e507541..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginStateMachine.java +++ /dev/null @@ -1,84 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import java.security.NoSuchAlgorithmException; -import java.util.EnumSet; -import java.util.Set; - -import org.mozilla.gecko.background.fxa.FxAccountClient; -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.Transition; -import org.mozilla.gecko.fxa.login.State.StateLabel; - -public class FxAccountLoginStateMachine { - public static final String LOG_TAG = FxAccountLoginStateMachine.class.getSimpleName(); - - public interface LoginStateMachineDelegate { - public FxAccountClient getClient(); - public long getCertificateDurationInMilliseconds(); - public long getAssertionDurationInMilliseconds(); - public void handleTransition(Transition transition, State state); - public void handleFinal(State state); - public BrowserIDKeyPair generateKeyPair() throws NoSuchAlgorithmException; - } - - public static class ExecuteDelegate { - protected final LoginStateMachineDelegate delegate; - protected final StateLabel desiredStateLabel; - // It's as difficult to detect arbitrary cycles as repeated states. - protected final Set<StateLabel> stateLabelsSeen = EnumSet.noneOf(StateLabel.class); - - protected ExecuteDelegate(StateLabel initialStateLabel, StateLabel desiredStateLabel, LoginStateMachineDelegate delegate) { - this.delegate = delegate; - this.desiredStateLabel = desiredStateLabel; - this.stateLabelsSeen.add(initialStateLabel); - } - - public FxAccountClient getClient() { - return delegate.getClient(); - } - - public long getCertificateDurationInMilliseconds() { - return delegate.getCertificateDurationInMilliseconds(); - } - - public long getAssertionDurationInMilliseconds() { - return delegate.getAssertionDurationInMilliseconds(); - } - - public BrowserIDKeyPair generateKeyPair() throws NoSuchAlgorithmException { - return delegate.generateKeyPair(); - } - - public void handleTransition(Transition transition, State state) { - // Always trigger the transition callback. - delegate.handleTransition(transition, state); - - // Possibly trigger the final callback. We trigger if we're at our desired - // state, or if we've seen this state before. - StateLabel stateLabel = state.getStateLabel(); - if (stateLabel == desiredStateLabel || stateLabelsSeen.contains(stateLabel)) { - delegate.handleFinal(state); - return; - } - - // If this wasn't the last state, leave a bread crumb and move on to the - // next state. - stateLabelsSeen.add(stateLabel); - state.execute(this); - } - } - - public void advance(State initialState, final StateLabel desiredStateLabel, final LoginStateMachineDelegate delegate) { - if (initialState.getStateLabel() == desiredStateLabel) { - // We're already where we want to be! - delegate.handleFinal(initialState); - return; - } - ExecuteDelegate executeDelegate = new ExecuteDelegate(initialState.getStateLabel(), desiredStateLabel, delegate); - initialState.execute(executeDelegate); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginTransition.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginTransition.java deleted file mode 100644 index 683217853..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/FxAccountLoginTransition.java +++ /dev/null @@ -1,68 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - - -public class FxAccountLoginTransition { - public interface Transition { - } - - public static class LogMessage implements Transition { - public final String detailMessage; - - public LogMessage(String detailMessage) { - this.detailMessage = detailMessage; - } - - @Override - public String toString() { - return getClass().getSimpleName() + (this.detailMessage == null ? "" : "('" + this.detailMessage + "')"); - } - } - - public static class AccountNeedsVerification extends LogMessage { - public AccountNeedsVerification() { - super(null); - } - } - - public static class AccountVerified extends LogMessage { - public AccountVerified() { - super(null); - } - } - - public static class PasswordRequired extends LogMessage { - public PasswordRequired() { - super(null); - } - } - - public static class LocalError implements Transition { - public final Exception e; - - public LocalError(Exception e) { - this.e = e; - } - - @Override - public String toString() { - return "Log(" + this.e + ")"; - } - } - - public static class RemoteError implements Transition { - public final Exception e; - - public RemoteError(Exception e) { - this.e = e; - } - - @Override - public String toString() { - return "Log(" + (this.e == null ? "null" : this.e) + ")"; - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Married.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Married.java deleted file mode 100644 index 1ec7b4051..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Married.java +++ /dev/null @@ -1,117 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; - -import org.mozilla.gecko.background.fxa.FxAccountUtils; -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.browserid.JSONWebTokenUtils; -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LogMessage; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.NonObjectJSONException; -import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.crypto.KeyBundle; - -public class Married extends TokensAndKeysState { - private static final String LOG_TAG = Married.class.getSimpleName(); - - protected final String certificate; - protected final String clientState; - - public Married(String email, String uid, byte[] sessionToken, byte[] kA, byte[] kB, BrowserIDKeyPair keyPair, String certificate) { - super(StateLabel.Married, email, uid, sessionToken, kA, kB, keyPair); - Utils.throwIfNull(certificate); - this.certificate = certificate; - try { - this.clientState = FxAccountUtils.computeClientState(kB); - } catch (NoSuchAlgorithmException e) { - // This should never occur. - throw new IllegalStateException("Unable to compute client state from kB."); - } - } - - @Override - public ExtendedJSONObject toJSONObject() { - ExtendedJSONObject o = super.toJSONObject(); - // Fields are non-null by constructor. - o.put("certificate", certificate); - return o; - } - - @Override - public void execute(final ExecuteDelegate delegate) { - delegate.handleTransition(new LogMessage("staying married"), this); - } - - public String generateAssertion(String audience, String issuer) throws NonObjectJSONException, IOException, GeneralSecurityException { - // We generate assertions with no iat and an exp after 2050 to avoid - // invalid-timestamp errors from the token server. - final long expiresAt = JSONWebTokenUtils.DEFAULT_FUTURE_EXPIRES_AT_IN_MILLISECONDS; - String assertion = JSONWebTokenUtils.createAssertion(keyPair.getPrivate(), certificate, audience, issuer, null, expiresAt); - if (!FxAccountUtils.LOG_PERSONAL_INFORMATION) { - return assertion; - } - - try { - FxAccountUtils.pii(LOG_TAG, "Generated assertion: " + assertion); - ExtendedJSONObject a = JSONWebTokenUtils.parseAssertion(assertion); - if (a != null) { - FxAccountUtils.pii(LOG_TAG, "aHeader : " + a.getObject("header")); - FxAccountUtils.pii(LOG_TAG, "aPayload : " + a.getObject("payload")); - FxAccountUtils.pii(LOG_TAG, "aSignature: " + a.getString("signature")); - String certificate = a.getString("certificate"); - if (certificate != null) { - ExtendedJSONObject c = JSONWebTokenUtils.parseCertificate(certificate); - FxAccountUtils.pii(LOG_TAG, "cHeader : " + c.getObject("header")); - FxAccountUtils.pii(LOG_TAG, "cPayload : " + c.getObject("payload")); - FxAccountUtils.pii(LOG_TAG, "cSignature: " + c.getString("signature")); - // Print the relevant timestamps in sorted order with labels. - HashMap<Long, String> map = new HashMap<Long, String>(); - map.put(a.getObject("payload").getLong("iat"), "aiat"); - map.put(a.getObject("payload").getLong("exp"), "aexp"); - map.put(c.getObject("payload").getLong("iat"), "ciat"); - map.put(c.getObject("payload").getLong("exp"), "cexp"); - ArrayList<Long> values = new ArrayList<Long>(map.keySet()); - Collections.sort(values); - for (Long value : values) { - FxAccountUtils.pii(LOG_TAG, map.get(value) + ": " + value); - } - } else { - FxAccountUtils.pii(LOG_TAG, "Could not parse certificate!"); - } - } else { - FxAccountUtils.pii(LOG_TAG, "Could not parse assertion!"); - } - } catch (Exception e) { - FxAccountUtils.pii(LOG_TAG, "Got exception dumping assertion debug info."); - } - return assertion; - } - - public KeyBundle getSyncKeyBundle() throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { - // TODO Document this choice for deriving from kB. - return FxAccountUtils.generateSyncKeyBundle(kB); - } - - public String getClientState() { - if (FxAccountUtils.LOG_PERSONAL_INFORMATION) { - FxAccountUtils.pii(LOG_TAG, "Client state: " + this.clientState); - } - return this.clientState; - } - - public Cohabiting makeCohabitingState() { - return new Cohabiting(email, uid, sessionToken, kA, kB, keyPair); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/MigratedFromSync11.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/MigratedFromSync11.java deleted file mode 100644 index c30ac2ff7..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/MigratedFromSync11.java +++ /dev/null @@ -1,28 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.PasswordRequired; - -public class MigratedFromSync11 extends State { - public final String password; - - public MigratedFromSync11(String email, String uid, boolean verified, String password) { - super(StateLabel.MigratedFromSync11, email, uid, verified); - // Null password is allowed. - this.password = password; - } - - @Override - public void execute(final ExecuteDelegate delegate) { - delegate.handleTransition(new PasswordRequired(), this); - } - - @Override - public Action getNeededAction() { - return Action.NeedsFinishMigrating; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Separated.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Separated.java deleted file mode 100644 index bda620df9..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/Separated.java +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.PasswordRequired; - - -public class Separated extends State { - public Separated(String email, String uid, boolean verified) { - super(StateLabel.Separated, email, uid, verified); - } - - @Override - public void execute(final ExecuteDelegate delegate) { - delegate.handleTransition(new PasswordRequired(), this); - } - - @Override - public Action getNeededAction() { - return Action.NeedsPassword; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/State.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/State.java deleted file mode 100644 index 797011ec2..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/State.java +++ /dev/null @@ -1,72 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.Utils; - -public abstract class State { - public static final long CURRENT_VERSION = 3L; - - public enum StateLabel { - Engaged, - Cohabiting, - Married, - Separated, - Doghouse, - MigratedFromSync11, - } - - public enum Action { - NeedsUpgrade, - NeedsPassword, - NeedsVerification, - NeedsFinishMigrating, - None, - } - - protected final StateLabel stateLabel; - public final String email; - public final String uid; - public final boolean verified; - - public State(StateLabel stateLabel, String email, String uid, boolean verified) { - Utils.throwIfNull(email, uid); - this.stateLabel = stateLabel; - this.email = email; - this.uid = uid; - this.verified = verified; - } - - public StateLabel getStateLabel() { - return this.stateLabel; - } - - public ExtendedJSONObject toJSONObject() { - ExtendedJSONObject o = new ExtendedJSONObject(); - o.put("version", State.CURRENT_VERSION); - o.put("email", email); - o.put("uid", uid); - o.put("verified", verified); - return o; - } - - public State makeSeparatedState() { - return new Separated(email, uid, verified); - } - - public State makeDoghouseState() { - return new Doghouse(email, uid, verified); - } - - public State makeMigratedFromSync11State(String password) { - return new MigratedFromSync11(email, uid, verified, password); - } - - public abstract void execute(ExecuteDelegate delegate); - - public abstract Action getNeededAction(); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/StateFactory.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/StateFactory.java deleted file mode 100644 index a98f2fb27..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/StateFactory.java +++ /dev/null @@ -1,206 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; - -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.background.fxa.FxAccountUtils; -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.browserid.DSACryptoImplementation; -import org.mozilla.gecko.browserid.RSACryptoImplementation; -import org.mozilla.gecko.fxa.login.State.StateLabel; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.NonObjectJSONException; -import org.mozilla.gecko.sync.Utils; - -/** - * Create {@link State} instances from serialized representations. - * <p> - * Version 1 recognizes 5 state labels (Engaged, Cohabiting, Married, Separated, - * Doghouse). In the Cohabiting and Married states, the associated key pairs are - * always RSA key pairs. - * <p> - * Version 2 is identical to version 1, except that in the Cohabiting and - * Married states, the associated keypairs are always DSA key pairs. - */ -public class StateFactory { - private static final String LOG_TAG = StateFactory.class.getSimpleName(); - - private static final int KEY_PAIR_SIZE_IN_BITS_V1 = 1024; - - public static BrowserIDKeyPair generateKeyPair() throws NoSuchAlgorithmException { - // New key pairs are always DSA. - return DSACryptoImplementation.generateKeyPair(KEY_PAIR_SIZE_IN_BITS_V1); - } - - protected static BrowserIDKeyPair keyPairFromJSONObjectV1(ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException { - // V1 key pairs are RSA. - return RSACryptoImplementation.fromJSONObject(o); - } - - protected static BrowserIDKeyPair keyPairFromJSONObjectV2(ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException { - // V2 key pairs are DSA. - return DSACryptoImplementation.fromJSONObject(o); - } - - public static State fromJSONObject(StateLabel stateLabel, ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException { - Long version = o.getLong("version"); - if (version == null) { - throw new IllegalStateException("version must not be null"); - } - - final int v = version.intValue(); - if (v == 3) { - // The most common case is the most recent version. - return fromJSONObjectV3(stateLabel, o); - } - if (v == 2) { - return fromJSONObjectV2(stateLabel, o); - } - if (v == 1) { - final State state = fromJSONObjectV1(stateLabel, o); - return migrateV1toV2(stateLabel, state); - } - throw new IllegalStateException("version must be in {1, 2}"); - } - - protected static State fromJSONObjectV1(StateLabel stateLabel, ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException { - switch (stateLabel) { - case Engaged: - return new Engaged( - o.getString("email"), - o.getString("uid"), - o.getBoolean("verified"), - Utils.hex2Byte(o.getString("unwrapkB")), - Utils.hex2Byte(o.getString("sessionToken")), - Utils.hex2Byte(o.getString("keyFetchToken"))); - case Cohabiting: - return new Cohabiting( - o.getString("email"), - o.getString("uid"), - Utils.hex2Byte(o.getString("sessionToken")), - Utils.hex2Byte(o.getString("kA")), - Utils.hex2Byte(o.getString("kB")), - keyPairFromJSONObjectV1(o.getObject("keyPair"))); - case Married: - return new Married( - o.getString("email"), - o.getString("uid"), - Utils.hex2Byte(o.getString("sessionToken")), - Utils.hex2Byte(o.getString("kA")), - Utils.hex2Byte(o.getString("kB")), - keyPairFromJSONObjectV1(o.getObject("keyPair")), - o.getString("certificate")); - case Separated: - return new Separated( - o.getString("email"), - o.getString("uid"), - o.getBoolean("verified")); - case Doghouse: - return new Doghouse( - o.getString("email"), - o.getString("uid"), - o.getBoolean("verified")); - default: - throw new IllegalStateException("unrecognized state label: " + stateLabel); - } - } - - /** - * Exactly the same as {@link fromJSONObjectV1}, except that all key pairs are DSA key pairs. - */ - protected static State fromJSONObjectV2(StateLabel stateLabel, ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException { - switch (stateLabel) { - case Cohabiting: - return new Cohabiting( - o.getString("email"), - o.getString("uid"), - Utils.hex2Byte(o.getString("sessionToken")), - Utils.hex2Byte(o.getString("kA")), - Utils.hex2Byte(o.getString("kB")), - keyPairFromJSONObjectV2(o.getObject("keyPair"))); - case Married: - return new Married( - o.getString("email"), - o.getString("uid"), - Utils.hex2Byte(o.getString("sessionToken")), - Utils.hex2Byte(o.getString("kA")), - Utils.hex2Byte(o.getString("kB")), - keyPairFromJSONObjectV2(o.getObject("keyPair")), - o.getString("certificate")); - default: - return fromJSONObjectV1(stateLabel, o); - } - } - - /** - * Exactly the same as {@link fromJSONObjectV2}, except that there's a new - * MigratedFromSyncV11 state. - */ - protected static State fromJSONObjectV3(StateLabel stateLabel, ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException { - switch (stateLabel) { - case MigratedFromSync11: - return new MigratedFromSync11( - o.getString("email"), - o.getString("uid"), - o.getBoolean("verified"), - o.getString("password")); - default: - return fromJSONObjectV2(stateLabel, o); - } - } - - protected static void logMigration(State from, State to) { - if (!FxAccountUtils.LOG_PERSONAL_INFORMATION) { - return; - } - try { - FxAccountUtils.pii(LOG_TAG, "V1 persisted state is: " + from.toJSONObject().toJSONString()); - } catch (Exception e) { - Logger.warn(LOG_TAG, "Error producing JSON representation of V1 state.", e); - } - FxAccountUtils.pii(LOG_TAG, "Generated new V2 state: " + to.toJSONObject().toJSONString()); - } - - protected static State migrateV1toV2(StateLabel stateLabel, State state) throws NoSuchAlgorithmException { - if (state == null) { - // This should never happen, but let's be careful. - Logger.error(LOG_TAG, "Got null state in migrateV1toV2; returning null."); - return state; - } - - Logger.info(LOG_TAG, "Migrating V1 persisted State to V2; stateLabel: " + stateLabel); - - // In V1, we use an RSA keyPair. In V2, we use a DSA keyPair. Only - // Cohabiting and Married states have a persisted keyPair at all; all - // other states need no conversion at all. - switch (stateLabel) { - case Cohabiting: { - // In the Cohabiting state, we can just generate a new key pair and move on. - final Cohabiting cohabiting = (Cohabiting) state; - final BrowserIDKeyPair keyPair = generateKeyPair(); - final State migrated = new Cohabiting(cohabiting.email, cohabiting.uid, cohabiting.sessionToken, cohabiting.kA, cohabiting.kB, keyPair); - logMigration(cohabiting, migrated); - return migrated; - } - case Married: { - // In the Married state, we cannot only change the key pair: the stored - // certificate signs the public key of the now obsolete key pair. We - // regress to the Cohabiting state; the next time we sync, we should - // advance back to Married. - final Married married = (Married) state; - final BrowserIDKeyPair keyPair = generateKeyPair(); - final State migrated = new Cohabiting(married.email, married.uid, married.sessionToken, married.kA, married.kB, keyPair); - logMigration(married, migrated); - return migrated; - } - default: - // Otherwise, V1 and V2 states are identical. - return state; - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/TokensAndKeysState.java b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/TokensAndKeysState.java deleted file mode 100644 index b5121a4d4..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/login/TokensAndKeysState.java +++ /dev/null @@ -1,45 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.fxa.login; - -import org.mozilla.gecko.browserid.BrowserIDKeyPair; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.Utils; - -public abstract class TokensAndKeysState extends State { - protected final byte[] sessionToken; - protected final byte[] kA; - protected final byte[] kB; - protected final BrowserIDKeyPair keyPair; - - public TokensAndKeysState(StateLabel stateLabel, String email, String uid, byte[] sessionToken, byte[] kA, byte[] kB, BrowserIDKeyPair keyPair) { - super(stateLabel, email, uid, true); - Utils.throwIfNull(sessionToken, kA, kB, keyPair); - this.sessionToken = sessionToken; - this.kA = kA; - this.kB = kB; - this.keyPair = keyPair; - } - - @Override - public ExtendedJSONObject toJSONObject() { - ExtendedJSONObject o = super.toJSONObject(); - // Fields are non-null by constructor. - o.put("sessionToken", Utils.byte2Hex(sessionToken)); - o.put("kA", Utils.byte2Hex(kA)); - o.put("kB", Utils.byte2Hex(kB)); - o.put("keyPair", keyPair.toJSONObject()); - return o; - } - - public byte[] getSessionToken() { - return sessionToken; - } - - @Override - public Action getNeededAction() { - return Action.None; - } -} |