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  }