forked from keybase/client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
revoke.go
154 lines (135 loc) · 3.48 KB
/
revoke.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package engine
import (
"fmt"
"github.com/keybase/client/go/libkb"
keybase1 "github.com/keybase/client/go/protocol"
)
type RevokeMode int
const (
RevokeKey RevokeMode = iota
RevokeDevice
)
type RevokeEngine struct {
libkb.Contextified
deviceID keybase1.DeviceID
kidString string
mode RevokeMode
force bool
}
type RevokeDeviceEngineArgs struct {
ID keybase1.DeviceID
Force bool
}
func NewRevokeDeviceEngine(args RevokeDeviceEngineArgs, g *libkb.GlobalContext) *RevokeEngine {
return &RevokeEngine{
deviceID: args.ID,
mode: RevokeDevice,
force: args.Force,
Contextified: libkb.NewContextified(g),
}
}
func NewRevokeKeyEngine(kid string, g *libkb.GlobalContext) *RevokeEngine {
return &RevokeEngine{
kidString: kid,
mode: RevokeKey,
Contextified: libkb.NewContextified(g),
}
}
func (e *RevokeEngine) Name() string {
return "Revoke"
}
func (e *RevokeEngine) Prereqs() Prereqs {
return Prereqs{
Device: true,
}
}
func (e *RevokeEngine) RequiredUIs() []libkb.UIKind {
return []libkb.UIKind{
libkb.LogUIKind,
libkb.SecretUIKind,
}
}
func (e *RevokeEngine) SubConsumers() []libkb.UIConsumer {
return []libkb.UIConsumer{}
}
func (e *RevokeEngine) getKIDsToRevoke(me *libkb.User) ([]keybase1.KID, error) {
if e.mode == RevokeDevice {
deviceKeys, err := me.GetComputedKeyFamily().GetAllActiveKeysForDevice(e.deviceID)
if err != nil {
return nil, err
}
return deviceKeys, nil
} else if e.mode == RevokeKey {
kid := keybase1.KIDFromString(e.kidString)
key, err := me.GetComputedKeyFamily().FindKeyWithKIDUnsafe(kid)
if err != nil {
return nil, err
}
if !libkb.IsPGP(key) {
return nil, fmt.Errorf("Key %s is not a PGP key. To revoke device keys, use the `device remove` command.", e.kidString)
}
for _, activePGPKey := range me.GetComputedKeyFamily().GetActivePGPKeys(false /* sibkeys only */) {
if activePGPKey.GetKID().Equal(kid) {
return []keybase1.KID{kid}, nil
}
}
return nil, fmt.Errorf("PGP key %s is not active", e.kidString)
} else {
return nil, fmt.Errorf("Unknown revoke mode: %d", e.mode)
}
}
func (e *RevokeEngine) Run(ctx *Context) error {
currentDevice := e.G().Env.GetDeviceID()
var deviceID keybase1.DeviceID
if e.mode == RevokeDevice {
deviceID = e.deviceID
if e.deviceID == currentDevice && !e.force {
return fmt.Errorf("Can't revoke the current device.")
}
}
me, err := libkb.LoadMe(libkb.NewLoadUserArg(e.G()))
if err != nil {
return err
}
kidsToRevoke, err := e.getKIDsToRevoke(me)
if err != nil {
return err
}
ctx.LogUI.Info("Revoking KIDs:")
for _, kid := range kidsToRevoke {
ctx.LogUI.Info(" %s", kid)
}
sigKey, err := e.G().Keyrings.GetSecretKeyWithPrompt(ctx.LoginContext, libkb.SecretKeyArg{
Me: me,
KeyType: libkb.DeviceSigningKeyType,
}, ctx.SecretUI, "to revoke another key")
if err != nil {
return err
}
if err = sigKey.CheckSecretKey(); err != nil {
return err
}
proof, err := me.RevokeKeysProof(sigKey, kidsToRevoke, deviceID)
if err != nil {
return err
}
sig, _, _, err := libkb.SignJSON(proof, sigKey)
if err != nil {
return err
}
kid := sigKey.GetKID()
_, err = e.G().API.Post(libkb.APIArg{
Endpoint: "sig/revoke",
NeedSession: true,
Args: libkb.HTTPArgs{
"signing_kid": libkb.S{Val: kid.String()},
"sig": libkb.S{Val: sig},
},
})
if err != nil {
return err
}
return nil
}