diff --git a/test/gpg/key.pub b/test/gpg/key.pub new file mode 100644 index 0000000..00b3220 --- /dev/null +++ b/test/gpg/key.pub @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFl4tiQBCADax2HrOug4wNlLirwTIKjuCgWq8fGq161gE9X5NxsRK98lB1gi +LcfruKXPwaB52ZC+K0iouSGpEO9ncPuzea3gXciYofW67JKnI7DnSDSxO64kwh2Z +KMCwhzy4veyfdZqO4XZ4rLFesSCKK8ik0ynhS4ArPyZHDEEho3tyHc6tVcHd/WBB +eCiNBX3S3qdAncg64SYmESvS5IQeljFabI9Z5QLGq6TFcArArd9dnBGQQgghzsV2 +ckpkubhwIPAxJN4iBGH5yD1eywXpKsgfIWDHUZ9XutM190sF2L9ExKqXDdEQ9CAf +5lTD3wuYrCNWbb6D/yyTrpB20TbsjgzqYdCTABEBAAG0FUpvZSBEb2UgPGpvZUBk +b2UuY29tPokBVAQTAQgAPhYhBEF6Dm5VVmp1W+fWjDi7G17VhlQXBQJZeLYkAhsD +BQkDwmcABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEDi7G17VhlQXM8wIAM/9 +uScli1xOD70WpkP+O4oK2I2+TWti5crp0BOS1VG3EUrKyqFt3dUIJ78nzbtoJFei +9VZJQyDfnsXdrjBdX29tbsa0ECmM/RLbYHaBSdsoR2EV/jfDERUISlg7wx1lhg+n +RlbbGycdFQJXB3F110w5NRm+Yo0AbkLEWzuNeopKDokf1c1EI2+E1pLABePth6KN +25VcC0Q6FyuB4+6JLURr7ia1MIJ6NsBiTY1LVbjlDBkUcGWGNhpu5rUGgUC4R6fS +BIhpWUaWcaRIrjLE+GPq/QZQXsglUIReBcLiWFpfv7W/To3u7bh5p/YwvYnctzpi +Pk1l10mCTCcuMwYfjp25AQ0EWXi2JAEIALMm4bWHD2ruDtKC9FNJVOwCz4bTzvyd +TYIlerEgwJ7PhW8FrhCltqBgOOCIqLWWhEkCSC9E1xc+X9qwSc7UcMRqKsCPjave +v5z+O6dGOVmpah/FZpSvYkRr6E6yKJ2k+VuFig/UOeW6/MMvf1e/mSa6jsGY4Wt5 +TXBoXULtyNu6z7o26Er8pkl1nqaI6IKNJv0ry2t/xI1mhSxvPRD756J8GTfbQLsv +Ijjs+qBLA6pEcntXOQBug/Cj9diRYBLDUE8UmIZQEFTIvqle0FBEuZ8hZlC9WyJ4 +/9FxKrWA8VynMHTYHMj69XtMPPRJ3djIxWM4WDccYv8OwtbV3MfPpIEAEQEAAYkB +PAQYAQgAJhYhBEF6Dm5VVmp1W+fWjDi7G17VhlQXBQJZeLYkAhsMBQkDwmcAAAoJ +EDi7G17VhlQX3GkIAJzDJT5eb4/iutl0Rs/6zWcimCVYTUSquHMb/GkoOffsEwV+ +nkaUgqXtjFNKQ4SwhVnupeyfLpw+8YvieJMZifDbo7a/LxlXRyzUzr4gEiO71x+B +YxgiEtQRPw8YgGXiIaphRudgTyYK1cVYzkU6ehaRPbMnsdcovZFHVCLHUcSuTiuh +Ruq9l5+FvMoYWWZkZUUpGn79zVXfDQNRPVlSKM3mJuocPGS5kxfVn9pLKN00je3+ +SUIv2KtoARGaSVC5fIGOL2Pk7hj39qiMjF4eCAXxf9jAAy59FPZny+Yh4cK4haPz +QjSEdU0DPh5K6uFuaz2DfHMMu4N0iVgtelwmorA= +=MDgQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/test/gpg/repomd.xml b/test/gpg/repomd.xml new file mode 100644 index 0000000..d7a8027 --- /dev/null +++ b/test/gpg/repomd.xml @@ -0,0 +1,69 @@ + + + 1499286698 + + 880055a50c05b20641530d09b23f64501a000b2f92fe252417c530178730a95e + 9d4a10310a4092bde6231253f62976337f4e4fa3ab5cdda001e141a156a9dffb + + 1499286654 + 14750183 + 134514273 + + + b429c60a20974912547de94994db64e87fd7ec20fe9acca47da30fc5ba42ce96 + af9579b55eba28eb19b98e763b7269e47de59645091b75dbb5cb3649afda0d1e + + 1499286654 + 40663907 + 582650352 + + + 070edd188871859175cfae62fb963038f8ae0b108dec1445f71d620ea7f788c9 + ad63825978f1dcffbeeba4946e0dc0eb05c749ad57a89a1b938a06e82475f53c + + 1499286654 + 7610619 + 100013004 + + + 00bf6ab375bd31ddb0df2789417d17f38ac72a091ea39ec37d7ddeb64ccaffb2 + ed291593c267db9c0ff530b504acd00018afd080ceead5a709020014fe783fbf + + 1499286679 + 28398595 + 138588160 + 10 + + + 192a4d58517814a4130f009abb7fc0899e06d63f78bc55f8e2429250acea6457 + 7c84685dff9dd1f3f7c9f81aad84ba57f97631822a6fd8d481df12e1b985b6e1 + + 1499286698 + 41798451 + 265166848 + 10 + + + 9e940b3015a8adef4956f3989ebb83c52268fdeabb00de3ebf30b1fd3a808335 + 399d8fa532962c21d81a3b5d4245e7662b0a44362fe58b3d594eae9b33835891 + + 1499286676 + 11963226 + 85381120 + 10 + + + e4d5d691a5a9b53222cd8e8c3d5c99f042fdec7a27e39570a08c866e90882ec4 + + 1499286608 + 1895236 + + + 9fa6d1959b8b0a97eb8827ee899bba8ebfdb197daa29e621815d73167b2eeb8e + e4d5d691a5a9b53222cd8e8c3d5c99f042fdec7a27e39570a08c866e90882ec4 + + 1499286654 + 453974 + 1895236 + + diff --git a/test/gpg/repomd.xml.asc b/test/gpg/repomd.xml.asc new file mode 100644 index 0000000..6ca7833 --- /dev/null +++ b/test/gpg/repomd.xml.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQEzBAABCAAdFiEEQXoOblVWanVb59aMOLsbXtWGVBcFAll40LIACgkQOLsbXtWG +VBddBwgAtqPnVmtcPBvOt4/ulA2KXMOz8g24xgNejn/oDAVAs+opIIZmOX4xQWXU +jeujEw6IiagsW1pwP4lLyNRkH49hWzlU0q/5WPg7BaHzOk20nq6fKtQU4u+uKK8/ +ODCsaRzKwQkHAPL9oXkFZUEMRZ9y4+IiEbTwFgvIuueE9fz5gALzwSlU3SH9917C +Mjxi7ofhP/0jmvMH4Bb795cQ/mxuCFT8zUCl/qZ+XQSJoVPA9oE9BToItU+Ib2AM +l1N61Werbw9Q9y1gGUqIGKywZpZQTJuxAYtpIQOZGSgJBA7k4YdluXBS2cab6U1g +WzAc8sn9PtxWULCsBjCkPDzTAlkZyA== +=vgbx +-----END PGP SIGNATURE----- diff --git a/test/pubringtests.py b/test/pubringtests.py new file mode 100644 index 0000000..271e573 --- /dev/null +++ b/test/pubringtests.py @@ -0,0 +1,43 @@ +import unittest +import gpg +import os +import shutil +import tempfile + +from yum import misc + +PWD = os.path.dirname(os.path.abspath(__file__)) +KEYDIR = '%s/gpg' % PWD +KEYFILE = '%s/key.pub' % KEYDIR +REPOMD = '%s/repomd.xml' % KEYDIR +SIGFILE = '%s/repomd.xml.asc' % KEYDIR +KEYID = '38BB1B5ED5865417' +FPR = '417A0E6E55566A755BE7D68C38BB1B5ED5865417' + +class PubringTests(unittest.TestCase): + def setUp(self): + self.gpgdir = tempfile.mkdtemp() + with open(KEYFILE) as f: + info = misc.getgpgkeyinfo(f.read()) + hexkeyid = misc.keyIdToRPMVer(info['keyid']).upper() + self.imported = misc.import_key_to_pubring(info['raw_key'], hexkeyid, + gpgdir=self.gpgdir) + self.ctx = gpg.Context() + + def tearDown(self): + shutil.rmtree(self.gpgdir) + + def testImportKey(self): + self.assertTrue(self.imported) + key = list(self.ctx.keylist())[0].subkeys[0] + self.assertEqual(key.fpr, FPR) + + def testKeyids(self): + ids = misc.return_keyids_from_pubring(self.gpgdir) + self.assertEqual(ids[0], KEYID) + self.assertTrue(len(ids) == 1) + + def testValid(self): + with open(SIGFILE) as s, open(REPOMD) as r: + valid = misc.valid_detached_sig(s, r, self.gpgdir) + self.assertTrue(valid) diff --git a/yum/misc.py b/yum/misc.py index d61531e..57ddb58 100644 --- a/yum/misc.py +++ b/yum/misc.py @@ -18,6 +18,7 @@ import constants import pgpmsg import tempfile import glob +import gpg import pwd import fnmatch import bz2 @@ -36,11 +37,6 @@ except ImportError: from rpmUtils.miscutils import stringToVersion, flagToString from stat import * try: - import gpgme - import gpgme.editutil -except ImportError: - gpgme = None -try: import hashlib _available_checksums = set(['md5', 'sha1', 'sha256', 'sha384', 'sha512']) except ImportError: @@ -543,27 +539,22 @@ def keyInstalled(ts, keyid, timestamp): def import_key_to_pubring(rawkey, keyid, cachedir=None, gpgdir=None, make_ro_copy=True): # FIXME - cachedir can be removed from this method when we break api - if gpgme is None: - return False if not gpgdir: gpgdir = '%s/gpgdir' % cachedir if not os.path.exists(gpgdir): + if os.geteuid() != 0: + return False os.makedirs(gpgdir) - key_fo = StringIO(rawkey) os.environ['GNUPGHOME'] = gpgdir # import the key - ctx = gpgme.Context() fp = open(os.path.join(gpgdir, 'gpg.conf'), 'wb') fp.write('') fp.close() - ctx.import_(key_fo) - key_fo.close() - # ultimately trust the key or pygpgme is definitionally stupid - k = ctx.get_key(keyid) - gpgme.editutil.edit_trust(ctx, k, gpgme.VALIDITY_ULTIMATE) + with gpg.Context() as ctx: + ctx.op_import(rawkey) if make_ro_copy: @@ -572,6 +563,10 @@ def import_key_to_pubring(rawkey, keyid, cachedir=None, gpgdir=None, make_ro_cop os.makedirs(rodir, mode=0755) for f in glob.glob(gpgdir + '/*'): basename = os.path.basename(f) + # Skip the gpg-agent files + if (basename.startswith('private-keys-v') or + basename == 'S.gpg-agent'): + continue ro_f = rodir + '/' + basename shutil.copy(f, ro_f) os.chmod(ro_f, 0755) @@ -591,11 +586,11 @@ preserve-permissions return True def return_keyids_from_pubring(gpgdir): - if gpgme is None or not os.path.exists(gpgdir): + if not os.path.exists(gpgdir): return [] os.environ['GNUPGHOME'] = gpgdir - ctx = gpgme.Context() + ctx = gpg.Context() keyids = [] for k in ctx.keylist(): for subkey in k.subkeys: @@ -607,9 +602,6 @@ def return_keyids_from_pubring(gpgdir): def valid_detached_sig(sig_file, signed_file, gpghome=None): """takes signature , file that was signed and an optional gpghomedir""" - if gpgme is None: - return False - if gpghome: if not os.path.exists(gpghome): return False @@ -624,25 +616,14 @@ def valid_detached_sig(sig_file, signed_file, gpghome=None): else: signed_text = open(signed_file, 'r') plaintext = None - ctx = gpgme.Context() + ctx = gpg.Context() try: - sigs = ctx.verify(sig, signed_text, plaintext) - except gpgme.GpgmeError, e: + ctx.verify(signed_text, sig, plaintext) + except (gpg.errors.GPGMEError, gpg.errors.BadSignatures): return False else: - if not sigs: - return False - # is there ever a case where we care about a sig beyond the first one? - thissig = sigs[0] - if not thissig: - return False - - if thissig.validity in (gpgme.VALIDITY_FULL, gpgme.VALIDITY_MARGINAL, - gpgme.VALIDITY_ULTIMATE): - return True - - return False + return True def getCacheDir(tmpdir='/var/tmp', reuse=True, prefix='yum-'): """return a path to a valid and safe cachedir - only used when not running diff --git a/yum/yumRepo.py b/yum/yumRepo.py index a663176..f99f5d1 100644 --- a/yum/yumRepo.py +++ b/yum/yumRepo.py @@ -1712,9 +1712,6 @@ Insufficient space in download directory %s if self.repo_gpgcheck and not self._override_sigchecks: - if misc.gpgme is None: - raise URLGrabError(-1, 'pygpgme is not working so repomd.xml can not be verified for %s' % (self)) - sigfile = self.cachedir + '/repomd.xml.asc' try: result = self._getFile(relative='repodata/repomd.xml.asc', diff --git a/yum/misc.py b/yum/misc.py index cc617b3..06b368e 100644 --- a/yum/misc.py +++ b/yum/misc.py @@ -561,11 +561,12 @@ def import_key_to_pubring(rawkey, keyid, cachedir=None, gpgdir=None, make_ro_cop if not os.path.exists(rodir): os.makedirs(rodir, mode=0755) for f in glob.glob(gpgdir + '/*'): - basename = os.path.basename(f) - # Skip the gpg-agent files - if (basename.startswith('private-keys-v') or - basename == 'S.gpg-agent'): + if not os.path.isfile(f): + # This is needed as gpg-agent puts some dirs/sockets in the + # gpgdir (we don't need to copy them anyway), see: + # https://www.gnupg.org/faq/whats-new-in-2.1.html continue + basename = os.path.basename(f) ro_f = rodir + '/' + basename shutil.copy(f, ro_f) os.chmod(ro_f, 0755)