Beispiel #1
0
func (c *CmdDeprovision) getBigScaryWarning(username string) (string, error) {
	// If the user is logged out, warn that we won't revoke their keys.
	loggedOutWarning := ""
	if !c.loggedIn {
		loggedOutWarning = `

Note that you aren't currently logged in. That means we won't publicly revoke
this device's keys. To do that from another device, use 'keybase device remove'.`
	}

	// If the user has PGP secret keys in the SKBKeyring, print an additional warning.
	keyring, err := libkb.LoadSKBKeyring(libkb.NewNormalizedUsername(username), c.G())
	if err != nil {
		return "", err
	}
	pgpWarning := ""
	if keyring.HasPGPKeys() {
		pgpWarning = fmt.Sprintf(`

Also, the secret keyring you're about to delete contains PGP keys. To list them
or copy them, use %s.`, "`keybase pgp export`")
	}

	// TODO: Print a list of the other devices on the user's account.
	return fmt.Sprintf(`
%s, BE CAREFUL!  \('o')/

You are about to delete this device from your account, including its secret
keys. If you don't have any other devices, you'll lose access to your account
and all your data!%s%s

Proceed?`, username, loggedOutWarning, pgpWarning), nil
}
Beispiel #2
0
func TestTokenVerifyToken(t *testing.T) {
	keyPair, err := libkb.GenerateNaclSigningKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	name := libkb.NewNormalizedUsername("alice")
	uid := libkb.UsernameToUID(name.String())
	expireIn := 10
	server := "test"
	clientName := "test_client"
	clientVersion := "41651"
	token := NewToken(uid, name, keyPair.GetKID(), server, expireIn, clientName, clientVersion)
	sig, _, err := keyPair.SignToString(token.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	_, err = VerifyToken("nope", server, testMaxTokenExpireIn)
	if err == nil {
		t.Fatal(fmt.Errorf("expected verification failure"))
	}
	token, err = VerifyToken(sig, server, testMaxTokenExpireIn)
	if err != nil {
		t.Fatal(err)
	}
	if err = checkToken(token, uid, name, keyPair.GetKID(),
		server, expireIn, clientName, clientVersion); err != nil {
		t.Fatal(err)
	}
}
Beispiel #3
0
func (s *SignupJoinEngine) Post(arg SignupJoinEngineRunArg) (err error) {
	var res *libkb.APIRes
	var ppGenTmp int
	res, err = s.G().API.Post(libkb.APIArg{
		Endpoint: "signup",
		Args: libkb.HTTPArgs{
			"salt":          libkb.S{Val: hex.EncodeToString(arg.PWSalt)},
			"pwh":           libkb.S{Val: hex.EncodeToString(arg.PWHash)},
			"username":      libkb.S{Val: arg.Username},
			"email":         libkb.S{Val: arg.Email},
			"invitation_id": libkb.S{Val: arg.InviteCode},
			"pwh_version":   libkb.I{Val: int(triplesec.Version)},
			"skip_mail":     libkb.B{Val: arg.SkipMail},
		}})
	if err == nil {
		s.username = libkb.NewNormalizedUsername(arg.Username)
		libkb.GetUIDVoid(res.Body.AtKey("uid"), &s.uid, &err)
		res.Body.AtKey("session").GetStringVoid(&s.session, &err)
		res.Body.AtKey("csrf_token").GetStringVoid(&s.csrf, &err)
		res.Body.AtPath("me.basics.passphrase_generation").GetIntVoid(&ppGenTmp, &err)
	}
	if err == nil {
		err = libkb.CheckUIDAgainstUsername(s.uid, arg.Username)
		s.ppGen = libkb.PassphraseGeneration(ppGenTmp)
	}
	return
}
func (k *KeybaseDaemonRPC) processUserPlusKeys(upk keybase1.UserPlusKeys) (
	UserInfo, error) {
	verifyingKeys, cryptPublicKeys, kidNames, err := filterKeys(upk.DeviceKeys)
	if err != nil {
		return UserInfo{}, err
	}

	revokedVerifyingKeys, revokedCryptPublicKeys, revokedKidNames, err :=
		filterRevokedKeys(upk.RevokedDeviceKeys)
	if err != nil {
		return UserInfo{}, err
	}

	if len(revokedKidNames) > 0 {
		for k, v := range revokedKidNames {
			kidNames[k] = v
		}
	}

	u := UserInfo{
		Name:                   libkb.NewNormalizedUsername(upk.Username),
		UID:                    upk.Uid,
		VerifyingKeys:          verifyingKeys,
		CryptPublicKeys:        cryptPublicKeys,
		KIDNames:               kidNames,
		RevokedVerifyingKeys:   revokedVerifyingKeys,
		RevokedCryptPublicKeys: revokedCryptPublicKeys,
	}

	k.setCachedUserInfo(upk.Uid, u)
	return u, nil
}
Beispiel #5
0
func NewDeprovisionEngine(g *libkb.GlobalContext, username string, doRevoke bool) *DeprovisionEngine {
	return &DeprovisionEngine{
		Contextified: libkb.NewContextified(g),
		username:     libkb.NewNormalizedUsername(username),
		doRevoke:     doRevoke,
	}
}
Beispiel #6
0
// TODO: this function can likely be replaced with a call to
// AssertionParseAndOnly when CORE-2967 and CORE-2968 are fixed.
func normalizeAssertionOrName(s string) (string, error) {
	if libkb.CheckUsername.F(s) {
		return libkb.NewNormalizedUsername(s).String(), nil
	}

	// TODO: this fails for http and https right now (see CORE-2968).
	socialAssertion, isSocialAssertion := libkb.NormalizeSocialAssertion(s)
	if isSocialAssertion {
		return socialAssertion.String(), nil
	}

	if expr, err := libkb.AssertionParseAndOnly(s); err == nil {
		// If the expression only contains a single url, make sure
		// it's not a just considered a single keybase username.  If
		// it is, then some non-username slipped into the default
		// "keybase" case and should be considered an error.
		urls := expr.CollectUrls(nil)
		if len(urls) == 1 && urls[0].IsKeybase() {
			return "", NoSuchUserError{s}
		}

		// Normalize and return.  Ideally `AssertionParseAndOnly`
		// would normalize for us, but that doesn't work yet, so for
		// now we'll just lower-case.  This will incorrectly lower
		// case http/https/web assertions, as well as case-sensitive
		// social assertions in AND expressions.  TODO: see CORE-2967.
		return strings.ToLower(s), nil
	}

	return "", BadTLFNameError{s}
}
Beispiel #7
0
func TestMaxExpires(t *testing.T) {
	keyPair, err := libkb.GenerateNaclSigningKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	name := libkb.NewNormalizedUsername("charlie")
	uid := libkb.UsernameToUID(name.String())
	expireIn := testMaxTokenExpireIn + 1
	server := "test"
	clientName := "test_client"
	clientVersion := "93021"
	challenge, err := GenerateChallenge()
	if err != nil {
		t.Fatal(err)
	}
	token := NewToken(uid, name, keyPair.GetKID(), server, challenge,
		time.Now().Unix(), expireIn, clientName, clientVersion)
	sig, _, err := keyPair.SignToString(token.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	_, err = VerifyToken(sig, server, challenge, testMaxTokenExpireIn)
	_, maxExpires := err.(MaxTokenExpiresError)
	if !maxExpires {
		t.Fatal(fmt.Errorf("expected max token expires error"))
	}
}
Beispiel #8
0
func TestTokenServerInvalid(t *testing.T) {
	keyPair, err := libkb.GenerateNaclSigningKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	name := libkb.NewNormalizedUsername("dana")
	uid := libkb.UsernameToUID(name.String())
	expireIn := 10
	server := "test"
	clientName := "test_client"
	clientVersion := "20192"
	token := NewToken(uid, name, keyPair.GetKID(), server, expireIn, clientName, clientVersion)
	sig, _, err := keyPair.SignToString(token.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	_, err = VerifyToken(sig, "nope", testMaxTokenExpireIn)
	_, invalid := err.(InvalidTokenServerError)
	if !invalid {
		t.Fatal(fmt.Errorf("expected invalid token server error"))
	}
	token, err = VerifyToken(sig, server, testMaxTokenExpireIn)
	if err != nil {
		t.Fatal(err)
	}
	if err = checkToken(token, uid, name, keyPair.GetKID(),
		server, expireIn, clientName, clientVersion); err != nil {
		t.Fatal(err)
	}
}
Beispiel #9
0
// normalizeUserNamesInTLF takes a split TLF name and, without doing
// any resolutions or identify calls, normalizes all elements of the
// name that are bare user names. It then returns the normalized name.
//
// Note that this normalizes (i.e., lower-cases) any assertions in the
// name as well, but doesn't resolve them.  This is safe since the
// libkb assertion parser does that same thing.
func normalizeUserNamesInTLF(writerNames, readerNames []string) string {
	sortedWriterNames := make([]string, len(writerNames))
	for i, w := range writerNames {
		sortedWriterNames[i] = libkb.NewNormalizedUsername(w).String()
	}
	sort.Strings(sortedWriterNames)
	normalizedName := strings.Join(sortedWriterNames, ",")
	if len(readerNames) > 0 {
		sortedReaderNames := make([]string, len(readerNames))
		for i, r := range readerNames {
			sortedReaderNames[i] =
				libkb.NewNormalizedUsername(r).String()
		}
		sort.Strings(sortedReaderNames)
		normalizedName += ReaderSep + strings.Join(sortedReaderNames, ",")
	}
	return normalizedName
}
Beispiel #10
0
// Resolve implements the KeybaseDaemon interface for KeybaseDaemonRPC.
func (k *KeybaseDaemonRPC) Resolve(ctx context.Context, assertion string) (
	libkb.NormalizedUsername, keybase1.UID, error) {
	user, err := k.identifyClient.Resolve2(ctx, assertion)
	if err != nil {
		return libkb.NormalizedUsername(""), keybase1.UID(""),
			convertIdentifyError(assertion, err)
	}
	return libkb.NewNormalizedUsername(user.Username), user.Uid, nil
}
Beispiel #11
0
func expectUsernameCall(u keybase1.UID, config *ConfigMock) {
	name := libkb.NewNormalizedUsername(fmt.Sprintf("user_%s", u))
	config.mockKbpki.EXPECT().GetNormalizedUsername(gomock.Any(), u).AnyTimes().
		Return(name, nil)
	config.mockKbpki.EXPECT().Resolve(gomock.Any(), string(name)).AnyTimes().
		Return(u, nil)
	// Ideally, this would be 0 or 1 times.
	config.mockKbpki.EXPECT().Identify(gomock.Any(), name.String(), gomock.Any()).AnyTimes().
		Return(UserInfo{Name: name, UID: u}, nil)
}
Beispiel #12
0
// saveLoginState stores the user's login state. The user config
// file is stored in a temporary location, since we're usually in a
// "config file transaction" at this point.
func (e *Kex2Provisionee) saveLoginState() error {
	if err := e.ctx.LoginContext.LoadLoginSession(e.username); err != nil {
		return err
	}
	err := e.ctx.LoginContext.SaveState(string(e.sessionToken), string(e.csrfToken), libkb.NewNormalizedUsername(e.username), e.uid, e.device.ID)
	if err != nil {
		return err
	}
	return nil
}
Beispiel #13
0
// Run starts the engine.
func (e *LoginCurrentDevice) Run(ctx *Context) error {
	// already logged in?
	in, err := e.G().LoginState().LoggedInProvisionedLoad()
	if err == nil && in {
		if len(e.username) == 0 || e.G().Env.GetUsername() == libkb.NewNormalizedUsername(e.username) {
			return nil
		}
	}

	var config *libkb.UserConfig
	if len(e.username) == 0 {
		config, err = e.G().Env.GetConfig().GetUserConfig()
	} else {
		nu := libkb.NewNormalizedUsername(e.username)
		config, err = e.G().Env.GetConfig().GetUserConfigForUsername(nu)
	}
	if err != nil {
		e.G().Log.Debug("error getting user config: %s (%T)", err, err)
		return errNoConfig
	}
	if config == nil {
		e.G().Log.Debug("user config is nil")
		return errNoConfig
	}
	if config.GetDeviceID().IsNil() {
		e.G().Log.Debug("no device in user config")
		return errNoDevice
	}

	// at this point, there is a user config either for the current user or for e.username
	// and it has a device id, so this should be a provisioned device.  Thus, they should
	// just login normally.

	var afterLogin = func(lctx libkb.LoginContext) error {
		if err := lctx.LocalSession().SetDeviceProvisioned(e.G().Env.GetDeviceID()); err != nil {
			// not a fatal error, session will stay in memory
			e.G().Log.Warning("error saving session file: %s", err)
		}
		return nil
	}
	return e.G().LoginState().LoginWithPrompt(e.username, ctx.LoginUI, ctx.SecretUI, afterLogin)
}
Beispiel #14
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)
}
func newTestUser(nKeys int) *testUser {
	un := genUsername()
	ret := testUser{
		username: libkb.NewNormalizedUsername(un),
		uid:      libkb.UsernameToUID(un),
		keys:     make([]keybase1.KID, nKeys),
	}
	for i := 0; i < nKeys; i++ {
		ret.keys[i] = genKID()
	}
	return &ret
}
Beispiel #16
0
// CurrentSession implements the KeybaseDaemon interface for KeybaseDaemonRPC.
func (k *KeybaseDaemonRPC) CurrentSession(ctx context.Context, sessionID int) (
	SessionInfo, error) {
	cachedCurrentSession := k.getCachedCurrentSession()
	if cachedCurrentSession != (SessionInfo{}) {
		return cachedCurrentSession, nil
	}

	res, err := k.sessionClient.CurrentSession(ctx, sessionID)
	if err != nil {
		if ncs := (NoCurrentSessionError{}); err.Error() ==
			NoCurrentSessionExpectedError {
			// Use an error with a proper OS error code attached to
			// it.  TODO: move ErrNoSession from client/go/service to
			// client/go/libkb, so we can use types for the check
			// above.
			err = ncs
		}
		return SessionInfo{}, err
	}
	// Import the KIDs to validate them.
	deviceSubkey, err := libkb.ImportKeypairFromKID(res.DeviceSubkeyKid)
	if err != nil {
		return SessionInfo{}, err
	}
	deviceSibkey, err := libkb.ImportKeypairFromKID(res.DeviceSibkeyKid)
	if err != nil {
		return SessionInfo{}, err
	}
	cryptPublicKey := MakeCryptPublicKey(deviceSubkey.GetKID())
	verifyingKey := MakeVerifyingKey(deviceSibkey.GetKID())
	s := SessionInfo{
		Name:           libkb.NewNormalizedUsername(res.Username),
		UID:            keybase1.UID(res.Uid),
		Token:          res.Token,
		CryptPublicKey: cryptPublicKey,
		VerifyingKey:   verifyingKey,
	}

	k.log.CDebugf(
		ctx, "new session with username %s, uid %s, crypt public key %s, and verifying key %s",
		s.Name, s.UID, s.CryptPublicKey, s.VerifyingKey)

	k.setCachedCurrentSession(s)

	return s, nil
}
Beispiel #17
0
func (k *KeybaseDaemonRPC) processUserPlusKeys(
	ctx context.Context, upk keybase1.UserPlusKeys) (UserInfo, error) {
	verifyingKeys, cryptPublicKeys, err := k.filterKeys(ctx, upk.Uid, upk.DeviceKeys)
	if err != nil {
		return UserInfo{}, err
	}

	u := UserInfo{
		Name:            libkb.NewNormalizedUsername(upk.Username),
		UID:             upk.Uid,
		VerifyingKeys:   verifyingKeys,
		CryptPublicKeys: cryptPublicKeys,
	}

	k.setCachedUserInfo(upk.Uid, u)
	return u, nil
}
Beispiel #18
0
func (c *CmdCA) runPromptLoop() error {
	var err error
	var s string
	re := regexp.MustCompile(`(\s|,|:)+`)

	api := auth.NewUserKeyAPIer(c.G().Log, c.G().API)
	ca := auth.NewCredentialAuthority(c.G().Log, api)

	for {
		s, err = c.G().UI.GetTerminalUI().Prompt(0, "ca> ")
		if err != nil {
			break
		}
		s = strings.TrimSpace(s)
		if len(s) == 0 {
			break
		}
		v := re.Split(s, -1)
		if len(v) != 3 {
			c.G().Log.Errorf("Need a triple: [<uid>,<username>,<kid>]")
			continue
		}

		uid, e2 := keybase1.UIDFromString(v[0])
		if e2 != nil {
			c.G().Log.Errorf("Bad UID %s: %s", v[0], e2)
			continue
		}

		un := libkb.NewNormalizedUsername(v[1])

		kid, e2 := keybase1.KIDFromStringChecked(v[2])
		if e2 != nil {
			c.G().Log.Errorf("Bad KID %s: %s", v[2], e2)
			continue
		}

		if e2 := ca.CheckUserKey(context.TODO(), uid, &un, &kid); e2 != nil {
			c.G().Log.Errorf("Bad check: %s", e2)
		}

	}
	return err
}
func (u *userKeyAPI) GetUser(ctx context.Context, uid keybase1.UID) (
	un libkb.NormalizedUsername, sibkeys, subkeys []keybase1.KID, err error) {
	u.log.Debug("+ GetUser")
	defer func() {
		u.log.Debug("- GetUser -> %v", err)
	}()
	var ukr userKeyRes
	err = u.api.GetDecode(libkb.APIArg{
		Endpoint: "user/keys",
		Args: libkb.HTTPArgs{
			"uid": libkb.S{Val: uid.String()},
		},
	}, &ukr)
	if err != nil {
		return "", nil, nil, err
	}
	un = libkb.NewNormalizedUsername(ukr.Username)
	return un, ukr.PublicKeys.Sibkeys, ukr.PublicKeys.Subkeys, nil
}
func (e *Kex2Provisionee) saveLoginState() error {
	var err error
	aerr := e.G().LoginState().Account(func(a *libkb.Account) {
		err = a.LoadLoginSession(e.username)
		if err != nil {
			return
		}
		err = a.SaveState(string(e.sessionToken), string(e.csrfToken), libkb.NewNormalizedUsername(e.username), e.uid)
		if err != nil {
			return
		}
	}, "Kex2Provisionee - saveLoginState()")
	if aerr != nil {
		return aerr
	}
	if err != nil {
		return err
	}
	return nil
}
Beispiel #21
0
func TestTokenExpired(t *testing.T) {
	keyPair, err := libkb.GenerateNaclSigningKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	name := libkb.NewNormalizedUsername("bob")
	uid := libkb.UsernameToUID(name.String())
	expireIn := 0
	server := "test"
	clientName := "test_client"
	clientVersion := "21021"
	token := NewToken(uid, name, keyPair.GetKID(), server, expireIn, clientName, clientVersion)
	sig, _, err := keyPair.SignToString(token.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	_, err = VerifyToken(sig, server, testMaxTokenExpireIn)
	_, expired := err.(TokenExpiredError)
	if !expired {
		t.Fatal(fmt.Errorf("expected token expired error"))
	}
}
Beispiel #22
0
func (c *CmdDeprovision) getBigScaryWarning(username string) (string, error) {
	// If the user has PGP secret keys in the SKBKeyring, print an additional warning.
	keyring, err := libkb.LoadSKBKeyring(libkb.NewNormalizedUsername(username), c.G())
	if err != nil {
		return "", err
	}
	pgpWarning := ""
	if keyring.HasPGPKeys() {
		pgpWarning = fmt.Sprintf(`

Also, the secret keyring you're about to delete contains PGP keys. To list them
or copy them, use %s.`, "`keybase pgp export`")
	}

	// TODO: Print a list of the other devices on the user's account.
	return fmt.Sprintf(`
%s, BE CAREFUL!  \('o')/

You are about to delete this device from your account, including its secret
keys. If you don't have any other devices, you'll lose access to your account
and all your data!%s

Proceed?`, username, pgpWarning), nil
}
// Test that the user cache works and is invalidated as expected.
func TestKeybaseDaemonUserCache(t *testing.T) {
	uid1 := keybase1.UID("uid1")
	uid2 := keybase1.UID("uid2")
	name1 := libkb.NewNormalizedUsername("name1")
	name2 := libkb.NewNormalizedUsername("name2")
	users := map[keybase1.UID]UserInfo{
		uid1: {Name: name1},
		uid2: {Name: name2},
	}
	client := &fakeKeybaseClient{users: users}
	c := newKeybaseDaemonRPCWithClient(
		nil, client, logger.NewTestLogger(t))

	// Should fill cache.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should fill cache.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should not be cached.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should invalidate cache for uid1.
	err := c.UserChanged(context.Background(), uid1)
	if err != nil {
		t.Fatal(err)
	}

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should still be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for uid2.
	err = c.UserChanged(context.Background(), uid2)
	if err != nil {
		t.Fatal(err)
	}

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for all users.
	c.OnDisconnected(UsingExistingConnection)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)
}
Beispiel #24
0
func (h *LoginHandler) ClearStoredSecret(_ context.Context, arg keybase1.ClearStoredSecretArg) error {
	return libkb.ClearStoredSecret(h.G(), libkb.NewNormalizedUsername(arg.Username))
}
// Test that the user cache works and is invalidated as expected.
func TestKeybaseDaemonUserCache(t *testing.T) {
	uid1 := keybase1.UID("uid1")
	uid2 := keybase1.UID("uid2")
	name1 := libkb.NewNormalizedUsername("name1")
	name2 := libkb.NewNormalizedUsername("name2")
	users := map[keybase1.UID]UserInfo{
		uid1: {Name: name1},
		uid2: {Name: name2},
	}
	client := &fakeKeybaseClient{users: users}
	c := newKeybaseDaemonRPCWithClient(
		nil, client, logger.NewTestLogger(t))

	// Should fill cache.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should fill cache.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should not be cached.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should invalidate cache for uid1.
	err := c.UserChanged(context.Background(), uid1)
	require.NoError(t, err)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should still be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for uid2.
	err = c.UserChanged(context.Background(), uid2)
	require.NoError(t, err)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for all users.
	c.OnDisconnected(context.Background(), rpc.UsingExistingConnection)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Test that CheckForRekey gets called only if the logged-in user
	// changes.
	session := SessionInfo{
		UID: uid1,
	}
	c.setCachedCurrentSession(session)
	ctr := NewSafeTestReporter(t)
	mockCtrl := gomock.NewController(ctr)
	config := NewConfigMock(mockCtrl, ctr)
	c.config = config
	defer func() {
		config.ctr.CheckForFailures()
		mockCtrl.Finish()
	}()
	errChan := make(chan error, 1)
	config.mockMdserv.EXPECT().CheckForRekeys(gomock.Any()).Do(
		func(ctx context.Context) {
			errChan <- nil
		}).Return(errChan)
	err = c.UserChanged(context.Background(), uid1)
	<-errChan
	// This one shouldn't trigger CheckForRekeys; if it does, the mock
	// controller will catch it during Finish.
	err = c.UserChanged(context.Background(), uid2)
}
Beispiel #26
0
func userHasStoredSecretViaSecretStore(tc *libkb.TestContext, username string) bool {
	secret, err := tc.G.SecretStoreAll.RetrieveSecret(libkb.NewNormalizedUsername(username))
	// TODO: Have RetrieveSecret return platform-independent errors
	// so that we can make sure we got the right one.
	return (len(secret) > 0 && err == nil)
}
Beispiel #27
0
// Init initializes a config and returns it.
//
// onInterruptFn is called whenever an interrupt signal is received
// (e.g., if the user hits Ctrl-C).
//
// Init should be called at the beginning of main. Shutdown (see
// below) should then be called at the end of main (usually via
// defer).
func Init(params InitParams, onInterruptFn func(), log logger.Logger) (Config, error) {
	initLibkb()

	localUser := libkb.NewNormalizedUsername(params.LocalUser)

	if params.CPUProfile != "" {
		// Let the GC/OS clean up the file handle.
		f, err := os.Create(params.CPUProfile)
		if err != nil {
			return nil, err
		}
		pprof.StartCPUProfile(f)
	}

	interruptChan := make(chan os.Signal, 1)
	signal.Notify(interruptChan, os.Interrupt)
	go func() {
		_ = <-interruptChan

		Shutdown(params.MemProfile)

		if onInterruptFn != nil {
			onInterruptFn()
		}

		os.Exit(1)
	}()

	config := NewConfigLocal()

	// 512K blocks by default, block changes embedded max == 8K.
	// Block size was chosen somewhat arbitrarily by trying to
	// minimize the overall size of the history written by a user when
	// appending 1KB writes to a file, up to a 1GB total file.  Here
	// is the output of a simple script that approximates that
	// calculation:
	//
	// Total history size for 0065536-byte blocks: 1134341128192 bytes
	// Total history size for 0131072-byte blocks: 618945052672 bytes
	// Total history size for 0262144-byte blocks: 412786622464 bytes
	// Total history size for 0524288-byte blocks: 412786622464 bytes
	// Total history size for 1048576-byte blocks: 618945052672 bytes
	// Total history size for 2097152-byte blocks: 1134341128192 bytes
	// Total history size for 4194304-byte blocks: 2216672886784 bytes
	bsplitter, err := NewBlockSplitterSimple(512*1024, 8*1024,
		config.Codec())
	if err != nil {
		return nil, err
	}
	config.SetBlockSplitter(bsplitter)

	if registry := config.MetricsRegistry(); registry != nil {
		keyCache := config.KeyCache()
		keyCache = NewKeyCacheMeasured(keyCache, registry)
		config.SetKeyCache(keyCache)
	}

	// Set logging
	config.SetLoggerMaker(func(module string) logger.Logger {
		mname := "kbfs"
		if module != "" {
			mname += fmt.Sprintf("(%s)", module)
		}
		// Add log depth so that context-based messages get the right
		// file printed out.
		lg := logger.NewWithCallDepth(mname, 1, os.Stderr)
		if params.Debug {
			// Turn on debugging.  TODO: allow a proper log file and
			// style to be specified.
			lg.Configure("", true, "")
		}
		return lg
	})

	kbfsOps := NewKBFSOpsStandard(config)
	config.SetKBFSOps(kbfsOps)
	config.SetNotifier(kbfsOps)
	config.SetKeyManager(NewKeyManagerStandard(config))

	mdServer, err := makeMDServer(
		config, params.ServerInMemory, params.ServerRootDir, params.MDServerAddr)
	if err != nil {
		return nil, fmt.Errorf("problem creating MD server: %v", err)
	}
	config.SetMDServer(mdServer)

	// note: the mdserver is the keyserver at the moment.
	keyServer, err := makeKeyServer(
		config, params.ServerInMemory, params.ServerRootDir, params.MDServerAddr)
	if err != nil {
		return nil, fmt.Errorf("problem creating key server: %v", err)
	}

	if registry := config.MetricsRegistry(); registry != nil {
		keyServer = NewKeyServerMeasured(keyServer, registry)
	}

	config.SetKeyServer(keyServer)

	daemon, err := makeKeybaseDaemon(config, params.ServerInMemory, params.ServerRootDir, localUser, config.Codec(), config.MakeLogger(""), params.Debug)
	if err != nil {
		return nil, fmt.Errorf("problem creating daemon: %s", err)
	}

	if registry := config.MetricsRegistry(); registry != nil {
		daemon = NewKeybaseDaemonMeasured(daemon, registry)
	}

	config.SetKeybaseDaemon(daemon)

	k := NewKBPKIClient(config)
	config.SetKBPKI(k)

	config.SetReporter(NewReporterKBPKI(config, 10, 1000))

	if localUser == "" {
		c := NewCryptoClient(config, libkb.G, config.MakeLogger(""))
		config.SetCrypto(c)
	} else {
		signingKey := MakeLocalUserSigningKeyOrBust(localUser)
		cryptPrivateKey := MakeLocalUserCryptPrivateKeyOrBust(localUser)
		config.SetCrypto(NewCryptoLocal(config, signingKey, cryptPrivateKey))
	}

	bserv, err := makeBlockServer(config, params.ServerInMemory, params.ServerRootDir, params.BServerAddr, log)
	if err != nil {
		return nil, fmt.Errorf("cannot open block database: %v", err)
	}

	if registry := config.MetricsRegistry(); registry != nil {
		bserv = NewBlockServerMeasured(bserv, registry)
	}

	config.SetBlockServer(bserv)

	return config, nil
}
Beispiel #28
0
func (e *loginProvisionedDevice) Run(ctx *Context) error {
	// already logged in?
	in, err := e.G().LoginState().LoggedInProvisionedLoad()
	if err == nil && in {
		if len(e.username) == 0 || e.G().Env.GetUsername() == libkb.NewNormalizedUsername(e.username) {
			// already logged in, make sure to unlock device keys
			return e.unlockDeviceKeys(ctx, nil)
		}
	}

	var config *libkb.UserConfig
	loadUserArg := libkb.LoadUserArg{
		PublicKeyOptional: true,
		ForceReload:       true,
	}
	if len(e.username) == 0 {
		e.G().Log.Debug("| using current username")
		config, err = e.G().Env.GetConfig().GetUserConfig()
		loadUserArg.Self = true
	} else {
		e.G().Log.Debug("| using new username %s", e.username)
		nu := libkb.NewNormalizedUsername(e.username)
		config, err = e.G().Env.GetConfig().GetUserConfigForUsername(nu)
		loadUserArg.Name = e.username
	}
	if err != nil {
		e.G().Log.Debug("error getting user config: %s (%T)", err, err)
		return errNoConfig
	}
	if config == nil {
		e.G().Log.Debug("user config is nil")
		return errNoConfig
	}
	deviceID := config.GetDeviceID()
	if deviceID.IsNil() {
		e.G().Log.Debug("no device in user config")
		return errNoDevice
	}

	// Make sure the device ID is still valid.
	me, err := libkb.LoadUser(loadUserArg)
	if err != nil {
		e.G().Log.Debug("error loading user profile: %#v", err)
		return err
	}
	if !me.HasDeviceInCurrentInstall(deviceID) {
		e.G().Log.Debug("current device is not valid")
		return errNoDevice
	}

	// set e.username so that LoginUI never needs to ask for it
	e.username = me.GetName()

	// at this point, there is a user config either for the current user or for e.username
	// and it has a device id, so this should be a provisioned device.  Thus, they should
	// just login normally.

	var afterLogin = func(lctx libkb.LoginContext) error {
		if err := lctx.LocalSession().SetDeviceProvisioned(e.G().Env.GetDeviceID()); err != nil {
			// not a fatal error, session will stay in memory
			e.G().Log.Warning("error saving session file: %s", err)
		}
		return nil
	}
	if err := e.G().LoginState().LoginWithPrompt(e.username, ctx.LoginUI, ctx.SecretUI, afterLogin); err != nil {
		return err
	}

	// login was successful, unlock the device keys
	return e.unlockDeviceKeys(ctx, me)
}
Beispiel #29
0
func (fu FakeUser) NormalizedUsername() libkb.NormalizedUsername {
	return libkb.NewNormalizedUsername(fu.Username)
}