Ejemplo n.º 1
0
            public override State Advance(TwoFactorAuth owner)
            {
                var names        = owner._settings.Devices.Select(i => i.Name).ToArray();
                var validAnswers = Enumerable.Range(0, owner._settings.Devices.Length)
                                   .Select(i => Ui.Answer.Device0 + i)
                                   .Concat(new[] { Ui.Answer.Email })
                                   .ToArray();
                var answer = owner._ui.AskToChooseOob(names, owner._settings.Email, validAnswers);

                if (answer == Ui.Answer.Email)
                {
                    Remote.AuthSendEmail(owner._clientInfo,
                                         owner._settings.Email,
                                         owner._settings.TransactionId,
                                         owner._http);
                    return(new WaitForEmail());
                }

                var deviceIndex = answer - Ui.Answer.Device0;

                if (deviceIndex >= 0 && deviceIndex < owner._settings.Devices.Length)
                {
                    Remote.AuthSendPush(owner._clientInfo,
                                        owner._settings.Devices[deviceIndex].Id,
                                        owner._settings.TransactionId,
                                        owner._http);
                    return(new WaitForOob(deviceIndex));
                }

                throw new InvalidOperationException(string.Format("Invalid answer '{0}'", answer));
            }
Ejemplo n.º 2
0
            public override State Advance(TwoFactorAuth owner)
            {
                var validAnswers = new[] { Ui.Answer.Check, Ui.Answer.Resend, Ui.Answer.Email };
                var answer       = owner._ui.AskToWaitForOob(owner._settings.Devices[_deviceIndex].Name,
                                                             owner._settings.Email,
                                                             validAnswers);

                switch (answer)
                {
                case Ui.Answer.Check:
                    return(Check(owner));

                case Ui.Answer.Resend:
                    Remote.AuthSendPush(owner._clientInfo,
                                        owner._settings.Devices[_deviceIndex].Id,
                                        owner._settings.TransactionId,
                                        owner._http);
                    return(this);

                case Ui.Answer.Email:
                    Remote.AuthSendEmail(owner._clientInfo,
                                         owner._settings.Email,
                                         owner._settings.TransactionId,
                                         owner._http);
                    return(new WaitForEmail());
                }

                throw new InvalidOperationException(string.Format("Invalid answer '{0}'", answer));
            }
Ejemplo n.º 3
0
 public override State Advance(TwoFactorAuth owner)
 {
     Remote.AuthSendPush(owner._clientInfo,
                         owner._settings.Devices[_deviceIndex].Id,
                         owner._settings.TransactionId,
                         owner._http);
     return(new WaitForOob(_deviceIndex));
 }
Ejemplo n.º 4
0
 public override State Advance(TwoFactorAuth owner)
 {
     Remote.AuthSendEmail(owner._clientInfo,
                          owner._settings.Email,
                          owner._settings.TransactionId,
                          owner._http);
     return(new WaitForEmail());
 }
Ejemplo n.º 5
0
            // TODO: Shared code for most states. It's not really good that it's in the base class.
            protected State Check(TwoFactorAuth owner)
            {
                var result = Remote.AuthCheck(owner._clientInfo,
                                              owner._settings.TransactionId,
                                              owner._http);

                if (result == null)
                {
                    return(new Failure("Failed"));
                }
                return(new Done(result));
            }
Ejemplo n.º 6
0
 public virtual State Advance(TwoFactorAuth owner)
 {
     throw new InvalidOperationException("Unreachable code");
 }
Ejemplo n.º 7
0
        // TODO: Write a test that runs the whole sequence and checks the result.
        public static Vault Open(string username,
                                 string password,
                                 Ui ui,
                                 ISecureStorage storage,
                                 IHttpClient http)
        {
            // Step 1: Register a new deice or use the existing one from the previous run.
            var deviceInfo = LoadDeviceInfo(storage) ??
                             Remote.RegisetNewDevice("truekey-sharp", http);

            // Step 2: Parse the token to decode OTP information.
            var otpInfo = Crypto.ParseClientToken(deviceInfo.Token);

            // Step 3: Validate the OTP info to make sure it's got only the
            //         things we support at the moment.
            Crypto.ValidateOtpInfo(otpInfo);

            // Store the token and ID for the next time.
            StoreDeviceInfo(deviceInfo, storage);

            // Bundle up everything in one place
            var clientInfo = new Remote.ClientInfo(username, "truekey-sharp", deviceInfo, otpInfo);

            // Step 4: Auth step 1 gives us a transaction id to pass along to the next step.
            var transactionId = Remote.AuthStep1(clientInfo, http);

            // Step 5: Auth step 2 gives us the instructions on what to do next. For a new client that
            //         would be some form of second factor auth. For a known client that would be a
            //         pair of OAuth tokens.
            var whatsNext = Remote.AuthStep2(clientInfo, password, transactionId, http);

            // The device is trusted if it's already authenticated at this point and
            // no second factor is needed.
            var isTrusted = whatsNext.IsAuthenticated;

            // Step 6: Auth FSM -- walk through all the auth steps until we're done.
            var oauthToken = TwoFactorAuth.Start(clientInfo, whatsNext, ui, http);

            // Step 7: Save this device as trusted not to repeat the two factor dance next times.
            if (!isTrusted)
            {
                Remote.SaveDeviceAsTrusted(clientInfo, transactionId, oauthToken, http);
            }

            // Step 8: Get the vault from the server.
            var encryptedVault = Remote.GetVault(oauthToken, http);

            // Step 9: Compute the master key.
            var masterKey = Crypto.DecryptMasterKey(password,
                                                    encryptedVault.MasterKeySalt,
                                                    encryptedVault.EncryptedMasterKey);

            // Step 10: Decrypt the accounts.
            var accounts = encryptedVault.EncryptedAccounts
                           .Select(i => new Account(
                                       i.Id,
                                       i.Name,
                                       i.Username,
                                       Crypto.Decrypt(masterKey, i.EncryptedPassword).ToUtf8(),
                                       i.Url,
                                       Crypto.Decrypt(masterKey, i.EncryptedNote).ToUtf8()))
                           .ToArray();

            return(new Vault(accounts));
        }