github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/login_test.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package engine
     5  
     6  import (
     7  	"bytes"
     8  	"crypto/rand"
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"path/filepath"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/keybase/clockwork"
    20  	"github.com/stretchr/testify/require"
    21  	"golang.org/x/net/context"
    22  
    23  	"github.com/keybase/client/go/kex2"
    24  	"github.com/keybase/client/go/libkb"
    25  	gregor1 "github.com/keybase/client/go/protocol/gregor1"
    26  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    27  )
    28  
    29  func TestLoginLogoutLogin(t *testing.T) {
    30  	tc := SetupEngineTest(t, "login")
    31  	defer tc.Cleanup()
    32  
    33  	u1 := CreateAndSignupFakeUser(tc, "login")
    34  	Logout(tc)
    35  	u1.LoginOrBust(tc)
    36  }
    37  
    38  // Test login switching between two different users.
    39  func TestLoginAndSwitchWithLogout(t *testing.T) {
    40  	tc := SetupEngineTest(t, "login")
    41  	defer tc.Cleanup()
    42  
    43  	u1 := CreateAndSignupFakeUser(tc, "first")
    44  	Logout(tc)
    45  	u2 := CreateAndSignupFakeUser(tc, "secon")
    46  	Logout(tc)
    47  	t.Logf("first logging back in")
    48  	u1.LoginOrBust(tc)
    49  	Logout(tc)
    50  	t.Logf("second logging back in")
    51  	u2.LoginOrBust(tc)
    52  }
    53  
    54  func TestLoginTwiceLogoutOnce(t *testing.T) {
    55  	tc := SetupEngineTest(t, "login")
    56  	defer tc.Cleanup()
    57  	u1 := CreateAndSignupFakeUser(tc, "first")
    58  	Logout(tc)
    59  	t.Logf("Logout first, and signup  u2")
    60  	u2 := CreateAndSignupFakeUser(tc, "secon")
    61  	t.Logf("Login u1")
    62  	err := u1.SwitchTo(tc.G, true)
    63  	require.NoError(t, err)
    64  	t.Logf("Logged in u1")
    65  	err = u2.SwitchTo(tc.G, true)
    66  	require.NoError(t, err)
    67  	eng := NewLogout(libkb.LogoutOptions{})
    68  	mctx := NewMetaContextForTest(tc).WithUIs(libkb.UIs{
    69  		LoginUI:  &libkb.TestLoginUI{},
    70  		SecretUI: &nullSecretUI{},
    71  	})
    72  	err = RunEngine2(mctx, eng)
    73  	require.NoError(t, err)
    74  	// Log back into the first user, but shouldn't need a password
    75  	err = u1.SwitchTo(tc.G, true)
    76  	require.NoError(t, err)
    77  	require.True(t, tc.G.ActiveDevice.Valid())
    78  	require.Equal(t, tc.G.ActiveDevice.UID(), u1.UID())
    79  }
    80  
    81  // Test login switching between two different users.
    82  func TestLoginAndSwitchWithoutLogout(t *testing.T) {
    83  	tc := SetupEngineTest(t, "login")
    84  	defer tc.Cleanup()
    85  	u1 := CreateAndSignupFakeUser(tc, "first")
    86  	Logout(tc)
    87  	t.Logf("Logout first, and signup  u2")
    88  	u2 := CreateAndSignupFakeUser(tc, "secon")
    89  	t.Logf("Login u1")
    90  	err := u1.SwitchTo(tc.G, true)
    91  	require.NoError(t, err)
    92  	t.Logf("Logged in u1")
    93  	err = u2.SwitchTo(tc.G, true)
    94  	require.NoError(t, err)
    95  	t.Logf("Logged in u2")
    96  
    97  	swtch := func(u *FakeUser) {
    98  		err := u.SwitchTo(tc.G, false)
    99  		require.NoError(t, err)
   100  	}
   101  	for i := 0; i < 3; i++ {
   102  		swtch(u1)
   103  		swtch(u2)
   104  	}
   105  }
   106  
   107  func TestLoginUsernameWhitespace(t *testing.T) {
   108  	tc := SetupEngineTest(t, "login")
   109  	defer tc.Cleanup()
   110  
   111  	u1 := CreateAndSignupFakeUser(tc, "lg")
   112  	Logout(tc)
   113  	u1.Username = " " + u1.Username
   114  	u1.LoginOrBust(tc)
   115  }
   116  
   117  // Login should now unlock device keys at the end, no matter what.
   118  func TestLoginUnlocksDeviceKeys(t *testing.T) {
   119  	tc := SetupEngineTest(t, "login")
   120  	defer tc.Cleanup()
   121  
   122  	u1 := CreateAndSignupFakeUser(tc, "login")
   123  	Logout(tc)
   124  	u1.LoginOrBust(tc)
   125  
   126  	assertPassphraseStreamCache(tc)
   127  	assertDeviceKeysCached(tc)
   128  	assertSecretStored(tc, u1.Username)
   129  }
   130  
   131  func TestLoginActiveDevice(t *testing.T) {
   132  	tc := SetupEngineTest(t, "login")
   133  	defer tc.Cleanup()
   134  
   135  	u1 := CreateAndSignupFakeUser(tc, "login")
   136  	Logout(tc)
   137  	u1.LoginOrBust(tc)
   138  
   139  	assertDeviceKeysCached(tc)
   140  	require.Equal(t, tc.G.ActiveDevice.Name(), defaultDeviceName)
   141  
   142  	simulateServiceRestart(t, tc, u1)
   143  
   144  	assertDeviceKeysCached(tc)
   145  	require.Equal(t, tc.G.ActiveDevice.Name(), defaultDeviceName)
   146  }
   147  
   148  func TestCreateFakeUserNoKeys(t *testing.T) {
   149  	tc := SetupEngineTest(t, "login")
   150  	defer tc.Cleanup()
   151  
   152  	createFakeUserWithNoKeys(tc)
   153  
   154  	me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G))
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	kf := me.GetKeyFamily()
   160  	if kf == nil {
   161  		t.Fatal("user has a nil key family")
   162  	}
   163  	if me.GetEldestKID().Exists() {
   164  		t.Fatalf("user has an eldest key, they should have no keys: %s", me.GetEldestKID())
   165  	}
   166  
   167  	ckf := me.GetComputedKeyFamily()
   168  	if ckf.HasActiveKey() {
   169  		t.Errorf("user has an active key, but they should have no keys")
   170  	}
   171  }
   172  
   173  func testUserHasDeviceKey(tc libkb.TestContext) {
   174  	me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G))
   175  	require.NoError(tc.T, err)
   176  
   177  	kf := me.GetKeyFamily()
   178  	require.NotNil(tc.T, kf)
   179  	require.False(tc.T, me.GetEldestKID().IsNil())
   180  
   181  	ckf := me.GetComputedKeyFamily()
   182  	require.NotNil(tc.T, ckf)
   183  
   184  	active := ckf.HasActiveKey()
   185  	require.True(tc.T, active)
   186  
   187  	subkey, err := me.GetDeviceSubkey()
   188  	require.NoError(tc.T, err)
   189  	require.NotNil(tc.T, subkey)
   190  }
   191  
   192  func TestUserEmails(t *testing.T) {
   193  	tc := SetupEngineTest(t, "login")
   194  	defer tc.Cleanup()
   195  
   196  	CreateAndSignupFakeUser(tc, "login")
   197  	emails, err := libkb.LoadUserEmails(NewMetaContextForTest(tc))
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	if len(emails) == 0 {
   202  		t.Errorf("No emails for user")
   203  	}
   204  }
   205  
   206  func TestProvisionDesktopAfterSwitch(t *testing.T) {
   207  	testProvisionAfterSwitch(t, true)
   208  }
   209  
   210  func TestProvisionAfterSwitchWithWrongUser(t *testing.T) {
   211  	testProvisionAfterSwitch(t, false)
   212  }
   213  
   214  func testProvisionAfterSwitch(t *testing.T, shouldItWork bool) {
   215  	// device X (provisioner) context:
   216  	t.Logf("setup X")
   217  	tcX := SetupEngineTest(t, "kex2provision")
   218  	defer tcX.Cleanup()
   219  
   220  	// device Y (provisionee) context:
   221  	t.Logf("setup Y")
   222  	tcY := SetupEngineTest(t, "template")
   223  	defer tcY.Cleanup()
   224  
   225  	// provisioner needs to be logged in
   226  	t.Logf("provisioner login")
   227  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
   228  	Logout(tcX)
   229  
   230  	var secretX kex2.Secret
   231  	_, err := rand.Read(secretX[:])
   232  	require.NoError(t, err)
   233  
   234  	// Now make a user Pam
   235  	userPam := CreateAndSignupFakeUserPaper(tcX, "login")
   236  
   237  	userProvisionAs := userX
   238  	if !shouldItWork {
   239  		userProvisionAs = userPam
   240  	}
   241  
   242  	// Now switch back to userX, which may or may not be userProvisionAs (above)
   243  	err = userX.SwitchTo(tcX.G, true)
   244  	require.NoError(t, err)
   245  
   246  	secretCh := make(chan kex2.Secret)
   247  
   248  	// provisionee calls login:
   249  	t.Logf("provisionee login")
   250  	uis := libkb.UIs{
   251  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
   252  		LoginUI:     &libkb.TestLoginUI{Username: userProvisionAs.Username},
   253  		LogUI:       tcY.G.UI.GetLogUI(),
   254  		SecretUI:    &libkb.TestSecretUI{},
   255  		GPGUI:       &gpgtestui{},
   256  	}
   257  
   258  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   259  
   260  	var wg sync.WaitGroup
   261  
   262  	assertError := func(err error) {
   263  		if shouldItWork {
   264  			require.NoError(t, err)
   265  		} else {
   266  			require.Error(t, err)
   267  			require.True(t, strings.Contains(err.Error(), "is a different user than we wanted"))
   268  		}
   269  	}
   270  
   271  	// start provisionee
   272  	t.Logf("start provisionee")
   273  	wg.Add(1)
   274  	go func() {
   275  		defer wg.Done()
   276  		m := NewMetaContextForTest(tcY).WithUIs(uis)
   277  		err := RunEngine2(m, eng)
   278  		assertError(err)
   279  	}()
   280  
   281  	// start provisioner
   282  	t.Logf("start provisioner")
   283  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
   284  	wg.Add(1)
   285  	go func() {
   286  		defer wg.Done()
   287  		uis := libkb.UIs{
   288  			SecretUI:    userProvisionAs.NewSecretUI(),
   289  			ProvisionUI: newTestProvisionUI(),
   290  		}
   291  		m := NewMetaContextForTest(tcX).WithUIs(uis)
   292  		err := RunEngine2(m, provisioner)
   293  		assertError(err)
   294  	}()
   295  
   296  	secretFromY := <-secretCh
   297  
   298  	provisioner.AddSecret(secretFromY)
   299  
   300  	t.Logf("wait")
   301  	wg.Wait()
   302  
   303  	require.False(t, t.Failed(), "prior failure in a goroutine")
   304  
   305  	if !shouldItWork {
   306  		return
   307  	}
   308  
   309  	t.Logf("asserts")
   310  	if err := AssertProvisioned(tcY); err != nil {
   311  		t.Fatal(err)
   312  	}
   313  
   314  	// after provisioning, the passphrase stream should be cached
   315  	// (note that this just checks the passphrase stream, not 3sec)
   316  	assertPassphraseStreamCache(tcY)
   317  
   318  	// after provisioning, the device keys should be cached
   319  	assertDeviceKeysCached(tcY)
   320  
   321  	// after provisioning, the secret should be stored
   322  	assertSecretStored(tcY, userX.Username)
   323  
   324  }
   325  
   326  func TestProvisionDesktop(t *testing.T) {
   327  	doWithSigChainVersions(func(sigVersion libkb.SigVersion) {
   328  		testProvisionDesktop(t, false, sigVersion)
   329  	})
   330  }
   331  
   332  func TestProvisionDesktopPUK(t *testing.T) {
   333  	testProvisionDesktop(t, true, libkb.KeybaseNullSigVersion)
   334  }
   335  
   336  func testProvisionDesktop(t *testing.T, upgradePerUserKey bool, sigVersion libkb.SigVersion) {
   337  	// device X (provisioner) context:
   338  	t.Logf("setup X")
   339  	tcX := SetupEngineTest(t, "kex2provision")
   340  	defer tcX.Cleanup()
   341  	tcX.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
   342  
   343  	// device Y (provisionee) context:
   344  	t.Logf("setup Y")
   345  	tcY := SetupEngineTest(t, "template")
   346  	defer tcY.Cleanup()
   347  	tcY.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
   348  
   349  	// provisioner needs to be logged in
   350  	t.Logf("provisioner login")
   351  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
   352  	var secretX kex2.Secret
   353  	if _, err := rand.Read(secretX[:]); err != nil {
   354  		t.Fatal(err)
   355  	}
   356  
   357  	secretCh := make(chan kex2.Secret)
   358  
   359  	// provisionee calls login:
   360  	t.Logf("provisionee login")
   361  	uis := libkb.UIs{
   362  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
   363  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
   364  		LogUI:       tcY.G.UI.GetLogUI(),
   365  		SecretUI:    &libkb.TestSecretUI{},
   366  		GPGUI:       &gpgtestui{},
   367  	}
   368  
   369  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   370  
   371  	var wg sync.WaitGroup
   372  
   373  	// start provisionee
   374  	t.Logf("start provisionee")
   375  	wg.Add(1)
   376  	go func() {
   377  		defer wg.Done()
   378  		m := NewMetaContextForTest(tcY).WithUIs(uis)
   379  		if err := RunEngine2(m, eng); err != nil {
   380  			t.Errorf("login error: %s", err)
   381  			return
   382  		}
   383  	}()
   384  
   385  	// start provisioner
   386  	t.Logf("start provisioner")
   387  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
   388  	wg.Add(1)
   389  	go func() {
   390  		defer wg.Done()
   391  
   392  		uis := libkb.UIs{
   393  			SecretUI:    userX.NewSecretUI(),
   394  			ProvisionUI: newTestProvisionUI(),
   395  		}
   396  		m := NewMetaContextForTest(tcX).WithUIs(uis)
   397  		if err := RunEngine2(m, provisioner); err != nil {
   398  			t.Errorf("provisioner error: %s", err)
   399  			return
   400  		}
   401  	}()
   402  
   403  	secretFromY := <-secretCh
   404  
   405  	provisioner.AddSecret(secretFromY)
   406  
   407  	t.Logf("wait")
   408  	wg.Wait()
   409  
   410  	require.False(t, t.Failed(), "prior failure in a goroutine")
   411  
   412  	t.Logf("asserts")
   413  	if err := AssertProvisioned(tcY); err != nil {
   414  		t.Fatal(err)
   415  	}
   416  
   417  	// after provisioning, the passphrase stream should be cached
   418  	// (note that this just checks the passphrase stream, not 3sec)
   419  	assertPassphraseStreamCache(tcY)
   420  
   421  	// after provisioning, the device keys should be cached
   422  	assertDeviceKeysCached(tcY)
   423  
   424  	// after provisioning, the secret should be stored
   425  	assertSecretStored(tcY, userX.Username)
   426  
   427  	t.Logf("test tracks")
   428  	testTrack(t, tcY, sigVersion, "t_alice")
   429  
   430  	// Make sure that we can still track without a passphrase
   431  	// after a simulated service restart.  In other words, that
   432  	// the full LKSec secret was written to the secret store.
   433  	simulateServiceRestart(t, tcY, userX)
   434  	testTrack(t, tcY, sigVersion, "t_bob")
   435  }
   436  
   437  func TestProvisionMobile(t *testing.T) {
   438  	// device X (provisioner) context:
   439  	tcX := SetupEngineTest(t, "kex2provision")
   440  	defer tcX.Cleanup()
   441  
   442  	// device Y (provisionee) context:
   443  	tcY := SetupEngineTest(t, "template")
   444  	defer tcY.Cleanup()
   445  
   446  	// provisioner needs to be logged in
   447  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
   448  	var secretX kex2.Secret
   449  	if _, err := rand.Read(secretX[:]); err != nil {
   450  		t.Fatal(err)
   451  	}
   452  
   453  	secretCh := make(chan kex2.Secret)
   454  
   455  	// provisionee calls login:
   456  	uis := libkb.UIs{
   457  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
   458  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
   459  		LogUI:       tcY.G.UI.GetLogUI(),
   460  		SecretUI:    &libkb.TestSecretUI{},
   461  		GPGUI:       &gpgtestui{},
   462  	}
   463  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_MOBILE, "", keybase1.ClientType_CLI)
   464  
   465  	var wg sync.WaitGroup
   466  
   467  	// start provisionee
   468  	wg.Add(1)
   469  	go func() {
   470  		defer wg.Done()
   471  		m := NewMetaContextForTest(tcY).WithUIs(uis)
   472  		if err := RunEngine2(m, eng); err != nil {
   473  			t.Errorf("login error: %s", err)
   474  			return
   475  		}
   476  	}()
   477  
   478  	// start provisioner
   479  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
   480  	wg.Add(1)
   481  	go func() {
   482  		defer wg.Done()
   483  
   484  		uis := libkb.UIs{
   485  			SecretUI:    userX.NewSecretUI(),
   486  			ProvisionUI: newTestProvisionUI(),
   487  		}
   488  		m := NewMetaContextForTest(tcX).WithUIs(uis)
   489  		if err := RunEngine2(m, provisioner); err != nil {
   490  			t.Errorf("provisioner error: %s", err)
   491  			return
   492  		}
   493  	}()
   494  
   495  	secretFromY := <-secretCh
   496  
   497  	provisioner.AddSecret(secretFromY)
   498  
   499  	wg.Wait()
   500  
   501  	if err := AssertProvisioned(tcY); err != nil {
   502  		t.Fatal(err)
   503  	}
   504  }
   505  
   506  func TestProvisionWithRevoke(t *testing.T) {
   507  	// device X (provisioner) context:
   508  	tcX := SetupEngineTest(t, "kex2provision")
   509  	defer tcX.Cleanup()
   510  
   511  	// device Y (provisionee) context:
   512  	tcY := SetupEngineTest(t, "template")
   513  	defer tcY.Cleanup()
   514  
   515  	// provisioner needs to be logged in
   516  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
   517  	var secretX kex2.Secret
   518  	if _, err := rand.Read(secretX[:]); err != nil {
   519  		t.Fatal(err)
   520  	}
   521  
   522  	secretCh := make(chan kex2.Secret)
   523  
   524  	// provisionee calls login:
   525  	uis := libkb.UIs{
   526  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
   527  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
   528  		LogUI:       tcY.G.UI.GetLogUI(),
   529  		SecretUI:    &libkb.TestSecretUI{},
   530  		GPGUI:       &gpgtestui{},
   531  	}
   532  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_MOBILE, "", keybase1.ClientType_CLI)
   533  
   534  	var wg sync.WaitGroup
   535  
   536  	// start provisionee
   537  	wg.Add(1)
   538  	go func() {
   539  		defer wg.Done()
   540  		m := NewMetaContextForTest(tcY).WithUIs(uis)
   541  		if err := RunEngine2(m, eng); err != nil {
   542  			t.Errorf("login error: %s", err)
   543  			return
   544  		}
   545  	}()
   546  
   547  	// start provisioner
   548  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
   549  	wg.Add(1)
   550  	go func() {
   551  		defer wg.Done()
   552  
   553  		uis := libkb.UIs{
   554  			SecretUI:    userX.NewSecretUI(),
   555  			ProvisionUI: newTestProvisionUI(),
   556  		}
   557  		m := NewMetaContextForTest(tcX).WithUIs(uis)
   558  		if err := RunEngine2(m, provisioner); err != nil {
   559  			t.Errorf("provisioner error: %s", err)
   560  			return
   561  		}
   562  	}()
   563  
   564  	secretFromY := <-secretCh
   565  
   566  	// x is going to revoke a device here to change the sigchain
   567  	revoked := revokeAnyPaperKey(tcX, userX)
   568  	if revoked == nil {
   569  		t.Fatal("revokeAnyPaperKey for user x did not revoke anything")
   570  	}
   571  
   572  	provisioner.AddSecret(secretFromY)
   573  
   574  	wg.Wait()
   575  
   576  	if err := AssertProvisioned(tcY); err != nil {
   577  		t.Fatal(err)
   578  	}
   579  }
   580  
   581  // If a user has device keys and no pgp keys, not selecting a device
   582  // should trigger the autoreset flow.
   583  func TestProvisionAutoreset(t *testing.T) {
   584  	// device X (provisioner) context:
   585  	tcX := SetupEngineTest(t, "provision_x")
   586  	defer tcX.Cleanup()
   587  
   588  	// create user (and device X)
   589  	userX := CreateAndSignupFakeUser(tcX, "login")
   590  	require.NoError(t, AssertLoggedIn(tcX), "should be logged in on device x")
   591  	require.NoError(t, AssertProvisioned(tcX), "should be provisioned on device x")
   592  
   593  	// device Y (provisionee) context:
   594  	tcY := SetupEngineTest(t, "provision_y")
   595  	defer tcY.Cleanup()
   596  
   597  	uis := libkb.UIs{
   598  		ProvisionUI: newTestProvisionUIChooseNoDevice(),
   599  		LoginUI: &libkb.TestLoginUI{
   600  			Username:     userX.Username,
   601  			ResetAccount: keybase1.ResetPromptResponse_CONFIRM_RESET,
   602  		},
   603  		LogUI:    tcY.G.UI.GetLogUI(),
   604  		SecretUI: &libkb.TestSecretUI{Passphrase: userX.Passphrase},
   605  		GPGUI:    &gpgtestui{},
   606  	}
   607  	m := NewMetaContextForTest(tcY).WithUIs(uis)
   608  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   609  	require.NoError(t, RunEngine2(m, eng), "expected login engine to succeed")
   610  	require.NotNil(t, AssertLoggedIn(tcY), "should not be logged in")
   611  
   612  	// Travel 5 days into future + 1h to make sure that it all runs
   613  	require.NoError(t, timeTravelReset(tcX, time.Hour*121))
   614  	require.NoError(t, processReset(tcX))
   615  
   616  	// Rather than sleeping we'll wait for autoreset by analyzing its state
   617  	var lastErr error
   618  	for i := 0; i < 60; i++ {
   619  		// up to 60 iters * 100ms = 6s
   620  		lastErr = assertAutoreset(tcX, userX.UID(), libkb.AutoresetEventReady)
   621  		if lastErr == nil {
   622  			break
   623  		}
   624  		time.Sleep(100 * time.Millisecond)
   625  	}
   626  	require.NoError(t, lastErr)
   627  
   628  	// Second iteration on device Y should result in a reset + provision
   629  	uis = libkb.UIs{
   630  		ProvisionUI: newTestProvisionUIChooseNoDevice(),
   631  		LoginUI: &libkb.TestLoginUI{
   632  			Username:     userX.Username,
   633  			ResetAccount: keybase1.ResetPromptResponse_CONFIRM_RESET,
   634  		},
   635  		LogUI:    tcY.G.UI.GetLogUI(),
   636  		SecretUI: &libkb.TestSecretUI{Passphrase: userX.Passphrase},
   637  		GPGUI:    &gpgtestui{},
   638  	}
   639  	m = NewMetaContextForTest(tcY).WithUIs(uis)
   640  	eng = NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   641  	require.NoError(t, RunEngine2(m, eng), "expected 2nd login engine to succeed")
   642  	require.NoError(t, AssertLoggedIn(tcY), "should be logged in")
   643  	require.NoError(t, AssertProvisioned(tcY), "should be provisioned on device y")
   644  }
   645  
   646  func timeTravelReset(tc libkb.TestContext, duration time.Duration) error {
   647  	mctx := libkb.NewMetaContextForTest(tc)
   648  	_, err := tc.G.API.Post(mctx, libkb.APIArg{
   649  		Endpoint:    "autoreset/timetravel",
   650  		SessionType: libkb.APISessionTypeREQUIRED,
   651  		Args: libkb.HTTPArgs{
   652  			"duration_sec": libkb.I{Val: int(gregor1.ToDurationSec(duration))},
   653  		},
   654  	})
   655  	return err
   656  }
   657  
   658  func processReset(tc libkb.TestContext) error {
   659  	mctx := libkb.NewMetaContextForTest(tc)
   660  	_, err := tc.G.API.Post(mctx, libkb.APIArg{
   661  		Endpoint:    "autoreset/process_dev",
   662  		SessionType: libkb.APISessionTypeNONE,
   663  		RetryCount:  5,
   664  	})
   665  	return err
   666  }
   667  
   668  func TestProvisionPassphraseNoKeysSolo(t *testing.T) {
   669  	testProvisionPassphraseNoKeysSolo(t, false)
   670  }
   671  
   672  func TestProvisionPassphraseNoKeysSoloPUK(t *testing.T) {
   673  	testProvisionPassphraseNoKeysSolo(t, true)
   674  }
   675  
   676  // If a user has no keys, provision via passphrase should work.
   677  func testProvisionPassphraseNoKeysSolo(t *testing.T, upgradePerUserKey bool) {
   678  	tcWeb := SetupEngineTest(t, "web")
   679  	defer tcWeb.Cleanup()
   680  	tcWeb.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
   681  
   682  	username, passphrase := createFakeUserWithNoKeys(tcWeb)
   683  
   684  	Logout(tcWeb)
   685  
   686  	hasZeroPaperDev(tcWeb, &FakeUser{Username: username, Passphrase: passphrase})
   687  
   688  	tc := SetupEngineTest(t, "login")
   689  	defer tc.Cleanup()
   690  	tc.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
   691  
   692  	uis := libkb.UIs{
   693  		ProvisionUI: newTestProvisionUIPassphrase(),
   694  		LoginUI:     &libkb.TestLoginUI{Username: username},
   695  		LogUI:       tc.G.UI.GetLogUI(),
   696  		SecretUI:    &libkb.TestSecretUI{Passphrase: passphrase},
   697  		GPGUI:       &gpgtestui{},
   698  	}
   699  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   700  	m := NewMetaContextForTest(tc).WithUIs(uis)
   701  	if err := RunEngine2(m, eng); err != nil {
   702  		t.Fatal(err)
   703  	}
   704  
   705  	// since this user didn't have any keys, login should have fixed that:
   706  	testUserHasDeviceKey(tc)
   707  
   708  	// and they should not have a paper backup key
   709  	hasZeroPaperDev(tc, &FakeUser{Username: username, Passphrase: passphrase})
   710  
   711  	if err := AssertProvisioned(tc); err != nil {
   712  		t.Fatal(err)
   713  	}
   714  
   715  	// secret should be stored
   716  	assertSecretStored(tc, username)
   717  }
   718  
   719  // Test bad name input (not valid username or email address).
   720  func TestProvisionPassphraseBadName(t *testing.T) {
   721  	tcWeb := SetupEngineTest(t, "web")
   722  	defer tcWeb.Cleanup()
   723  
   724  	_, passphrase := createFakeUserWithNoKeys(tcWeb)
   725  
   726  	Logout(tcWeb)
   727  
   728  	tc := SetupEngineTest(t, "login")
   729  	defer tc.Cleanup()
   730  
   731  	uis := libkb.UIs{
   732  		ProvisionUI: newTestProvisionUIPassphrase(),
   733  		LoginUI:     &libkb.TestLoginUI{Username: strings.Repeat("X", 20)},
   734  		LogUI:       tc.G.UI.GetLogUI(),
   735  		SecretUI:    &libkb.TestSecretUI{Passphrase: passphrase},
   736  		GPGUI:       &gpgtestui{},
   737  	}
   738  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   739  	m := NewMetaContextForTest(tc).WithUIs(uis)
   740  	err := RunEngine2(m, eng)
   741  	require.Error(t, err)
   742  	require.IsType(t, libkb.BadUsernameError{}, err)
   743  }
   744  
   745  // If a user has (only) a synced pgp key, provision via passphrase
   746  // should work.
   747  func TestProvisionPassphraseSyncedPGP(t *testing.T) {
   748  	tc := SetupEngineTest(t, "login")
   749  	u1 := createFakeUserWithPGPOnly(t, tc)
   750  	t.Log("Created fake user")
   751  	Logout(tc)
   752  	tc.Cleanup()
   753  
   754  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   755  	tc = SetupEngineTest(t, "login")
   756  	defer tc.Cleanup()
   757  
   758  	uis := libkb.UIs{
   759  		ProvisionUI: newTestProvisionUIPassphrase(),
   760  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
   761  		LogUI:       tc.G.UI.GetLogUI(),
   762  		SecretUI:    u1.NewSecretUI(),
   763  		GPGUI:       &gpgtestui{},
   764  	}
   765  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   766  	m := NewMetaContextForTest(tc).WithUIs(uis)
   767  	if err := RunEngine2(m, eng); err != nil {
   768  		t.Fatal(err)
   769  	}
   770  
   771  	// since this user didn't have any device keys, login should have fixed that:
   772  	testUserHasDeviceKey(tc)
   773  
   774  	// and they should not have a paper backup key
   775  	hasZeroPaperDev(tc, u1)
   776  
   777  	if err := AssertProvisioned(tc); err != nil {
   778  		t.Fatal(err)
   779  	}
   780  
   781  	// after provisioning, the secret should be stored
   782  	assertSecretStored(tc, u1.Username)
   783  
   784  	// should be able to sign and to track someone (no passphrase prompt)
   785  	testSign(t, tc)
   786  	simulateServiceRestart(t, tc, u1)
   787  	testSign(t, tc)
   788  }
   789  
   790  // If a user has (only) a synced pgp key, provision via passphrase
   791  // should work, if they specify email address as username.
   792  func TestProvisionPassphraseSyncedPGPEmail(t *testing.T) {
   793  	tc := SetupEngineTest(t, "login")
   794  	u1 := createFakeUserWithPGPOnly(t, tc)
   795  	Logout(tc)
   796  	tc.Cleanup()
   797  
   798  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   799  	tc = SetupEngineTest(t, "login")
   800  	defer tc.Cleanup()
   801  
   802  	uis := libkb.UIs{
   803  		ProvisionUI: newTestProvisionUIPassphrase(),
   804  		LoginUI:     &libkb.TestLoginUI{Username: u1.Email},
   805  		LogUI:       tc.G.UI.GetLogUI(),
   806  		SecretUI:    u1.NewSecretUI(),
   807  		GPGUI:       &gpgtestui{},
   808  	}
   809  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   810  	m := NewMetaContextForTest(tc).WithUIs(uis)
   811  	err := RunEngine2(m, eng)
   812  	require.Error(t, err)
   813  	require.IsType(t, libkb.BadUsernameError{}, err)
   814  	require.Contains(t, err.Error(), "not supported")
   815  }
   816  
   817  // Check that a bad passphrase fails to unlock a synced pgp key
   818  func TestProvisionSyncedPGPBadPassphrase(t *testing.T) {
   819  	tc := SetupEngineTest(t, "login")
   820  	u1 := createFakeUserWithPGPOnly(t, tc)
   821  	t.Log("Created fake user")
   822  	Logout(tc)
   823  	tc.Cleanup()
   824  
   825  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   826  	tc = SetupEngineTest(t, "login")
   827  	defer tc.Cleanup()
   828  
   829  	uis := libkb.UIs{
   830  		ProvisionUI: newTestProvisionUIPassphrase(),
   831  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
   832  		LogUI:       tc.G.UI.GetLogUI(),
   833  		SecretUI:    &libkb.TestSecretUI{Passphrase: u1.Passphrase + u1.Passphrase},
   834  		GPGUI:       &gpgtestui{},
   835  	}
   836  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   837  	m := NewMetaContextForTest(tc).WithUIs(uis)
   838  	if err := RunEngine2(m, eng); err == nil {
   839  		t.Fatal("sync pgp provision worked with bad passphrase")
   840  	} else if _, ok := err.(libkb.PassphraseError); !ok {
   841  		t.Errorf("error: %T, expected libkb.PassphraseError", err)
   842  	}
   843  }
   844  
   845  // If a user is logged in as alice, then logs in as bob (who has
   846  // no keys), provision via passphrase should work.
   847  // Bug https://keybase.atlassian.net/browse/CORE-2605
   848  func TestProvisionPassphraseNoKeysSwitchUser(t *testing.T) {
   849  	// this is the web user
   850  	tcWeb := SetupEngineTest(t, "web")
   851  	username, passphrase := createFakeUserWithNoKeys(tcWeb)
   852  	Logout(tcWeb)
   853  	tcWeb.Cleanup()
   854  
   855  	tc := SetupEngineTest(t, "login")
   856  	defer tc.Cleanup()
   857  
   858  	// this is a provisioned user.  stay logged in as this user
   859  	// and start login process for web user.
   860  	CreateAndSignupFakeUser(tc, "alice")
   861  
   862  	Logout(tc)
   863  
   864  	uis := libkb.UIs{
   865  		ProvisionUI: newTestProvisionUIPassphrase(),
   866  		LoginUI:     &libkb.TestLoginUI{Username: username},
   867  		LogUI:       tc.G.UI.GetLogUI(),
   868  		SecretUI:    &libkb.TestSecretUI{Passphrase: passphrase},
   869  		GPGUI:       &gpgtestui{},
   870  	}
   871  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, username, keybase1.ClientType_CLI)
   872  	m := NewMetaContextForTest(tc).WithUIs(uis)
   873  	if err := RunEngine2(m, eng); err != nil {
   874  		t.Fatal(err)
   875  	}
   876  
   877  	// since this user didn't have any keys, login should have fixed that:
   878  	testUserHasDeviceKey(tc)
   879  
   880  	t.Logf("user has device key")
   881  
   882  	// and they should not have a paper backup key
   883  	hasZeroPaperDev(tc, &FakeUser{Username: username, Passphrase: passphrase})
   884  
   885  	t.Logf("user has paper device")
   886  
   887  	if err := AssertProvisioned(tc); err != nil {
   888  		t.Fatal(err)
   889  	}
   890  
   891  	// after provisioning, the secret should be stored
   892  	assertSecretStored(tc, username)
   893  }
   894  
   895  // If a user has a synced pgp key, they can use it to provision their first device.
   896  // After that, if they have a PUK, then they should not be able to provision with
   897  // the synced pgp key again.
   898  func TestProvisionSyncedPGPWithPUK(t *testing.T) {
   899  	tc := SetupEngineTest(t, "login")
   900  	u1 := createFakeUserWithPGPOnly(t, tc)
   901  	Logout(tc)
   902  	tc.Cleanup()
   903  
   904  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   905  	// (PUK is on)
   906  	tc = SetupEngineTest(t, "login")
   907  	defer tc.Cleanup()
   908  
   909  	uis := libkb.UIs{
   910  		ProvisionUI: newTestProvisionUIPassphrase(),
   911  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
   912  		LogUI:       tc.G.UI.GetLogUI(),
   913  		SecretUI:    u1.NewSecretUI(),
   914  		GPGUI:       &gpgtestui{},
   915  	}
   916  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   917  	m := NewMetaContextForTest(tc).WithUIs(uis)
   918  	if err := RunEngine2(m, eng); err != nil {
   919  		t.Fatal(err)
   920  	}
   921  
   922  	// since this user didn't have any device keys, login should have fixed that:
   923  	testUserHasDeviceKey(tc)
   924  	if err := AssertProvisioned(tc); err != nil {
   925  		t.Fatal(err)
   926  	}
   927  
   928  	// force them to have a puk
   929  	ForcePUK(tc)
   930  
   931  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   932  	// (PUK is on)
   933  	tc2 := SetupEngineTest(t, "login")
   934  	defer tc2.Cleanup()
   935  
   936  	uis2 := libkb.UIs{
   937  		ProvisionUI: newTestProvisionUIPassphrase(),
   938  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
   939  		LogUI:       tc2.G.UI.GetLogUI(),
   940  		SecretUI:    u1.NewSecretUI(),
   941  		GPGUI:       &gpgtestui{},
   942  	}
   943  
   944  	// this should fail, the user should not be allowed to use synced pgp key to provision
   945  	// second device when PUK is on:
   946  	eng2 := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   947  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
   948  	err := RunEngine2(m2, eng2)
   949  	require.Error(t, err, "Provision w/ synced pgp key on device 2 w/ PUK enabled should fail")
   950  	require.IsType(t, err, libkb.ProvisionViaDeviceRequiredError{})
   951  }
   952  
   953  // Provision device using a private GPG key (not synced to keybase
   954  // server), import private key to lksec. With PUK, shouldn't be allowed on
   955  // device 2.
   956  func TestProvisionGPGWithPUK(t *testing.T) {
   957  	tc := SetupEngineTest(t, "login")
   958  	defer tc.Cleanup()
   959  
   960  	u1 := createFakeUserWithPGPPubOnly(t, tc)
   961  	Logout(tc)
   962  
   963  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   964  	tc2 := SetupEngineTest(t, "login")
   965  	defer tc2.Cleanup()
   966  
   967  	// we need the gpg keyring that's in the first homedir
   968  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
   969  		t.Fatal(err)
   970  	}
   971  
   972  	// run login on new device
   973  	uis2 := libkb.UIs{
   974  		ProvisionUI: newTestProvisionUIGPGImport(),
   975  		LogUI:       tc2.G.UI.GetLogUI(),
   976  		SecretUI:    u1.NewSecretUI(),
   977  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
   978  		GPGUI:       &gpgtestui{},
   979  	}
   980  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
   981  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
   982  	if err := RunEngine2(m2, eng); err != nil {
   983  		t.Fatal(err)
   984  	}
   985  
   986  	testUserHasDeviceKey(tc2)
   987  	if err := AssertProvisioned(tc2); err != nil {
   988  		t.Fatal(err)
   989  	}
   990  
   991  	// force them to have a puk
   992  	ForcePUK(tc2)
   993  
   994  	// redo SetupEngineTest to get a new home directory...should look like a new device.
   995  	tc3 := SetupEngineTest(t, "login")
   996  	defer tc3.Cleanup()
   997  
   998  	// we need the gpg keyring
   999  	if err := tc2.MoveGpgKeyringTo(tc3); err != nil {
  1000  		t.Fatal(err)
  1001  	}
  1002  
  1003  	// run login on new device
  1004  	uis3 := libkb.UIs{
  1005  		ProvisionUI: newTestProvisionUIGPGImport(),
  1006  		LogUI:       tc3.G.UI.GetLogUI(),
  1007  		SecretUI:    u1.NewSecretUI(),
  1008  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1009  		GPGUI:       &gpgtestui{},
  1010  	}
  1011  	eng3 := NewLogin(tc3.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1012  	m3 := NewMetaContextForTest(tc3).WithUIs(uis3)
  1013  	err := RunEngine2(m3, eng3)
  1014  	require.Error(t, err, "Provision w/ gpg key on device 2 w/ PUK enabled should fail")
  1015  	require.IsType(t, err, libkb.ProvisionViaDeviceRequiredError{})
  1016  }
  1017  
  1018  // Test provisioning where we use one username, but suddenly we are
  1019  // key-exchanging with someone else.
  1020  func TestProvisionWithUnexpectedX(t *testing.T) {
  1021  	t.Logf("Setting contexts and users")
  1022  
  1023  	// We want to provision as this user:
  1024  	tcV := SetupEngineTest(t, "kex2provision")
  1025  	defer tcV.Cleanup()
  1026  	wantedUser := CreateAndSignupFakeUserPaper(tcV, "usr1")
  1027  
  1028  	// But actually this one will respond:
  1029  	tcF := SetupEngineTest(t, "unexpected")
  1030  	defer tcF.Cleanup()
  1031  	actualUser := CreateAndSignupFakeUserPaper(tcF, "usr2")
  1032  	var secretX kex2.Secret
  1033  	_, err := rand.Read(secretX[:])
  1034  	require.NoError(t, err)
  1035  
  1036  	// device Y (provisionee) context:
  1037  	tcY := SetupEngineTest(t, "template")
  1038  	defer tcY.Cleanup()
  1039  
  1040  	secretCh := make(chan kex2.Secret)
  1041  
  1042  	// provisionee calls login:
  1043  	t.Logf("provisionee login")
  1044  	uis := libkb.UIs{
  1045  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  1046  		LoginUI:     &libkb.TestLoginUI{Username: wantedUser.Username},
  1047  		LogUI:       tcY.G.UI.GetLogUI(),
  1048  		SecretUI:    &libkb.TestSecretUI{},
  1049  		GPGUI:       &gpgtestui{},
  1050  	}
  1051  
  1052  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1053  
  1054  	var wg sync.WaitGroup
  1055  
  1056  	// start provisionee
  1057  	t.Logf("start provisionee")
  1058  	wg.Add(1)
  1059  	go func() {
  1060  		defer wg.Done()
  1061  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  1062  		err := RunEngine2(m, eng)
  1063  		require.Error(t, err)
  1064  		require.Contains(t, err.Error(), "different user")
  1065  	}()
  1066  
  1067  	// start provisioner
  1068  	t.Logf("start provisioner")
  1069  	provisioner := NewKex2Provisioner(tcF.G, secretX, nil)
  1070  	wg.Add(1)
  1071  	go func() {
  1072  		defer wg.Done()
  1073  
  1074  		uis := libkb.UIs{
  1075  			SecretUI:    actualUser.NewSecretUI(),
  1076  			ProvisionUI: newTestProvisionUI(),
  1077  		}
  1078  		m := NewMetaContextForTest(tcF).WithUIs(uis)
  1079  		err := RunEngine2(m, provisioner)
  1080  		require.Error(t, err)
  1081  		require.Contains(t, err.Error(), "different user")
  1082  	}()
  1083  
  1084  	secretFromY := <-secretCh
  1085  	provisioner.AddSecret(secretFromY)
  1086  
  1087  	t.Logf("wait")
  1088  	wg.Wait()
  1089  }
  1090  
  1091  func testSign(t *testing.T, tc libkb.TestContext) {
  1092  	// should be able to sign something with new device keys without
  1093  	// entering a passphrase
  1094  	var sink bytes.Buffer
  1095  
  1096  	sarg := &SaltpackSignArg{
  1097  		Sink:   libkb.NopWriteCloser{W: &sink},
  1098  		Source: io.NopCloser(bytes.NewBufferString("hello")),
  1099  	}
  1100  
  1101  	signEng := NewSaltpackSign(tc.G, sarg)
  1102  	uis := libkb.UIs{
  1103  		IdentifyUI: &FakeIdentifyUI{},
  1104  		SecretUI:   &libkb.TestSecretUI{}, // empty
  1105  	}
  1106  
  1107  	m := NewMetaContextForTest(tc).WithUIs(uis)
  1108  	if err := RunEngine2(m, signEng); err != nil {
  1109  		t.Fatal(err)
  1110  	}
  1111  }
  1112  
  1113  func testTrack(t *testing.T, tc libkb.TestContext, sigVersion libkb.SigVersion, whom string) {
  1114  
  1115  	if sigVersion == libkb.KeybaseNullSigVersion {
  1116  		sigVersion = libkb.GetDefaultSigVersion(tc.G)
  1117  	}
  1118  	// should be able to track someone (no passphrase prompt)
  1119  	targ := &TrackEngineArg{
  1120  		UserAssertion: whom,
  1121  		Options:       keybase1.TrackOptions{BypassConfirm: true},
  1122  		SigVersion:    sigVersion,
  1123  	}
  1124  	uis := libkb.UIs{
  1125  		LogUI:      tc.G.UI.GetLogUI(),
  1126  		IdentifyUI: &FakeIdentifyUI{},
  1127  		SecretUI:   &libkb.TestSecretUI{},
  1128  	}
  1129  
  1130  	teng := NewTrackEngine(tc.G, targ)
  1131  	m := NewMetaContextForTest(tc).WithUIs(uis)
  1132  	err := RunEngine2(m, teng)
  1133  	require.NoError(t, err)
  1134  }
  1135  
  1136  func testProvisionPaperOnly(t *testing.T, changePaperkey func(s string) string) {
  1137  	tc := SetupEngineTest(t, "login")
  1138  	defer tc.Cleanup()
  1139  
  1140  	fu := NewFakeUserOrBust(t, "paper")
  1141  	arg := MakeTestSignupEngineRunArg(fu)
  1142  	arg.SkipPaper = false
  1143  	loginUI := &paperLoginUI{Username: fu.Username}
  1144  	uis := libkb.UIs{
  1145  		LogUI:    tc.G.UI.GetLogUI(),
  1146  		GPGUI:    &gpgtestui{},
  1147  		SecretUI: fu.NewSecretUI(),
  1148  		LoginUI:  loginUI,
  1149  	}
  1150  	s := NewSignupEngine(tc.G, &arg)
  1151  	err := RunEngine2(NewMetaContextForTest(tc).WithUIs(uis), s)
  1152  	if err != nil {
  1153  		tc.T.Fatal(err)
  1154  	}
  1155  
  1156  	assertNumDevicesAndKeys(tc, fu, 2, 4)
  1157  
  1158  	Logout(tc)
  1159  
  1160  	if len(loginUI.PaperPhrase) == 0 {
  1161  		t.Fatal("login ui has no paper key phrase")
  1162  	}
  1163  
  1164  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1165  	tc2 := SetupEngineTest(t, "login")
  1166  	fakeClock := clockwork.NewFakeClockAt(time.Now())
  1167  	tc2.G.SetClock(fakeClock)
  1168  	// to pick up the new clock...
  1169  	defer tc2.Cleanup()
  1170  
  1171  	secUI := fu.NewSecretUI()
  1172  	secUI.Passphrase = changePaperkey(loginUI.PaperPhrase)
  1173  	provUI := newTestProvisionUIPaper()
  1174  	provLoginUI := &libkb.TestLoginUI{Username: fu.Username}
  1175  	uis2 := libkb.UIs{
  1176  		ProvisionUI: provUI,
  1177  		LogUI:       tc2.G.UI.GetLogUI(),
  1178  		SecretUI:    secUI,
  1179  		LoginUI:     provLoginUI,
  1180  		GPGUI:       &gpgtestui{},
  1181  	}
  1182  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1183  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1184  	if err := RunEngine2(m2, eng); err != nil {
  1185  		t.Fatal(err)
  1186  	}
  1187  
  1188  	testUserHasDeviceKey(tc2)
  1189  
  1190  	assertNumDevicesAndKeys(tc, fu, 3, 6)
  1191  
  1192  	if err := AssertProvisioned(tc2); err != nil {
  1193  		t.Fatal(err)
  1194  	}
  1195  
  1196  	if provUI.calledChooseDeviceType != 0 {
  1197  		t.Errorf("expected 0 calls to ChooseDeviceType, got %d", provUI.calledChooseDeviceType)
  1198  	}
  1199  	if provLoginUI.CalledGetEmailOrUsername != 1 {
  1200  		t.Errorf("expected 1 call to GetEmailOrUsername, got %d", provLoginUI.CalledGetEmailOrUsername)
  1201  	}
  1202  	var device *libkb.DeviceWithKeys
  1203  
  1204  	ch := make(chan struct{})
  1205  	pch := func() {
  1206  		ch <- struct{}{}
  1207  	}
  1208  
  1209  	wrapper := m2.ActiveDevice().ProvisioningKeyWrapper(m2)
  1210  	if wrapper != nil {
  1211  		device = wrapper.DeviceWithKeys()
  1212  		wrapper.SetTestPostCleanHook(pch)
  1213  	}
  1214  
  1215  	if device == nil || device.EncryptionKey() == nil {
  1216  		t.Errorf("Got a null paper encryption key")
  1217  	}
  1218  
  1219  	fakeClock.Advance(libkb.ProvisioningKeyMemoryTimeout + 1*time.Minute)
  1220  	<-ch
  1221  
  1222  	device = m2.ActiveDevice().ProvisioningKey(m2)
  1223  	if device != nil {
  1224  		t.Errorf("Got a non-null paper encryption key after timeout")
  1225  	}
  1226  
  1227  	testSign(t, tc2)
  1228  
  1229  	testTrack(t, tc2, libkb.KeybaseNullSigVersion, "t_alice")
  1230  
  1231  	simulateServiceRestart(t, tc2, fu)
  1232  
  1233  	// should be able to sign and to track someone (no passphrase prompt)
  1234  	testSign(t, tc2)
  1235  	testTrack(t, tc2, libkb.KeybaseNullSigVersion, "t_bob")
  1236  }
  1237  
  1238  func removePaperkeyPrefix(paperkey string) string {
  1239  	return strings.Join(strings.Split(paperkey, " ")[2:], " ")
  1240  }
  1241  
  1242  func TestProvisionPaperOnlyNoPrefix(t *testing.T) {
  1243  	testProvisionPaperOnly(t, removePaperkeyPrefix)
  1244  }
  1245  
  1246  func TestProvisionPaperOnly(t *testing.T) {
  1247  	testProvisionPaperOnly(t, func(s string) string { return s })
  1248  }
  1249  
  1250  func simulateServiceRestart(t *testing.T, tc libkb.TestContext, fu *FakeUser) {
  1251  
  1252  	// Simulate restarting the service by wiping out the
  1253  	// passphrase stream cache and cached secret keys
  1254  	tc.SimulateServiceRestart()
  1255  
  1256  	// now assert we can login without a passphrase
  1257  	uis := libkb.UIs{
  1258  		LoginUI:     &libkb.TestLoginUI{Username: fu.Username},
  1259  		LogUI:       tc.G.UI.GetLogUI(),
  1260  		SecretUI:    &libkb.TestSecretUI{},
  1261  		GPGUI:       &gpgtestui{},
  1262  		ProvisionUI: newTestProvisionUI(),
  1263  	}
  1264  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1265  	m := NewMetaContextForTest(tc).WithUIs(uis)
  1266  	err := RunEngine2(m, eng)
  1267  	require.NoError(t, err)
  1268  }
  1269  
  1270  func TestProvisionPaperCommandLine(t *testing.T) {
  1271  	tc := SetupEngineTest(t, "login")
  1272  	defer tc.Cleanup()
  1273  	fu := NewFakeUserOrBust(t, "paper")
  1274  	arg := MakeTestSignupEngineRunArg(fu)
  1275  	arg.SkipPaper = false
  1276  	loginUI := &paperLoginUI{Username: fu.Username}
  1277  	uis := libkb.UIs{
  1278  		LogUI:    tc.G.UI.GetLogUI(),
  1279  		GPGUI:    &gpgtestui{},
  1280  		SecretUI: fu.NewSecretUI(),
  1281  		LoginUI:  loginUI,
  1282  	}
  1283  	s := NewSignupEngine(tc.G, &arg)
  1284  	err := RunEngine2(NewMetaContextForTest(tc).WithUIs(uis), s)
  1285  	require.NoError(t, err)
  1286  
  1287  	assertNumDevicesAndKeys(tc, fu, 2, 4)
  1288  
  1289  	Logout(tc)
  1290  
  1291  	require.True(t, len(loginUI.PaperPhrase) > 0)
  1292  
  1293  	// redo SetupEngineTest to get a new home directory...should look like a
  1294  	// new device.
  1295  	tc2 := SetupEngineTest(t, "login")
  1296  	defer tc2.Cleanup()
  1297  
  1298  	secUI := fu.NewSecretUI()
  1299  	provUI := newTestProvisionUIPaper()
  1300  	provLoginUI := &libkb.TestLoginUI{Username: fu.Username}
  1301  	uis = libkb.UIs{
  1302  		ProvisionUI: provUI,
  1303  		LogUI:       tc2.G.UI.GetLogUI(),
  1304  		SecretUI:    secUI,
  1305  		LoginUI:     provLoginUI,
  1306  		GPGUI:       &gpgtestui{},
  1307  	}
  1308  
  1309  	m := NewMetaContextForTest(tc2).WithUIs(uis)
  1310  	eng := NewPaperProvisionEngine(tc2.G, fu.Username, "fakedevice", loginUI.PaperPhrase)
  1311  	err = RunEngine2(m, eng)
  1312  	require.NoError(t, err)
  1313  
  1314  	testUserHasDeviceKey(tc2)
  1315  
  1316  	assertNumDevicesAndKeys(tc, fu, 3, 6)
  1317  	err = AssertProvisioned(tc2)
  1318  	require.NoError(t, err)
  1319  
  1320  	require.Equal(t, provUI.calledChooseDeviceType, 0)
  1321  	require.Equal(t, provLoginUI.CalledGetEmailOrUsername, 0)
  1322  }
  1323  
  1324  func TestSelfProvision(t *testing.T) {
  1325  	tc := SetupEngineTest(t, "login")
  1326  	defer tc.Cleanup()
  1327  
  1328  	user := CreateAndSignupFakeUser(tc, "clone")
  1329  	secUI := user.NewSecretUI()
  1330  	provUI := newTestProvisionUIPaper()
  1331  	provLoginUI := &libkb.TestLoginUI{Username: user.Username}
  1332  	uis := libkb.UIs{
  1333  		ProvisionUI: provUI,
  1334  		LogUI:       tc.G.UI.GetLogUI(),
  1335  		SecretUI:    secUI,
  1336  		LoginUI:     provLoginUI,
  1337  		GPGUI:       &gpgtestui{},
  1338  	}
  1339  
  1340  	m := NewMetaContextForTest(tc).WithUIs(uis)
  1341  	// Test the happy case of successfully self provisioning.
  1342  	assertValidSelfProvision(t, tc, m, user)
  1343  }
  1344  
  1345  func assertValidSelfProvision(t *testing.T, tc libkb.TestContext, m libkb.MetaContext, user *FakeUser) {
  1346  	libkb.CreateClonedDevice(tc, m)
  1347  	newName := tc.G.ActiveDevice.Name() + "uncloneme"
  1348  	eng := NewSelfProvisionEngine(tc.G, newName)
  1349  	err := RunEngine2(m, eng)
  1350  	require.NoError(t, err)
  1351  
  1352  	testUserHasDeviceKey(tc)
  1353  	assertNumDevicesAndKeys(tc, user, 2, 4)
  1354  	err = AssertProvisioned(tc)
  1355  	require.NoError(t, err)
  1356  	require.Equal(t, tc.G.ActiveDevice.Name(), newName)
  1357  
  1358  	assertDeviceKeysCached(tc)
  1359  	assertPassphraseStreamCache(tc)
  1360  	assertSecretStored(tc, user.Username)
  1361  
  1362  	// GetBootstrapStatus should return without error and with LoggedIn set to
  1363  	// true.
  1364  	beng := NewBootstrap(tc.G)
  1365  	err = RunEngine2(m, beng)
  1366  	require.NoError(t, err)
  1367  	status := beng.Status()
  1368  	require.True(t, status.LoggedIn)
  1369  	require.True(t, status.Registered)
  1370  
  1371  	t.Logf("test tracks")
  1372  	testTrack(t, tc, libkb.KeybaseNullSigVersion, "t_alice")
  1373  	testSign(t, tc)
  1374  
  1375  	// Make sure that we can still track without a passphrase
  1376  	// after a simulated service restart.  In other words, that
  1377  	// the full LKSec secret was written to the secret store.
  1378  	simulateServiceRestart(t, tc, user)
  1379  	testSign(t, tc)
  1380  	testTrack(t, tc, libkb.KeybaseNullSigVersion, "t_bob")
  1381  	assertDeviceKeysCached(tc)
  1382  	require.Equal(t, tc.G.ActiveDevice.Name(), newName)
  1383  
  1384  	Logout(tc)
  1385  	user.LoginOrBust(tc)
  1386  }
  1387  
  1388  func TestSelfProvisionFailNoClone(t *testing.T) {
  1389  	// If we don't have a clone, we can't run this engine
  1390  	testFailSelfProvision(t, func(tc libkb.TestContext, m libkb.MetaContext) string {
  1391  		return "new"
  1392  	})
  1393  }
  1394  
  1395  func TestSelfProvisionFailDuplicateName(t *testing.T) {
  1396  	testFailSelfProvision(t, func(tc libkb.TestContext, m libkb.MetaContext) string {
  1397  		libkb.CreateClonedDevice(tc, m)
  1398  		// Use the default name so we get an error when provisioning.
  1399  		return ""
  1400  	})
  1401  }
  1402  
  1403  func testFailSelfProvision(t *testing.T, fn func(tc libkb.TestContext, m libkb.MetaContext) string) {
  1404  
  1405  	tc := SetupEngineTest(t, "login")
  1406  	defer tc.Cleanup()
  1407  
  1408  	user := CreateAndSignupFakeUser(tc, "clone")
  1409  
  1410  	secUI := user.NewSecretUI()
  1411  	provUI := newTestProvisionUIPaper()
  1412  	provLoginUI := &libkb.TestLoginUI{Username: user.Username}
  1413  	uis := libkb.UIs{
  1414  		ProvisionUI: provUI,
  1415  		LogUI:       tc.G.UI.GetLogUI(),
  1416  		SecretUI:    secUI,
  1417  		LoginUI:     provLoginUI,
  1418  		GPGUI:       &gpgtestui{},
  1419  	}
  1420  	m := NewMetaContextForTest(tc).WithUIs(uis)
  1421  
  1422  	suffix := fn(tc, m)
  1423  	oldName := tc.G.ActiveDevice.Name()
  1424  	newName := oldName + suffix
  1425  
  1426  	t.Logf("self provision running %v %v", oldName, newName)
  1427  	eng := NewSelfProvisionEngine(tc.G, newName)
  1428  	err := RunEngine2(m, eng)
  1429  	require.Error(t, err)
  1430  	t.Logf("self provision failed successfully %v %v", oldName, newName)
  1431  
  1432  	testUserHasDeviceKey(tc)
  1433  	// Since provisioning failed, we still just have a single device.
  1434  	assertNumDevicesAndKeys(tc, user, 1, 2)
  1435  	require.Equal(t, tc.G.ActiveDevice.Name(), oldName)
  1436  
  1437  	// GetBootstrapStatus should return without error and with LoggedIn set
  1438  	// to true.
  1439  	beng := NewBootstrap(tc.G)
  1440  	err = RunEngine2(m, beng)
  1441  	require.NoError(t, err)
  1442  	status := beng.Status()
  1443  	require.True(t, status.LoggedIn)
  1444  	require.True(t, status.Registered)
  1445  
  1446  	Logout(tc)
  1447  	user.LoginOrBust(tc)
  1448  
  1449  	// Make sure we can successfully self provision after we've failed.
  1450  	assertValidSelfProvision(t, tc, m, user)
  1451  }
  1452  
  1453  // Provision device using a private GPG key (not synced to keybase
  1454  // server), import private key to lksec.
  1455  func TestProvisionGPGImportOK(t *testing.T) {
  1456  	tc := SetupEngineTest(t, "login")
  1457  	defer tc.Cleanup()
  1458  
  1459  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1460  	Logout(tc)
  1461  
  1462  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1463  	tc2 := SetupEngineTest(t, "login")
  1464  	defer tc2.Cleanup()
  1465  
  1466  	// we need the gpg keyring that's in the first homedir
  1467  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1468  		t.Fatal(err)
  1469  	}
  1470  
  1471  	// run login on new device
  1472  	uis2 := libkb.UIs{
  1473  		ProvisionUI: newTestProvisionUIGPGImport(),
  1474  		LogUI:       tc2.G.UI.GetLogUI(),
  1475  		SecretUI:    u1.NewSecretUI(),
  1476  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1477  		GPGUI:       &gpgtestui{},
  1478  	}
  1479  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1480  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1481  	if err := RunEngine2(m2, eng); err != nil {
  1482  		t.Fatal(err)
  1483  	}
  1484  
  1485  	testUserHasDeviceKey(tc2)
  1486  
  1487  	// highly possible they didn't have a paper key, so make sure they still don't have one:
  1488  	hasZeroPaperDev(tc2, u1)
  1489  
  1490  	if err := AssertProvisioned(tc2); err != nil {
  1491  		t.Fatal(err)
  1492  	}
  1493  
  1494  	// since they imported their pgp key, they should be able to pgp sign something:
  1495  	if err := signString(tc2, "sign me", u1.NewSecretUI()); err != nil {
  1496  		t.Error("pgp sign failed after gpg provision w/ import")
  1497  		t.Fatal(err)
  1498  	}
  1499  
  1500  	// after provisioning, the secret should be stored
  1501  	assertSecretStored(tc2, u1.Username)
  1502  }
  1503  
  1504  // Provision device using a private GPG key (not synced to keybase
  1505  // server), import private key to lksec.  User selects key from
  1506  // several matching keys.
  1507  func TestProvisionGPGImportMultiple(t *testing.T) {
  1508  	tc := SetupEngineTest(t, "login")
  1509  	defer tc.Cleanup()
  1510  
  1511  	u1 := createFakeUserWithPGPMult(t, tc)
  1512  	Logout(tc)
  1513  
  1514  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1515  	tc2 := SetupEngineTest(t, "login")
  1516  	defer tc2.Cleanup()
  1517  
  1518  	// we need the gpg keyring that's in the first homedir
  1519  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1520  		t.Fatal(err)
  1521  	}
  1522  
  1523  	// run login on new device
  1524  	uis2 := libkb.UIs{
  1525  		ProvisionUI: newTestProvisionUIGPGImport(),
  1526  		LogUI:       tc2.G.UI.GetLogUI(),
  1527  		SecretUI:    u1.NewSecretUI(),
  1528  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1529  		GPGUI:       &gpgtestui{},
  1530  	}
  1531  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1532  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1533  	if err := RunEngine2(m2, eng); err != nil {
  1534  		t.Fatal(err)
  1535  	}
  1536  
  1537  	testUserHasDeviceKey(tc2)
  1538  
  1539  	// highly possible they didn't have a paper key, so make sure they still don't have one:
  1540  	hasZeroPaperDev(tc2, u1)
  1541  
  1542  	if err := AssertProvisioned(tc2); err != nil {
  1543  		t.Fatal(err)
  1544  	}
  1545  
  1546  	// since they imported their pgp key, they should be able to pgp sign something:
  1547  	if err := signString(tc2, "sign me", u1.NewSecretUI()); err != nil {
  1548  		t.Error("pgp sign failed after gpg provision w/ import")
  1549  		t.Fatal(err)
  1550  	}
  1551  
  1552  	// after provisioning, the secret should be stored
  1553  	assertSecretStored(tc2, u1.Username)
  1554  }
  1555  
  1556  // Provision device using a private GPG key (not synced to keybase
  1557  // server), use gpg to sign (no private key import).
  1558  func TestProvisionGPGSign(t *testing.T) {
  1559  	// use tcCheck just to check gpg version
  1560  	tcCheck := SetupEngineTest(t, "check")
  1561  	defer tcCheck.Cleanup()
  1562  	skipOldGPG(tcCheck)
  1563  
  1564  	// this test sometimes fails at the GPG level with a "Bad signature" error,
  1565  	// so we're going to retry it several times to hopefully get past it.
  1566  	attempts := 10
  1567  	for i := 0; i < attempts; i++ {
  1568  		tc := SetupEngineTest(t, "login")
  1569  		defer tc.Cleanup()
  1570  
  1571  		u1 := createFakeUserWithPGPPubOnly(t, tc)
  1572  		Logout(tc)
  1573  
  1574  		// redo SetupEngineTest to get a new home directory...should look like a new device.
  1575  		tc2 := SetupEngineTest(t, "login")
  1576  		defer tc2.Cleanup()
  1577  
  1578  		// we need the gpg keyring that's in the first homedir
  1579  		if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1580  			t.Fatal(err)
  1581  		}
  1582  
  1583  		// run login on new device
  1584  		uis2 := libkb.UIs{
  1585  			ProvisionUI: newTestProvisionUIGPGSign(),
  1586  			LogUI:       tc2.G.UI.GetLogUI(),
  1587  			SecretUI:    u1.NewSecretUI(),
  1588  			LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1589  			GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1590  		}
  1591  		eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1592  		m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1593  		if err := RunEngine2(m2, eng); err != nil {
  1594  			t.Logf("test run %d:  RunEngine(Login) error: %s", i+1, err)
  1595  			continue
  1596  		}
  1597  
  1598  		t.Logf("test run %d: RunEngine(Login) succeeded", i+1)
  1599  
  1600  		testUserHasDeviceKey(tc2)
  1601  
  1602  		// highly possible they didn't have a paper key, so make sure they still don't have one:
  1603  		hasZeroPaperDev(tc2, u1)
  1604  
  1605  		if err := AssertProvisioned(tc2); err != nil {
  1606  			t.Fatal(err)
  1607  		}
  1608  
  1609  		// after provisioning, the secret should be stored
  1610  		assertSecretStored(tc2, u1.Username)
  1611  
  1612  		checkPerUserKeyCount(&tc2, 1)
  1613  
  1614  		// since they *did not* import a pgp key, they should *not* be able to pgp sign something:
  1615  		if err := signString(tc2, "sign me", u1.NewSecretUI()); err == nil {
  1616  			t.Error("pgp sign worked after gpg provision w/o import")
  1617  			t.Fatal(err)
  1618  		}
  1619  
  1620  		t.Logf("test run %d: all checks passed, returning", i+1)
  1621  		return
  1622  	}
  1623  
  1624  	t.Fatalf("TestProvisionGPGSign failed %d times", attempts)
  1625  }
  1626  
  1627  func TestProvisionGPGSignFailedSign(t *testing.T) {
  1628  	tc := SetupEngineTest(t, "login")
  1629  	defer tc.Cleanup()
  1630  
  1631  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1632  	Logout(tc)
  1633  
  1634  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1635  	tc2 := SetupEngineTest(t, "login")
  1636  	defer tc2.Cleanup()
  1637  
  1638  	// we need the gpg keyring that's in the first homedir
  1639  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1640  		t.Fatal(err)
  1641  	}
  1642  
  1643  	// run login on new device
  1644  	uis2 := libkb.UIs{
  1645  		ProvisionUI: newTestProvisionUIGPGSign(),
  1646  		LogUI:       tc2.G.UI.GetLogUI(),
  1647  		SecretUI:    u1.NewSecretUI(),
  1648  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1649  		GPGUI:       &gpgTestUIBadSign{},
  1650  	}
  1651  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1652  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1653  	if err := RunEngine2(m2, eng); err == nil {
  1654  		t.Fatal("expected a failure in login")
  1655  	}
  1656  
  1657  	cf := tc2.G.Env.GetConfigFilename()
  1658  	jf := libkb.NewJSONConfigFile(tc2.G, cf)
  1659  	if err := jf.Load(true); err != nil {
  1660  		t.Fatal(err)
  1661  	}
  1662  	devid := jf.GetDeviceID()
  1663  	if !devid.IsNil() {
  1664  		t.Fatalf("got a non-nil Device ID after failed GPG provision (%v)", devid)
  1665  	}
  1666  }
  1667  
  1668  // Provision device using a private GPG key (not synced to keybase
  1669  // server), use gpg to sign (no private key import).
  1670  // Enable secret storage.  keybase-issues#1822
  1671  func TestProvisionGPGSignSecretStore(t *testing.T) {
  1672  	tcCheck := SetupEngineTest(t, "check")
  1673  	defer tcCheck.Cleanup()
  1674  	skipOldGPG(tcCheck)
  1675  
  1676  	// this test sometimes fails at the GPG level with a "Bad signature" error,
  1677  	// so we're going to retry it several times to hopefully get past it.
  1678  	attempts := 10
  1679  	for i := 0; i < attempts; i++ {
  1680  		tc := SetupEngineTest(t, "login")
  1681  		defer tc.Cleanup()
  1682  
  1683  		u1 := createFakeUserWithPGPPubOnly(t, tc)
  1684  		Logout(tc)
  1685  
  1686  		// redo SetupEngineTest to get a new home directory...should look like a new device.
  1687  		tc2 := SetupEngineTest(t, "login")
  1688  		defer tc2.Cleanup()
  1689  
  1690  		// we need the gpg keyring that's in the first homedir
  1691  		if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1692  			t.Fatal(err)
  1693  		}
  1694  
  1695  		// create a secret UI that stores the secret
  1696  		secUI := u1.NewSecretUI()
  1697  		secUI.StoreSecret = true
  1698  
  1699  		// run login on new device
  1700  		uis2 := libkb.UIs{
  1701  			ProvisionUI: newTestProvisionUIGPGSign(),
  1702  			LogUI:       tc2.G.UI.GetLogUI(),
  1703  			SecretUI:    secUI,
  1704  			LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1705  			GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1706  		}
  1707  		eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1708  		m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1709  		if err := RunEngine2(m2, eng); err != nil {
  1710  			t.Logf("test run %d:  RunEngine(Login) error: %s", i+1, err)
  1711  			continue
  1712  		}
  1713  
  1714  		t.Logf("test run %d: RunEngine(Login) succeeded", i+1)
  1715  
  1716  		testUserHasDeviceKey(tc2)
  1717  
  1718  		// highly possible they didn't have a paper key, so make sure they still don't have one:
  1719  		hasZeroPaperDev(tc2, u1)
  1720  
  1721  		if err := AssertProvisioned(tc2); err != nil {
  1722  			t.Fatal(err)
  1723  		}
  1724  
  1725  		// after provisioning, the secret should be stored
  1726  		assertSecretStored(tc2, u1.Username)
  1727  
  1728  		t.Logf("test run %d: all checks passed, returning", i+1)
  1729  		return
  1730  	}
  1731  
  1732  	t.Fatalf("TestProvisionGPGSignSecretStore failed %d times", attempts)
  1733  }
  1734  
  1735  // Provision device using a private GPG key (not synced to keybase
  1736  // server). Import private key to lksec fails, switches to gpg
  1737  // sign, which works.
  1738  func TestProvisionGPGSwitchToSign(t *testing.T) {
  1739  	tcCheck := SetupEngineTest(t, "check")
  1740  	defer tcCheck.Cleanup()
  1741  	skipOldGPG(tcCheck)
  1742  
  1743  	// this test sometimes fails at the GPG level with a "Bad signature" error,
  1744  	// so we're going to retry it several times to hopefully get past it.
  1745  	attempts := 10
  1746  	for i := 0; i < attempts; i++ {
  1747  		tc := SetupEngineTest(t, "login")
  1748  		defer tc.Cleanup()
  1749  
  1750  		u1 := createFakeUserWithPGPPubOnly(t, tc)
  1751  		Logout(tc)
  1752  
  1753  		// redo SetupEngineTest to get a new home directory...should look like a new device.
  1754  		tc2 := SetupEngineTest(t, "login")
  1755  		defer tc2.Cleanup()
  1756  
  1757  		// we need the gpg keyring that's in the first homedir
  1758  		if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1759  			t.Fatal(err)
  1760  		}
  1761  
  1762  		// load the user (bypassing LoginUsername for this test...)
  1763  		user, err := libkb.LoadUser(libkb.NewLoadUserByNameArg(tc2.G, u1.Username))
  1764  		if err != nil {
  1765  			t.Fatal(err)
  1766  		}
  1767  
  1768  		// run login on new device
  1769  		uis := libkb.UIs{
  1770  			ProvisionUI: newTestProvisionUIGPGImport(),
  1771  			LogUI:       tc2.G.UI.GetLogUI(),
  1772  			SecretUI:    u1.NewSecretUI(),
  1773  			LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1774  			GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1775  		}
  1776  
  1777  		arg := loginProvisionArg{
  1778  			DeviceType: keybase1.DeviceTypeV2_DESKTOP,
  1779  			ClientType: keybase1.ClientType_CLI,
  1780  			User:       user,
  1781  		}
  1782  
  1783  		eng := newLoginProvision(tc2.G, &arg)
  1784  		// use a gpg client that will fail to import any gpg key
  1785  		eng.gpgCli = newGPGImportFailer(tc2.G)
  1786  		m := NewMetaContextForTest(tc2).WithUIs(uis).WithNewProvisionalLoginContext()
  1787  
  1788  		if err := RunEngine2(m, eng); err != nil {
  1789  			t.Logf("test run %d:  RunEngine(Login) error: %s", i+1, err)
  1790  			continue
  1791  		}
  1792  
  1793  		t.Logf("test run %d: RunEngine(Login) succeeded", i+1)
  1794  
  1795  		testUserHasDeviceKey(tc2)
  1796  
  1797  		// highly possible they didn't have a paper key, so make sure they still don't have one:
  1798  		hasZeroPaperDev(tc2, u1)
  1799  
  1800  		if err := AssertProvisioned(tc2); err != nil {
  1801  			t.Fatal(err)
  1802  		}
  1803  
  1804  		// after provisioning, the secret should be stored
  1805  		assertSecretStored(tc2, u1.Username)
  1806  
  1807  		// since they did not import their pgp key, they should not be able
  1808  		// to pgp sign something:
  1809  		if err := signString(tc2, "sign me", u1.NewSecretUI()); err == nil {
  1810  			t.Fatal("pgp sign worked after gpg sign provisioning")
  1811  		}
  1812  		t.Logf("test run %d: all checks passed, returning", i+1)
  1813  		return
  1814  	}
  1815  
  1816  	t.Fatalf("TestProvisionGPGSwitchToSign failed %d times", attempts)
  1817  }
  1818  
  1819  // Try provision device using a private GPG key (not synced to keybase
  1820  // server). Import private key to lksec fails, user does not want
  1821  // to switch to gpg sign, so provisioning fails.
  1822  func TestProvisionGPGNoSwitchToSign(t *testing.T) {
  1823  	tc := SetupEngineTest(t, "login")
  1824  	defer tc.Cleanup()
  1825  
  1826  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1827  	Logout(tc)
  1828  
  1829  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1830  	tc2 := SetupEngineTest(t, "login")
  1831  	defer tc2.Cleanup()
  1832  
  1833  	// we need the gpg keyring that's in the first homedir
  1834  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  1835  		t.Fatal(err)
  1836  	}
  1837  
  1838  	// load the user (bypassing LoginUsername for this test...)
  1839  	user, err := libkb.LoadUser(libkb.NewLoadUserByNameArg(tc2.G, u1.Username))
  1840  	if err != nil {
  1841  		t.Fatal(err)
  1842  	}
  1843  
  1844  	// instruct provisioning ui to not allow the switch to gpg sign:
  1845  	provUI := newTestProvisionUIGPGImport()
  1846  	provUI.abortSwitchToGPGSign = true
  1847  
  1848  	// run login on new device
  1849  	uis := libkb.UIs{
  1850  		ProvisionUI: provUI,
  1851  		LogUI:       tc2.G.UI.GetLogUI(),
  1852  		SecretUI:    u1.NewSecretUI(),
  1853  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1854  		GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1855  	}
  1856  
  1857  	arg := loginProvisionArg{
  1858  		DeviceType: keybase1.DeviceTypeV2_DESKTOP,
  1859  		ClientType: keybase1.ClientType_CLI,
  1860  		User:       user,
  1861  	}
  1862  
  1863  	eng := newLoginProvision(tc2.G, &arg)
  1864  	// use a gpg client that will fail to import any gpg key
  1865  	eng.gpgCli = newGPGImportFailer(tc2.G)
  1866  
  1867  	m := NewMetaContextForTest(tc2).WithUIs(uis)
  1868  
  1869  	if err := RunEngine2(m, eng); err == nil {
  1870  		t.Fatal("provisioning worked despite not allowing switch to gpg sign")
  1871  	}
  1872  }
  1873  
  1874  // User with pgp keys, but on a device without any gpg keyring.
  1875  func TestProvisionGPGNoKeyring(t *testing.T) {
  1876  	tc := SetupEngineTest(t, "login")
  1877  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1878  	Logout(tc)
  1879  	tc.Cleanup()
  1880  
  1881  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1882  	tc2 := SetupEngineTest(t, "login")
  1883  	defer tc2.Cleanup()
  1884  
  1885  	// run login on new device
  1886  	uis2 := libkb.UIs{
  1887  		ProvisionUI: newTestProvisionUIGPGImport(),
  1888  		LogUI:       tc2.G.UI.GetLogUI(),
  1889  		SecretUI:    u1.NewSecretUI(),
  1890  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1891  		GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc.G)},
  1892  	}
  1893  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1894  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1895  	if err := RunEngine2(m2, eng); err == nil {
  1896  		t.Fatal("provision worked without gpg keyring")
  1897  	} else if _, ok := err.(libkb.NoMatchingGPGKeysError); !ok {
  1898  		t.Errorf("error %T, expected libkb.NoMatchingGPGKeysError", err)
  1899  	}
  1900  }
  1901  
  1902  // User with pgp keys, but on a device with gpg keys that don't
  1903  // match.
  1904  func TestProvisionGPGNoMatch(t *testing.T) {
  1905  	tc := SetupEngineTest(t, "login")
  1906  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1907  	Logout(tc)
  1908  	tc.Cleanup()
  1909  
  1910  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1911  	tc2 := SetupEngineTest(t, "login")
  1912  	defer tc2.Cleanup()
  1913  
  1914  	// make a new keyring, not associated with keybase
  1915  	if err := tc2.GenerateGPGKeyring(u1.Email); err != nil {
  1916  		t.Fatal(err)
  1917  	}
  1918  
  1919  	// run login on new device
  1920  	uis2 := libkb.UIs{
  1921  		ProvisionUI: newTestProvisionUIGPGImport(),
  1922  		LogUI:       tc2.G.UI.GetLogUI(),
  1923  		SecretUI:    u1.NewSecretUI(),
  1924  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1925  		GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1926  	}
  1927  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1928  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1929  	if err := RunEngine2(m2, eng); err == nil {
  1930  		t.Fatal("provision worked without matching gpg key")
  1931  	} else if _, ok := err.(libkb.NoMatchingGPGKeysError); !ok {
  1932  		t.Errorf("error %T, expected libkb.NoMatchingGPGKeysError", err)
  1933  	}
  1934  }
  1935  
  1936  // User with pgp keys, but on a device without gpg.
  1937  func TestProvisionGPGNoGPGExecutable(t *testing.T) {
  1938  	tc := SetupEngineTest(t, "login")
  1939  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1940  	Logout(tc)
  1941  	tc.Cleanup()
  1942  
  1943  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1944  	tc2 := SetupEngineTest(t, "login")
  1945  	defer tc2.Cleanup()
  1946  
  1947  	// this should make it unable to find gpg
  1948  	tc2.G.Env.Test.GPG = filepath.Join(string(filepath.Separator), "dev", "null")
  1949  
  1950  	// run login on new device
  1951  	uis2 := libkb.UIs{
  1952  		ProvisionUI: newTestProvisionUIGPGImport(),
  1953  		LogUI:       tc2.G.UI.GetLogUI(),
  1954  		SecretUI:    u1.NewSecretUI(),
  1955  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1956  		GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1957  	}
  1958  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1959  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1960  	err := RunEngine2(m2, eng)
  1961  	if err == nil {
  1962  		t.Fatal("provision worked without gpg")
  1963  	}
  1964  	if _, ok := err.(libkb.GPGUnavailableError); !ok {
  1965  		t.Errorf("login run err type: %T, expected libkb.GPGUnavailableError", err)
  1966  	}
  1967  }
  1968  
  1969  // User with pgp keys, but on a device where gpg executable
  1970  // specified is not found.
  1971  func TestProvisionGPGNoGPGFound(t *testing.T) {
  1972  	tc := SetupEngineTest(t, "login")
  1973  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  1974  	Logout(tc)
  1975  	tc.Cleanup()
  1976  
  1977  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  1978  	tc2 := SetupEngineTest(t, "login")
  1979  	defer tc2.Cleanup()
  1980  
  1981  	// this should make it unable to find gpg
  1982  	tc2.G.Env.Test.GPG = filepath.Join(string(filepath.Separator), "not", "a", "directory", "that", "ever", "exists", "bin", "gpg")
  1983  
  1984  	// run login on new device
  1985  	uis2 := libkb.UIs{
  1986  		ProvisionUI: newTestProvisionUIGPGImport(),
  1987  		LogUI:       tc2.G.UI.GetLogUI(),
  1988  		SecretUI:    u1.NewSecretUI(),
  1989  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  1990  		GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  1991  	}
  1992  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  1993  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  1994  	err := RunEngine2(m2, eng)
  1995  	if err == nil {
  1996  		t.Fatal("provision worked without gpg")
  1997  	}
  1998  	if _, ok := err.(libkb.GPGUnavailableError); !ok {
  1999  		t.Errorf("login run err type: %T, expected libkb.GPGUnavailableError", err)
  2000  	}
  2001  }
  2002  
  2003  func TestProvisionDupDevice(t *testing.T) {
  2004  	// device X (provisioner) context:
  2005  	tcX := SetupEngineTest(t, "kex2provision")
  2006  	defer tcX.Cleanup()
  2007  
  2008  	// device Y (provisionee) context:
  2009  	tcY := SetupEngineTest(t, "template")
  2010  	defer tcY.Cleanup()
  2011  
  2012  	// provisioner needs to be logged in
  2013  	userX := CreateAndSignupFakeUser(tcX, "login")
  2014  
  2015  	secretCh := make(chan kex2.Secret)
  2016  
  2017  	provui := &testProvisionDupDeviceUI{newTestProvisionUISecretCh(secretCh)}
  2018  
  2019  	// provisionee calls login:
  2020  	uis := libkb.UIs{
  2021  		ProvisionUI: provui,
  2022  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  2023  		LogUI:       tcY.G.UI.GetLogUI(),
  2024  		SecretUI:    &libkb.TestSecretUI{},
  2025  		GPGUI:       &gpgtestui{},
  2026  	}
  2027  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2028  	m := NewMetaContextForTest(tcY).WithUIs(uis)
  2029  
  2030  	// start provisionee
  2031  	if err := RunEngine2(m, eng); err == nil {
  2032  		t.Errorf("login ran without error")
  2033  		return
  2034  	}
  2035  
  2036  	// Note: there is no need to start the provisioner as the provisionee will
  2037  	// fail because of the duplicate device name before the provisioner
  2038  	// is needed.
  2039  
  2040  	// double-check that provisioning failed
  2041  	if err := AssertProvisioned(tcY); err == nil {
  2042  		t.Fatal("device provisioned using existing name")
  2043  	}
  2044  }
  2045  
  2046  // If a user has no keys, provision via passphrase should work.
  2047  // This tests when they have another account on the same machine.
  2048  func TestProvisionPassphraseNoKeysMultipleAccounts(t *testing.T) {
  2049  	tcWeb := SetupEngineTest(t, "login")
  2050  
  2051  	// create a "web" user with no keys
  2052  	username, passphrase := createFakeUserWithNoKeys(tcWeb)
  2053  	Logout(tcWeb)
  2054  	tcWeb.Cleanup()
  2055  
  2056  	// create a new test context
  2057  	tc := SetupEngineTest(t, "fake")
  2058  	defer tc.Cleanup()
  2059  
  2060  	// create a user to fill up config with something
  2061  	CreateAndSignupFakeUser(tc, "fake")
  2062  	Logout(tc)
  2063  
  2064  	// now try to log in as the web user
  2065  	uis := libkb.UIs{
  2066  		ProvisionUI: newTestProvisionUIPassphrase(),
  2067  		LoginUI:     &libkb.TestLoginUI{Username: username},
  2068  		LogUI:       tc.G.UI.GetLogUI(),
  2069  		SecretUI:    &libkb.TestSecretUI{Passphrase: passphrase},
  2070  		GPGUI:       &gpgtestui{},
  2071  	}
  2072  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, username, keybase1.ClientType_CLI)
  2073  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2074  	if err := RunEngine2(m, eng); err != nil {
  2075  		t.Fatal(err)
  2076  	}
  2077  
  2078  	// since this user didn't have any keys, login should have fixed that:
  2079  	testUserHasDeviceKey(tc)
  2080  
  2081  	// and they should not have a paper backup key by default
  2082  	hasZeroPaperDev(tc, &FakeUser{Username: username, Passphrase: passphrase})
  2083  
  2084  	if err := AssertProvisioned(tc); err != nil {
  2085  		t.Fatal(err)
  2086  	}
  2087  
  2088  	// after provisioning, the secret should be stored
  2089  	assertSecretStored(tc, username)
  2090  }
  2091  
  2092  // We have obviated the unlock command by combining it with login.
  2093  func TestLoginStreamCache(t *testing.T) {
  2094  	tc := SetupEngineTest(t, "login")
  2095  	defer tc.Cleanup()
  2096  
  2097  	u1 := SignupFakeUserStoreSecret(tc, "login")
  2098  	assertSecretStored(tc, u1.Username)
  2099  
  2100  	if !assertStreamCache(tc, true) {
  2101  		t.Fatal("expected valid stream cache after signup")
  2102  	}
  2103  
  2104  	clearCaches(tc.G)
  2105  
  2106  	if !assertStreamCache(tc, false) {
  2107  		t.Fatal("expected invalid stream cache after clear")
  2108  	}
  2109  
  2110  	// This should not unlock the stream cache
  2111  	u1.LoginOrBust(tc)
  2112  
  2113  	if !assertStreamCache(tc, false) {
  2114  		t.Fatal("expected no valid stream cache after login")
  2115  	}
  2116  	assertDeviceKeysCached(tc)
  2117  	assertSecretStored(tc, u1.Username)
  2118  }
  2119  
  2120  // Check the device type
  2121  func TestLoginInvalidDeviceType(t *testing.T) {
  2122  	tcWeb := SetupEngineTest(t, "web")
  2123  	defer tcWeb.Cleanup()
  2124  
  2125  	username, passphrase := createFakeUserWithNoKeys(tcWeb)
  2126  
  2127  	Logout(tcWeb)
  2128  
  2129  	tc := SetupEngineTest(t, "login")
  2130  	defer tc.Cleanup()
  2131  
  2132  	uis := libkb.UIs{
  2133  		ProvisionUI: newTestProvisionUIPassphrase(),
  2134  		LoginUI:     &libkb.TestLoginUI{Username: username},
  2135  		LogUI:       tc.G.UI.GetLogUI(),
  2136  		SecretUI:    &libkb.TestSecretUI{Passphrase: passphrase},
  2137  		GPGUI:       &gpgtestui{},
  2138  	}
  2139  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_PAPER, "", keybase1.ClientType_CLI)
  2140  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2141  	if err := RunEngine2(m, eng); err == nil {
  2142  		t.Fatal("login with paper device type worked")
  2143  	} else if _, ok := err.(libkb.InvalidArgumentError); !ok {
  2144  		t.Errorf("err type: %T, expected libkb.InvalidArgumentError", err)
  2145  	}
  2146  }
  2147  
  2148  // Test that login provision checks for nil user in argument.
  2149  func TestProvisionNilUser(t *testing.T) {
  2150  	tc := SetupEngineTest(t, "login")
  2151  	defer tc.Cleanup()
  2152  
  2153  	arg := loginProvisionArg{
  2154  		DeviceType: keybase1.DeviceTypeV2_DESKTOP,
  2155  		ClientType: keybase1.ClientType_CLI,
  2156  		User:       nil,
  2157  	}
  2158  	eng := newLoginProvision(tc.G, &arg)
  2159  	uis := libkb.UIs{
  2160  		ProvisionUI: newTestProvisionUIPassphrase(),
  2161  		LoginUI:     &libkb.TestLoginUI{},
  2162  		LogUI:       tc.G.UI.GetLogUI(),
  2163  		SecretUI:    &libkb.TestSecretUI{},
  2164  		GPGUI:       &gpgtestui{},
  2165  	}
  2166  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2167  	if err := RunEngine2(m, eng); err == nil {
  2168  		t.Fatal("loginprovision with nil user worked")
  2169  	} else if _, ok := err.(libkb.InvalidArgumentError); !ok {
  2170  		t.Errorf("err type: %T, expected libkb.InvalidArgumentError", err)
  2171  	}
  2172  }
  2173  
  2174  func userPlusPaper(t *testing.T) (*FakeUser, string) {
  2175  	tc := SetupEngineTest(t, "fake")
  2176  	defer tc.Cleanup()
  2177  	fu := NewFakeUserOrBust(t, "fake")
  2178  	arg := MakeTestSignupEngineRunArg(fu)
  2179  	arg.SkipPaper = false
  2180  	loginUI := &paperLoginUI{Username: fu.Username}
  2181  	uis := libkb.UIs{
  2182  		LogUI:    tc.G.UI.GetLogUI(),
  2183  		GPGUI:    &gpgtestui{},
  2184  		SecretUI: fu.NewSecretUI(),
  2185  		LoginUI:  loginUI,
  2186  	}
  2187  	s := NewSignupEngine(tc.G, &arg)
  2188  	if err := RunEngine2(NewMetaContextForTest(tc).WithUIs(uis), s); err != nil {
  2189  		t.Fatal(err)
  2190  	}
  2191  	Logout(tc)
  2192  	return fu, loginUI.PaperPhrase
  2193  }
  2194  
  2195  func TestProvisionPaperFailures(t *testing.T) {
  2196  	// create two users
  2197  	ux, uxPaper := userPlusPaper(t)
  2198  	_, uyPaper := userPlusPaper(t)
  2199  
  2200  	// try provision as ux on a new device with uy's paper key
  2201  	tc := SetupEngineTest(t, "login")
  2202  	defer tc.Cleanup()
  2203  
  2204  	secUI := ux.NewSecretUI()
  2205  	secUI.Passphrase = uyPaper
  2206  	provUI := newTestProvisionUIPaper()
  2207  	provLoginUI := &libkb.TestLoginUI{Username: ux.Username}
  2208  	uis := libkb.UIs{
  2209  		ProvisionUI: provUI,
  2210  		LogUI:       tc.G.UI.GetLogUI(),
  2211  		SecretUI:    secUI,
  2212  		LoginUI:     provLoginUI,
  2213  		GPGUI:       &gpgtestui{},
  2214  	}
  2215  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2216  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2217  	if err := RunEngine2(m, eng); err == nil {
  2218  		t.Fatal("provision with another user's paper key worked")
  2219  	}
  2220  
  2221  	// try provision as ux on a new device with swapped word paper key
  2222  	tcSwap := SetupEngineTest(t, "login")
  2223  	defer tcSwap.Cleanup()
  2224  
  2225  	words := strings.Fields(uxPaper)
  2226  	didSwap := false
  2227  	for i := 2; i < len(words)-1; i++ {
  2228  		if words[i] != words[i+1] {
  2229  			tc.G.Log.Debug("swapped word %d (%s) and %d (%s)", i, words[i], i+1, words[i+1])
  2230  			didSwap = true
  2231  			words[i], words[i+1] = words[i+1], words[i]
  2232  			break
  2233  		}
  2234  	}
  2235  	if !didSwap {
  2236  		t.Fatalf("paper key words were all the same; could not swap: %s", uxPaper)
  2237  	}
  2238  	swapped := strings.Join(words, " ")
  2239  	secUI = ux.NewSecretUI()
  2240  	secUI.Passphrase = swapped
  2241  	provUI = newTestProvisionUIPaper()
  2242  	provLoginUI = &libkb.TestLoginUI{Username: ux.Username}
  2243  	uis = libkb.UIs{
  2244  		ProvisionUI: provUI,
  2245  		LogUI:       tcSwap.G.UI.GetLogUI(),
  2246  		SecretUI:    secUI,
  2247  		LoginUI:     provLoginUI,
  2248  		GPGUI:       &gpgtestui{},
  2249  	}
  2250  	eng = NewLogin(tcSwap.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2251  	m = NewMetaContextForTest(tcSwap).WithUIs(uis)
  2252  	err := RunEngine2(m, eng)
  2253  	if err == nil {
  2254  		t.Fatal("provision with swapped word paper key worked")
  2255  	}
  2256  	if _, ok := err.(libkb.NotFoundError); !ok {
  2257  		t.Fatalf("error type: %T, expected libkb.NotFoundError", err)
  2258  	}
  2259  
  2260  	// try provision as ux on a new device first with fu's paper key
  2261  	// then with ux's paper key (testing retry works)
  2262  	tc2 := SetupEngineTest(t, "login")
  2263  	defer tc2.Cleanup()
  2264  
  2265  	retrySecUI := &testRetrySecretUI{
  2266  		Passphrases: []string{uyPaper, uxPaper},
  2267  	}
  2268  	provUI = newTestProvisionUIPaper()
  2269  	provLoginUI = &libkb.TestLoginUI{Username: ux.Username}
  2270  	uis = libkb.UIs{
  2271  		ProvisionUI: provUI,
  2272  		LogUI:       tc2.G.UI.GetLogUI(),
  2273  		SecretUI:    retrySecUI,
  2274  		LoginUI:     provLoginUI,
  2275  		GPGUI:       &gpgtestui{},
  2276  	}
  2277  	eng = NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2278  	m = NewMetaContextForTest(tc2).WithUIs(uis)
  2279  	if err := RunEngine2(m, eng); err != nil {
  2280  		t.Fatal(err)
  2281  	}
  2282  	if retrySecUI.index != len(retrySecUI.Passphrases) {
  2283  		t.Errorf("retry sec ui index: %d, expected %d", retrySecUI.index, len(retrySecUI.Passphrases))
  2284  	}
  2285  
  2286  	// try provision as ux on a new device first with garbage paper key
  2287  	// then with ux's paper key (testing retry works)
  2288  	tc3 := SetupEngineTest(t, "login")
  2289  	defer tc3.Cleanup()
  2290  
  2291  	retrySecUI = &testRetrySecretUI{
  2292  		Passphrases: []string{"garbage garbage garbage", uxPaper},
  2293  	}
  2294  	provUI = newTestProvisionUIPaper()
  2295  	provLoginUI = &libkb.TestLoginUI{Username: ux.Username}
  2296  	uis = libkb.UIs{
  2297  		ProvisionUI: provUI,
  2298  		LogUI:       tc3.G.UI.GetLogUI(),
  2299  		SecretUI:    retrySecUI,
  2300  		LoginUI:     provLoginUI,
  2301  		GPGUI:       &gpgtestui{},
  2302  	}
  2303  	eng = NewLogin(tc3.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2304  	m = NewMetaContextForTest(tc3).WithUIs(uis)
  2305  	if err := RunEngine2(m, eng); err != nil {
  2306  		t.Fatal(err)
  2307  	}
  2308  	if retrySecUI.index != len(retrySecUI.Passphrases) {
  2309  		t.Errorf("retry sec ui index: %d, expected %d", retrySecUI.index, len(retrySecUI.Passphrases))
  2310  	}
  2311  
  2312  	// try provision as ux on a new device first with invalid version paper key
  2313  	// then with ux's paper key (testing retry works)
  2314  	tc4 := SetupEngineTest(t, "login")
  2315  	defer tc4.Cleanup()
  2316  
  2317  	paperNextVer, err := libkb.MakePaperKeyPhrase(libkb.PaperKeyVersion + 1)
  2318  	if err != nil {
  2319  		t.Fatal(err)
  2320  	}
  2321  	retrySecUI = &testRetrySecretUI{
  2322  		Passphrases: []string{paperNextVer.String(), uxPaper},
  2323  	}
  2324  	provUI = newTestProvisionUIPaper()
  2325  	provLoginUI = &libkb.TestLoginUI{Username: ux.Username}
  2326  	uis = libkb.UIs{
  2327  		ProvisionUI: provUI,
  2328  		LogUI:       tc4.G.UI.GetLogUI(),
  2329  		SecretUI:    retrySecUI,
  2330  		LoginUI:     provLoginUI,
  2331  		GPGUI:       &gpgtestui{},
  2332  	}
  2333  	eng = NewLogin(tc4.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2334  	m = NewMetaContextForTest(tc4).WithUIs(uis)
  2335  	if err := RunEngine2(m, eng); err != nil {
  2336  		t.Fatal(err)
  2337  	}
  2338  	if retrySecUI.index != len(retrySecUI.Passphrases) {
  2339  		t.Errorf("retry sec ui index: %d, expected %d", retrySecUI.index, len(retrySecUI.Passphrases))
  2340  	}
  2341  
  2342  }
  2343  
  2344  // After kex provisioning, try using a synced pgp key to sign
  2345  // something.
  2346  func TestProvisionKexUseSyncPGP(t *testing.T) {
  2347  	// device X (provisioner) context:
  2348  	tcX := SetupEngineTestRealTriplesec(t, "kex2provision")
  2349  	defer tcX.Cleanup()
  2350  
  2351  	// device Y (provisionee) context:
  2352  	tcY := SetupEngineTestRealTriplesec(t, "template")
  2353  	defer tcY.Cleanup()
  2354  
  2355  	// create provisioner with synced pgp key
  2356  	userX := createFakeUserWithPGPSibkeyPushedPaper(tcX)
  2357  	var secretX kex2.Secret
  2358  	if _, err := rand.Read(secretX[:]); err != nil {
  2359  		t.Fatal(err)
  2360  	}
  2361  
  2362  	secretCh := make(chan kex2.Secret)
  2363  
  2364  	// provisionee calls login:
  2365  	uis := libkb.UIs{
  2366  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  2367  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  2368  		LogUI:       tcY.G.UI.GetLogUI(),
  2369  		SecretUI:    &libkb.TestSecretUI{},
  2370  		GPGUI:       &gpgtestui{},
  2371  	}
  2372  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2373  
  2374  	var wg sync.WaitGroup
  2375  
  2376  	// start provisionee
  2377  	wg.Add(1)
  2378  	go func() {
  2379  		defer wg.Done()
  2380  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  2381  		if err := RunEngine2(m, eng); err != nil {
  2382  			t.Errorf("login error: %s", err)
  2383  			return
  2384  		}
  2385  	}()
  2386  
  2387  	// start provisioner
  2388  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  2389  	wg.Add(1)
  2390  	go func() {
  2391  		defer wg.Done()
  2392  
  2393  		uis := libkb.UIs{
  2394  			SecretUI:    userX.NewSecretUI(),
  2395  			ProvisionUI: newTestProvisionUI(),
  2396  		}
  2397  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  2398  		if err := RunEngine2(m, provisioner); err != nil {
  2399  			t.Errorf("provisioner error: %s", err)
  2400  			return
  2401  		}
  2402  	}()
  2403  	secretFromY := <-secretCh
  2404  	provisioner.AddSecret(secretFromY)
  2405  
  2406  	wg.Wait()
  2407  
  2408  	if err := AssertProvisioned(tcY); err != nil {
  2409  		t.Fatal(err)
  2410  	}
  2411  
  2412  	t.Logf(strings.Repeat("*", 100))
  2413  	t.Logf("provisioned")
  2414  	t.Logf(strings.Repeat("*", 100))
  2415  
  2416  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_alice")
  2417  
  2418  	// tsec isn't cached on device Y, so this should fail since the
  2419  	// secret ui doesn't know the passphrase:
  2420  	if err := signString(tcY, "sign me", &libkb.TestSecretUI{}); err == nil {
  2421  		t.Fatal("sign worked on device Y after provisioning without knowing passphrase")
  2422  	}
  2423  
  2424  	// but if we know the passphrase, it should prompt for it
  2425  	// and use it
  2426  	if err := signString(tcY, "sign me", userX.NewSecretUI()); err != nil {
  2427  		t.Fatalf("sign failed on device Y with passphrase in secret ui: %s", err)
  2428  	}
  2429  }
  2430  
  2431  // Provision one (physical) device with multiple users.
  2432  func TestProvisionMultipleUsers(t *testing.T) {
  2433  	// make some users with synced pgp keys
  2434  	users := make([]*FakeUser, 3)
  2435  	for i := 0; i < len(users); i++ {
  2436  		tc := SetupEngineTest(t, "login")
  2437  		users[i] = createFakeUserWithPGPOnly(t, tc)
  2438  		Logout(tc)
  2439  		tc.Cleanup()
  2440  	}
  2441  
  2442  	// provision user[0] on a new device
  2443  	tc := SetupEngineTest(t, "login")
  2444  	defer tc.Cleanup()
  2445  
  2446  	uis := libkb.UIs{
  2447  		ProvisionUI: newTestProvisionUIPassphrase(),
  2448  		LoginUI:     &libkb.TestLoginUI{Username: users[0].Username},
  2449  		LogUI:       tc.G.UI.GetLogUI(),
  2450  		SecretUI:    users[0].NewSecretUI(),
  2451  		GPGUI:       &gpgtestui{},
  2452  	}
  2453  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2454  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2455  	if err := RunEngine2(m, eng); err != nil {
  2456  		t.Fatal(err)
  2457  	}
  2458  
  2459  	testUserHasDeviceKey(tc)
  2460  	hasZeroPaperDev(tc, users[0])
  2461  	if err := AssertProvisioned(tc); err != nil {
  2462  		t.Fatal(err)
  2463  	}
  2464  
  2465  	Logout(tc)
  2466  
  2467  	// provision user[1] on the same device, specifying username
  2468  	uis = libkb.UIs{
  2469  		ProvisionUI: newTestProvisionUIPassphrase(),
  2470  		LoginUI:     &libkb.TestLoginUI{},
  2471  		LogUI:       tc.G.UI.GetLogUI(),
  2472  		SecretUI:    users[1].NewSecretUI(),
  2473  		GPGUI:       &gpgtestui{},
  2474  	}
  2475  	eng = NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, users[1].Username, keybase1.ClientType_CLI)
  2476  	m = NewMetaContextForTest(tc).WithUIs(uis)
  2477  	if err := RunEngine2(m, eng); err != nil {
  2478  		t.Fatal(err)
  2479  	}
  2480  
  2481  	testUserHasDeviceKey(tc)
  2482  	hasZeroPaperDev(tc, users[1])
  2483  	if err := AssertProvisioned(tc); err != nil {
  2484  		t.Fatal(err)
  2485  	}
  2486  
  2487  	Logout(tc)
  2488  
  2489  	// provision user[2] on the same device, specifying email
  2490  	uis = libkb.UIs{
  2491  		ProvisionUI: newTestProvisionUIPassphrase(),
  2492  		LoginUI:     &libkb.TestLoginUI{},
  2493  		LogUI:       tc.G.UI.GetLogUI(),
  2494  		SecretUI:    users[2].NewSecretUI(),
  2495  		GPGUI:       &gpgtestui{},
  2496  	}
  2497  	eng = NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, users[2].Username, keybase1.ClientType_CLI)
  2498  	m = NewMetaContextForTest(tc).WithUIs(uis)
  2499  	if err := RunEngine2(m, eng); err != nil {
  2500  		t.Fatal(err)
  2501  	}
  2502  
  2503  	testUserHasDeviceKey(tc)
  2504  	hasZeroPaperDev(tc, users[2])
  2505  	if err := AssertProvisioned(tc); err != nil {
  2506  		t.Fatal(err)
  2507  	}
  2508  
  2509  	Logout(tc)
  2510  
  2511  	// login via email does not work anymore (CORE-10470)
  2512  	uis = libkb.UIs{
  2513  		ProvisionUI: newTestProvisionUIPassphrase(),
  2514  		LoginUI:     &libkb.TestLoginUI{},
  2515  		LogUI:       tc.G.UI.GetLogUI(),
  2516  		SecretUI:    users[2].NewSecretUI(),
  2517  		GPGUI:       &gpgtestui{},
  2518  	}
  2519  	eng = NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, users[2].Email, keybase1.ClientType_CLI)
  2520  	m = NewMetaContextForTest(tc).WithUIs(uis)
  2521  	err := RunEngine2(m, eng)
  2522  	require.Error(t, err)
  2523  	require.IsType(t, libkb.BadUsernameError{}, err)
  2524  	require.Contains(t, err.Error(), "not supported")
  2525  }
  2526  
  2527  // create a standard user with device keys, reset account, login.
  2528  func TestResetAccount(t *testing.T) {
  2529  	tc := SetupEngineTest(t, "login")
  2530  	defer tc.Cleanup()
  2531  
  2532  	u := CreateAndSignupFakeUser(tc, "login")
  2533  	originalDevice := tc.G.Env.GetDeviceID()
  2534  	ResetAccount(tc, u)
  2535  
  2536  	// this will reprovision as an eldest device:
  2537  	u.LoginOrBust(tc)
  2538  	if err := AssertProvisioned(tc); err != nil {
  2539  		t.Fatal(err)
  2540  	}
  2541  
  2542  	newDevice := tc.G.Env.GetDeviceID()
  2543  
  2544  	if newDevice == originalDevice {
  2545  		t.Errorf("device id did not change: %s", newDevice)
  2546  	}
  2547  
  2548  	testUserHasDeviceKey(tc)
  2549  }
  2550  
  2551  // create a standard user with device keys, reset account (but don't logout), login.
  2552  func TestResetAccountNoLogout(t *testing.T) {
  2553  	tc := SetupEngineTest(t, "login")
  2554  	defer tc.Cleanup()
  2555  
  2556  	u := CreateAndSignupFakeUser(tc, "login")
  2557  	originalDevice := tc.G.Env.GetDeviceID()
  2558  	ResetAccountNoLogout(tc, u)
  2559  
  2560  	// this will reprovision as an eldest device:
  2561  	u.LoginOrBust(tc)
  2562  	if err := AssertProvisioned(tc); err != nil {
  2563  		t.Fatal(err)
  2564  	}
  2565  
  2566  	newDevice := tc.G.Env.GetDeviceID()
  2567  
  2568  	if newDevice == originalDevice {
  2569  		t.Errorf("device id did not change: %s", newDevice)
  2570  	}
  2571  
  2572  	testUserHasDeviceKey(tc)
  2573  }
  2574  
  2575  // create a standard user with device keys, reset account (but don't logout), login.
  2576  // Prime the FullSelfer cache before reset.
  2577  func TestResetAccountNoLogoutSelfCache(t *testing.T) {
  2578  	tc := SetupEngineTest(t, "login")
  2579  	defer tc.Cleanup()
  2580  
  2581  	u := CreateAndSignupFakeUser(tc, "login")
  2582  	originalDevice := tc.G.Env.GetDeviceID()
  2583  
  2584  	// make sure FullSelf is cached
  2585  	err := tc.G.GetFullSelfer().WithSelf(context.TODO(), func(u *libkb.User) error {
  2586  		t.Logf("full self user: %s", u.GetName())
  2587  		return nil
  2588  	})
  2589  	require.NoError(t, err)
  2590  
  2591  	ResetAccountNoLogout(tc, u)
  2592  
  2593  	// this will reprovision as an eldest device:
  2594  	u.LoginOrBust(tc)
  2595  	if err := AssertProvisioned(tc); err != nil {
  2596  		t.Fatal(err)
  2597  	}
  2598  
  2599  	newDevice := tc.G.Env.GetDeviceID()
  2600  
  2601  	if newDevice == originalDevice {
  2602  		t.Errorf("device id did not change: %s", newDevice)
  2603  	}
  2604  
  2605  	testUserHasDeviceKey(tc)
  2606  }
  2607  
  2608  // After resetting account, try provisioning in a clean home dir.
  2609  func TestResetAccountNewHome(t *testing.T) {
  2610  	tc := SetupEngineTest(t, "login")
  2611  	defer tc.Cleanup()
  2612  
  2613  	u := CreateAndSignupFakeUser(tc, "login")
  2614  	originalDevice := tc.G.Env.GetDeviceID()
  2615  	ResetAccount(tc, u)
  2616  
  2617  	tcp := SetupEngineTest(t, "login")
  2618  	// this will reprovision as an eldest device:
  2619  	u.LoginOrBust(tcp)
  2620  	if err := AssertProvisioned(tcp); err != nil {
  2621  		t.Fatal(err)
  2622  	}
  2623  
  2624  	newDevice := tcp.G.Env.GetDeviceID()
  2625  
  2626  	if newDevice == originalDevice {
  2627  		t.Errorf("device id did not change: %s", newDevice)
  2628  	}
  2629  
  2630  	testUserHasDeviceKey(tcp)
  2631  }
  2632  
  2633  // After account reset, establish new eldest keys, paper key.
  2634  // Provision another device with paper key.
  2635  func TestResetAccountPaper(t *testing.T) {
  2636  	tc := SetupEngineTest(t, "login")
  2637  	defer tc.Cleanup()
  2638  
  2639  	u := CreateAndSignupFakeUser(tc, "login")
  2640  	ResetAccount(tc, u)
  2641  
  2642  	// login, creating new eldest key, new paper keys
  2643  	loginUI := &paperLoginUI{Username: u.Username}
  2644  	uis := libkb.UIs{
  2645  		ProvisionUI: newTestProvisionUI(),
  2646  		LogUI:       tc.G.UI.GetLogUI(),
  2647  		GPGUI:       &gpgtestui{},
  2648  		SecretUI:    u.NewSecretUI(),
  2649  		LoginUI:     loginUI,
  2650  	}
  2651  	li := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, u.Username, keybase1.ClientType_CLI)
  2652  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2653  	if err := RunEngine2(m, li); err != nil {
  2654  		t.Fatal(err)
  2655  	}
  2656  	paper := loginUI.PaperPhrase
  2657  	if len(paper) != 0 {
  2658  		t.Fatal("paper phrase exists in login ui")
  2659  	}
  2660  	testUserHasDeviceKey(tc)
  2661  
  2662  	uis = libkb.UIs{
  2663  		LogUI:    tc.G.UI.GetLogUI(),
  2664  		LoginUI:  &libkb.TestLoginUI{},
  2665  		SecretUI: &libkb.TestSecretUI{},
  2666  	}
  2667  	peng := NewPaperKey(tc.G)
  2668  	m = NewMetaContextForTest(tc).WithUIs(uis)
  2669  	if err := RunEngine2(m, peng); err != nil {
  2670  		t.Fatal(err)
  2671  	}
  2672  	if len(peng.Passphrase()) == 0 {
  2673  		t.Fatal("empty paper phrase")
  2674  	}
  2675  	paper = peng.Passphrase()
  2676  
  2677  	// provision on new device with paper key
  2678  	tcp := SetupEngineTest(t, "login")
  2679  	defer tcp.Cleanup()
  2680  
  2681  	secUI := u.NewSecretUI()
  2682  	secUI.Passphrase = paper
  2683  	provUI := newTestProvisionUIPaper()
  2684  	provLoginUI := &libkb.TestLoginUI{Username: u.Username}
  2685  	uis = libkb.UIs{
  2686  		ProvisionUI: provUI,
  2687  		LogUI:       tcp.G.UI.GetLogUI(),
  2688  		SecretUI:    secUI,
  2689  		LoginUI:     provLoginUI,
  2690  		GPGUI:       &gpgtestui{},
  2691  	}
  2692  	eng := NewLogin(tcp.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2693  	m = NewMetaContextForTest(tcp).WithUIs(uis)
  2694  	if err := RunEngine2(m, eng); err != nil {
  2695  		t.Fatal(err)
  2696  	}
  2697  
  2698  	testUserHasDeviceKey(tcp)
  2699  }
  2700  
  2701  // After resetting account, try kex2 provisioning.
  2702  func TestResetAccountKexProvision(t *testing.T) {
  2703  	tc := SetupEngineTest(t, "login")
  2704  	defer tc.Cleanup()
  2705  
  2706  	u := CreateAndSignupFakeUser(tc, "login")
  2707  
  2708  	ResetAccount(tc, u)
  2709  
  2710  	// create provisioner device
  2711  	tcX := SetupEngineTest(t, "login")
  2712  	defer tcX.Cleanup()
  2713  	// this will reprovision as an eldest device:
  2714  	u.LoginOrBust(tcX)
  2715  	if err := AssertProvisioned(tcX); err != nil {
  2716  		t.Fatal(err)
  2717  	}
  2718  	testUserHasDeviceKey(tcX)
  2719  	var secretX kex2.Secret
  2720  	if _, err := rand.Read(secretX[:]); err != nil {
  2721  		t.Fatal(err)
  2722  	}
  2723  	secretCh := make(chan kex2.Secret)
  2724  
  2725  	// provisionee context:
  2726  	tcY := SetupEngineTest(t, "template")
  2727  	defer tcY.Cleanup()
  2728  
  2729  	// provisionee calls login:
  2730  	uis := libkb.UIs{
  2731  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  2732  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  2733  		LogUI:       tcY.G.UI.GetLogUI(),
  2734  		SecretUI:    &libkb.TestSecretUI{},
  2735  		GPGUI:       &gpgtestui{},
  2736  	}
  2737  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2738  
  2739  	var wg sync.WaitGroup
  2740  
  2741  	// start provisionee
  2742  	wg.Add(1)
  2743  	go func() {
  2744  		defer wg.Done()
  2745  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  2746  		if err := RunEngine2(m, eng); err != nil {
  2747  			t.Errorf("login error: %s", err)
  2748  			return
  2749  		}
  2750  	}()
  2751  
  2752  	// start provisioner
  2753  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  2754  	wg.Add(1)
  2755  	go func() {
  2756  		defer wg.Done()
  2757  
  2758  		uis := libkb.UIs{
  2759  			SecretUI:    u.NewSecretUI(),
  2760  			ProvisionUI: newTestProvisionUI(),
  2761  		}
  2762  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  2763  		if err := RunEngine2(m, provisioner); err != nil {
  2764  			t.Errorf("provisioner error: %s", err)
  2765  			return
  2766  		}
  2767  	}()
  2768  	secretFromY := <-secretCh
  2769  	provisioner.AddSecret(secretFromY)
  2770  
  2771  	wg.Wait()
  2772  
  2773  	err := AssertProvisioned(tcY)
  2774  	require.NoError(t, err)
  2775  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_alice")
  2776  }
  2777  
  2778  // Try to replicate @nistur sigchain.
  2779  // github issue: https://github.com/keybase/client/issues/2356
  2780  func TestResetThenPGPOnlyThenProvision(t *testing.T) {
  2781  	tc0 := SetupEngineTest(t, "login")
  2782  	defer tc0.Cleanup()
  2783  
  2784  	// user with synced pgp key
  2785  	u := createFakeUserWithPGPOnly(t, tc0)
  2786  	Logout(tc0)
  2787  
  2788  	// provision a device with that key
  2789  	tc := SetupEngineTest(t, "login")
  2790  	defer tc.Cleanup()
  2791  
  2792  	uis := libkb.UIs{
  2793  		ProvisionUI: newTestProvisionUIPassphrase(),
  2794  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  2795  		LogUI:       tc.G.UI.GetLogUI(),
  2796  		SecretUI:    u.NewSecretUI(),
  2797  		GPGUI:       &gpgtestui{},
  2798  	}
  2799  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2800  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2801  	if err := RunEngine2(m, eng); err != nil {
  2802  		t.Fatal(err)
  2803  	}
  2804  
  2805  	// since this user didn't have any device keys, login should have fixed that:
  2806  	testUserHasDeviceKey(tc)
  2807  
  2808  	// now reset account
  2809  	ResetAccount(tc, u)
  2810  
  2811  	// Now login again so we can post a PGP key
  2812  	m = m.WithNewProvisionalLoginContext()
  2813  	err := libkb.PassphraseLoginNoPrompt(m, u.Username, u.Passphrase)
  2814  	require.NoError(t, err, "passphrase login no prompt worked")
  2815  
  2816  	// Generate a new test PGP key for the user, and specify the PushSecret
  2817  	// flag so that their triplesec'ed key is pushed to the server.
  2818  	gen := libkb.PGPGenArg{
  2819  		PrimaryBits: 768,
  2820  		SubkeyBits:  768,
  2821  	}
  2822  	gen.AddDefaultUID(tc.G)
  2823  	peng := NewPGPKeyImportEngine(tc.G, PGPKeyImportEngineArg{
  2824  		Gen:        &gen,
  2825  		PushSecret: true,
  2826  		NoSave:     true,
  2827  	})
  2828  
  2829  	if err := RunEngine2(m, peng); err != nil {
  2830  		tc.T.Fatal(err)
  2831  	}
  2832  
  2833  	m = m.CommitProvisionalLogin()
  2834  	Logout(tc)
  2835  
  2836  	// Now finally try a login
  2837  	eng = NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2838  	if err := RunEngine2(m, eng); err != nil {
  2839  		t.Fatal(err)
  2840  	}
  2841  
  2842  	// since this user didn't have any device keys, login should have fixed that:
  2843  	testUserHasDeviceKey(tc)
  2844  }
  2845  
  2846  // Try to replicate @nistur sigchain.
  2847  // github issue: https://github.com/keybase/client/issues/2356
  2848  func TestResetAccountLikeNistur(t *testing.T) {
  2849  	tc0 := SetupEngineTest(t, "login")
  2850  	defer tc0.Cleanup()
  2851  
  2852  	// user with synced pgp key
  2853  	u := createFakeUserWithPGPOnly(t, tc0)
  2854  	Logout(tc0)
  2855  
  2856  	// provision a device with that key
  2857  	tc := SetupEngineTest(t, "login")
  2858  	defer tc.Cleanup()
  2859  
  2860  	uis := libkb.UIs{
  2861  		ProvisionUI: newTestProvisionUIPassphrase(),
  2862  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  2863  		LogUI:       tc.G.UI.GetLogUI(),
  2864  		SecretUI:    u.NewSecretUI(),
  2865  		GPGUI:       &gpgtestui{},
  2866  	}
  2867  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2868  	m := NewMetaContextForTest(tc).WithUIs(uis)
  2869  	if err := RunEngine2(m, eng); err != nil {
  2870  		t.Fatal(err)
  2871  	}
  2872  
  2873  	// since this user didn't have any device keys, login should have fixed that:
  2874  	testUserHasDeviceKey(tc)
  2875  
  2876  	// now reset account
  2877  	ResetAccount(tc, u)
  2878  
  2879  	// create provisioner device
  2880  	tcX := SetupEngineTest(t, "login")
  2881  	defer tcX.Cleanup()
  2882  
  2883  	// this will reprovision as an eldest device:
  2884  	u.LoginOrBust(tcX)
  2885  	if err := AssertProvisioned(tcX); err != nil {
  2886  		t.Fatal(err)
  2887  	}
  2888  	testUserHasDeviceKey(tcX)
  2889  	var secretX kex2.Secret
  2890  	if _, err := rand.Read(secretX[:]); err != nil {
  2891  		t.Fatal(err)
  2892  	}
  2893  	secretCh := make(chan kex2.Secret)
  2894  
  2895  	// provisionee context:
  2896  	tcY := SetupEngineTest(t, "template")
  2897  	defer tcY.Cleanup()
  2898  
  2899  	// provisionee calls login:
  2900  	uis = libkb.UIs{
  2901  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  2902  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  2903  		LogUI:       tcY.G.UI.GetLogUI(),
  2904  		SecretUI:    &libkb.TestSecretUI{},
  2905  		GPGUI:       &gpgtestui{},
  2906  	}
  2907  	eng = NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2908  
  2909  	var wg sync.WaitGroup
  2910  
  2911  	// start provisionee
  2912  	wg.Add(1)
  2913  	go func() {
  2914  		defer wg.Done()
  2915  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  2916  		if err := RunEngine2(m, eng); err != nil {
  2917  			t.Errorf("login error: %s", err)
  2918  			return
  2919  		}
  2920  	}()
  2921  
  2922  	// start provisioner
  2923  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  2924  	wg.Add(1)
  2925  	go func() {
  2926  		defer wg.Done()
  2927  
  2928  		uis := libkb.UIs{
  2929  			SecretUI:    u.NewSecretUI(),
  2930  			ProvisionUI: newTestProvisionUI(),
  2931  		}
  2932  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  2933  		if err := RunEngine2(m, provisioner); err != nil {
  2934  			t.Errorf("provisioner error: %s", err)
  2935  			return
  2936  		}
  2937  	}()
  2938  	secretFromY := <-secretCh
  2939  	provisioner.AddSecret(secretFromY)
  2940  
  2941  	wg.Wait()
  2942  
  2943  	err := AssertProvisioned(tcY)
  2944  	require.NoError(t, err)
  2945  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_alice")
  2946  }
  2947  
  2948  // Establish two devices.  Reset on one of them, login on the other.
  2949  func TestResetMultipleDevices(t *testing.T) {
  2950  	tcX := SetupEngineTest(t, "login")
  2951  	defer tcX.Cleanup()
  2952  
  2953  	// create provisioner device
  2954  	u := CreateAndSignupFakeUser(tcX, "login")
  2955  	if err := AssertProvisioned(tcX); err != nil {
  2956  		t.Fatal(err)
  2957  	}
  2958  	testUserHasDeviceKey(tcX)
  2959  	var secretX kex2.Secret
  2960  	if _, err := rand.Read(secretX[:]); err != nil {
  2961  		t.Fatal(err)
  2962  	}
  2963  	secretCh := make(chan kex2.Secret)
  2964  
  2965  	// provisionee context:
  2966  	tcY := SetupEngineTest(t, "template")
  2967  	defer tcY.Cleanup()
  2968  
  2969  	// provisionee calls login:
  2970  	uis := libkb.UIs{
  2971  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  2972  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  2973  		LogUI:       tcY.G.UI.GetLogUI(),
  2974  		SecretUI:    &libkb.TestSecretUI{},
  2975  		GPGUI:       &gpgtestui{},
  2976  	}
  2977  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  2978  
  2979  	var wg sync.WaitGroup
  2980  
  2981  	// start provisionee
  2982  	wg.Add(1)
  2983  	go func() {
  2984  		defer wg.Done()
  2985  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  2986  		if err := RunEngine2(m, eng); err != nil {
  2987  			t.Errorf("login error: %s", err)
  2988  			return
  2989  		}
  2990  	}()
  2991  
  2992  	// start provisioner
  2993  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  2994  	wg.Add(1)
  2995  	go func() {
  2996  		defer wg.Done()
  2997  
  2998  		uis := libkb.UIs{
  2999  			SecretUI:    u.NewSecretUI(),
  3000  			ProvisionUI: newTestProvisionUI(),
  3001  		}
  3002  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3003  		if err := RunEngine2(m, provisioner); err != nil {
  3004  			t.Errorf("provisioner error: %s", err)
  3005  			return
  3006  		}
  3007  	}()
  3008  	secretFromY := <-secretCh
  3009  	provisioner.AddSecret(secretFromY)
  3010  
  3011  	wg.Wait()
  3012  
  3013  	if err := AssertProvisioned(tcY); err != nil {
  3014  		t.Fatal(err)
  3015  	}
  3016  
  3017  	// have two devices in contexts tcX and tcY
  3018  	deviceX := tcX.G.Env.GetDeviceID()
  3019  
  3020  	// logout on tcX
  3021  	Logout(tcX)
  3022  
  3023  	// reset on tcY
  3024  	ResetAccount(tcY, u)
  3025  
  3026  	// login on tcX
  3027  	u.LoginOrBust(tcX)
  3028  
  3029  	if err := AssertProvisioned(tcX); err != nil {
  3030  		t.Fatal(err)
  3031  	}
  3032  
  3033  	if tcX.G.Env.GetDeviceID() == deviceX {
  3034  		t.Error("device id did not change")
  3035  	}
  3036  }
  3037  
  3038  // If there is a bad device id in the config file, provisioning
  3039  // appears to succeed and provision the new device, but the config
  3040  // file retains the bad device id and further attempts to
  3041  // do anything fail (they say login required, and running login
  3042  // results in provisioning again...)
  3043  // Seems to only happen w/ kex2.
  3044  func TestProvisionWithBadConfig(t *testing.T) {
  3045  	// device X (provisioner) context:
  3046  	tcX := SetupEngineTest(t, "kex2provision")
  3047  	defer tcX.Cleanup()
  3048  
  3049  	// device Y (provisionee) context:
  3050  	tcY := SetupEngineTest(t, "template")
  3051  	defer tcY.Cleanup()
  3052  
  3053  	// provisioner needs to be logged in
  3054  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
  3055  	var secretX kex2.Secret
  3056  	if _, err := rand.Read(secretX[:]); err != nil {
  3057  		t.Fatal(err)
  3058  	}
  3059  
  3060  	// copy the config info from device X to device Y
  3061  	uc, err := tcX.G.Env.GetConfig().GetUserConfig()
  3062  	if err != nil {
  3063  		t.Fatal(err)
  3064  	}
  3065  	if err := tcY.G.Env.GetConfigWriter().SetUserConfig(uc, true); err != nil {
  3066  		t.Fatal(err)
  3067  	}
  3068  	// but give device Y a new random device ID that doesn't exist:
  3069  	newID, err := libkb.NewDeviceID()
  3070  	if err != nil {
  3071  		t.Fatal(err)
  3072  	}
  3073  	if err := tcY.G.Env.GetConfigWriter().SetDeviceID(newID); err != nil {
  3074  		t.Fatal(err)
  3075  	}
  3076  
  3077  	secretCh := make(chan kex2.Secret)
  3078  
  3079  	// provisionee calls login:
  3080  	uis := libkb.UIs{
  3081  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  3082  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  3083  		LogUI:       tcY.G.UI.GetLogUI(),
  3084  		SecretUI:    &libkb.TestSecretUI{},
  3085  		GPGUI:       &gpgtestui{},
  3086  	}
  3087  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3088  
  3089  	var wg sync.WaitGroup
  3090  
  3091  	// start provisionee
  3092  	wg.Add(1)
  3093  	go func() {
  3094  		defer wg.Done()
  3095  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  3096  		if err := RunEngine2(m, eng); err != nil {
  3097  			t.Errorf("login error: %s", err)
  3098  			return
  3099  		}
  3100  	}()
  3101  
  3102  	// start provisioner
  3103  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  3104  	wg.Add(1)
  3105  	go func() {
  3106  		defer wg.Done()
  3107  
  3108  		uis := libkb.UIs{
  3109  			SecretUI:    userX.NewSecretUI(),
  3110  			ProvisionUI: newTestProvisionUI(),
  3111  		}
  3112  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3113  		if err := RunEngine2(m, provisioner); err != nil {
  3114  			t.Errorf("provisioner error: %s", err)
  3115  			return
  3116  		}
  3117  	}()
  3118  	secretFromY := <-secretCh
  3119  	provisioner.AddSecret(secretFromY)
  3120  
  3121  	wg.Wait()
  3122  
  3123  	if tcY.G.Env.GetDeviceID() == newID {
  3124  		t.Errorf("y device id: %s, same as %s.  expected it to change.", tcY.G.Env.GetDeviceID(), newID)
  3125  	}
  3126  	if tcY.G.Env.GetDeviceID() == tcX.G.Env.GetDeviceID() {
  3127  		t.Error("y device id matches x device id, they should be different")
  3128  	}
  3129  
  3130  	err = AssertProvisioned(tcY)
  3131  	require.NoError(t, err)
  3132  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_alice")
  3133  }
  3134  
  3135  // If the provisioner has their secret stored, they should not be
  3136  // prompted to enter a passphrase when they provision a device.
  3137  func TestProvisionerSecretStore(t *testing.T) {
  3138  	// device X (provisioner) context:
  3139  	tcX := SetupEngineTest(t, "kex2provision")
  3140  	defer tcX.Cleanup()
  3141  
  3142  	// device Y (provisionee) context:
  3143  	tcY := SetupEngineTest(t, "template")
  3144  	defer tcY.Cleanup()
  3145  
  3146  	// create provisioner w/ stored secret
  3147  	userX := SignupFakeUserStoreSecret(tcX, "login")
  3148  	// userX := CreateAndSignupFakeUser(tcX, "login")
  3149  	var secretX kex2.Secret
  3150  	if _, err := rand.Read(secretX[:]); err != nil {
  3151  		t.Fatal(err)
  3152  	}
  3153  	clearCaches(tcX.G)
  3154  
  3155  	secretCh := make(chan kex2.Secret)
  3156  
  3157  	// provisionee calls login:
  3158  	uis := libkb.UIs{
  3159  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  3160  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  3161  		LogUI:       tcY.G.UI.GetLogUI(),
  3162  		SecretUI:    &libkb.TestSecretUI{},
  3163  		GPGUI:       &gpgtestui{},
  3164  	}
  3165  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3166  	m := NewMetaContextForTest(tcY).WithUIs(uis)
  3167  
  3168  	// start provisionee
  3169  	errY := make(chan error, 1)
  3170  	go func() {
  3171  		errY <- RunEngine2(m, eng)
  3172  	}()
  3173  
  3174  	// start provisioner
  3175  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  3176  	errX := make(chan error, 1)
  3177  	go func() {
  3178  		uis := libkb.UIs{
  3179  			SecretUI:    &testNoPromptSecretUI{},
  3180  			ProvisionUI: newTestProvisionUI(),
  3181  		}
  3182  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3183  		errX <- RunEngine2(m, provisioner)
  3184  	}()
  3185  	secretFromY := <-secretCh
  3186  	go provisioner.AddSecret(secretFromY)
  3187  
  3188  	var xDone, yDone bool
  3189  	for {
  3190  		select {
  3191  		case e := <-errY:
  3192  			if e != nil {
  3193  				t.Fatalf("provisionee error: %s", e)
  3194  			}
  3195  			yDone = true
  3196  		case e := <-errX:
  3197  			if e != nil {
  3198  				t.Fatalf("provisioner error: %s", e)
  3199  			}
  3200  			xDone = true
  3201  		}
  3202  		if xDone && yDone {
  3203  			break
  3204  		}
  3205  	}
  3206  
  3207  	if err := AssertProvisioned(tcY); err != nil {
  3208  		t.Fatal(err)
  3209  	}
  3210  
  3211  	// On device Y, logout and login. This should tickle Bug3964
  3212  	Logout(tcY)
  3213  	uis = libkb.UIs{
  3214  		ProvisionUI: newTestProvisionUIPassphrase(),
  3215  		LoginUI:     &libkb.TestLoginUI{},
  3216  		LogUI:       tcY.G.UI.GetLogUI(),
  3217  		SecretUI:    userX.NewSecretUI(),
  3218  		GPGUI:       &gpgtestui{},
  3219  	}
  3220  	eng = NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, userX.Username, keybase1.ClientType_CLI)
  3221  	m = NewMetaContextForTest(tcY).WithUIs(uis)
  3222  	if err := RunEngine2(m, eng); err != nil {
  3223  		t.Fatal(err)
  3224  	}
  3225  }
  3226  
  3227  // GPG key required for provisioning, but user on a mobile device.
  3228  func TestProvisionGPGMobile(t *testing.T) {
  3229  	tc := SetupEngineTest(t, "login")
  3230  	defer tc.Cleanup()
  3231  
  3232  	u1 := createFakeUserWithPGPPubOnly(t, tc)
  3233  	Logout(tc)
  3234  
  3235  	// redo SetupEngineTest to get a new home directory...should look like a new device.
  3236  	tc2 := SetupEngineTest(t, "login")
  3237  	defer tc2.Cleanup()
  3238  
  3239  	// we need the gpg keyring that's in the first homedir
  3240  	if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  3241  		t.Fatal(err)
  3242  	}
  3243  
  3244  	// run login on new device
  3245  	uis := libkb.UIs{
  3246  		ProvisionUI: newTestProvisionUIGPGImport(),
  3247  		LogUI:       tc2.G.UI.GetLogUI(),
  3248  		SecretUI:    u1.NewSecretUI(),
  3249  		LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  3250  		GPGUI:       &gpgtestui{},
  3251  	}
  3252  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_MOBILE, "", keybase1.ClientType_CLI)
  3253  	m := NewMetaContextForTest(tc2).WithUIs(uis)
  3254  	err := RunEngine2(m, eng)
  3255  	if err == nil {
  3256  		t.Fatal("no error provisioning with gpg on mobile")
  3257  	}
  3258  	if _, ok := err.(libkb.GPGUnavailableError); !ok {
  3259  		t.Errorf("error type: %T, expected libkb.GPGUnavailableError", err)
  3260  	}
  3261  }
  3262  
  3263  func TestProvisionEnsureNoPaperKey(t *testing.T) {
  3264  	testProvisionEnsureNoPaperKey(t, false)
  3265  }
  3266  
  3267  func TestProvisionEnsureNoPaperKeyPUK(t *testing.T) {
  3268  	testProvisionEnsureNoPaperKey(t, true)
  3269  }
  3270  
  3271  // Provisioning a new device when the user has no paper keys should work
  3272  // and not generate a paper key.
  3273  func testProvisionEnsureNoPaperKey(t *testing.T, upgradePerUserKey bool) {
  3274  	// This test is based on TestProvisionDesktop.
  3275  
  3276  	t.Logf("create 2 contexts")
  3277  
  3278  	// device X (provisioner) context:
  3279  	tcX := SetupEngineTest(t, "kex2provision")
  3280  	defer tcX.Cleanup()
  3281  	tcX.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
  3282  
  3283  	// device Y (provisionee) context:
  3284  	tcY := SetupEngineTest(t, "template")
  3285  	defer tcY.Cleanup()
  3286  	tcY.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
  3287  
  3288  	// provisioner needs to be logged in
  3289  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
  3290  	var secretX kex2.Secret
  3291  	if _, err := rand.Read(secretX[:]); err != nil {
  3292  		t.Fatal(err)
  3293  	}
  3294  
  3295  	t.Logf("check for initial paper key")
  3296  	originalPaperKey := hasOnePaperDev(tcY, userX)
  3297  
  3298  	t.Logf("revoke paper keys from X")
  3299  	{
  3300  		uis := libkb.UIs{
  3301  			LoginUI:  &libkb.TestLoginUI{Username: userX.Username},
  3302  			LogUI:    tcX.G.UI.GetLogUI(),
  3303  			SecretUI: &libkb.TestSecretUI{},
  3304  		}
  3305  		eng := NewRevokeDeviceEngine(tcX.G, RevokeDeviceEngineArgs{
  3306  			ID:        originalPaperKey,
  3307  			ForceSelf: false,
  3308  		})
  3309  		m := libkb.NewMetaContextTODO(tcX.G).WithUIs(uis)
  3310  		err := RunEngine2(m, eng)
  3311  		require.NoError(t, err, "revoke original paper key")
  3312  	}
  3313  
  3314  	t.Logf("check for no paper key")
  3315  	hasZeroPaperDev(tcX, userX)
  3316  
  3317  	t.Logf("do kex provision")
  3318  
  3319  	secretCh := make(chan kex2.Secret)
  3320  
  3321  	// provisionee calls login:
  3322  	uis := libkb.UIs{
  3323  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  3324  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  3325  		LogUI:       tcY.G.UI.GetLogUI(),
  3326  		SecretUI:    &libkb.TestSecretUI{},
  3327  		GPGUI:       &gpgtestui{},
  3328  	}
  3329  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3330  
  3331  	var wg sync.WaitGroup
  3332  
  3333  	// start provisionee
  3334  	wg.Add(1)
  3335  	go func() {
  3336  		defer wg.Done()
  3337  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  3338  		if err := RunEngine2(m, eng); err != nil {
  3339  			t.Errorf("provisionee login error: %s", err)
  3340  			return
  3341  		}
  3342  	}()
  3343  
  3344  	// start provisioner
  3345  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  3346  	wg.Add(1)
  3347  	go func() {
  3348  		defer wg.Done()
  3349  
  3350  		uis := libkb.UIs{
  3351  			SecretUI:    userX.NewSecretUI(),
  3352  			ProvisionUI: newTestProvisionUI(),
  3353  		}
  3354  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3355  		if err := RunEngine2(m, provisioner); err != nil {
  3356  			t.Errorf("provisioner error: %s", err)
  3357  			return
  3358  		}
  3359  	}()
  3360  	secretFromY := <-secretCh
  3361  	provisioner.AddSecret(secretFromY)
  3362  
  3363  	wg.Wait()
  3364  
  3365  	require.False(t, t.Failed(), "prior failure in a goroutine")
  3366  
  3367  	if err := AssertProvisioned(tcY); err != nil {
  3368  		t.Fatal(err)
  3369  	}
  3370  
  3371  	t.Logf("kex finished")
  3372  
  3373  	// after provisioning, the passphrase stream should be cached
  3374  	// (note that this just checks the passphrase stream, not 3sec)
  3375  	assertPassphraseStreamCache(tcY)
  3376  
  3377  	// after provisioning, the device keys should be cached
  3378  	assertDeviceKeysCached(tcY)
  3379  
  3380  	// Make sure that we can still track without a passphrase
  3381  	// after a simulated service restart.  In other words, that
  3382  	// the full LKSec secret was written to the secret store.
  3383  	simulateServiceRestart(t, tcY, userX)
  3384  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_bob")
  3385  
  3386  	t.Logf("check for no paper key")
  3387  	hasZeroPaperDev(tcY, userX)
  3388  	hasZeroPaperDev(tcX, userX)
  3389  }
  3390  
  3391  // Device X provisions device Y, then device Y revokes X.
  3392  func TestProvisionAndRevoke(t *testing.T) {
  3393  	// This test is based on TestProvisionDesktop.
  3394  
  3395  	t.Logf("create 2 contexts")
  3396  
  3397  	// device X (provisioner) context:
  3398  	tcX := SetupEngineTest(t, "kex2provision")
  3399  	defer tcX.Cleanup()
  3400  
  3401  	// device Y (provisionee) context:
  3402  	tcY := SetupEngineTest(t, "template")
  3403  	defer tcY.Cleanup()
  3404  
  3405  	// provisioner needs to be logged in
  3406  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
  3407  	var secretX kex2.Secret
  3408  	if _, err := rand.Read(secretX[:]); err != nil {
  3409  		t.Fatal(err)
  3410  	}
  3411  
  3412  	t.Logf("check for initial paper key")
  3413  	_ = hasOnePaperDev(tcY, userX)
  3414  
  3415  	t.Logf("do kex provision")
  3416  
  3417  	secretCh := make(chan kex2.Secret)
  3418  
  3419  	// provisionee calls login:
  3420  	uis := libkb.UIs{
  3421  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  3422  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  3423  		LogUI:       tcY.G.UI.GetLogUI(),
  3424  		SecretUI:    &libkb.TestSecretUI{},
  3425  		GPGUI:       &gpgtestui{},
  3426  	}
  3427  	eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3428  
  3429  	var wg sync.WaitGroup
  3430  
  3431  	// start provisionee
  3432  	wg.Add(1)
  3433  	go func() {
  3434  		defer wg.Done()
  3435  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  3436  		if err := RunEngine2(m, eng); err != nil {
  3437  			t.Errorf("provisionee login error: %s", err)
  3438  			return
  3439  		}
  3440  	}()
  3441  
  3442  	// start provisioner
  3443  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  3444  	wg.Add(1)
  3445  	go func() {
  3446  		defer wg.Done()
  3447  
  3448  		uis := libkb.UIs{
  3449  			SecretUI:    userX.NewSecretUI(),
  3450  			ProvisionUI: newTestProvisionUI(),
  3451  		}
  3452  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3453  		if err := RunEngine2(m, provisioner); err != nil {
  3454  			t.Errorf("provisioner error: %s", err)
  3455  			return
  3456  		}
  3457  	}()
  3458  	secretFromY := <-secretCh
  3459  	provisioner.AddSecret(secretFromY)
  3460  
  3461  	wg.Wait()
  3462  
  3463  	require.False(t, t.Failed(), "prior failure in a goroutine")
  3464  
  3465  	if err := AssertProvisioned(tcY); err != nil {
  3466  		t.Fatal(err)
  3467  	}
  3468  
  3469  	t.Logf("kex finished")
  3470  
  3471  	// after provisioning, the passphrase stream should be cached
  3472  	// (note that this just checks the passphrase stream, not 3sec)
  3473  	assertPassphraseStreamCache(tcY)
  3474  
  3475  	// after provisioning, the device keys should be cached
  3476  	assertDeviceKeysCached(tcY)
  3477  
  3478  	t.Logf("revoke device X from Y")
  3479  
  3480  	// require.NoError(t, doRevokeDevice(tcY, userX, tcX.G.ActiveDevice.DeviceID(), false))
  3481  	{
  3482  		uis := libkb.UIs{
  3483  			LoginUI:  &libkb.TestLoginUI{Username: userX.Username},
  3484  			LogUI:    tcY.G.UI.GetLogUI(),
  3485  			SecretUI: &libkb.TestSecretUI{},
  3486  		}
  3487  		eng := NewRevokeDeviceEngine(tcY.G, RevokeDeviceEngineArgs{
  3488  			ID:        tcX.G.ActiveDevice.DeviceID(),
  3489  			ForceSelf: false,
  3490  		})
  3491  		m := libkb.NewMetaContextTODO(tcY.G).WithUIs(uis)
  3492  		err := RunEngine2(m, eng)
  3493  		require.NoError(t, err, "revoke original paper key")
  3494  	}
  3495  
  3496  	t.Logf("revoke finished")
  3497  
  3498  	// Make sure that we can still track without a passphrase
  3499  	// after a simulated service restart.  In other words, that
  3500  	// the full LKSec secret was written to the secret store.
  3501  	simulateServiceRestart(t, tcY, userX)
  3502  	testTrack(t, tcY, libkb.KeybaseNullSigVersion, "t_bob")
  3503  
  3504  	t.Logf("check for paper key")
  3505  	hasOnePaperDev(tcY, userX)
  3506  	hasOnePaperDev(tcX, userX)
  3507  }
  3508  
  3509  // Test bootstrap, login offline after service restart when provisioned via
  3510  // GPG sign.
  3511  func TestBootstrapAfterGPGSign(t *testing.T) {
  3512  	// use tcCheck just to check gpg version
  3513  	tcCheck := SetupEngineTest(t, "check")
  3514  	defer tcCheck.Cleanup()
  3515  	skipOldGPG(tcCheck)
  3516  
  3517  	// this test sometimes fails at the GPG level with a "Bad signature" error,
  3518  	// so we're going to retry it several times to hopefully get past it.
  3519  	attempts := 10
  3520  	for i := 0; i < attempts; i++ {
  3521  		tc := SetupEngineTest(t, "login")
  3522  		defer tc.Cleanup()
  3523  
  3524  		u1 := createFakeUserWithPGPPubOnly(t, tc)
  3525  		Logout(tc)
  3526  
  3527  		// redo SetupEngineTest to get a new home directory...should look like a new device.
  3528  		tc2 := SetupEngineTest(t, "login")
  3529  		defer tc2.Cleanup()
  3530  
  3531  		// we need the gpg keyring that's in the first homedir
  3532  		if err := tc.MoveGpgKeyringTo(tc2); err != nil {
  3533  			t.Fatal(err)
  3534  		}
  3535  
  3536  		// run login on new device
  3537  		uis := libkb.UIs{
  3538  			ProvisionUI: newTestProvisionUIGPGSign(),
  3539  			LogUI:       tc2.G.UI.GetLogUI(),
  3540  			SecretUI:    u1.NewSecretUI(),
  3541  			LoginUI:     &libkb.TestLoginUI{Username: u1.Username},
  3542  			GPGUI:       &gpgtestui{Contextified: libkb.NewContextified(tc2.G)},
  3543  		}
  3544  		eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3545  		m := NewMetaContextForTest(tc2).WithUIs(uis)
  3546  		if err := RunEngine2(m, eng); err != nil {
  3547  			t.Logf("test run %d:  RunEngine(Login) error: %s", i+1, err)
  3548  			continue
  3549  		}
  3550  
  3551  		t.Logf("test run %d: RunEngine(Login) succeeded", i+1)
  3552  
  3553  		testUserHasDeviceKey(tc2)
  3554  
  3555  		// highly possible they didn't have a paper key, so make sure they still don't have one:
  3556  		hasZeroPaperDev(tc2, u1)
  3557  
  3558  		if err := AssertProvisioned(tc2); err != nil {
  3559  			t.Fatal(err)
  3560  		}
  3561  
  3562  		// do a upak load to make sure it is cached
  3563  		arg := libkb.NewLoadUserByUIDArg(context.TODO(), tc2.G, u1.UID())
  3564  		_, _, err := tc2.G.GetUPAKLoader().Load(arg)
  3565  		require.NoError(t, err)
  3566  
  3567  		// Simulate restarting the service by wiping out the
  3568  		// passphrase stream cache and cached secret keys
  3569  		tc2.SimulateServiceRestart()
  3570  		tc2.G.GetUPAKLoader().ClearMemory()
  3571  
  3572  		// LoginOffline will run when service restarts.
  3573  		// Since this was GPG sign, there will be no secret stored.
  3574  		oeng := NewLoginOffline(tc2.G)
  3575  		oerr := RunEngine2(m, oeng)
  3576  		if oerr != nil {
  3577  			t.Fatalf("LoginOffline failed after gpg sign + svc restart: %s", oerr)
  3578  		}
  3579  
  3580  		// GetBootstrapStatus should return without error and with LoggedIn set
  3581  		// to true.
  3582  		beng := NewBootstrap(tc2.G)
  3583  		m = NewMetaContextForTest(tc2)
  3584  		if err := RunEngine2(m, beng); err != nil {
  3585  			t.Fatal(err)
  3586  		}
  3587  		status := beng.Status()
  3588  		if status.LoggedIn != true {
  3589  			t.Error("bootstrap status -> logged out, expected logged in")
  3590  		}
  3591  		if !status.Registered {
  3592  			t.Error("registered false")
  3593  		}
  3594  
  3595  		t.Logf("test run %d: all checks passed, returning", i+1)
  3596  		return
  3597  	}
  3598  
  3599  	t.Fatalf("TestBootstrapAfterGPGSign failed %d times", attempts)
  3600  }
  3601  
  3602  func TestLoginAlready(t *testing.T) {
  3603  	tc := SetupEngineTest(t, "login")
  3604  	defer tc.Cleanup()
  3605  
  3606  	u1 := CreateAndSignupFakeUser(tc, "login")
  3607  	Logout(tc)
  3608  	u1.LoginOrBust(tc)
  3609  
  3610  	// Logging in again with same username should not return an error
  3611  	if err := u1.Login(tc.G); err != nil {
  3612  		t.Fatal(err)
  3613  	}
  3614  
  3615  	// Logging in with a different username should returh LoggedInError
  3616  	u1.Username = "x" + u1.Username
  3617  	err := u1.Login(tc.G)
  3618  	if err == nil {
  3619  		t.Fatal("login with different username should return an error")
  3620  	}
  3621  	if _, ok := err.(libkb.LoggedInError); !ok {
  3622  		t.Fatalf("err type: %T (%s), expected libkb.LoggedInError", err, err)
  3623  	}
  3624  }
  3625  
  3626  func TestLoginUsernameOnProvisionedDevice(t *testing.T) {
  3627  	tc := SetupEngineTest(t, "login")
  3628  	defer tc.Cleanup()
  3629  
  3630  	u1 := CreateAndSignupFakeUser(tc, "login")
  3631  	Logout(tc)
  3632  
  3633  	secui := u1.NewCountSecretUI()
  3634  	uis := libkb.UIs{
  3635  		ProvisionUI: newTestProvisionUIPassphrase(),
  3636  		LoginUI:     &libkb.TestLoginUI{},
  3637  		LogUI:       tc.G.UI.GetLogUI(),
  3638  		SecretUI:    secui,
  3639  		GPGUI:       &gpgtestui{},
  3640  	}
  3641  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, u1.Username, keybase1.ClientType_CLI)
  3642  	m := NewMetaContextForTest(tc).WithUIs(uis)
  3643  	if err := RunEngine2(m, eng); err != nil {
  3644  		t.Fatalf("login with email should work now, got error: %s (%T)", err, err)
  3645  	}
  3646  
  3647  	assertPassphraseStreamCache(tc)
  3648  	assertDeviceKeysCached(tc)
  3649  	assertSecretStored(tc, u1.Username)
  3650  
  3651  	require.Equal(t, 1, secui.CallCount, "expecting a passphrase prompt when logging in with username")
  3652  }
  3653  
  3654  func TestLoginEmailOnProvisionedDevice(t *testing.T) {
  3655  	tc := SetupEngineTest(t, "login")
  3656  	defer tc.Cleanup()
  3657  
  3658  	u1 := CreateAndSignupFakeUser(tc, "login")
  3659  	Logout(tc)
  3660  
  3661  	secui := u1.NewCountSecretUI()
  3662  	uis := libkb.UIs{
  3663  		ProvisionUI: newTestProvisionUIPassphrase(),
  3664  		LoginUI:     &libkb.TestLoginUI{},
  3665  		LogUI:       tc.G.UI.GetLogUI(),
  3666  		SecretUI:    secui,
  3667  		GPGUI:       &gpgtestui{},
  3668  	}
  3669  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, u1.Email, keybase1.ClientType_CLI)
  3670  	m := NewMetaContextForTest(tc).WithUIs(uis)
  3671  	err := RunEngine2(m, eng)
  3672  	require.Error(t, err)
  3673  	require.IsType(t, libkb.BadUsernameError{}, err)
  3674  	require.Contains(t, err.Error(), "not supported")
  3675  }
  3676  func TestBeforeResetDeviceName(t *testing.T) {
  3677  	tc := SetupEngineTest(t, "login")
  3678  	defer tc.Cleanup()
  3679  
  3680  	u := CreateAndSignupFakeUser(tc, "login")
  3681  	originalDeviceName := u.DeviceName
  3682  	t.Logf("original device name: %s", originalDeviceName)
  3683  	ResetAccount(tc, u)
  3684  
  3685  	provui := &testProvisionSetNameUI{
  3686  		testProvisionUI: newTestProvisionUI(),
  3687  		DeviceName:      originalDeviceName,
  3688  	}
  3689  	uis := libkb.UIs{
  3690  		ProvisionUI: provui,
  3691  		LoginUI:     &libkb.TestLoginUI{Username: u.Username},
  3692  		LogUI:       tc.G.UI.GetLogUI(),
  3693  		SecretUI:    u.NewSecretUI(),
  3694  		GPGUI:       &gpgtestui{},
  3695  	}
  3696  	eng := NewLogin(tc.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3697  	m := NewMetaContextForTest(tc).WithUIs(uis)
  3698  	err := RunEngine2(m, eng)
  3699  	if err == nil {
  3700  		t.Errorf("Login worked with pre-reset device name")
  3701  	}
  3702  	if len(provui.ExistingDevicesFromArg) == 0 {
  3703  		t.Fatalf("no existing devices provided to provision ui, expected 1 (pre reset)")
  3704  	}
  3705  	if provui.ExistingDevicesFromArg[0] != originalDeviceName {
  3706  		t.Errorf("existing device name 0: %q, expected %q", provui.ExistingDevicesFromArg[0], originalDeviceName)
  3707  	}
  3708  }
  3709  
  3710  func TestProvisioningWithSmartPunctuationDeviceName(t *testing.T) {
  3711  	tc := SetupEngineTest(t, "login")
  3712  	defer tc.Cleanup()
  3713  
  3714  	fu := NewFakeUserOrBust(tc.T, "login")
  3715  	tc.G.Log.Debug("New test user: %s / %s", fu.Username, fu.Email)
  3716  
  3717  	arg := MakeTestSignupEngineRunArg(fu)
  3718  	desiredName := arg.DeviceName + "'s test's cool-thing-device"
  3719  	arg.DeviceName += "’s test‘s cool—thing–device"
  3720  	SignupFakeUserWithArg(tc, fu, arg)
  3721  	fu.LoginOrBust(tc)
  3722  	if err := fu.LoadUser(tc); err != nil {
  3723  		t.Errorf("unable to load user: %q", err)
  3724  	}
  3725  	deviceNames, err := fu.User.DeviceNames()
  3726  	if err != nil {
  3727  		t.Errorf("unable to list device names: %q", err)
  3728  	}
  3729  	if len(deviceNames) < 1 {
  3730  		t.Error("no devices returned")
  3731  	}
  3732  	if deviceNames[0] != desiredName {
  3733  		t.Errorf("device name 0: %q, should be %q", deviceNames[0], desiredName)
  3734  	}
  3735  }
  3736  
  3737  func TestProvisionAutomatedPaperKey(t *testing.T) {
  3738  	tc := SetupEngineTest(t, "login")
  3739  	defer tc.Cleanup()
  3740  
  3741  	fu := NewFakeUserOrBust(t, "paper")
  3742  	arg := MakeTestSignupEngineRunArg(fu)
  3743  	arg.SkipPaper = false
  3744  	loginUI := &paperLoginUI{Username: fu.Username}
  3745  	uis := libkb.UIs{
  3746  		LogUI:    tc.G.UI.GetLogUI(),
  3747  		GPGUI:    &gpgtestui{},
  3748  		SecretUI: fu.NewSecretUI(),
  3749  		LoginUI:  loginUI,
  3750  	}
  3751  	s := NewSignupEngine(tc.G, &arg)
  3752  	err := RunEngine2(NewMetaContextForTest(tc).WithUIs(uis), s)
  3753  	if err != nil {
  3754  		tc.T.Fatal(err)
  3755  	}
  3756  
  3757  	assertNumDevicesAndKeys(tc, fu, 2, 4)
  3758  
  3759  	Logout(tc)
  3760  
  3761  	if len(loginUI.PaperPhrase) == 0 {
  3762  		t.Fatal("login ui has no paper key phrase")
  3763  	}
  3764  
  3765  	// redo SetupEngineTest to get a new home directory
  3766  	tc2 := SetupEngineTest(t, "login")
  3767  	defer tc2.Cleanup()
  3768  
  3769  	provUI := newTestProvisionUIPaper()
  3770  	provLoginUI := &libkb.TestLoginUI{}
  3771  	uis2 := libkb.UIs{
  3772  		ProvisionUI: provUI,
  3773  		LogUI:       tc2.G.UI.GetLogUI(),
  3774  		SecretUI:    fu.NewSecretUI(),
  3775  		LoginUI:     provLoginUI,
  3776  		GPGUI:       &gpgtestui{},
  3777  	}
  3778  	eng := NewLogin(tc2.G, keybase1.DeviceTypeV2_DESKTOP, fu.Username, keybase1.ClientType_CLI)
  3779  	eng.PaperKey = loginUI.PaperPhrase
  3780  	eng.DeviceName = "a different device name"
  3781  	m2 := NewMetaContextForTest(tc2).WithUIs(uis2)
  3782  	require.NoError(t, RunEngine2(m2, eng), "run login engine")
  3783  
  3784  	assertNumDevicesAndKeys(tc, fu, 3, 6)
  3785  	require.NoError(t, AssertProvisioned(tc2), "provisioned")
  3786  
  3787  	require.Equal(t, provLoginUI.CalledGetEmailOrUsername, 0, "expected no calls to GetEmailOrUsername")
  3788  	require.Equal(t, provUI.calledChooseDevice, 0, "expected no calls to ChooseDevice")
  3789  }
  3790  
  3791  // Device X provisions device Y (which has a cached passphrase stream), device X changes the password,
  3792  // device Y provisions device Z (which could break because of the outdated passphrase stream)
  3793  func TestProvisionAfterPasswordChange(t *testing.T) {
  3794  	t.Logf("create 3 contexts")
  3795  
  3796  	// device X (initial provisioner and passphrase changer) context:
  3797  	tcX := SetupEngineTest(t, "kex2race1")
  3798  	defer tcX.Cleanup()
  3799  
  3800  	// device Y (second provisioner and race condition culprit) context:
  3801  	tcY := SetupEngineTest(t, "kex2race2")
  3802  	defer tcY.Cleanup()
  3803  
  3804  	// device Z (provisionee) context:
  3805  	tcZ := SetupEngineTest(t, "kex2race3")
  3806  	defer tcZ.Cleanup()
  3807  
  3808  	// the initial needs to sign up and log in
  3809  	userX := CreateAndSignupFakeUserPaper(tcX, "login")
  3810  	var secretX kex2.Secret
  3811  	if _, err := rand.Read(secretX[:]); err != nil {
  3812  		t.Fatal(err)
  3813  	}
  3814  
  3815  	t.Logf("kex#1 starting")
  3816  
  3817  	secretCh := make(chan kex2.Secret)
  3818  
  3819  	// provisionee calls login:
  3820  	uis := libkb.UIs{
  3821  		ProvisionUI: newTestProvisionUISecretCh(secretCh),
  3822  		LoginUI:     &libkb.TestLoginUI{Username: userX.Username},
  3823  		LogUI:       tcX.G.UI.GetLogUI(),
  3824  		SecretUI:    &libkb.TestSecretUI{},
  3825  		GPGUI:       &gpgtestui{},
  3826  	}
  3827  
  3828  	var wg sync.WaitGroup
  3829  
  3830  	// start provisionee for step #1
  3831  	wg.Add(1)
  3832  	go func() {
  3833  		defer wg.Done()
  3834  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  3835  		eng := NewLogin(tcY.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3836  		if err := RunEngine2(m, eng); err != nil {
  3837  			t.Errorf("provisionee login error: %s", err)
  3838  			return
  3839  		}
  3840  	}()
  3841  
  3842  	// start provisioner for step #1
  3843  	provisioner := NewKex2Provisioner(tcX.G, secretX, nil)
  3844  	wg.Add(1)
  3845  	go func() {
  3846  		defer wg.Done()
  3847  
  3848  		// We're reusing the m from the PGP key generation
  3849  		m := NewMetaContextForTest(tcX).WithUIs(uis)
  3850  		if err := RunEngine2(m, provisioner); err != nil {
  3851  			t.Errorf("provisioner error: %s", err)
  3852  			return
  3853  		}
  3854  	}()
  3855  	secretFromY := <-secretCh
  3856  	provisioner.AddSecret(secretFromY)
  3857  
  3858  	wg.Wait()
  3859  
  3860  	require.False(t, t.Failed(), "prior failure in a goroutine")
  3861  
  3862  	// 2nd device should be provisioned
  3863  	if err := AssertProvisioned(tcY); err != nil {
  3864  		t.Fatal(err)
  3865  	}
  3866  
  3867  	t.Logf("kex#1 finished")
  3868  
  3869  	// after provisioning, the passphrase stream in device Y should be cached
  3870  	assertPassphraseStreamCache(tcY)
  3871  	assertDeviceKeysCached(tcY)
  3872  
  3873  	// now we have the following:
  3874  	// 1) the initial provisioner
  3875  	// 2) an already provisioned device with a cached passphrase stream
  3876  	// 3) a totally clean device
  3877  	// in order to trigger the race we have to make the cached ppstream in (2) outdated
  3878  
  3879  	// Change the password on device 1 to modify ppgen
  3880  	newPassphrase := "password1234"
  3881  	require.NoError(t, RunEngine2(
  3882  		NewMetaContextForTest(tcX).WithUIs(libkb.UIs{
  3883  			SecretUI: &libkb.TestSecretUI{},
  3884  		}),
  3885  		NewPassphraseChange(tcX.G, &keybase1.PassphraseChangeArg{
  3886  			OldPassphrase: userX.Passphrase,
  3887  			Passphrase:    newPassphrase,
  3888  		}),
  3889  	))
  3890  
  3891  	// Now provision Z from Y
  3892  	t.Logf("kex#2 starting")
  3893  
  3894  	// start provisionee for step #2
  3895  	wg.Add(1)
  3896  	go func() {
  3897  		defer wg.Done()
  3898  		m := NewMetaContextForTest(tcZ).WithUIs(uis)
  3899  		eng := NewLogin(tcZ.G, keybase1.DeviceTypeV2_DESKTOP, "", keybase1.ClientType_CLI)
  3900  		if err := RunEngine2(m, eng); err != nil {
  3901  			t.Errorf("provisionee login error: %s", err)
  3902  			return
  3903  		}
  3904  	}()
  3905  
  3906  	// start provisioner for step #2
  3907  	var secretY kex2.Secret
  3908  	if _, err := rand.Read(secretY[:]); err != nil {
  3909  		t.Fatal(err)
  3910  	}
  3911  	provisioner = NewKex2Provisioner(tcY.G, secretY, nil)
  3912  	wg.Add(1)
  3913  	go func() {
  3914  		defer wg.Done()
  3915  
  3916  		// We're reusing the m from the PGP key generation
  3917  		m := NewMetaContextForTest(tcY).WithUIs(uis)
  3918  		// m.ActiveDevice().ClearPassphraseStreamCache()
  3919  		if err := RunEngine2(m, provisioner); err != nil {
  3920  			t.Errorf("provisioner error: %s", err)
  3921  			return
  3922  		}
  3923  	}()
  3924  	secretFromZ := <-secretCh
  3925  	provisioner.AddSecret(secretFromZ)
  3926  
  3927  	wg.Wait()
  3928  
  3929  	require.False(t, t.Failed(), "prior failure in a goroutine")
  3930  
  3931  	// 3rd device should be provisioned
  3932  	if err := AssertProvisioned(tcZ); err != nil {
  3933  		t.Fatal(err)
  3934  	}
  3935  
  3936  	t.Logf("kex#2 finished")
  3937  }
  3938  
  3939  type testProvisionUI struct {
  3940  	secretCh               chan kex2.Secret
  3941  	method                 keybase1.ProvisionMethod
  3942  	gpgMethod              keybase1.GPGMethod
  3943  	chooseDevice           keybase1.DeviceTypeV2
  3944  	calledChooseDevice     int
  3945  	verbose                bool
  3946  	calledChooseDeviceType int
  3947  	abortSwitchToGPGSign   bool
  3948  	lastDevices            []keybase1.Device
  3949  }
  3950  
  3951  func newTestProvisionUI() *testProvisionUI {
  3952  	ui := &testProvisionUI{method: keybase1.ProvisionMethod_DEVICE}
  3953  	if len(os.Getenv("KB_TEST_VERBOSE")) > 0 {
  3954  		ui.verbose = true
  3955  	}
  3956  	ui.gpgMethod = keybase1.GPGMethod_GPG_IMPORT
  3957  	return ui
  3958  }
  3959  
  3960  func newTestProvisionUISecretCh(ch chan kex2.Secret) *testProvisionUI {
  3961  	ui := newTestProvisionUI()
  3962  	ui.secretCh = ch
  3963  	ui.chooseDevice = keybase1.DeviceTypeV2_DESKTOP
  3964  	return ui
  3965  }
  3966  
  3967  func newTestProvisionUINoSecret() *testProvisionUI {
  3968  	ui := newTestProvisionUI()
  3969  	ui.chooseDevice = keybase1.DeviceTypeV2_DESKTOP
  3970  	return ui
  3971  }
  3972  
  3973  func newTestProvisionUIPassphrase() *testProvisionUI {
  3974  	ui := newTestProvisionUI()
  3975  	ui.method = keybase1.ProvisionMethod_PASSPHRASE
  3976  	return ui
  3977  }
  3978  
  3979  func newTestProvisionUIChooseNoDevice() *testProvisionUI {
  3980  	ui := newTestProvisionUI()
  3981  	ui.chooseDevice = keybase1.DeviceTypeV2_NONE
  3982  	return ui
  3983  }
  3984  
  3985  func newTestProvisionUIPaper() *testProvisionUI {
  3986  	ui := newTestProvisionUI()
  3987  	ui.method = keybase1.ProvisionMethod_PAPER_KEY
  3988  	ui.chooseDevice = keybase1.DeviceTypeV2_PAPER
  3989  	return ui
  3990  }
  3991  
  3992  func newTestProvisionUIGPGImport() *testProvisionUI {
  3993  	ui := newTestProvisionUI()
  3994  	ui.method = keybase1.ProvisionMethod_GPG_IMPORT
  3995  	ui.gpgMethod = keybase1.GPGMethod_GPG_IMPORT
  3996  	return ui
  3997  }
  3998  
  3999  func newTestProvisionUIGPGSign() *testProvisionUI {
  4000  	ui := newTestProvisionUI()
  4001  	ui.method = keybase1.ProvisionMethod_GPG_SIGN
  4002  	ui.gpgMethod = keybase1.GPGMethod_GPG_SIGN
  4003  	return ui
  4004  }
  4005  
  4006  func (u *testProvisionUI) printf(format string, a ...interface{}) {
  4007  	if !u.verbose {
  4008  		return
  4009  	}
  4010  	fmt.Printf("testProvisionUI: "+format+"\n", a...)
  4011  }
  4012  
  4013  func (u *testProvisionUI) ChooseProvisioningMethod(_ context.Context, _ keybase1.ChooseProvisioningMethodArg) (keybase1.ProvisionMethod, error) {
  4014  	panic("ChooseProvisioningMethod deprecated")
  4015  }
  4016  
  4017  func (u *testProvisionUI) ChooseGPGMethod(_ context.Context, _ keybase1.ChooseGPGMethodArg) (keybase1.GPGMethod, error) {
  4018  	u.printf("ChooseGPGMethod")
  4019  	return u.gpgMethod, nil
  4020  }
  4021  
  4022  func (u *testProvisionUI) SwitchToGPGSignOK(ctx context.Context, arg keybase1.SwitchToGPGSignOKArg) (bool, error) {
  4023  	if u.abortSwitchToGPGSign {
  4024  		return false, nil
  4025  	}
  4026  	return true, nil
  4027  }
  4028  
  4029  func (u *testProvisionUI) ChooseDevice(_ context.Context, arg keybase1.ChooseDeviceArg) (keybase1.DeviceID, error) {
  4030  	u.printf("ChooseDevice")
  4031  	u.calledChooseDevice++
  4032  
  4033  	u.lastDevices = arg.Devices
  4034  
  4035  	if len(arg.Devices) == 0 {
  4036  		return "", nil
  4037  	}
  4038  
  4039  	if u.chooseDevice == keybase1.DeviceTypeV2_NONE {
  4040  		return "", nil
  4041  	}
  4042  
  4043  	for _, d := range arg.Devices {
  4044  		if d.Type == u.chooseDevice {
  4045  			return d.DeviceID, nil
  4046  		}
  4047  	}
  4048  	return "", nil
  4049  }
  4050  
  4051  func (u *testProvisionUI) ChooseDeviceType(_ context.Context, _ keybase1.ChooseDeviceTypeArg) (keybase1.DeviceType, error) {
  4052  	u.printf("ChooseDeviceType")
  4053  	u.calledChooseDeviceType++
  4054  	return keybase1.DeviceType_DESKTOP, nil
  4055  }
  4056  
  4057  func (u *testProvisionUI) DisplayAndPromptSecret(_ context.Context, arg keybase1.DisplayAndPromptSecretArg) (keybase1.SecretResponse, error) {
  4058  	u.printf("DisplayAndPromptSecret")
  4059  	var ks kex2.Secret
  4060  	copy(ks[:], arg.Secret)
  4061  	u.secretCh <- ks
  4062  	var sr keybase1.SecretResponse
  4063  	return sr, nil
  4064  }
  4065  
  4066  func (u *testProvisionUI) PromptNewDeviceName(_ context.Context, arg keybase1.PromptNewDeviceNameArg) (string, error) {
  4067  	u.printf("PromptNewDeviceName")
  4068  	return libkb.RandString("device", 5)
  4069  }
  4070  
  4071  func (u *testProvisionUI) DisplaySecretExchanged(_ context.Context, _ int) error {
  4072  	u.printf("DisplaySecretExchanged")
  4073  	return nil
  4074  }
  4075  
  4076  func (u *testProvisionUI) ProvisioneeSuccess(_ context.Context, _ keybase1.ProvisioneeSuccessArg) error {
  4077  	u.printf("ProvisioneeSuccess")
  4078  	return nil
  4079  }
  4080  
  4081  func (u *testProvisionUI) ProvisionerSuccess(_ context.Context, _ keybase1.ProvisionerSuccessArg) error {
  4082  	u.printf("ProvisionerSuccess")
  4083  	return nil
  4084  }
  4085  
  4086  type testProvisionDupDeviceUI struct {
  4087  	*testProvisionUI
  4088  }
  4089  
  4090  // return an existing device name
  4091  func (u *testProvisionDupDeviceUI) PromptNewDeviceName(_ context.Context, arg keybase1.PromptNewDeviceNameArg) (string, error) {
  4092  	return arg.ExistingDevices[0], nil
  4093  }
  4094  
  4095  type testProvisionSetNameUI struct {
  4096  	*testProvisionUI
  4097  	DeviceName             string
  4098  	ExistingDevicesFromArg []string
  4099  }
  4100  
  4101  // return an existing device name
  4102  func (u *testProvisionSetNameUI) PromptNewDeviceName(_ context.Context, arg keybase1.PromptNewDeviceNameArg) (string, error) {
  4103  	u.ExistingDevicesFromArg = arg.ExistingDevices
  4104  	return u.DeviceName, nil
  4105  }
  4106  
  4107  type paperLoginUI struct {
  4108  	Username    string
  4109  	PaperPhrase string
  4110  }
  4111  
  4112  var _ libkb.LoginUI = (*paperLoginUI)(nil)
  4113  
  4114  func (p *paperLoginUI) GetEmailOrUsername(_ context.Context, _ int) (string, error) {
  4115  	return p.Username, nil
  4116  }
  4117  
  4118  func (p *paperLoginUI) PromptRevokePaperKeys(_ context.Context, arg keybase1.PromptRevokePaperKeysArg) (bool, error) {
  4119  	return false, nil
  4120  }
  4121  
  4122  func (p *paperLoginUI) DisplayPaperKeyPhrase(_ context.Context, arg keybase1.DisplayPaperKeyPhraseArg) error {
  4123  	return nil
  4124  }
  4125  
  4126  func (p *paperLoginUI) DisplayPrimaryPaperKey(_ context.Context, arg keybase1.DisplayPrimaryPaperKeyArg) error {
  4127  	p.PaperPhrase = arg.Phrase
  4128  	return nil
  4129  }
  4130  
  4131  func (p *paperLoginUI) PromptResetAccount(_ context.Context, arg keybase1.PromptResetAccountArg) (keybase1.ResetPromptResponse, error) {
  4132  	return keybase1.ResetPromptResponse_NOTHING, nil
  4133  }
  4134  
  4135  func (p *paperLoginUI) DisplayResetProgress(_ context.Context, arg keybase1.DisplayResetProgressArg) error {
  4136  	return nil
  4137  }
  4138  
  4139  func (p *paperLoginUI) ExplainDeviceRecovery(_ context.Context, arg keybase1.ExplainDeviceRecoveryArg) error {
  4140  	return nil
  4141  }
  4142  
  4143  func (p *paperLoginUI) PromptPassphraseRecovery(_ context.Context, arg keybase1.PromptPassphraseRecoveryArg) (bool, error) {
  4144  	return false, nil
  4145  }
  4146  
  4147  func (p *paperLoginUI) ChooseDeviceToRecoverWith(_ context.Context, arg keybase1.ChooseDeviceToRecoverWithArg) (keybase1.DeviceID, error) {
  4148  	return "", nil
  4149  }
  4150  
  4151  func (p *paperLoginUI) DisplayResetMessage(_ context.Context, arg keybase1.DisplayResetMessageArg) error {
  4152  	return nil
  4153  }
  4154  
  4155  func signString(tc libkb.TestContext, input string, secUI libkb.SecretUI) error {
  4156  	var sink bytes.Buffer
  4157  
  4158  	earg := PGPSignArg{
  4159  		Sink:   libkb.NopWriteCloser{W: &sink},
  4160  		Source: io.NopCloser(bytes.NewBufferString(input)),
  4161  		Opts: keybase1.PGPSignOptions{
  4162  			Mode: keybase1.SignMode_ATTACHED,
  4163  		},
  4164  	}
  4165  
  4166  	eng := NewPGPSignEngine(tc.G, &earg)
  4167  	m := NewMetaContextForTest(tc).WithUIs(libkb.UIs{
  4168  		PgpUI:    &TestPgpUI{},
  4169  		SecretUI: secUI,
  4170  	})
  4171  	return RunEngine2(m, eng)
  4172  }
  4173  
  4174  type testRetrySecretUI struct {
  4175  	Passphrases []string
  4176  	StoreSecret bool
  4177  	index       int
  4178  }
  4179  
  4180  func (t *testRetrySecretUI) GetPassphrase(p keybase1.GUIEntryArg, terminal *keybase1.SecretEntryArg) (keybase1.GetPassphraseRes, error) {
  4181  	n := t.index
  4182  	if n >= len(t.Passphrases) {
  4183  		n = len(t.Passphrases) - 1
  4184  	}
  4185  	t.index++
  4186  	return keybase1.GetPassphraseRes{
  4187  		Passphrase:  t.Passphrases[n],
  4188  		StoreSecret: t.StoreSecret,
  4189  	}, nil
  4190  }
  4191  
  4192  type testNoPromptSecretUI struct {
  4193  }
  4194  
  4195  func (t *testNoPromptSecretUI) GetPassphrase(p keybase1.GUIEntryArg, terminal *keybase1.SecretEntryArg) (res keybase1.GetPassphraseRes, err error) {
  4196  	err = errors.New("GetPassphrase called on testNoPromptSecretUI")
  4197  	return res, err
  4198  }
  4199  
  4200  type gpgImportFailer struct {
  4201  	g *libkb.GlobalContext
  4202  }
  4203  
  4204  func newGPGImportFailer(g *libkb.GlobalContext) *gpgImportFailer {
  4205  	return &gpgImportFailer{g: g}
  4206  }
  4207  
  4208  func (g *gpgImportFailer) ImportKey(_ libkb.MetaContext, secret bool, fp libkb.PGPFingerprint, tty string) (*libkb.PGPKeyBundle, error) {
  4209  	return nil, errors.New("failed to import key")
  4210  }
  4211  
  4212  func (g *gpgImportFailer) Index(mctx libkb.MetaContext, secret bool, query string) (ki *libkb.GpgKeyIndex, w libkb.Warnings, err error) {
  4213  	// use real gpg for this part
  4214  	gpg := g.g.GetGpgClient()
  4215  	if err := gpg.Configure(mctx); err != nil {
  4216  		return nil, w, err
  4217  	}
  4218  	return gpg.Index(mctx, secret, query)
  4219  }
  4220  
  4221  func skipOldGPG(tc libkb.TestContext) {
  4222  	gpg := tc.G.GetGpgClient()
  4223  	if err := gpg.Configure(tc.MetaContext()); err != nil {
  4224  		tc.T.Skip(fmt.Sprintf("skipping test due to gpg configure error: %s", err))
  4225  	}
  4226  	ok, err := gpg.VersionAtLeast("2.0.29")
  4227  	if err != nil {
  4228  		tc.T.Fatal(err)
  4229  	}
  4230  	if ok {
  4231  		return
  4232  	}
  4233  
  4234  	v, err := gpg.SemanticVersion()
  4235  	if err != nil {
  4236  		tc.T.Fatal(err)
  4237  	}
  4238  	tc.T.Skip(fmt.Sprintf("skipping test due to gpg version < 2.0.29 (%v)", v))
  4239  }
  4240  
  4241  func assertDeviceKeysCached(tc libkb.TestContext) {
  4242  	_, _, _, sk, ek := tc.G.ActiveDevice.AllFields()
  4243  	if sk == nil {
  4244  		tc.T.Error("cached signing key nil")
  4245  	}
  4246  	if ek == nil {
  4247  		tc.T.Error("cached encryption key nil")
  4248  	}
  4249  }
  4250  
  4251  func assertPassphraseStreamCache(tc libkb.TestContext) {
  4252  	var ppsValid bool
  4253  	if ppsc := tc.G.ActiveDevice.PassphraseStreamCache(); ppsc != nil {
  4254  		ppsValid = ppsc.ValidPassphraseStream()
  4255  	}
  4256  	if !ppsValid {
  4257  		tc.T.Fatal("passphrase stream not cached")
  4258  	}
  4259  }
  4260  
  4261  func assertSecretStored(tc libkb.TestContext, username string) {
  4262  	secret, err := tc.G.SecretStore().RetrieveSecret(NewMetaContextForTest(tc), libkb.NewNormalizedUsername(username))
  4263  	require.NoError(tc.T, err, "no error fetching secret")
  4264  	require.False(tc.T, secret.IsNil(), "secret was non-nil")
  4265  }
  4266  
  4267  func assertSecretNotStored(tc libkb.TestContext, username string) {
  4268  	nun := libkb.NewNormalizedUsername(username)
  4269  	_, err := tc.G.SecretStore().RetrieveSecret(NewMetaContextForTest(tc), nun)
  4270  	require.Error(tc.T, err, "no secret found")
  4271  	require.Equal(tc.T, err, libkb.NewErrSecretForUserNotFound(nun))
  4272  }
  4273  
  4274  func assertAutoreset(tc libkb.TestContext, uid keybase1.UID, expectedStatus int) error {
  4275  	mctx := libkb.NewMetaContextForTest(tc)
  4276  	resp, err := tc.G.API.Get(mctx, libkb.APIArg{
  4277  		Endpoint:    "autoreset/status_dev",
  4278  		SessionType: libkb.APISessionTypeOPTIONAL,
  4279  		Args: libkb.HTTPArgs{
  4280  			"uid": libkb.S{Val: uid.String()},
  4281  		},
  4282  	})
  4283  	if err != nil {
  4284  		return err
  4285  	}
  4286  
  4287  	status, ok := resp.Body.AtPathGetInt("autoreset.type")
  4288  	if expectedStatus == -1 {
  4289  		if ok {
  4290  			return fmt.Errorf("expected account %s to not be in reset pipeline", uid.String())
  4291  		}
  4292  		return nil
  4293  	}
  4294  	if !ok {
  4295  		return fmt.Errorf("expected account %s to be in %d state (got null)", uid.String(), expectedStatus)
  4296  	}
  4297  	if status != expectedStatus {
  4298  		return fmt.Errorf("expected account %s to be in %d state (got %d)", uid.String(), expectedStatus, status)
  4299  	}
  4300  	return nil
  4301  }