github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/id_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  	"reflect"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/keybase/client/go/libkb"
    13  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func runIdentify(tc *libkb.TestContext, username string) (idUI *FakeIdentifyUI, res *keybase1.Identify2ResUPK2, err error) {
    18  	idUI = &FakeIdentifyUI{}
    19  	arg := keybase1.Identify2Arg{
    20  		UserAssertion:    username,
    21  		AlwaysBlock:      true,
    22  		IdentifyBehavior: keybase1.TLFIdentifyBehavior_CLI,
    23  	}
    24  
    25  	uis := libkb.UIs{
    26  		LogUI:      tc.G.UI.GetLogUI(),
    27  		IdentifyUI: idUI,
    28  	}
    29  
    30  	eng := NewResolveThenIdentify2(tc.G, &arg)
    31  	m := NewMetaContextForTest(*tc).WithUIs(uis)
    32  	err = RunEngine2(m, eng)
    33  	if err != nil {
    34  		return idUI, nil, err
    35  	}
    36  	res, err = eng.Result(m)
    37  	if err != nil {
    38  		return idUI, nil, err
    39  	}
    40  	return idUI, res, nil
    41  }
    42  
    43  func checkAliceProofs(tb libkb.TestingTB, idUI *FakeIdentifyUI, user *keybase1.UserPlusKeysV2) {
    44  	checkKeyedProfile(tb, idUI, user, "alice", map[string]string{
    45  		"github":  "kbtester2",
    46  		"twitter": "tacovontaco",
    47  	})
    48  }
    49  
    50  func checkBobProofs(tb libkb.TestingTB, idUI *FakeIdentifyUI, user *keybase1.UserPlusKeysV2) {
    51  	checkKeyedProfile(tb, idUI, user, "bob", map[string]string{
    52  		"github":  "kbtester1",
    53  		"twitter": "kbtester1",
    54  	})
    55  }
    56  
    57  func checkCharlieProofs(tb libkb.TestingTB, idUI *FakeIdentifyUI, user *keybase1.UserPlusKeysV2) {
    58  	checkKeyedProfile(tb, idUI, user, "charlie", map[string]string{
    59  		"github":  "tacoplusplus",
    60  		"twitter": "tacovontaco",
    61  	})
    62  }
    63  
    64  func checkDougProofs(tb libkb.TestingTB, idUI *FakeIdentifyUI, user *keybase1.UserPlusKeysV2) {
    65  	checkKeyedProfile(tb, idUI, user, "doug", nil)
    66  }
    67  
    68  func checkKeyedProfile(tb libkb.TestingTB, idUI *FakeIdentifyUI, them *keybase1.UserPlusKeysV2, name string, expectedProofs map[string]string) {
    69  	if them == nil {
    70  		tb.Fatal("nil 'them' user")
    71  	} else {
    72  		exported := &keybase1.User{
    73  			Uid:      them.GetUID(),
    74  			Username: them.GetName(),
    75  		}
    76  		if !reflect.DeepEqual(idUI.User, exported) {
    77  			tb.Fatal("LaunchNetworkChecks User not equal to result user.", idUI.User, exported)
    78  		}
    79  	}
    80  
    81  	if !reflect.DeepEqual(expectedProofs, idUI.Proofs) {
    82  		tb.Fatal("Wrong proofs.", expectedProofs, idUI.Proofs)
    83  	}
    84  }
    85  
    86  func checkDisplayKeys(t *testing.T, idUI *FakeIdentifyUI, callCount, keyCount int) {
    87  	if idUI.DisplayKeyCalls != callCount {
    88  		t.Errorf("DisplayKey calls: %d.  expected %d.", idUI.DisplayKeyCalls, callCount)
    89  	}
    90  
    91  	if len(idUI.Keys) != keyCount {
    92  		t.Errorf("keys: %d, expected %d.", len(idUI.Keys), keyCount)
    93  		for k, v := range idUI.Keys {
    94  			t.Logf("key: %+v, %+v", k, v)
    95  		}
    96  	}
    97  }
    98  
    99  func TestIdAlice(t *testing.T) {
   100  	tc := SetupEngineTest(t, "id")
   101  	defer tc.Cleanup()
   102  	idUI, result, err := runIdentify(&tc, "t_alice")
   103  	require.NoError(t, err)
   104  	checkAliceProofs(t, idUI, &result.Upk.Current)
   105  	checkDisplayKeys(t, idUI, 1, 1)
   106  }
   107  
   108  func TestIdBob(t *testing.T) {
   109  	tc := SetupEngineTest(t, "id")
   110  	defer tc.Cleanup()
   111  	idUI, result, err := runIdentify(&tc, "t_bob")
   112  	require.NoError(t, err)
   113  	checkBobProofs(t, idUI, &result.Upk.Current)
   114  	checkDisplayKeys(t, idUI, 1, 1)
   115  }
   116  
   117  func TestIdCharlie(t *testing.T) {
   118  	tc := SetupEngineTest(t, "id")
   119  	defer tc.Cleanup()
   120  	idUI, result, err := runIdentify(&tc, "t_charlie")
   121  	require.NoError(t, err)
   122  	checkCharlieProofs(t, idUI, &result.Upk.Current)
   123  	checkDisplayKeys(t, idUI, 1, 1)
   124  }
   125  
   126  func TestIdDoug(t *testing.T) {
   127  	tc := SetupEngineTest(t, "id")
   128  	defer tc.Cleanup()
   129  	idUI, result, err := runIdentify(&tc, "t_doug")
   130  	require.NoError(t, err)
   131  	checkDougProofs(t, idUI, &result.Upk.Current)
   132  	checkDisplayKeys(t, idUI, 1, 1)
   133  }
   134  
   135  func TestIdEllen(t *testing.T) {
   136  	tc := SetupEngineTest(t, "id")
   137  	defer tc.Cleanup()
   138  	idUI, _, err := runIdentify(&tc, "t_ellen")
   139  	require.NoError(t, err)
   140  	checkDisplayKeys(t, idUI, 0, 0)
   141  }
   142  
   143  // TestIdPGPNotEldest creates a user with a pgp key that isn't
   144  // eldest key, then runs identify to make sure the pgp key is
   145  // still displayed.
   146  func TestIdPGPNotEldest(t *testing.T) {
   147  	tc := SetupEngineTest(t, "id")
   148  	defer tc.Cleanup()
   149  
   150  	// create new user, then add pgp key
   151  	u := CreateAndSignupFakeUser(tc, "login")
   152  	uis := libkb.UIs{LogUI: tc.G.UI.GetLogUI(), SecretUI: u.NewSecretUI()}
   153  	_, _, key := genPGPKeyAndArmor(t, tc, u.Email)
   154  	eng, err := NewPGPKeyImportEngineFromBytes(tc.G, []byte(key), true)
   155  	require.NoError(t, err)
   156  
   157  	m := NewMetaContextForTest(tc).WithUIs(uis)
   158  	err = RunEngine2(m, eng)
   159  	require.NoError(t, err)
   160  
   161  	Logout(tc)
   162  
   163  	idUI, _, err := runIdentify(&tc, u.Username)
   164  	require.NoError(t, err)
   165  
   166  	checkDisplayKeys(t, idUI, 1, 1)
   167  }
   168  
   169  func TestIdGenericSocialProof(t *testing.T) {
   170  	tc := SetupEngineTest(t, "id")
   171  	defer tc.Cleanup()
   172  
   173  	// create new user and have them prove a gubble.social account
   174  	fu := CreateAndSignupFakeUser(tc, "login")
   175  	proveGubbleSocial(tc, fu, libkb.KeybaseSignatureV2)
   176  	proveGubbleCloud(tc, fu, libkb.KeybaseSignatureV2)
   177  	Logout(tc)
   178  
   179  	fu2 := CreateAndSignupFakeUser(tc, "login")
   180  	fu2.LoginOrBust(tc)
   181  
   182  	idUI, result, err := runIdentify(&tc, fu.Username)
   183  	require.NoError(t, err)
   184  
   185  	expectedResult := keybase1.ProofResult{
   186  		State:  keybase1.ProofState_OK,
   187  		Status: keybase1.ProofStatus_OK,
   188  		Desc:   "",
   189  	}
   190  
   191  	require.Equal(t, expectedResult, idUI.ProofResults["gubble.social"].ProofResult)
   192  	require.Equal(t, expectedResult, idUI.ProofResults["gubble.cloud"].ProofResult)
   193  
   194  	checkKeyedProfile(t, idUI, &result.Upk.Current, fu.Username, map[string]string{
   195  		"gubble.social": fu.Username,
   196  		"gubble.cloud":  fu.Username,
   197  	})
   198  }
   199  
   200  type FakeIdentifyUI struct {
   201  	Proofs          map[string]string
   202  	ProofResults    map[string]keybase1.LinkCheckResult
   203  	User            *keybase1.User
   204  	Keys            map[libkb.PGPFingerprint]*keybase1.TrackDiff
   205  	DisplayKeyCalls int
   206  	DisplayKeyDiffs []*keybase1.TrackDiff
   207  	Outcome         *keybase1.IdentifyOutcome
   208  	StartCount      int
   209  	Token           keybase1.TrackToken
   210  	BrokenTracking  bool
   211  	DisplayTLFArg   keybase1.DisplayTLFCreateWithInviteArg
   212  	DisplayTLFCount int
   213  	FakeConfirm     bool
   214  	LastTrack       *keybase1.TrackSummary
   215  	sync.Mutex
   216  }
   217  
   218  func (ui *FakeIdentifyUI) FinishWebProofCheck(_ libkb.MetaContext, proof keybase1.RemoteProof, result keybase1.LinkCheckResult) error {
   219  	ui.Lock()
   220  	defer ui.Unlock()
   221  	if ui.Proofs == nil {
   222  		ui.Proofs = make(map[string]string)
   223  	}
   224  	ui.Proofs[proof.Key] = proof.Value
   225  
   226  	if ui.ProofResults == nil {
   227  		ui.ProofResults = make(map[string]keybase1.LinkCheckResult)
   228  	}
   229  	ui.ProofResults[proof.Key] = result
   230  	if result.BreaksTracking {
   231  		ui.BrokenTracking = true
   232  	}
   233  	return nil
   234  }
   235  
   236  func (ui *FakeIdentifyUI) FinishSocialProofCheck(_ libkb.MetaContext, proof keybase1.RemoteProof, result keybase1.LinkCheckResult) error {
   237  	ui.Lock()
   238  	defer ui.Unlock()
   239  	if ui.Proofs == nil {
   240  		ui.Proofs = make(map[string]string)
   241  	}
   242  	ui.Proofs[proof.Key] = proof.Value
   243  	if ui.ProofResults == nil {
   244  		ui.ProofResults = make(map[string]keybase1.LinkCheckResult)
   245  	}
   246  	ui.ProofResults[proof.Key] = result
   247  	if result.BreaksTracking {
   248  		ui.BrokenTracking = true
   249  	}
   250  	return nil
   251  }
   252  
   253  func (ui *FakeIdentifyUI) Confirm(_ libkb.MetaContext, outcome *keybase1.IdentifyOutcome) (result keybase1.ConfirmResult, err error) {
   254  	ui.Lock()
   255  	defer ui.Unlock()
   256  
   257  	// Do a short sleep. This helps trigger bugs when other code is racing
   258  	// against the UI here. (Note from Jack: In the bug I initially added this
   259  	// for, 10ms was just enough to trigger it. I'm adding in an extra factor
   260  	// of 10.)
   261  	time.Sleep(100 * time.Millisecond)
   262  
   263  	ui.Outcome = outcome
   264  	bypass := ui.FakeConfirm || outcome.TrackOptions.BypassConfirm
   265  	result.IdentityConfirmed = bypass
   266  	result.RemoteConfirmed = bypass && !outcome.TrackOptions.ExpiringLocal
   267  	return
   268  }
   269  
   270  func (ui *FakeIdentifyUI) DisplayCryptocurrency(libkb.MetaContext, keybase1.Cryptocurrency) error {
   271  	return nil
   272  }
   273  
   274  func (ui *FakeIdentifyUI) DisplayStellarAccount(libkb.MetaContext, keybase1.StellarAccount) error {
   275  	return nil
   276  }
   277  
   278  func (ui *FakeIdentifyUI) DisplayKey(_ libkb.MetaContext, ik keybase1.IdentifyKey) error {
   279  	ui.Lock()
   280  	defer ui.Unlock()
   281  	if ui.Keys == nil {
   282  		ui.Keys = make(map[libkb.PGPFingerprint]*keybase1.TrackDiff)
   283  	}
   284  
   285  	fp := libkb.ImportPGPFingerprintSlice(ik.PGPFingerprint)
   286  	if fp != nil {
   287  		ui.Keys[*fp] = ik.TrackDiff
   288  	}
   289  
   290  	if ik.TrackDiff != nil {
   291  		ui.DisplayKeyDiffs = append(ui.DisplayKeyDiffs, ik.TrackDiff)
   292  	}
   293  
   294  	ui.DisplayKeyCalls++
   295  	return nil
   296  }
   297  func (ui *FakeIdentifyUI) ReportLastTrack(_ libkb.MetaContext, summary *keybase1.TrackSummary) error {
   298  	ui.LastTrack = summary
   299  	return nil
   300  }
   301  
   302  func (ui *FakeIdentifyUI) Start(_ libkb.MetaContext, username string, _ keybase1.IdentifyReason, _ bool) error {
   303  	ui.Lock()
   304  	defer ui.Unlock()
   305  	ui.StartCount++
   306  	return nil
   307  }
   308  
   309  func (ui *FakeIdentifyUI) Cancel(libkb.MetaContext) error {
   310  	return nil
   311  }
   312  
   313  func (ui *FakeIdentifyUI) Finish(libkb.MetaContext) error {
   314  	return nil
   315  }
   316  
   317  func (ui *FakeIdentifyUI) Dismiss(_ libkb.MetaContext, _ string, _ keybase1.DismissReason) error {
   318  	return nil
   319  }
   320  
   321  func (ui *FakeIdentifyUI) LaunchNetworkChecks(_ libkb.MetaContext, id *keybase1.Identity, user *keybase1.User) error {
   322  	ui.Lock()
   323  	defer ui.Unlock()
   324  	ui.User = user
   325  	return nil
   326  }
   327  
   328  func (ui *FakeIdentifyUI) DisplayTrackStatement(libkb.MetaContext, string) error {
   329  	return nil
   330  }
   331  
   332  func (ui *FakeIdentifyUI) DisplayUserCard(libkb.MetaContext, keybase1.UserCard) error {
   333  	return nil
   334  }
   335  
   336  func (ui *FakeIdentifyUI) ReportTrackToken(_ libkb.MetaContext, tok keybase1.TrackToken) error {
   337  	ui.Token = tok
   338  	return nil
   339  }
   340  
   341  func (ui *FakeIdentifyUI) SetStrict(b bool) {
   342  }
   343  
   344  func (ui *FakeIdentifyUI) DisplayTLFCreateWithInvite(_ libkb.MetaContext, arg keybase1.DisplayTLFCreateWithInviteArg) error {
   345  	ui.DisplayTLFCount++
   346  	ui.DisplayTLFArg = arg
   347  	return nil
   348  }