forked from keybase/client
/
cmd_passphrase_recover.go
139 lines (116 loc) · 3.71 KB
/
cmd_passphrase_recover.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package client
import (
"errors"
"golang.org/x/net/context"
"github.com/keybase/cli"
"github.com/keybase/client/go/libcmdline"
"github.com/keybase/client/go/libkb"
"github.com/keybase/go-framed-msgpack-rpc/rpc"
)
type CmdPassphraseRecover struct {
libkb.Contextified
}
func NewCmdPassphraseRecover(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
return cli.Command{
Name: "recover",
Usage: "Recover your keybase account passphrase",
Action: func(c *cli.Context) {
cl.ChooseCommand(NewCmdPassphraseRecoverRunner(g), "recover", c)
},
}
}
func NewCmdPassphraseRecoverRunner(g *libkb.GlobalContext) *CmdPassphraseRecover {
return &CmdPassphraseRecover{
Contextified: libkb.NewContextified(g),
}
}
func (c *CmdPassphraseRecover) Run() error {
ui := c.G().UI.GetTerminalUI()
protocols := []rpc.Protocol{
NewSecretUIProtocol(c.G()),
}
if err := RegisterProtocolsWithContext(protocols, c.G()); err != nil {
return err
}
// Check that there is a UID.
// This a proxy for whether this device has been provisioned for the recoverer.
uid := c.G().GetMyUID()
if !uid.Exists() {
return c.errNoUID()
}
// Login with unlocked keys or a prompted paper key.
err := c.loginWithPaperKey(context.TODO())
switch err.(type) {
case libkb.InputCanceledError:
return c.errLockedKeys()
}
if err != nil {
return err
}
// Check whether the user would lose server-stored encrypted PGP keys.
// (bug) This will return true even if those keys are already lost.
hsk, err := hasServerKeys(c.G())
if err != nil {
return err
}
// Confirm with the user.
ui.Printf("Password recovery will put your account on probation for 5 days.\n")
ui.Printf("You won't be able to perform certain actions, like revoking devices.\n")
if hsk.HasServerKeys {
ui.Printf("You have uploaded an encrypted PGP private key, it will be lost.\n")
}
err = ui.PromptForConfirmation("Continue with password recovery?")
if err != nil {
return err
}
// Ask for the new passphase.
pp, err := PromptNewPassphrase(c.G())
if err != nil {
return err
}
// Run the main recovery engine.At this point the user should be logged in with
// unlocked keys. This has the potential to issue all sorts of prompts
// but given that we should now be logged in and unlocked, it shouldn't
// issue any prompts.
return passphraseChange(c.G(), newChangeArg(pp, true))
// BUG the user sometimes ends up recovered and unlocked, but logged out after all this.
// Running `keybase login` or restarting the service both effortlessly log them in.
}
func (c *CmdPassphraseRecover) loginWithPaperKey(ctx context.Context) error {
// TODO How can we be sure here that a missing SecretUI isn't going to cause a panic?
client, err := GetLoginClient(c.G())
if err != nil {
return err
}
err = client.LoginWithPaperKey(ctx, 0)
if err != nil {
return err
}
return err
}
func (c *CmdPassphraseRecover) ParseArgv(ctx *cli.Context) error {
return nil
}
func (c *CmdPassphraseRecover) GetUsage() libkb.Usage {
return libkb.Usage{
Config: true,
API: true,
KbKeyring: true,
}
}
func (c *CmdPassphraseRecover) errNoUID() error {
return errors.New(`Can't recover without a UID.
If you have not provisioned this device before but do have
your paper key, try running: keybase login
`)
}
func (c *CmdPassphraseRecover) errLockedKeys() error {
return errors.New(`Cannot unlock device keys.
These device keys are locked and you did not enter a paper key.
To change your forgotten passphrase you will need either a device
with unlocked keys or your paper key.
If you'd like to reset your account: https://keybase.io/#account-reset
`)
}