1// Package cli implements a GPG CLI crypto backend. 2package cli 3 4import ( 5 "context" 6 "os" 7 8 "github.com/gopasspw/gopass/internal/backend/crypto/gpg" 9 "github.com/gopasspw/gopass/pkg/debug" 10 lru "github.com/hashicorp/golang-lru" 11) 12 13var ( 14 // defaultArgs contains the default GPG args for non-interactive use. Note: Do not use '--batch' 15 // as this will disable (necessary) passphrase questions! 16 defaultArgs = []string{"--quiet", "--yes", "--compress-algo=none", "--no-encrypt-to", "--no-auto-check-trustdb"} 17 // Ext is the file extension used by this backend 18 Ext = "gpg" 19 // IDFile is the name of the recipients file used by this backend 20 IDFile = ".gpg-id" 21) 22 23// GPG is a gpg wrapper 24type GPG struct { 25 binary string 26 args []string 27 pubKeys gpg.KeyList 28 privKeys gpg.KeyList 29 listCache *lru.TwoQueueCache 30 throwKids bool 31} 32 33// Config is the gpg wrapper config 34type Config struct { 35 Binary string 36 Args []string 37 Umask int 38} 39 40// New creates a new GPG wrapper 41func New(ctx context.Context, cfg Config) (*GPG, error) { 42 // ensure created files don't have group or world perms set 43 // this setting should be inherited by sub-processes 44 umask(cfg.Umask) 45 46 // make sure GPG_TTY is set (if possible) 47 if gt := os.Getenv("GPG_TTY"); gt == "" { 48 if t := tty(); t != "" { 49 _ = os.Setenv("GPG_TTY", t) 50 } 51 } 52 53 gcfg, err := gpgConfig() 54 if err != nil { 55 debug.Log("failed to read GPG config: %s", err) 56 } 57 _, throwKids := gcfg["throw-keyids"] 58 59 g := &GPG{ 60 binary: "gpg", 61 args: append(defaultArgs, cfg.Args...), 62 throwKids: throwKids, 63 } 64 65 debug.Log("initializing LRU cache") 66 cache, err := lru.New2Q(1024) 67 if err != nil { 68 return nil, err 69 } 70 g.listCache = cache 71 debug.Log("LRU cache initialized") 72 73 debug.Log("detecting binary") 74 bin, err := Binary(ctx, cfg.Binary) 75 if err != nil { 76 return nil, err 77 } 78 g.binary = bin 79 debug.Log("binary detected") 80 81 return g, nil 82} 83 84// Initialized always returns nil 85func (g *GPG) Initialized(ctx context.Context) error { 86 return nil 87} 88 89// Name returns gpg 90func (g *GPG) Name() string { 91 return "gpg" 92} 93 94// Ext returns gpg 95func (g *GPG) Ext() string { 96 return Ext 97} 98 99// IDFile returns .gpg-id 100func (g *GPG) IDFile() string { 101 return IDFile 102} 103 104// Concurrency returns 1 to avoid concurrency issues 105// with many GPG setups. 106func (g *GPG) Concurrency() int { 107 return 1 108} 109