// Run starts the engine. func (e *ProveCheck) Run(ctx *Context) error { found, status, err := libkb.CheckPostedViaSigID(e.sigID) if err != nil { return err } e.found = found e.status = keybase1.ProofStatus(status) e.G().Log.Debug("looking for ChainLink for %s", e.sigID) me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G())) if err != nil { return err } link := me.LinkFromSigID(e.sigID) if link == nil { return fmt.Errorf("no chain link found for %s", e.sigID) } e.G().Log.Debug("chain link found: (%T)", link.Typed()) if rlink, ok := link.Typed().(libkb.RemoteProofChainLink); ok { e.proofText = rlink.ProofText() e.G().Log.Debug("chain link proof text: %q", e.proofText) } else { e.G().Log.Warning("chain link had invalid type: %T", link.Typed()) } return nil }
func (e *PGPKeyImportEngine) loadMe() (err error) { if e.me = e.arg.Me; e.me != nil { return } e.me, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G())) return err }
// Run starts the engine. func (k *KexProvisioner) Run(ctx *Context) error { k.engctx = ctx var err error uarg := libkb.NewLoadUserPubOptionalArg(k.G()) uarg.LoginContext = ctx.LoginContext k.user, err = libkb.LoadMe(uarg) if err != nil { return err } dp := k.G().Env.GetDeviceID() if dp.IsNil() { // Prereqs w/ Device: true should catch this earlier, but just in case: return libkb.DeviceRequiredError{} } k.deviceID = dp k.G().Log.Debug("device id: %s", k.deviceID) if k.user.GetComputedKeyFamily() == nil { return libkb.KeyFamilyError{Msg: "nil ckf"} } k.deviceSibkey, err = k.user.GetComputedKeyFamily().GetSibkeyForDevice(k.deviceID) if err != nil { k.G().Log.Warning("KexProvisioner.Run: error getting device sibkey: %s", err) return err } token, csrf := k.sessionArgs(ctx) k.sec, err = kex.SecretFromPhrase(k.user.GetName(), k.secretPhrase) if err != nil { return err } k.serverMu.Lock() k.server = kex.NewSender(kex.DirectionXtoY, k.sec.Secret(), token, csrf, k.G()) k.serverMu.Unlock() arg := libkb.SecretKeyArg{ Me: k.user, KeyType: libkb.DeviceSigningKeyType, } k.sigKey, err = k.G().Keyrings.GetSecretKeyWithPrompt(ctx.LoginContext, arg, ctx.SecretUI, "new device install") if err != nil { k.G().Log.Warning("KexProvisioner.Run: GetSecretKey error: %s", err) return err } k.G().Log.Debug("KexProvisioner: starting receive loop") var nilDeviceID keybase1.DeviceID m := kex.NewMeta(k.user.GetUID(), k.sec.StrongID(), nilDeviceID, k.deviceID, kex.DirectionYtoX) err = k.loopReceives(ctx, m, k.sec) if err != nil { k.G().Log.Warning("Error in KEX receive: %s", err) } return err }
// createFakeUserWithPGPOnly creates a new fake/testing user, who signed // up on the Web site, and used the Web site to generate his/her key. They // used triplesec-encryption and synced their key to the keybase servers. func createFakeUserWithPGPOnly(t *testing.T, tc libkb.TestContext) *FakeUser { fu := NewFakeUserOrBust(tc.T, "login") secui := &libkb.TestSecretUI{Passphrase: fu.Passphrase} ctx := &Context{ GPGUI: &gpgtestui{}, SecretUI: secui, LogUI: tc.G.UI.GetLogUI(), LoginUI: &libkb.TestLoginUI{Username: fu.Username}, } s := NewSignupEngine(nil, tc.G) f := func(a libkb.LoginContext) error { if err := s.genPassphraseStream(a, fu.Passphrase); err != nil { return err } if err := s.join(a, fu.Username, fu.Email, testInviteCode, true); err != nil { return err } return s.fakeLKS() } if err := s.G().LoginState().ExternalFunc(f, "createFakeUserWithPGPOnly"); err != nil { tc.T.Fatal(err) } // Generate a new test PGP key for the user, and specify the PushSecret // flag so that their triplesec'ed key is pushed to the server. gen := libkb.PGPGenArg{ PrimaryBits: 1024, SubkeyBits: 1024, } gen.AddDefaultUID() peng := NewPGPKeyImportEngine(PGPKeyImportEngineArg{ Gen: &gen, PushSecret: true, Lks: s.lks, NoSave: true, }) if err := RunEngine(peng, ctx); err != nil { tc.T.Fatal(err) } var err error fu.User, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G)) if err != nil { tc.T.Fatal(err) } return fu }
func (e *DeviceHistory) loadUser() error { arg := libkb.NewLoadUserPubOptionalArg(e.G()) if len(e.username) == 0 { arg.Self = true } else { arg.Name = e.username } u, err := libkb.LoadUser(arg) if err != nil { return err } e.user = u return nil }
func (e *ListTrackers2Engine) lookupUID() error { if len(e.arg.Assertion) == 0 { e.uid = e.G().GetMyUID() if !e.uid.Exists() { return libkb.NoUIDError{} } return nil } larg := libkb.NewLoadUserPubOptionalArg(e.G()) larg.Name = e.arg.Assertion u, err := libkb.LoadUser(larg) if err != nil { return err } e.uid = u.GetUID() return nil }
// see issue #578 func TestTrackRetrack(t *testing.T) { tc := SetupEngineTest(t, "track") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "track") tc.G.LoginState().Account(func(a *libkb.Account) { a.ClearStreamCache() }, "clear stream cache") idUI := &FakeIdentifyUI{} secretUI := fu.NewSecretUI() var err error fu.User, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G)) if err != nil { t.Fatal(err) } seqnoBefore := fu.User.GetSigChainLastKnownSeqno() arg := &TrackEngineArg{ UserAssertion: "t_alice", Options: keybase1.TrackOptions{BypassConfirm: true}, } ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), IdentifyUI: idUI, SecretUI: secretUI, } eng := NewTrackEngine(arg, tc.G) err = RunEngine(eng, ctx) if err != nil { t.Fatal(err) } if !secretUI.CalledGetSecret { t.Errorf("expected get secret call") } fu.User, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G)) if err != nil { t.Fatal(err) } seqnoAfter := fu.User.GetSigChainLastKnownSeqno() if seqnoAfter == seqnoBefore { t.Errorf("seqno after track: %d, expected > %d", seqnoAfter, seqnoBefore) } Logout(tc) fu.LoginOrBust(tc) // clear out the passphrase cache tc.G.LoginState().Account(func(a *libkb.Account) { a.ClearStreamCache() }, "clear stream cache") // reset the flag secretUI.CalledGetSecret = false eng = NewTrackEngine(arg, tc.G) err = RunEngine(eng, ctx) if err != nil { t.Fatal(err) } if secretUI.CalledGetSecret { t.Errorf("get secret called on retrack") } fu.User, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tc.G)) if err != nil { t.Fatal(err) } seqnoRetrack := fu.User.GetSigChainLastKnownSeqno() if seqnoRetrack > seqnoAfter { t.Errorf("seqno after retrack: %d, expected %d", seqnoRetrack, seqnoAfter) } }
func (e *GPGImportKeyEngine) Run(ctx *Context) (err error) { gpg := e.G().GetGpgClient() me := e.arg.Me if me == nil { if me, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G())); err != nil { return err } } if !e.arg.OnlyImport { if err = PGPCheckMulti(me, e.arg.AllowMulti); err != nil { return err } } if err = gpg.Configure(); err != nil { return err } index, warns, err := gpg.Index(true, e.arg.Query) if err != nil { return err } warns.Warn() var gks []keybase1.GPGKey for _, key := range index.Keys { gk := keybase1.GPGKey{ Algorithm: fmt.Sprintf("%d%s", key.Bits, key.AlgoString()), KeyID: key.GetFingerprint().ToKeyID(), Expiration: key.ExpirationString(), Identities: key.GetPGPIdentities(), } gks = append(gks, gk) } if len(gks) == 0 { return fmt.Errorf("No PGP keys available to choose from.") } res, err := ctx.GPGUI.SelectKeyAndPushOption(context.TODO(), keybase1.SelectKeyAndPushOptionArg{Keys: gks}) if err != nil { return err } e.G().Log.Debug("SelectKey result: %+v", res) var selected *libkb.GpgPrimaryKey for _, key := range index.Keys { if key.GetFingerprint().ToKeyID() == res.KeyID { selected = key break } } if selected == nil { return nil } publicKeys := me.GetActivePGPKeys(false) duplicate := false for _, key := range publicKeys { if key.GetFingerprint().Eq(*(selected.GetFingerprint())) { duplicate = true break } } if duplicate && !e.arg.OnlyImport { // This key's already been posted to the server. res, err := ctx.GPGUI.ConfirmDuplicateKeyChosen(context.TODO(), 0) if err != nil { return err } if !res { return libkb.SibkeyAlreadyExistsError{} } // We're sending a key update, then. fp := fmt.Sprintf("%s", *(selected.GetFingerprint())) eng := NewPGPUpdateEngine([]string{fp}, false, e.G()) err = RunEngine(eng, ctx) e.duplicatedFingerprints = eng.duplicatedFingerprints return err } bundle, err := gpg.ImportKey(true, *(selected.GetFingerprint())) if err != nil { return fmt.Errorf("ImportKey error: %s", err) } if err := bundle.Unlock("Import of key into keybase keyring", ctx.SecretUI); err != nil { return err } e.G().Log.Info("Bundle unlocked: %s", selected.GetFingerprint().ToKeyID()) eng := NewPGPKeyImportEngine(PGPKeyImportEngineArg{ Pregen: bundle, SigningKey: e.arg.Signer, Me: me, AllowMulti: e.arg.AllowMulti, NoSave: e.arg.SkipImport, OnlySave: e.arg.OnlyImport, Lks: e.arg.Lks, }) if err = RunEngine(eng, ctx); err != nil { // It's important to propagate a CanceledError unmolested, // since the UI needs to know that. See: // https://github.com/keybase/client/issues/226 if _, ok := err.(libkb.CanceledError); !ok { err = libkb.KeyGenError{Msg: err.Error()} } return } e.G().Log.Info("Key %s imported", selected.GetFingerprint().ToKeyID()) e.last = bundle return nil }
func (e *PGPKeyExportEngine) loadMe() (err error) { e.me, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G())) return }
// TestLoginNewDeviceKexCancelOnY is a device provisioning test. It // simulates the scenario where a user logs in to a new device and // uses an existing device to provision it. This test checks that // everything works ok if device Y cancels while waiting for // device X to enter secret phrase. func TestLoginNewDeviceKexCancelOnY(t *testing.T) { kex.HelloTimeout = 5 * time.Second kex.IntraTimeout = 5 * time.Second kex.PollDuration = 1 * time.Second // test context for device X tcX := SetupEngineTest(t, "loginX") defer tcX.Cleanup() // sign up with device X u := CreateAndSignupFakeUser(tcX, "login") docuiShared := lockuiDeviceShared{} docui := &lockuiDevice{lockui: &lockui{deviceName: "device X"}, shared: &docuiShared} secui := &libkb.TestSecretUI{Passphrase: u.Passphrase} // test that we can get the secret key: // XXX this is necessary for the test to pass once the goroutine starts me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tcX.G)) if err != nil { t.Fatal(err) } arg := libkb.SecretKeyArg{ Me: me, KeyType: libkb.DeviceSigningKeyType, } _, err = tcX.G.Keyrings.GetSecretKeyWithPrompt(nil, arg, secui, "new device install") if err != nil { t.Fatal(err) } var wg sync.WaitGroup var li *LoginEngine wg.Add(1) go func() { // authorize on device X ctx := &Context{LogUI: tcX.G.UI.GetLogUI(), LocksmithUI: docui, SecretUI: secui} // wait for docui to know the secret for len(docui.secretPhrase()) == 0 { time.Sleep(50 * time.Millisecond) } // wait a little longer for Y... time.Sleep(50 * time.Millisecond) // so device Y should be waiting for device X to enter the secret phrase. // cancel it here: li.Cancel() // and now enter the secret phrase on device X and see what happens kx := NewKexProvisioner(tcX.G, docui.secretPhrase()) err := RunEngine(kx, ctx) if err == nil { t.Error("kex sib succeeded, it should have failed.") } if _, ok := err.(libkb.CanceledError); !ok { t.Errorf("unexpected kex sib run error: %s", err) } wg.Done() }() // test context for device Y tcY := SetupEngineTest(t, "loginY") defer tcY.Cleanup() if tcY.G == tcX.G { t.Fatalf("tcY.G == tcX.G") } // log in with device Y li = NewLoginWithPromptEngine(u.Username, tcY.G) ydocui := &lockuiDevice{lockui: &lockui{deviceName: "device Y"}, shared: &docuiShared} ctx := &Context{LogUI: tcY.G.UI.GetLogUI(), LocksmithUI: ydocui, GPGUI: &gpgtestui{}, SecretUI: secui, LoginUI: &libkb.TestLoginUI{}} err = RunEngine(li, ctx) if err == nil { t.Fatal("device Y login should have failed") } if _, ok := err.(libkb.CanceledError); !ok { t.Errorf("device Y login err: %s (%T)", err, err) } wg.Wait() }
// TestLoginNewDeviceKex is a device provisioning test. It // simulates the scenario where a user logs in to a new device and // uses an existing device to provision it. This test uses // the api server for all kex communication. func TestLoginNewDeviceKex1(t *testing.T) { kex.HelloTimeout = 5 * time.Second kex.IntraTimeout = 5 * time.Second kex.PollDuration = 1 * time.Second // test context for device X tcX := SetupEngineTest(t, "loginX") defer tcX.Cleanup() // sign up with device X u := CreateAndSignupFakeUser(tcX, "login") docuiShared := lockuiDeviceShared{} docui := &lockuiDevice{lockui: &lockui{deviceName: "device X"}, shared: &docuiShared} secui := &libkb.TestSecretUI{Passphrase: u.Passphrase} // test that we can get the secret key: // XXX this is necessary for the test to pass once the goroutine starts me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tcX.G)) if err != nil { t.Fatal(err) } arg := libkb.SecretKeyArg{ Me: me, KeyType: libkb.DeviceSigningKeyType, } _, err = tcX.G.Keyrings.GetSecretKeyWithPrompt(nil, arg, secui, "new device install") if err != nil { t.Fatal(err) } var wg sync.WaitGroup wg.Add(1) go func() { // authorize on device X ctx := &Context{LogUI: tcX.G.UI.GetLogUI(), LocksmithUI: docui, SecretUI: secui} // wait for docui to know the secret for len(docui.secretPhrase()) == 0 { time.Sleep(50 * time.Millisecond) } kx := NewKexProvisioner(tcX.G, docui.secretPhrase()) if err := RunEngine(kx, ctx); err != nil { t.Fatal(err) } wg.Done() }() // test context for device Y tcY := SetupEngineTest(t, "loginY") defer tcY.Cleanup() if tcY.G == tcX.G { t.Fatalf("tcY.G == tcX.G") } // log in with device Y li := NewLoginWithPromptEngine(u.Username, tcY.G) ydocui := &lockuiDevice{lockui: &lockui{deviceName: "device Y"}, shared: &docuiShared} ctx := &Context{LogUI: tcY.G.UI.GetLogUI(), LocksmithUI: ydocui, GPGUI: &gpgtestui{}, SecretUI: secui, LoginUI: &libkb.TestLoginUI{}} if err := RunEngine(li, ctx); err != nil { t.Fatal(err) } wg.Wait() testUserHasDeviceKey(tcY) }
// TestLoginNewDeviceKexBadPhrase is a device provisioning test. // It simulates the scenario where a user logs in to a new device and // uses an existing device to provision it, but a bad secret // phrase is entered on the existing device. func TestLoginNewDeviceKexBadPhrase(t *testing.T) { kex.HelloTimeout = 5 * time.Second kex.IntraTimeout = 5 * time.Second kex.PollDuration = 1 * time.Second // test context for device X tcX := SetupEngineTest(t, "loginX") defer tcX.Cleanup() // sign up with device X u := CreateAndSignupFakeUser(tcX, "login") docuiShared := lockuiDeviceShared{} docui := &lockuiDevice{lockui: &lockui{deviceName: "device X"}, shared: &docuiShared} secui := &libkb.TestSecretUI{Passphrase: u.Passphrase} // test that we can get the secret key: // XXX this is necessary for the test to pass once the goroutine starts me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(tcX.G)) if err != nil { t.Fatal(err) } arg := libkb.SecretKeyArg{ Me: me, KeyType: libkb.DeviceSigningKeyType, } _, err = tcX.G.Keyrings.GetSecretKeyWithPrompt(nil, arg, secui, "new device install") if err != nil { t.Fatal(err) } var li *LoginEngine var wg sync.WaitGroup wg.Add(1) go func() { defer func() { // cancel the login engine when this is done. if li != nil { li.Cancel() } }() // authorize on device X ctx := &Context{LogUI: tcX.G.UI.GetLogUI(), LocksmithUI: docui, SecretUI: secui} // wait for docui to know the secret for len(docui.secretPhrase()) == 0 { time.Sleep(50 * time.Millisecond) } // ok, we know the secret phrase, but will enter it incorrectly: kx := NewKexProvisioner(tcX.G, docui.secretPhrase()+" gibberish") err := RunEngine(kx, ctx) if _, ok := err.(libkb.InvalidKexPhraseError); !ok { t.Fatal(err) } wg.Done() }() // test context for device Y tcY := SetupEngineTest(t, "loginY") defer tcY.Cleanup() if tcY.G == tcX.G { t.Fatalf("tcY.G == tcX.G") } // log in with device Y li = NewLoginWithPromptEngine(u.Username, tcY.G) ydocui := &lockuiDevice{lockui: &lockui{deviceName: "device Y"}, shared: &docuiShared} ctx := &Context{LogUI: tcY.G.UI.GetLogUI(), LocksmithUI: ydocui, GPGUI: &gpgtestui{}, SecretUI: secui, LoginUI: &libkb.TestLoginUI{}} err = RunEngine(li, ctx) if err != nil { if _, ok := err.(libkb.CanceledError); !ok { t.Fatal(err) } } else { t.Fatal("login on device Y should have returned error") } wg.Wait() }