github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/teambot/notify.go (about)

     1  package teambot
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/keybase/client/go/libkb"
     8  	"github.com/keybase/client/go/protocol/keybase1"
     9  )
    10  
    11  func NotifyTeambotEKNeeded(mctx libkb.MetaContext, teamID keybase1.TeamID, generation keybase1.EkGeneration) error {
    12  	return notifyTeambotKeyNeeded(mctx, teamID, keybase1.TeamApplication_CHAT, int(generation), true /* isEphemeral */)
    13  }
    14  
    15  func NotifyTeambotKeyNeeded(mctx libkb.MetaContext, teamID keybase1.TeamID,
    16  	app keybase1.TeamApplication, generation keybase1.TeambotKeyGeneration) error {
    17  	return notifyTeambotKeyNeeded(mctx, teamID, app, int(generation), false /* isEphemeral */)
    18  }
    19  
    20  func notifyTeambotKeyNeeded(mctx libkb.MetaContext, teamID keybase1.TeamID,
    21  	app keybase1.TeamApplication, generation int, isEphemeral bool) (err error) {
    22  	defer mctx.Trace("notifyTeambotKeyNeeded", &err)()
    23  	apiArg := libkb.APIArg{
    24  		Endpoint:    "teambot/key_needed",
    25  		SessionType: libkb.APISessionTypeREQUIRED,
    26  		Args: libkb.HTTPArgs{
    27  			"team_id":      libkb.S{Val: string(teamID)},
    28  			"generation":   libkb.U{Val: uint64(generation)},
    29  			"application":  libkb.I{Val: int(app)},
    30  			"is_ephemeral": libkb.B{Val: isEphemeral},
    31  		},
    32  	}
    33  	_, err = mctx.G().GetAPI().Post(mctx, apiArg)
    34  	return err
    35  }
    36  
    37  const teambotKeyWrongKIDDBVersion = 1
    38  const MaxTeambotKeyWrongKIDPermitted = time.Hour * 24
    39  
    40  func TeambotEKWrongKIDCacheKey(teamID keybase1.TeamID, botUID keybase1.UID,
    41  	generation keybase1.EkGeneration) libkb.DbKey {
    42  	return teambotKeyWrongKIDCacheKey(teamID, botUID, keybase1.TeamApplication_CHAT, int(generation), true /* isEphemeral */)
    43  }
    44  
    45  func TeambotKeyWrongKIDCacheKey(teamID keybase1.TeamID, botUID keybase1.UID,
    46  	generation keybase1.TeambotKeyGeneration, app keybase1.TeamApplication) libkb.DbKey {
    47  	return teambotKeyWrongKIDCacheKey(teamID, botUID, app, int(generation), false /* isEphemeral */)
    48  }
    49  
    50  func teambotKeyWrongKIDCacheKey(teamID keybase1.TeamID, botUID keybase1.UID,
    51  	app keybase1.TeamApplication, generation int, isEphemeral bool) libkb.DbKey {
    52  	prefix := "TeambotKey"
    53  	if isEphemeral {
    54  		prefix = "TeambotEK"
    55  	}
    56  	key := fmt.Sprintf("%sWrongKID-%s-%s-%d-%d-%d", prefix, teamID, botUID,
    57  		app, generation, teambotKeyWrongKIDDBVersion)
    58  	return libkb.DbKey{
    59  		Typ: libkb.DBTeambotKeyWrongKID,
    60  		Key: key,
    61  	}
    62  }
    63  
    64  func TeambotEKWrongKIDPermitted(mctx libkb.MetaContext, teamID keybase1.TeamID,
    65  	botUID keybase1.UID, generation keybase1.EkGeneration, now keybase1.Time) (bool, keybase1.Time, error) {
    66  	return teambotKeyWrongKIDPermitted(mctx, teamID, botUID,
    67  		keybase1.TeamApplication_CHAT, int(generation), now, true /* isEphemeral */)
    68  }
    69  
    70  func TeambotKeyWrongKIDPermitted(mctx libkb.MetaContext, teamID keybase1.TeamID,
    71  	botUID keybase1.UID, app keybase1.TeamApplication,
    72  	generation keybase1.TeambotKeyGeneration, now keybase1.Time) (bool, keybase1.Time, error) {
    73  	return teambotKeyWrongKIDPermitted(mctx, teamID, botUID,
    74  		app, int(generation), now, false /* isEphemeral */)
    75  }
    76  
    77  // teambotKeyWrongKIDPermitted checks if we can use a teambot key which is signed by
    78  // an old PTK. Since bot members cannot create a new keys, we allow old
    79  // signatures to be used for a short window, allowing a member to generate a
    80  // new key signed by the latest PTK.
    81  func teambotKeyWrongKIDPermitted(mctx libkb.MetaContext, teamID keybase1.TeamID,
    82  	botUID keybase1.UID, app keybase1.TeamApplication, generation int,
    83  	now keybase1.Time, isEphemeral bool) (bool, keybase1.Time, error) {
    84  	key := teambotKeyWrongKIDCacheKey(teamID, botUID, app, generation, isEphemeral)
    85  	var ctime keybase1.Time
    86  	found, err := mctx.G().GetKVStore().GetInto(&ctime, key)
    87  	if err != nil {
    88  		return false, 0, err
    89  	}
    90  	if !found {
    91  		// Store when we first noticed wrongKID was set.
    92  		err = mctx.G().GetKVStore().PutObj(key, nil, now)
    93  		return true, 0, err
    94  	}
    95  	return now.Time().Sub(ctime.Time()) < MaxTeambotKeyWrongKIDPermitted, ctime, nil
    96  }