func TestReset(t *testing.T) { tc := SetupEngineTest(t, "reset") defer tc.Cleanup() // Sign up a new user and have it store its secret in the // secret store (if possible). fu := NewFakeUserOrBust(tc.T, "reset") arg := MakeTestSignupEngineRunArg(fu) arg.StoreSecret = libkb.HasSecretStore() ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), GPGUI: &gpgtestui{}, SecretUI: fu.NewSecretUI(), LoginUI: libkb.TestLoginUI{Username: fu.Username}, } s := NewSignupEngine(&arg, tc.G) err := RunEngine(s, ctx) if err != nil { tc.T.Fatal(err) } if libkb.HasSecretStore() { secretStore := libkb.NewSecretStore(fu.NormalizedUsername()) _, err := secretStore.RetrieveSecret() if err != nil { t.Fatal(err) } } dbPath := tc.G.Env.GetDbFilename() sessionPath := tc.G.Env.GetSessionFilename() assertFileExists(t, dbPath) assertFileExists(t, sessionPath) if !LoggedIn(tc) { t.Fatal("Unexpectedly logged out") } e := NewResetEngine(tc.G) ctx = &Context{} if err := RunEngine(e, ctx); err != nil { t.Fatal(err) } if LoggedIn(tc) { t.Error("Unexpectedly still logged in") } if libkb.HasSecretStore() { secretStore := libkb.NewSecretStore(fu.NormalizedUsername()) secret, err := secretStore.RetrieveSecret() if err == nil { t.Errorf("Unexpectedly got secret %v", secret) } } assertFileDoesNotExist(t, dbPath) assertFileDoesNotExist(t, sessionPath) }
// Test that the login flow with passphrase but without saving the // secret works. func TestLoginWithPassphraseNoStore(t *testing.T) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "login with passphrase (no store)") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "lwpns") Logout(tc) if err := tc.G.LoginState().LoginWithPassphrase(fu.Username, fu.Passphrase, false, nil); err != nil { t.Error(err) } Logout(tc) if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err == nil { t.Error("Did not get expected error") } if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } }
// testEngineWithSecretStore takes a given engine-running function and // makes sure that it works with the secret store, i.e. that it stores // data into it when told to and reads data out from it. func testEngineWithSecretStore( t *testing.T, runEngine func(libkb.TestContext, *FakeUser, libkb.SecretUI)) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "wss") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "wss") tc.ResetLoginState() testSecretUI := libkb.TestSecretUI{ Passphrase: fu.Passphrase, StoreSecret: true, } runEngine(tc, fu, &testSecretUI) if !testSecretUI.CalledGetSecret { t.Fatal("GetSecret() unexpectedly not called") } tc.ResetLoginState() testSecretUI = libkb.TestSecretUI{} runEngine(tc, fu, &testSecretUI) if testSecretUI.CalledGetSecret { t.Fatal("GetSecret() unexpectedly called") } }
// Test changing the passphrase when user forgets current passphrase // and is logged out, but has a backup key (generated by a secret from // the secret store). func TestPassphraseChangeLoggedOutBackupKeySecretStore(t *testing.T) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "PassphraseChange") defer tc.Cleanup() u := NewFakeUserOrBust(tc.T, "login") signupArg := MakeTestSignupEngineRunArg(u) signupArg.StoreSecret = true _ = SignupFakeUserWithArg(tc, u, signupArg) // This needs to happen *before* resetting the login state, as // this call will cause the login state to be reloaded. assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change") tc.ResetLoginState() secretUI := libkb.TestSecretUI{} ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), LoginUI: libkb.TestLoginUI{}, SecretUI: &secretUI, } beng := NewPaperKey(tc.G) if err := RunEngine(beng, ctx); err != nil { t.Fatal(err) } if secretUI.CalledGetSecret { t.Fatal("GetSecret() unexpectedly called") } backupPassphrase := beng.Passphrase() ctx.SecretUI = &libkb.TestSecretUI{BackupPassphrase: backupPassphrase} Logout(tc) newPassphrase := "password1234" arg := &keybase1.PassphraseChangeArg{ Passphrase: newPassphrase, Force: true, } eng := NewPassphraseChange(arg, tc.G) if err := RunEngine(eng, ctx); err != nil { t.Fatal(err) } verifyPassphraseChange(tc, u, newPassphrase) u.Passphrase = newPassphrase assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change") }
// Test that the login flow with passphrase and with saving the secret // works. func TestLoginWithPassphraseWithStore(t *testing.T) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "login with passphrase (with store)") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "lwpws") Logout(tc) if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } if err := tc.G.LoginState().LoginWithPassphrase(fu.Username, fu.Passphrase, true, nil); err != nil { t.Error(err) } Logout(tc) if !userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly does not have a stored secret", fu.Username) } // TODO: Mock out the SecretStore and make sure that it's // actually consulted. if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err != nil { t.Error(err) } if err := libkb.ClearStoredSecret(fu.NormalizedUsername()); err != nil { t.Error(err) } if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } }
func (s *CmdSignup) prompt() (err error) { s.G().Log.Debug("+ prompt") defer func() { s.G().Log.Debug("- prompt -> %s", libkb.ErrToOk(err)) }() if !s.doPrompt { return nil } if s.prompter == nil { s.MakePrompter() } if err = s.prompter.Run(); err != nil { s.G().Log.Debug("| Prompter failed\n") return } arg := keybase1.GetNewPassphraseArg{ TerminalPrompt: "Pick a strong passphrase", PinentryDesc: "Pick a strong passphrase (12+ characters)", PinentryPrompt: "Passphrase", UseSecretStore: libkb.HasSecretStore(), } f := s.fields.passphraseRetry if f.Disabled || libkb.IsYes(f.GetValue()) { var res keybase1.GetNewPassphraseRes res, err = s.G().UI.GetSecretUI().GetNewPassphrase(arg) if err != nil { return } s.passphrase = res.Passphrase s.storeSecret = res.StoreSecret } return }
// Test that the signup with saving the secret, logout, then login // flow works. func TestSignupWithStoreThenLogin(t *testing.T) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "signup with store then login") defer tc.Cleanup() fu := NewFakeUserOrBust(tc.T, "lssl") if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } arg := MakeTestSignupEngineRunArg(fu) arg.StoreSecret = true _ = SignupFakeUserWithArg(tc, fu, arg) Logout(tc) // TODO: Mock out the SecretStore and make sure that it's // actually consulted. if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err != nil { t.Error(err) } if err := libkb.ClearStoredSecret(fu.NormalizedUsername()); err != nil { t.Error(err) } if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } }
// Test that the login flow using the secret store works. func TestLoginWithStoredSecret(t *testing.T) { // TODO: Get this working on non-OS X platforms (by mocking // out the SecretStore). if !libkb.HasSecretStore() { t.Skip("Skipping test since there is no secret store") } tc := SetupEngineTest(t, "login with stored secret") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "lwss") Logout(tc) if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } mockGetPassphrase := &GetKeybasePassphraseMock{ Passphrase: fu.Passphrase, StoreSecret: true, } if err := tc.G.LoginState().LoginWithPrompt("", nil, mockGetPassphrase, nil); err != nil { t.Fatal(err) } mockGetPassphrase.CheckLastErr(t) if !mockGetPassphrase.Called { t.Errorf("secretUI.GetKeybasePassphrase() unexpectedly not called") } Logout(tc) if !userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly does not have a stored secret", fu.Username) } // TODO: Mock out the SecretStore and make sure that it's // actually consulted. if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err != nil { t.Error(err) } Logout(tc) if err := libkb.ClearStoredSecret(fu.NormalizedUsername()); err != nil { t.Error(err) } if userHasStoredSecret(&tc, fu.Username) { t.Errorf("User %s unexpectedly has a stored secret", fu.Username) } if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err == nil { t.Error("Did not get expected error") } if err := tc.G.LoginState().LoginWithStoredSecret("", nil); err == nil { t.Error("Did not get expected error") } fu = CreateAndSignupFakeUser(tc, "lwss") Logout(tc) if err := tc.G.LoginState().LoginWithStoredSecret(fu.Username, nil); err == nil { t.Error("Did not get expected error") } }
func TestDeprovision(t *testing.T) { tc := SetupEngineTest(t, "deprovision") defer tc.Cleanup() // Sign up a new user and have it store its secret in the // secret store (if possible). fu := NewFakeUserOrBust(tc.T, "dpr") arg := MakeTestSignupEngineRunArg(fu) arg.StoreSecret = libkb.HasSecretStore() ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), GPGUI: &gpgtestui{}, SecretUI: fu.NewSecretUI(), LoginUI: &libkb.TestLoginUI{Username: fu.Username}, } s := NewSignupEngine(&arg, tc.G) err := RunEngine(s, ctx) if err != nil { tc.T.Fatal(err) } if libkb.HasSecretStore() { secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername()) _, err := secretStore.RetrieveSecret() if err != nil { t.Fatal(err) } } dbPath := tc.G.Env.GetDbFilename() sessionPath := tc.G.Env.GetSessionFilename() secretKeysPath := tc.G.SKBFilenameForUser(fu.NormalizedUsername()) numKeys := getNumKeys(tc, *fu) assertFileExists(t, dbPath) assertFileExists(t, sessionPath) assertFileExists(t, secretKeysPath) if !isUserInConfigFile(tc, *fu) { t.Fatalf("User %s is not in the config file %s", fu.Username, tc.G.Env.GetConfigFilename()) } if !isUserConfigInMemory(tc) { t.Fatalf("user config is not in memory") } if !LoggedIn(tc) { t.Fatal("Unexpectedly logged out") } e := NewDeprovisionEngine(tc.G, fu.Username) ctx = &Context{ LogUI: tc.G.UI.GetLogUI(), SecretUI: fu.NewSecretUI(), } if err := RunEngine(e, ctx); err != nil { t.Fatal(err) } if LoggedIn(tc) { t.Error("Unexpectedly still logged in") } if libkb.HasSecretStore() { secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername()) secret, err := secretStore.RetrieveSecret() if err == nil { t.Errorf("Unexpectedly got secret %v", secret) } } assertFileDoesNotExist(t, dbPath) assertFileDoesNotExist(t, sessionPath) assertFileDoesNotExist(t, secretKeysPath) if isUserInConfigFile(tc, *fu) { t.Fatalf("User %s is still in the config file %s", fu.Username, tc.G.Env.GetConfigFilename()) } if isUserConfigInMemory(tc) { t.Fatalf("user config is still in memory") } newNumKeys := getNumKeys(tc, *fu) if newNumKeys != numKeys-2 { t.Fatalf("failed to revoke device keys, before: %d, after: %d", numKeys, newNumKeys) } }