github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/device_add_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  	"crypto/rand"
     8  	"fmt"
     9  	"sync"
    10  	"testing"
    11  
    12  	"golang.org/x/net/context"
    13  
    14  	"github.com/keybase/client/go/kex2"
    15  	"github.com/keybase/client/go/libkb"
    16  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestDeviceAdd(t *testing.T) {
    21  	testDeviceAdd(t, false)
    22  }
    23  
    24  func TestDeviceAddPUK(t *testing.T) {
    25  	testDeviceAdd(t, true)
    26  }
    27  
    28  func runDeviceAddTest(t *testing.T, wg *sync.WaitGroup, tcY *libkb.TestContext, secretY kex2.Secret,
    29  	uid keybase1.UID) {
    30  	defer wg.Done()
    31  	err := (func() error {
    32  		uis := libkb.UIs{
    33  			ProvisionUI: &testProvisionUI{secretCh: make(chan kex2.Secret, 1)},
    34  		}
    35  		m := NewMetaContextForTest(*tcY).WithUIs(uis).WithNewProvisionalLoginContext()
    36  		deviceID, err := libkb.NewDeviceID()
    37  		if err != nil {
    38  			return err
    39  		}
    40  		suffix, err := libkb.RandBytes(5)
    41  		if err != nil {
    42  			return err
    43  		}
    44  		dname := fmt.Sprintf("device_%x", suffix)
    45  		device := &libkb.Device{
    46  			ID:          deviceID,
    47  			Description: &dname,
    48  			Type:        keybase1.DeviceTypeV2_DESKTOP,
    49  		}
    50  		provisionee := NewKex2Provisionee(tcY.G, device, secretY, uid, fakeSalt())
    51  		return RunEngine2(m, provisionee)
    52  	})()
    53  	require.NoError(t, err, "kex2 provisionee")
    54  }
    55  
    56  func testDeviceAdd(t *testing.T, upgradePerUserKey bool) {
    57  	// device X (provisioner) context:
    58  	tcX := SetupEngineTest(t, "kex2provision")
    59  	defer tcX.Cleanup()
    60  	tcX.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
    61  
    62  	// device Y (provisionee) context:
    63  	tcY := SetupEngineTest(t, "template")
    64  	defer tcY.Cleanup()
    65  	tcY.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
    66  
    67  	// provisioner needs to be logged in
    68  	userX := CreateAndSignupFakeUser(tcX, "login")
    69  
    70  	var secretY kex2.Secret
    71  	if _, err := rand.Read(secretY[:]); err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	var wg sync.WaitGroup
    76  
    77  	// start provisionee
    78  	wg.Add(1)
    79  	go runDeviceAddTest(t, &wg, &tcY, secretY, userX.UID())
    80  
    81  	// run DeviceAdd engine on device X
    82  	uis := libkb.UIs{
    83  		SecretUI:    userX.NewSecretUI(),
    84  		ProvisionUI: &testXProvisionUI{secret: secretY},
    85  	}
    86  	eng := NewDeviceAdd(tcX.G)
    87  	m := NewMetaContextForTest(tcX).WithUIs(uis)
    88  	if err := RunEngine2(m, eng); err != nil {
    89  		t.Errorf("device add error: %s", err)
    90  	}
    91  
    92  	wg.Wait()
    93  }
    94  
    95  func TestDeviceAddPhraseLegacyDesktop(t *testing.T) {
    96  	testDeviceAddPhrase(t, libkb.Kex2SecretTypeV1Desktop)
    97  }
    98  
    99  func TestDeviceAddPhraseLegacyMobile(t *testing.T) {
   100  	testDeviceAddPhrase(t, libkb.Kex2SecretTypeV1Mobile)
   101  }
   102  
   103  func TestDeviceAddPhraseV2(t *testing.T) {
   104  	testDeviceAddPhrase(t, libkb.Kex2SecretTypeV2)
   105  }
   106  
   107  func testDeviceAddPhrase(t *testing.T, typ libkb.Kex2SecretType) {
   108  
   109  	// device X (provisioner) context:
   110  	tcX := SetupEngineTest(t, "kex2provision")
   111  	defer tcX.Cleanup()
   112  
   113  	// device Y (provisionee) context:
   114  	tcY := SetupEngineTest(t, "template")
   115  	defer tcY.Cleanup()
   116  
   117  	// provisioner needs to be logged in
   118  	userX := CreateAndSignupFakeUser(tcX, "login")
   119  
   120  	secretY, err := libkb.NewKex2SecretFromTypeAndUID(typ, userX.UID())
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	var wg sync.WaitGroup
   126  
   127  	// start provisionee
   128  	wg.Add(1)
   129  	go runDeviceAddTest(t, &wg, &tcY, secretY.Secret(), userX.UID())
   130  
   131  	// run DeviceAdd engine on device X
   132  	uis := libkb.UIs{
   133  		SecretUI:    userX.NewSecretUI(),
   134  		ProvisionUI: &testPhraseProvisionUI{phrase: secretY.Phrase()},
   135  	}
   136  	eng := NewDeviceAdd(tcX.G)
   137  	m := NewMetaContextForTest(tcX).WithUIs(uis)
   138  	if err := RunEngine2(m, eng); err != nil {
   139  		t.Errorf("device add error: %s", err)
   140  	}
   141  
   142  	wg.Wait()
   143  }
   144  
   145  func TestDeviceAddStoredSecret(t *testing.T) {
   146  	// device X (provisioner) context:
   147  	tcX := SetupEngineTest(t, "kex2provision")
   148  	defer tcX.Cleanup()
   149  
   150  	// device Y (provisionee) context:
   151  	tcY := SetupEngineTest(t, "template")
   152  	defer tcY.Cleanup()
   153  
   154  	// provisioner needs to be logged in
   155  	userX := SignupFakeUserStoreSecret(tcX, "login")
   156  
   157  	var secretY kex2.Secret
   158  	if _, err := rand.Read(secretY[:]); err != nil {
   159  		t.Fatal(err)
   160  	}
   161  
   162  	var wg sync.WaitGroup
   163  
   164  	// start provisionee
   165  	wg.Add(1)
   166  	go runDeviceAddTest(t, &wg, &tcY, secretY, userX.UID())
   167  
   168  	testSecretUI := userX.NewSecretUI()
   169  
   170  	// run DeviceAdd engine on device X
   171  	uis := libkb.UIs{
   172  		SecretUI:    testSecretUI,
   173  		ProvisionUI: &testXProvisionUI{secret: secretY},
   174  	}
   175  	eng := NewDeviceAdd(tcX.G)
   176  	m := NewMetaContextForTest(tcX).WithUIs(uis)
   177  	if err := RunEngine2(m, eng); err != nil {
   178  		t.Errorf("device add error: %s", err)
   179  	}
   180  
   181  	wg.Wait()
   182  
   183  	if testSecretUI.CalledGetPassphrase {
   184  		t.Fatal("GetPassphrase() unexpectedly called")
   185  	}
   186  }
   187  
   188  type testXProvisionUI struct {
   189  	secret kex2.Secret
   190  	testProvisionUI
   191  }
   192  
   193  func (u *testXProvisionUI) DisplayAndPromptSecret(_ context.Context, arg keybase1.DisplayAndPromptSecretArg) (keybase1.SecretResponse, error) {
   194  	return keybase1.SecretResponse{Secret: u.secret[:]}, nil
   195  }
   196  
   197  type testPhraseProvisionUI struct {
   198  	phrase string
   199  	testProvisionUI
   200  }
   201  
   202  func (u *testPhraseProvisionUI) DisplayAndPromptSecret(_ context.Context, arg keybase1.DisplayAndPromptSecretArg) (keybase1.SecretResponse, error) {
   203  	return keybase1.SecretResponse{Phrase: u.phrase}, nil
   204  }