forked from keybase/client
/
passphrase_state.go
107 lines (92 loc) · 3.59 KB
/
passphrase_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright 2019 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package libkb
import (
"fmt"
"time"
"github.com/keybase/client/go/protocol/keybase1"
)
func randomPassphraseToState(hasRandomPassphrase bool) keybase1.PassphraseState {
if hasRandomPassphrase {
return keybase1.PassphraseState_RANDOM
}
return keybase1.PassphraseState_KNOWN
}
func LoadPassphraseState(mctx MetaContext) (passphraseState keybase1.PassphraseState, err error) {
return LoadPassphraseStateWithForceRepoll(mctx)
}
// forceRepoll only forces repoll when the state is RANDOM, but not when it is KNOWN.
func LoadPassphraseStateWithForceRepoll(mctx MetaContext) (passphraseState keybase1.PassphraseState, err error) {
mctx = mctx.WithLogTag("PPSTATE")
defer mctx.Trace(fmt.Sprintf("LoadPassphraseState()"), &err)()
// If we're in standalone mode, we don't get the gregor msg about
// passphrase_state changes. So, force a repoll to the server if the state
// isn't currently KNOWN.
forceRepoll := mctx.G().GregorListener == nil
if len(mctx.G().Env.GetUsername().String()) == 0 {
mctx.Debug("LoadPassphraseState: user is not logged in")
return passphraseState, NewLoginRequiredError("LoadPassphraseState")
}
configState := mctx.G().Env.GetConfig().GetPassphraseState()
if configState != nil {
mctx.Debug("LoadPassphraseState: state found in config.json: %#v", configState)
if !forceRepoll || *configState == keybase1.PassphraseState_KNOWN {
return *configState, nil
}
}
mctx.Debug("LoadPassphraseState: state not found in config.json; checking legacy leveldb")
legacyState, err := loadPassphraseStateFromLegacy(mctx)
if err == nil {
mctx.Debug("LoadPassphraseState: state found in legacy leveldb: %#v", legacyState)
MaybeSavePassphraseState(mctx, legacyState)
if !forceRepoll || legacyState == keybase1.PassphraseState_KNOWN {
return legacyState, nil
}
}
mctx.Debug("LoadPassphraseState: could not find state in legacy leveldb (%s); checking remote", err)
remoteState, err := LoadPassphraseStateFromRemote(mctx)
if err == nil {
MaybeSavePassphraseState(mctx, remoteState)
return remoteState, nil
}
return passphraseState, fmt.Errorf("failed to load passphrase state from any path, including remote: %s", err)
}
func MaybeSavePassphraseState(mctx MetaContext, passphraseState keybase1.PassphraseState) {
err := mctx.G().Env.GetConfigWriter().SetPassphraseState(passphraseState)
if err == nil {
mctx.Debug("Added PassphraseState=%#v to config file", passphraseState)
} else {
mctx.Warning("Failed to save passphraseState=%#v to config file: %s", passphraseState, err)
}
}
func loadPassphraseStateFromLegacy(mctx MetaContext) (passphraseState keybase1.PassphraseState, err error) {
currentUID := mctx.CurrentUID()
cacheKey := DbKey{
Typ: DBLegacyHasRandomPW,
Key: currentUID.String(),
}
var hasRandomPassphrase bool
found, err := mctx.G().GetKVStore().GetInto(&hasRandomPassphrase, cacheKey)
if err != nil {
return passphraseState, err
}
if !found {
return passphraseState, fmt.Errorf("passphrase state not found in leveldb")
}
return randomPassphraseToState(hasRandomPassphrase), nil
}
func LoadPassphraseStateFromRemote(mctx MetaContext) (passphraseState keybase1.PassphraseState, err error) {
var ret struct {
AppStatusEmbed
RandomPassphrase bool `json:"random_pw"`
}
err = mctx.G().API.GetDecode(mctx, APIArg{
Endpoint: "user/has_random_pw",
SessionType: APISessionTypeREQUIRED,
InitialTimeout: 10 * time.Second,
}, &ret)
if err != nil {
return passphraseState, err
}
return randomPassphraseToState(ret.RandomPassphrase), nil
}