github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/pgp_update.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  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/keybase/client/go/libkb"
    11  )
    12  
    13  type PGPUpdateEngine struct {
    14  	selectedFingerprints   map[string]bool
    15  	all                    bool
    16  	duplicatedFingerprints []libkb.PGPFingerprint
    17  	libkb.Contextified
    18  }
    19  
    20  func NewPGPUpdateEngine(g *libkb.GlobalContext, fingerprints []string, all bool) *PGPUpdateEngine {
    21  	selectedFingerprints := make(map[string]bool)
    22  	for _, fpString := range fingerprints {
    23  		selectedFingerprints[strings.ToLower(fpString)] = true
    24  	}
    25  	return &PGPUpdateEngine{
    26  		selectedFingerprints: selectedFingerprints,
    27  		all:                  all,
    28  		Contextified:         libkb.NewContextified(g),
    29  	}
    30  }
    31  
    32  func (e *PGPUpdateEngine) Name() string {
    33  	return "PGPUpdate"
    34  }
    35  
    36  func (e *PGPUpdateEngine) Prereqs() Prereqs {
    37  	return Prereqs{
    38  		Device: true,
    39  	}
    40  }
    41  
    42  func (e *PGPUpdateEngine) RequiredUIs() []libkb.UIKind {
    43  	return []libkb.UIKind{
    44  		libkb.LogUIKind,
    45  		libkb.SecretUIKind,
    46  	}
    47  }
    48  
    49  func (e *PGPUpdateEngine) SubConsumers() []libkb.UIConsumer {
    50  	return []libkb.UIConsumer{}
    51  }
    52  
    53  func (e *PGPUpdateEngine) Run(m libkb.MetaContext) error {
    54  	if e.all && len(e.selectedFingerprints) > 0 {
    55  		return fmt.Errorf("Cannot use explicit fingerprints with --all.")
    56  	}
    57  
    58  	me, err := libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m))
    59  	if err != nil {
    60  		return err
    61  	}
    62  	fingerprints := me.GetActivePGPFingerprints(false /* not just sibkeys */)
    63  	if len(fingerprints) > 1 && !e.all && len(e.selectedFingerprints) == 0 {
    64  		return fmt.Errorf("You have more than one PGP key. To update all of them, use --all.")
    65  	}
    66  
    67  	gpgCLI := libkb.NewGpgCLI(m.G(), m.UIs().LogUI)
    68  	err = gpgCLI.Configure(m)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	del := libkb.Delegator{
    74  		DelegationType: libkb.DelegationTypePGPUpdate,
    75  		Me:             me,
    76  		Expire:         libkb.KeyExpireIn,
    77  		Contextified:   libkb.NewContextified(e.G()),
    78  	}
    79  
    80  	err = del.LoadSigningKey(m, m.UIs().SecretUI)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	for _, fingerprint := range fingerprints {
    86  		if len(e.selectedFingerprints) > 0 && !e.selectedFingerprints[fingerprint.String()] {
    87  			m.UIs().LogUI.Warning("Skipping update for key %s", fingerprint.String())
    88  			continue
    89  		}
    90  		bundle, err := gpgCLI.ImportKey(m, false /* secret */, fingerprint, "")
    91  		if err != nil {
    92  			_, isNoKey := err.(libkb.NoKeyError)
    93  			if isNoKey {
    94  				m.UIs().LogUI.Warning(
    95  					"No key matching fingerprint %s found in the GPG keyring.",
    96  					fingerprint.String())
    97  				continue
    98  			} else {
    99  				return err
   100  			}
   101  		}
   102  
   103  		bundle.InitGPGKey()
   104  		del.NewKey = bundle
   105  
   106  		m.UIs().LogUI.Info("Posting update for key %s.", fingerprint.String())
   107  		if err := del.Run(m); err != nil {
   108  			if appStatusErr, ok := err.(libkb.AppStatusError); ok && appStatusErr.Code == libkb.SCKeyDuplicateUpdate {
   109  				m.UIs().LogUI.Info("Key was already up to date.")
   110  				e.duplicatedFingerprints = append(e.duplicatedFingerprints, fingerprint)
   111  				continue
   112  			}
   113  			return err
   114  		}
   115  		m.UIs().LogUI.Info("Update succeeded for key %s.", fingerprint)
   116  	}
   117  	return nil
   118  }