github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/saltpack_sender_identify.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package engine 5 6 import ( 7 "github.com/keybase/client/go/libkb" 8 keybase1 "github.com/keybase/client/go/protocol/keybase1" 9 ) 10 11 type SaltpackSenderIdentifyArg struct { 12 publicKey keybase1.KID 13 isAnon bool 14 interactive bool 15 forceRemoteCheck bool 16 reason keybase1.IdentifyReason 17 userAssertion string // optional 18 } 19 20 type SaltpackSenderIdentify struct { 21 libkb.Contextified 22 arg *SaltpackSenderIdentifyArg 23 res keybase1.SaltpackSender 24 } 25 26 func (e *SaltpackSenderIdentify) Name() string { 27 return "SaltpackSenderIdentify" 28 } 29 30 func NewSaltpackSenderIdentify(g *libkb.GlobalContext, arg *SaltpackSenderIdentifyArg) *SaltpackSenderIdentify { 31 return &SaltpackSenderIdentify{ 32 Contextified: libkb.NewContextified(g), 33 arg: arg, 34 } 35 } 36 37 // GetPrereqs returns the engine prereqs. 38 func (e *SaltpackSenderIdentify) Prereqs() Prereqs { 39 return Prereqs{} 40 } 41 42 // RequiredUIs returns the required UIs. 43 func (e *SaltpackSenderIdentify) RequiredUIs() []libkb.UIKind { 44 return []libkb.UIKind{} 45 } 46 47 // SubConsumers returns the other UI consumers for this engine. 48 func (e *SaltpackSenderIdentify) SubConsumers() []libkb.UIConsumer { 49 return []libkb.UIConsumer{ 50 &Identify2WithUID{}, 51 } 52 } 53 54 func (e *SaltpackSenderIdentify) Run(m libkb.MetaContext) (err error) { 55 defer m.Trace("SaltpackSenderIdentify::Run", &err)() 56 57 if e.arg.isAnon { 58 e.res.SenderType = keybase1.SaltpackSenderType_ANONYMOUS 59 return 60 } 61 62 // Essentially nothing that this key/basics.json endpoint tells us is 63 // verifiable. Don't even retain the username it gives us here; we'll get 64 // it from LoadUser instead, where we check some of the server's work. 65 // 66 // Security note: This is an opportunity for the server to maliciously DOS 67 // us, by lying and saying a key doesn't exist. If we wanted to really 68 // prevent this, we could include a KID->UID index in the Merkle tree that 69 // we pin against the bitcoin blockchain, and trust that Someone Out There 70 // would audit it for consistency with the main body of the tree. File this 71 // one away in the Book of Things We Would Do With Infinite Time and Money. 72 var maybeUID keybase1.UID 73 _, maybeUID, err = libkb.KeyLookupKIDIncludingRevoked(m, e.arg.publicKey) 74 if _, ok := err.(libkb.NotFoundError); ok { 75 // The key in question might not be a Keybase key at all (for example, 76 // anything generated with the Python saltpack implementation, which 77 // isn't Keybase-aware). In that case we'll get this NotFoundError, and 78 // we can just report it as an unknown sender. 79 e.res.SenderType = keybase1.SaltpackSenderType_UNKNOWN 80 err = nil 81 return 82 } else if err != nil { 83 return 84 } 85 86 loadUserArg := libkb.NewLoadUserArgWithMetaContext(m).WithUID(maybeUID) 87 var user *libkb.User 88 user, err = libkb.LoadUser(loadUserArg) 89 if err != nil { 90 return 91 } 92 93 // Use the ComputedKeyFamily assembled by LoadUser to get the status of the 94 // key we started with. (This is where we'll detect corner cases like the 95 // server straight up lying about who owns a given key. An inconsistency 96 // like that will be an error here.) 97 var maybeSenderType *keybase1.SaltpackSenderType 98 maybeSenderType, err = user.GetComputedKeyFamily().GetSaltpackSenderTypeIfInactive(e.arg.publicKey) 99 if err != nil { 100 return 101 } 102 103 // At this point, since GetSaltpackSenderTypeOrActive has not returned an 104 // error, we can consider the UID/username returned by the server to be 105 // "mostly legit". It's still possible that the signing key might be 106 // revoked (this sort of thing is indicated by a non-nil sender type, which 107 // we check for now) or the identify that comes next could report a broken 108 // tracking statement, but those are states that we'll report to the user, 109 // as opposed to unexpected failures or corner case server lies. 110 e.res.Uid = user.GetUID() 111 e.res.Username = user.GetName() 112 e.res.Fullname, err = libkb.GetFullName(m, user.GetUID()) 113 if err != nil { 114 return err 115 } 116 if maybeSenderType != nil { 117 e.res.SenderType = *maybeSenderType 118 return 119 } 120 121 // The key is active! This is the happy path. We'll do an identify and show 122 // it to the user, and the SenderType will follow from that. 123 err = e.identifySender(m) 124 125 return 126 } 127 128 func (e *SaltpackSenderIdentify) identifySender(m libkb.MetaContext) (err error) { 129 defer m.Trace("SaltpackDecrypt::identifySender", &err)() 130 131 var lin bool 132 var uid keybase1.UID 133 if lin, uid = isLoggedIn(m); lin && uid.Equal(e.res.Uid) { 134 e.res.SenderType = keybase1.SaltpackSenderType_SELF 135 if len(e.arg.userAssertion) == 0 { 136 m.Debug("| Sender is self") 137 return nil 138 } 139 } 140 141 iarg := keybase1.Identify2Arg{ 142 Uid: e.res.Uid, 143 UseDelegateUI: !e.arg.interactive, 144 AlwaysBlock: e.arg.interactive, 145 ForceRemoteCheck: e.arg.forceRemoteCheck, 146 NeedProofSet: true, 147 NoErrorOnTrackFailure: true, 148 Reason: e.arg.reason, 149 UserAssertion: e.arg.userAssertion, 150 IdentifyBehavior: keybase1.TLFIdentifyBehavior_SALTPACK, 151 } 152 eng := NewIdentify2WithUID(e.G(), &iarg) 153 if err = RunEngine2(m, eng); err != nil { 154 return err 155 } 156 157 if e.res.SenderType == keybase1.SaltpackSenderType_SELF { 158 // if we already know the sender type, then return now 159 return nil 160 } 161 162 switch eng.getTrackType() { 163 case identify2NoTrack: 164 e.res.SenderType = keybase1.SaltpackSenderType_NOT_TRACKED 165 case identify2TrackOK: 166 e.res.SenderType = keybase1.SaltpackSenderType_TRACKING_OK 167 case identify2TrackBroke: 168 e.res.SenderType = keybase1.SaltpackSenderType_TRACKING_BROKE 169 default: 170 panic("unexpected track type") 171 } 172 return nil 173 } 174 175 func (e *SaltpackSenderIdentify) Result() keybase1.SaltpackSender { 176 return e.res 177 }