Merge pull request #256 from qrwteyrutiyoup/keys

Updates on PGP keys
This commit is contained in:
Morgana 2018-03-18 22:08:53 +00:00 committed by GitHub
commit aedbe04b04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 44 deletions

View File

@ -68,7 +68,7 @@ _yay() {
s u')
common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile
noconfirm noprogressbar noscriptlet quiet save mflags buildir editor
makepkg pacman tar git config requestsplitn sudoloop nosudoloop
makepkg pacman tar git gpg gpgflags config requestsplitn sudoloop nosudoloop
redownload noredownload redownloadall root verbose' 'b d h q r v')
core=('database files help query remove sync upgrade version' 'D F Q R S U V h')

9
cmd.go
View File

@ -46,6 +46,7 @@ Permanent configuration options:
--pacman <file> pacman command to use
--tar <file> bsdtar command to use
--git <file> git command to use
--gpg <file> gpg command to use
--config <file> pacman.conf file to use
--requestsplitn <n> Max amount of packages to query per AUR request
@ -63,9 +64,10 @@ Permanent configuration options:
--noredownload Skip pkgbuild download if in cache and up to date
--rebuild Always build target packages
--rebuildall Always build all AUR packages
--rebuildtree Always build all AUR packages even if installed
--rebuildtree Always build all AUR packages even if installed
--norebuild Skip package build if in cache and up to date
--mflags <flags> Pass arguments to makepkg
--gpgflags <flags> Pass arguments to gpg
--sudoloop Loop sudo calls in the background to avoid timeout
--nosudoloop Do not loop sudo calls in the background
@ -202,7 +204,6 @@ func initAlpm() (err error) {
alpmConf.IgnoreGroup = append(alpmConf.IgnoreGroup, strings.Split(value, ",")...)
}
//TODO
//current system does not allow duplicate arguments
//but pacman allows multiple cachdirs to be passed
@ -411,6 +412,8 @@ func handleConfig(option, value string) bool {
config.ReBuild = "tree"
case "norebuild":
config.ReBuild = "no"
case "gpgflags":
config.GpgFlags = value
case "mflags":
config.MFlags = value
case "builddir":
@ -425,6 +428,8 @@ func handleConfig(option, value string) bool {
config.TarBin = value
case "git":
config.GitBin = value
case "gpg":
config.GpgBin = value
case "requestsplitn":
n, err := strconv.Atoi(value)
if err == nil && n > 0 {

View File

@ -35,6 +35,7 @@ type Configuration struct {
ReBuild string `json:"rebuild"`
GitBin string `json:"gitbin"`
GpgBin string `json:"gpgbin"`
GpgFlags string `json:"gpgflags"`
MFlags string `json:"mflags"`
RequestSplitN int `json:"requestsplitn"`
SearchMode int `json:"-"`
@ -127,6 +128,7 @@ func defaultSettings(config *Configuration) {
config.NoConfirm = false
config.PacmanBin = "pacman"
config.PacmanConf = "/etc/pacman.conf"
config.GpgFlags = ""
config.MFlags = ""
config.SortMode = BottomUp
config.SudoLoop = false

View File

@ -214,7 +214,7 @@ func install(parser *arguments) error {
return nil
}
err = checkPgpKeys(dc.Aur, dc.Bases, nil)
err = checkPgpKeys(dc.Aur, dc.Bases)
if err != nil {
return err
}

22
keys.go
View File

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
"path"
"strings"
rpc "github.com/mikkeloscar/aur"
@ -40,19 +41,17 @@ func (set pgpKeySet) get(key string) bool {
}
// checkPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
// asks the user whether yay should try to import them. gpgExtraArgs are extra
// parameters to pass to gpg, in order to facilitate testing, such as using a
// different keyring. It can be nil.
func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, gpgExtraArgs []string) error {
// asks the user whether yay should try to import them.
func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error {
// Let's check the keys individually, and then we can offer to import
// the problematic ones.
problematic := make(pgpKeySet)
args := append(gpgExtraArgs, "--list-keys")
args := append(strings.Fields(config.GpgFlags), "--list-keys")
// Mapping all the keys.
for _, pkg := range pkgs {
dir := config.BuildDir + pkg.PackageBase + "/"
pkgbuild, err := gopkg.ParseSRCINFO(dir + ".SRCINFO")
srcinfo := path.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO")
pkgbuild, err := gopkg.ParseSRCINFO(srcinfo)
if err != nil {
return fmt.Errorf("%s: %s", pkg.Name, err)
}
@ -83,16 +82,15 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, gpgExtraArgs []s
return err
}
if continueTask(question, "nN") {
return importKeys(gpgExtraArgs, problematic.toSlice())
return importKeys(problematic.toSlice())
}
return nil
}
// importKeys tries to import the list of keys specified in its argument. As
// in checkGpgKeys, gpgExtraArgs are extra parameters to pass to gpg.
func importKeys(gpgExtraArgs, keys []string) error {
args := append(gpgExtraArgs, "--recv-keys")
// importKeys tries to import the list of keys specified in its argument.
func importKeys(keys []string) error {
args := append(strings.Fields(config.GpgFlags), "--recv-keys")
cmd := exec.Command(config.GpgBin, append(args, keys...)...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr

View File

@ -1,9 +1,11 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"testing"
rpc "github.com/mikkeloscar/aur"
@ -18,13 +20,29 @@ func newSplitPkg(basename, name string) *rpc.Pkg {
return &rpc.Pkg{Name: name, PackageBase: basename}
}
func initTestKeyring() (string, error) {
config.GpgBin = "gpg"
tmpdir, err := ioutil.TempDir("/tmp", "yay-test-keyring")
if err != nil {
return "", err
func createSrcinfo(pkgbase, srcinfoData string) error {
dir := path.Join(config.BuildDir, pkgbase)
if err := os.Mkdir(dir, 0755); err != nil {
return err
}
return tmpdir, nil
return ioutil.WriteFile(path.Join(dir, ".SRCINFO"), []byte(srcinfoData), 0666)
}
func createDummyPkg(pkgbase string, keys []string, split []string) string {
var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("pkgbase = %s\n\tpkgver = 42\n\tarch = x86_64\n", pkgbase))
// Keys.
for _, k := range keys {
buffer.WriteString(fmt.Sprintf("validpgpkeys = %s\n", k))
}
buffer.WriteString(fmt.Sprintf("\npkgname = %s\n", pkgbase))
for _, s := range split {
buffer.WriteString(fmt.Sprintf("\npkgname = %s%s\n", pkgbase, s))
}
return buffer.String()
}
func TestFormatKeysToImport(t *testing.T) {
@ -116,14 +134,16 @@ func TestFormatKeysToImport(t *testing.T) {
}
func TestImportKeys(t *testing.T) {
keyring, err := initTestKeyring()
keyringDir, err := ioutil.TempDir("/tmp", "yay-test-keyring")
if err != nil {
t.Fatalf("Unable to init test keyring %q: %v\n", keyring, err)
t.Fatalf("Unable to init test keyring %q: %v\n", keyringDir, err)
}
// Removing the leftovers.
defer os.RemoveAll(keyring)
keyringArgs := []string{"--homedir", keyring}
defer os.RemoveAll(keyringDir)
config.GpgBin = "gpg"
config.GpgFlags = fmt.Sprintf("--homedir %s", keyringDir)
casetests := []struct {
keys []string
@ -163,7 +183,7 @@ func TestImportKeys(t *testing.T) {
}
for _, tt := range casetests {
err := importKeys(keyringArgs, tt.keys)
err := importKeys(tt.keys)
if !tt.wantError {
if err != nil {
t.Fatalf("Got error %q, want no error", err)
@ -178,14 +198,40 @@ func TestImportKeys(t *testing.T) {
}
func TestCheckPgpKeys(t *testing.T) {
keyring, err := initTestKeyring()
keyringDir, err := ioutil.TempDir("/tmp", "yay-test-keyring")
if err != nil {
t.Fatalf("Unable to init test keyring %q: %v\n", keyring, err)
t.Fatalf("Unable to init test keyring: %v\n", err)
}
defer os.RemoveAll(keyringDir)
buildDir, err := ioutil.TempDir("/tmp", "yay-test-build-dir")
if err != nil {
t.Fatalf("Unable to init temp build dir: %v\n", err)
}
defer os.RemoveAll(buildDir)
config.BuildDir = buildDir
config.GpgBin = "gpg"
config.GpgFlags = fmt.Sprintf("--homedir %s", keyringDir)
// Creating the dummy package data used in the tests.
dummyData := map[string]string{
"cower": createDummyPkg("cower", []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}, nil),
"libc++": createDummyPkg("libc++", []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}, []string{"abi", "experimental"}),
"dummy-1": createDummyPkg("dummy-1", []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}, nil),
"dummy-2": createDummyPkg("dummy-2", []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}, nil),
"dummy-3": createDummyPkg("dummy-3", []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}, nil),
"dummy-4": createDummyPkg("dummy-4", []string{"11E521D646982372EB577A1F8F0871F202119294"}, nil),
"dummy-5": createDummyPkg("dummy-5", []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}, nil),
"dummy-6": createDummyPkg("dummy-6", []string{"THIS-SHOULD-FAIL"}, nil),
"dummy-7": createDummyPkg("dummy-7", []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}, nil),
}
// Removing the leftovers.
defer os.RemoveAll(keyring)
keyringArgs := []string{"--homedir", keyring}
for pkgbase, srcinfoData := range dummyData {
if err = createSrcinfo(pkgbase, srcinfoData); err != nil {
t.Fatalf("Unable to create dummy data for package %q: %v\n", pkgbase, err)
}
}
casetests := []struct {
pkgs []*rpc.Pkg
@ -197,7 +243,6 @@ func TestCheckPgpKeys(t *testing.T) {
// 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner.
{
pkgs: []*rpc.Pkg{newPkg("cower")},
srcinfos: map[string]*gopkg.PKGBUILD{"cower": &gopkg.PKGBUILD{Pkgbase: "cower", Validpgpkeys: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}}},
bases: map[string][]*rpc.Pkg{"cower": {newPkg("cower")}},
wantError: false,
},
@ -206,7 +251,6 @@ func TestCheckPgpKeys(t *testing.T) {
// B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.
{
pkgs: []*rpc.Pkg{newPkg("libc++")},
srcinfos: map[string]*gopkg.PKGBUILD{"libc++": &gopkg.PKGBUILD{Pkgbase: "libc++", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}}},
bases: map[string][]*rpc.Pkg{"libc++": {newPkg("libc++")}},
wantError: false,
},
@ -214,7 +258,6 @@ func TestCheckPgpKeys(t *testing.T) {
// ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds.
{
pkgs: []*rpc.Pkg{newPkg("dummy-1"), newPkg("dummy-2")},
srcinfos: map[string]*gopkg.PKGBUILD{"dummy-1": &gopkg.PKGBUILD{Pkgbase: "dummy-1", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}, "dummy-2": &gopkg.PKGBUILD{Pkgbase: "dummy-2", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}},
bases: map[string][]*rpc.Pkg{"dummy-1": {newPkg("dummy-1")}, "dummy-2": {newPkg("dummy-2")}},
wantError: false,
},
@ -224,36 +267,32 @@ func TestCheckPgpKeys(t *testing.T) {
// C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.
{
pkgs: []*rpc.Pkg{newPkg("dummy-3")},
srcinfos: map[string]*gopkg.PKGBUILD{"dummy-3": &gopkg.PKGBUILD{Pkgbase: "dummy-3", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}},
bases: map[string][]*rpc.Pkg{"dummy-3": {newPkg("dummy-3")}},
wantError: false,
},
// Two dummy packages with existing keys.
{
pkgs: []*rpc.Pkg{newPkg("dummy-4"), newPkg("dummy-5")},
srcinfos: map[string]*gopkg.PKGBUILD{"dummy-4": &gopkg.PKGBUILD{Pkgbase: "dummy-4", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294"}}, "dummy-5": &gopkg.PKGBUILD{Pkgbase: "dummy-5", Validpgpkeys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}},
bases: map[string][]*rpc.Pkg{"dummy-4": {newPkg("dummy-4")}, "dummy-5": {newPkg("dummy-5")}},
wantError: false,
},
// Dummy package with invalid key, should fail.
{
pkgs: []*rpc.Pkg{newPkg("dummy-7")},
srcinfos: map[string]*gopkg.PKGBUILD{"dummy-7": &gopkg.PKGBUILD{Pkgbase: "dummy-7", Validpgpkeys: []string{"THIS-SHOULD-FAIL"}}},
bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}},
pkgs: []*rpc.Pkg{newPkg("dummy-6")},
bases: map[string][]*rpc.Pkg{"dummy-6": {newPkg("dummy-6")}},
wantError: true,
},
// Dummy package with both an invalid an another valid key, should fail.
// A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler.
{
pkgs: []*rpc.Pkg{newPkg("dummy-8")},
srcinfos: map[string]*gopkg.PKGBUILD{"dummy-8": &gopkg.PKGBUILD{Pkgbase: "dummy-8", Validpgpkeys: []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}}},
bases: map[string][]*rpc.Pkg{"dummy-8": {newPkg("dummy-8")}},
pkgs: []*rpc.Pkg{newPkg("dummy-7")},
bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}},
wantError: true,
},
}
for _, tt := range casetests {
err := checkPgpKeys(tt.pkgs, tt.srcinfos, tt.bases, keyringArgs)
err := checkPgpKeys(tt.pkgs, tt.bases)
if !tt.wantError {
if err != nil {
t.Fatalf("Got error %q, want no error", err)

View File

@ -427,6 +427,8 @@ func hasParam(arg string) bool {
//yay params
case "mflags":
return true
case "gpgflags":
return true
case "builddir":
return true
case "editor":
@ -439,6 +441,8 @@ func hasParam(arg string) bool {
return true
case "git":
return true
case "gpg":
return true
case "requestsplitn":
return true
default:

14
yay.8
View File

@ -152,6 +152,12 @@ The command to use for \fBgit\fR calls. This can be a command in
\fBPATH\fR or an absolute path to the file\&.
.RE
.PP
\fB\-\-gpg <file>\fR
.RS 4
The command to use for \fBgpg\fR calls. This can be a command in
\fBPATH\fR or an absolute path to the file\&.
.RE
.PP
\fB\-\-config <file>\fR
.RS 4
The pacman config file to use\&.
@ -257,6 +263,14 @@ passed to makepkg. Multiple arguments may be passed by supplying a space
separated list that is quoted by the shell.
.RE
.PP
\fB\-\-gpgflags <flags>\fR
.RS 4
Passes arguments to gpg\&. These flags get passed to every instance where
gpg is called by Yay. Arguments are split on whitespace before being
passed to gpg. Multiple arguments may be passed by supplying a space
separated list that is quoted by the shell.
.RE
.PP
\fB\-\-sudoloop\fR
.RS 4
Loop sudo calls in the background to prevent sudo from timing out during long

View File

@ -46,6 +46,7 @@ _pacman_opts_common=(
'--pacman[pacman command to use]:pacman:_files'
'--tar[bsdtar command to use]:tar:_files'
'--git[git command to use]:git:_files'
'--gpg[gpg command to use]:gpg:_files'
'--bottomup[Show AUR packages first]'
'--topdown[Show repository packages first]'
@ -59,6 +60,7 @@ _pacman_opts_common=(
'--redownloadall[Always download pkgbuilds of all AUR packages]'
'--noredownload[Skip pkgbuild download if in cache and up to date]'
'--mflags[Pass arguments to makepkg]:mflags'
'--gpgflags[Pass arguments to gpg]:gpgflags'
'--sudoloop[Loop sudo calls in the backgroud to avoid timeout]'
'--nosudoloop[Do not loop sudo calls in the backgrount]'
)