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