github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/pgp_pull_private.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  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/keybase/client/go/libkb"
    11  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    12  )
    13  
    14  type PGPPullPrivate struct {
    15  	arg keybase1.PGPPullPrivateArg
    16  }
    17  
    18  func (e *PGPPullPrivate) Name() string {
    19  	return "PGPPullPrivate"
    20  }
    21  
    22  func (e *PGPPullPrivate) Prereqs() Prereqs {
    23  	return Prereqs{}
    24  }
    25  
    26  func (e *PGPPullPrivate) RequiredUIs() []libkb.UIKind {
    27  	return []libkb.UIKind{}
    28  }
    29  
    30  func (e *PGPPullPrivate) SubConsumers() []libkb.UIConsumer {
    31  	return []libkb.UIConsumer{}
    32  }
    33  
    34  func NewPGPPullPrivate(arg keybase1.PGPPullPrivateArg) *PGPPullPrivate {
    35  	return &PGPPullPrivate{arg}
    36  }
    37  
    38  func (e *PGPPullPrivate) read(m libkb.MetaContext, fs *keybase1.SimpleFSClient, filepath string) (armored string, err error) {
    39  	opid, err := fs.SimpleFSMakeOpid(m.Ctx())
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  	err = fs.SimpleFSOpen(m.Ctx(), keybase1.SimpleFSOpenArg{
    44  		OpID:  opid,
    45  		Dest:  keybase1.NewPathWithKbfsPath(filepath),
    46  		Flags: keybase1.OpenFlags_READ | keybase1.OpenFlags_EXISTING,
    47  	})
    48  	if err != nil {
    49  		return "", fmt.Errorf("pgp key not found; you may need to run `keybase pgp push-private` first (error: %s)", err)
    50  	}
    51  	defer fs.SimpleFSClose(m.Ctx(), opid)
    52  	var offset int64
    53  	bufsize := 64 * 1024
    54  	var data []byte
    55  	for {
    56  		m.Debug("SimpleFS: Reading at %d", offset)
    57  
    58  		content, err := fs.SimpleFSRead(m.Ctx(), keybase1.SimpleFSReadArg{
    59  			OpID:   opid,
    60  			Offset: offset,
    61  			Size:   bufsize,
    62  		})
    63  		if err != nil {
    64  			return "", err
    65  		}
    66  		m.Debug("SimpleFS: Read %d", len(content.Data))
    67  
    68  		if len(content.Data) > 0 {
    69  			offset += int64(len(content.Data))
    70  			data = append(data, content.Data...)
    71  		} else {
    72  			break
    73  		}
    74  	}
    75  	return string(data), nil
    76  }
    77  
    78  func (e *PGPPullPrivate) pull(m libkb.MetaContext, fp libkb.PGPFingerprint, tty string, fs *keybase1.SimpleFSClient) error {
    79  
    80  	username := m.CurrentUsername()
    81  	if username.IsNil() {
    82  		return libkb.NewLoginRequiredError("no username found")
    83  	}
    84  
    85  	filepath := "/private/" + username.String() + "/.keys/pgp/" + fp.String() + ".asc"
    86  
    87  	armored, err := e.read(m, fs, filepath)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	err = m.G().GetGpgClient().ExportKeyArmored(m, armored)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	return nil
    97  }
    98  
    99  func (e *PGPPullPrivate) Run(m libkb.MetaContext) (err error) {
   100  
   101  	defer m.Trace("PGPPullPrivate#Run", &err)()
   102  
   103  	tty, err := m.UIs().GPGUI.GetTTY(m.Ctx())
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	fingerprints, err := getPrivateFingerprints(m, e.arg.Fingerprints)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	if len(fingerprints) == 0 {
   113  		return errors.New("no PGP keys provided")
   114  	}
   115  
   116  	fs, err := simpleFSClient(m)
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	for _, fp := range fingerprints {
   122  		err = e.pull(m, fp, tty, fs)
   123  		if err != nil {
   124  			return err
   125  		}
   126  	}
   127  
   128  	return nil
   129  }