Esempio n. 1
0
func TestReset(t *testing.T) {
	tc := SetupEngineTest(t, "reset")
	defer tc.Cleanup()

	// Sign up a new user and have it store its secret in the
	// secret store (if possible).
	fu := NewFakeUserOrBust(tc.T, "reset")
	arg := MakeTestSignupEngineRunArg(fu)
	arg.StoreSecret = libkb.HasSecretStore()
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}

	if libkb.HasSecretStore() {
		secretStore := libkb.NewSecretStore(fu.NormalizedUsername())
		_, err := secretStore.RetrieveSecret()
		if err != nil {
			t.Fatal(err)
		}
	}

	dbPath := tc.G.Env.GetDbFilename()
	sessionPath := tc.G.Env.GetSessionFilename()

	assertFileExists(t, dbPath)
	assertFileExists(t, sessionPath)

	if !LoggedIn(tc) {
		t.Fatal("Unexpectedly logged out")
	}

	e := NewResetEngine(tc.G)
	ctx = &Context{}
	if err := RunEngine(e, ctx); err != nil {
		t.Fatal(err)
	}

	if LoggedIn(tc) {
		t.Error("Unexpectedly still logged in")
	}

	if libkb.HasSecretStore() {
		secretStore := libkb.NewSecretStore(fu.NormalizedUsername())
		secret, err := secretStore.RetrieveSecret()
		if err == nil {
			t.Errorf("Unexpectedly got secret %v", secret)
		}
	}

	assertFileDoesNotExist(t, dbPath)
	assertFileDoesNotExist(t, sessionPath)
}
// findAndDecryptPrivatePGPKeys gets the user's private pgp keys if
// any exist and decrypts them.
func (c *PassphraseChange) findAndDecryptPrivatePGPKeys(ctx *Context) ([]libkb.GenericKey, error) {
	ska := libkb.SecretKeyArg{
		Me:      c.me,
		KeyType: libkb.PGPKeyType,
	}

	// get all the pgp key skb blocks from the keyring:
	var blocks []*libkb.SKB
	err := c.G().LoginState().Keyring(func(kr *libkb.SKBKeyringFile) {
		blocks = kr.SearchWithComputedKeyFamily(c.me.GetComputedKeyFamily(), ska)
	}, "PassphraseChange - findAndDecryptPrivatePGPKey")
	if err != nil {
		return nil, err
	}

	// and the synced secret keys:
	syncKeys, err := c.me.AllSyncedSecretKeys(ctx.LoginContext)
	if err != nil {
		return nil, err
	}
	if syncKeys != nil {
		blocks = append(blocks, syncKeys...)
	}

	secretRetriever := libkb.NewSecretStore(c.G(), c.me.GetNormalizedName())

	// avoid duplicates:
	keys := make(map[keybase1.KID]libkb.GenericKey)
	for _, block := range blocks {
		block.SetUID(c.me.GetUID())
		var key libkb.GenericKey
		if c.usingPaper {
			key, err = block.UnlockWithStoredSecret(secretRetriever)
			if err != nil {
				switch err.(type) {
				case libkb.BadKeyError:
					// expected error, ok to proceed...
					continue
				default:
					// unexpected error type:
					return nil, err
				}
			}
		} else {
			parg := ctx.SecretKeyPromptArg(libkb.SecretKeyArg{}, "passphrase change")
			key, err = block.PromptAndUnlock(parg, "your keybase passphrase", secretRetriever, nil, c.me)
			if err != nil {
				return nil, err
			}
		}
		keys[key.GetKID()] = key
	}

	keyList := make([]libkb.GenericKey, 0, len(keys))
	for _, key := range keys {
		keyList = append(keyList, key)
	}

	return keyList, nil
}
Esempio n. 3
0
// findAndDecryptPrivatePGPKeys gets the user's private pgp keys if
// any exist and decrypts them.
func (c *PassphraseChange) findAndDecryptPrivatePGPKeys(ctx *Context) ([]libkb.GenericKey, error) {

	var keyList []libkb.GenericKey

	// Using a paper key makes TripleSec-synced keys unrecoverable
	if c.usingPaper {
		c.G().Log.Debug("using a paper key, thus TripleSec-synced keys are unrecoverable")
		return keyList, nil
	}

	// Only use the synced secret keys:
	blocks, err := c.me.AllSyncedSecretKeys(ctx.LoginContext)
	if err != nil {
		return nil, err
	}

	secretRetriever := libkb.NewSecretStore(c.G(), c.me.GetNormalizedName())

	for _, block := range blocks {
		parg := ctx.SecretKeyPromptArg(libkb.SecretKeyArg{}, "passphrase change")
		key, err := block.PromptAndUnlock(parg, secretRetriever, c.me)
		if err != nil {
			return nil, err
		}
		keyList = append(keyList, key)
	}

	return keyList, nil
}
Esempio n. 4
0
func userHasStoredSecretViaSecretStore(tc *libkb.TestContext, username string) bool {
	secretStore := libkb.NewSecretStore(libkb.NewNormalizedUsername(username))
	if secretStore == nil {
		tc.T.Errorf("SecretStore for %s unexpectedly nil", username)
		return false
	}
	_, err := secretStore.RetrieveSecret()
	// TODO: Have RetrieveSecret return platform-independent errors
	// so that we can make sure we got the right one.
	return (err == nil)
}
Esempio n. 5
0
func (e *TrackToken) storeRemoteTrack(ctx *Context) (err error) {
	e.G().Log.Debug("+ StoreRemoteTrack")

	defer func() {
		e.G().Log.Debug("- StoreRemoteTrack -> %s", libkb.ErrToOk(err))
	}()

	var secretStore libkb.SecretStore
	if e.arg.Me != nil {
		e.lockedKey.SetUID(e.arg.Me.GetUID())
		secretStore = libkb.NewSecretStore(e.G(), e.arg.Me.GetNormalizedName())
	}
	// need to unlock private key
	parg := ctx.SecretKeyPromptArg(libkb.SecretKeyArg{}, "tracking signature")
	e.signingKeyPriv, err = e.lockedKey.PromptAndUnlock(parg, e.lockedWhich, secretStore, nil, e.arg.Me)
	if err != nil {
		return err
	}
	if e.signingKeyPriv == nil {
		return libkb.NoSecretKeyError{}
	}

	sig, sigid, err := e.signingKeyPriv.SignToString(e.trackStatementBytes)
	if err != nil {
		return err
	}

	_, err = e.G().API.Post(libkb.APIArg{
		Endpoint:    "follow",
		NeedSession: true,
		Args: libkb.HTTPArgs{
			"sig_id_base":  libkb.S{Val: sigid.ToString(false)},
			"sig_id_short": libkb.S{Val: sigid.ToShortID()},
			"sig":          libkb.S{Val: sig},
			"uid":          libkb.UIDArg(e.them.GetUID()),
			"type":         libkb.S{Val: "track"},
			"signing_kid":  e.signingKeyPub.GetKID(),
		},
	})

	if err != nil {
		e.G().Log.Info("api error: %s", err)
		return err
	}

	linkid := libkb.ComputeLinkID(e.trackStatementBytes)
	e.arg.Me.SigChainBump(linkid, sigid)

	return err
}
Esempio n. 6
0
func (s *SignupEngine) registerDevice(a libkb.LoginContext, ctx *Context, deviceName string) error {
	s.lks = libkb.NewLKSec(s.ppStream, s.uid, s.G())
	args := &DeviceWrapArgs{
		Me:         s.me,
		DeviceName: deviceName,
		DeviceType: libkb.DeviceTypeDesktop,
		Lks:        s.lks,
		IsEldest:   true,
	}
	eng := NewDeviceWrap(args, s.G())
	ctx.LoginContext = a
	if err := RunEngine(eng, ctx); err != nil {
		return err
	}
	s.signingKey = eng.SigningKey()
	s.encryptionKey = eng.EncryptionKey()

	if err := ctx.LoginContext.LocalSession().SetDeviceProvisioned(s.G().Env.GetDeviceID()); err != nil {
		// this isn't a fatal error, session will stay in memory...
		s.G().Log.Warning("error saving session file: %s", err)
	}

	if s.arg.StoreSecret {
		// Create the secret store as late as possible here
		// (instead of when we first get the value of
		// StoreSecret) as the username may change during the
		// signup process.
		secretStore := libkb.NewSecretStore(s.G(), s.me.GetNormalizedName())
		secret, err := s.lks.GetSecret(a)
		if err != nil {
			return err
		}
		// Ignore any errors storing the secret.
		storeSecretErr := secretStore.StoreSecret(secret)
		if storeSecretErr != nil {
			s.G().Log.Warning("StoreSecret error: %s", storeSecretErr)
		}
	}

	// is there any reason *not* to do this?
	ctx.LoginContext.SetCachedSecretKey(libkb.SecretKeyArg{KeyType: libkb.DeviceSigningKeyType}, s.signingKey)
	ctx.LoginContext.SetCachedSecretKey(libkb.SecretKeyArg{KeyType: libkb.DeviceEncryptionKeyType}, eng.EncryptionKey())

	s.G().Log.Debug("registered new device: %s", s.G().Env.GetDeviceID())
	s.G().Log.Debug("eldest kid: %s", s.me.GetEldestKID())

	return nil
}
Esempio n. 7
0
func (e *PaperKeyGen) getClientHalfFromSecretStore() ([]byte, libkb.PassphraseGeneration, error) {
	zeroGen := libkb.PassphraseGeneration(0)

	secretStore := libkb.NewSecretStore(e.G(), e.arg.Me.GetNormalizedName())
	if secretStore == nil {
		return nil, zeroGen, errors.New("No secret store available")
	}

	secret, err := secretStore.RetrieveSecret()
	if err != nil {
		return nil, zeroGen, err
	}

	devid := e.G().Env.GetDeviceID()
	if devid.IsNil() {
		return nil, zeroGen, fmt.Errorf("no device id set")
	}

	var dev libkb.DeviceKey
	aerr := e.G().LoginState().Account(func(a *libkb.Account) {
		if err = libkb.RunSyncer(a.SecretSyncer(), e.arg.Me.GetUID(), a.LoggedIn(), a.LocalSession()); err != nil {
			return
		}
		dev, err = a.SecretSyncer().FindDevice(devid)
	}, "BackupKeygen.Run() -- retrieving passphrase generation)")
	if aerr != nil {
		return nil, zeroGen, aerr
	}
	if err != nil {
		return nil, zeroGen, err
	}

	serverHalf, err := hex.DecodeString(dev.LksServerHalf)
	if err != nil {
		return nil, zeroGen, err
	}

	if len(secret) != len(serverHalf) {
		return nil, zeroGen, fmt.Errorf("secret has length %d, server half has length %d", len(secret), len(serverHalf))
	}

	clientHalf := make([]byte, len(secret))
	libkb.XORBytes(clientHalf, secret, serverHalf)

	return clientHalf, dev.PPGen, nil
}
Esempio n. 8
0
// Test that the signup engine stores the secret correctly when
// StoreSecret is set.
func TestLocalKeySecurityStoreSecret(t *testing.T) {
	tc := SetupEngineTest(t, "signup")
	defer tc.Cleanup()
	fu := NewFakeUserOrBust(t, "se")

	secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername())
	if secretStore == nil {
		t.Skip("No SecretStore on this platform")
	}

	_, err := secretStore.RetrieveSecret()
	if err == nil {
		t.Fatal("User unexpectedly has secret")
	}

	arg := MakeTestSignupEngineRunArg(fu)
	arg.StoreSecret = true
	s := SignupFakeUserWithArg(tc, fu, arg)

	secret, err := s.lks.GetSecret(nil)
	if err != nil {
		t.Fatal(err)
	}

	storedSecret, err := secretStore.RetrieveSecret()
	if err != nil {
		t.Error(err)
	}

	if string(secret) != string(storedSecret) {
		t.Errorf("Expected %v, got %v", secret, storedSecret)
	}

	err = secretStore.ClearSecret()
	if err != nil {
		t.Error(err)
	}
}
Esempio n. 9
0
func assertDeprovisionWithSetup(tc libkb.TestContext) {
	// Sign up a new user and have it store its secret in the
	// secret store (if possible).
	fu := NewFakeUserOrBust(tc.T, "dpr")
	arg := MakeTestSignupEngineRunArg(fu)
	arg.SkipPaper = false
	arg.StoreSecret = tc.G.SecretStoreAll != nil
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}

	if tc.G.SecretStoreAll != nil {
		secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername())
		_, err := secretStore.RetrieveSecret()
		if err != nil {
			tc.T.Fatal(err)
		}
	}

	dbPath := tc.G.Env.GetDbFilename()
	sessionPath := tc.G.Env.GetSessionFilename()
	secretKeysPath := tc.G.SKBFilenameForUser(fu.NormalizedUsername())
	numKeys := getNumKeys(tc, *fu)

	assertFileExists(tc.T, dbPath)
	assertFileExists(tc.T, sessionPath)
	assertFileExists(tc.T, secretKeysPath)
	if !isUserInConfigFile(tc, *fu) {
		tc.T.Fatalf("User %s is not in the config file %s", fu.Username, tc.G.Env.GetConfigFilename())
	}
	if !isUserConfigInMemory(tc) {
		tc.T.Fatal("user config is not in memory")
	}

	if !LoggedIn(tc) {
		tc.T.Fatal("Unexpectedly logged out")
	}

	e := NewDeprovisionEngine(tc.G, fu.Username, true /* doRevoke */)
	ctx = &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	if err := RunEngine(e, ctx); err != nil {
		tc.T.Fatal(err)
	}

	if LoggedIn(tc) {
		tc.T.Error("Unexpectedly still logged in")
	}

	if tc.G.SecretStoreAll != nil {
		secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername())
		secret, err := secretStore.RetrieveSecret()
		if err == nil {
			tc.T.Errorf("Unexpectedly got secret %v", secret)
		}
	}

	assertFileDoesNotExist(tc.T, dbPath)
	assertFileDoesNotExist(tc.T, sessionPath)
	assertFileDoesNotExist(tc.T, secretKeysPath)
	if isUserInConfigFile(tc, *fu) {
		tc.T.Fatalf("User %s is still in the config file %s", fu.Username, tc.G.Env.GetConfigFilename())
	}
	if isUserConfigInMemory(tc) {
		tc.T.Fatal("user config is still in memory")
	}

	newNumKeys := getNumKeys(tc, *fu)
	if newNumKeys != numKeys-2 {
		tc.T.Fatalf("failed to revoke device keys, before: %d, after: %d", numKeys, newNumKeys)
	}
}
Esempio n. 10
0
func TestDeprovisionLoggedOut(t *testing.T) {
	tc := SetupEngineTest(t, "deprovision")
	defer tc.Cleanup()

	// Sign up a new user and have it store its secret in the
	// secret store (if possible).
	fu := NewFakeUserOrBust(tc.T, "dpr")
	arg := MakeTestSignupEngineRunArg(fu)
	arg.StoreSecret = libkb.HasSecretStore()
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}

	if libkb.HasSecretStore() {
		secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername())
		_, err := secretStore.RetrieveSecret()
		if err != nil {
			t.Fatal(err)
		}
	}

	dbPath := tc.G.Env.GetDbFilename()
	sessionPath := tc.G.Env.GetSessionFilename()
	secretKeysPath := tc.G.SKBFilenameForUser(fu.NormalizedUsername())
	numKeys := getNumKeys(tc, *fu)

	assertFileExists(t, dbPath)
	assertFileExists(t, sessionPath)
	assertFileExists(t, secretKeysPath)
	if !isUserInConfigFile(tc, *fu) {
		t.Fatalf("User %s is not in the config file %s", fu.Username, tc.G.Env.GetConfigFilename())
	}
	if !isUserConfigInMemory(tc) {
		t.Fatalf("user config is not in memory")
	}

	if !LoggedIn(tc) {
		t.Fatal("Unexpectedly logged out")
	}

	// Unlike the first test, this time we log out before we run the
	// deprovision. That should mean that no keys get revoked, but everything
	// else should be the same.
	tc.G.Logout()

	e := NewDeprovisionEngine(tc.G, fu.Username)
	ctx = &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	if err := RunEngine(e, ctx); err != nil {
		t.Fatal(err)
	}

	if LoggedIn(tc) {
		t.Error("Unexpectedly still logged in")
	}

	if libkb.HasSecretStore() {
		secretStore := libkb.NewSecretStore(tc.G, fu.NormalizedUsername())
		secret, err := secretStore.RetrieveSecret()
		if err == nil {
			t.Errorf("Unexpectedly got secret %v", secret)
		}
	}

	assertFileDoesNotExist(t, dbPath)
	assertFileDoesNotExist(t, sessionPath)
	assertFileDoesNotExist(t, secretKeysPath)
	if isUserInConfigFile(tc, *fu) {
		t.Fatalf("User %s is still in the config file %s", fu.Username, tc.G.Env.GetConfigFilename())
	}
	if isUserConfigInMemory(tc) {
		t.Fatalf("user config is still in memory")
	}

	newNumKeys := getNumKeys(tc, *fu)
	if newNumKeys != numKeys {
		t.Fatalf("expected the same number of device keys, before: %d, after: %d", numKeys, newNumKeys)
	}
}