commit: d30191b887bb3a3d896c2b8bbf57571e8821b413 Author: Michał Górny <mgorny <AT> gentoo <DOT> org> AuthorDate: Thu Feb 1 13:30:46 2018 +0000 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org> CommitDate: Mon Feb 5 18:43:35 2018 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=d30191b8
git: Support running the verification against sync-openpgp-key-path Closes: https://github.com/gentoo/portage/pull/252 Reviewed-by: Zac Medico <zmedico <AT> gentoo.org> pym/portage/sync/modules/git/git.py | 101 +++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 31 deletions(-) diff --git a/pym/portage/sync/modules/git/git.py b/pym/portage/sync/modules/git/git.py index 7e5ddf3b5..cec760d00 100644 --- a/pym/portage/sync/modules/git/git.py +++ b/pym/portage/sync/modules/git/git.py @@ -1,6 +1,7 @@ # Copyright 2005-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import io import logging import subprocess @@ -13,6 +14,12 @@ bad = create_color_func("BAD") warn = create_color_func("WARN") from portage.sync.syncbase import NewBase +try: + from gemato.exceptions import GematoException + import gemato.openpgp +except ImportError: + gemato = None + class GitSync(NewBase): '''Git sync class''' @@ -141,39 +148,71 @@ class GitSync(NewBase): 'sync-git-verify-commit-signature', 'false') != 'true'): return True - rev_cmd = [self.bin_command, "log", "--pretty=format:%G?", "-1"] - try: - status = (portage._unicode_decode( - subprocess.check_output(rev_cmd, - cwd=portage._unicode_encode(self.repo.location))) - .strip()) - except subprocess.CalledProcessError: - return False - - out = EOutput() - if status == 'G': # good signature is good - out.einfo('Trusted signature found on top commit') - return True - elif status == 'U': # untrusted - out.ewarn('Top commit signature is valid but not trusted') - return True + if self.repo.sync_openpgp_key_path is not None: + if gemato is None: + writemsg_level("!!! Verifying against specified key requires gemato-11.0+ installed\n", + level=logging.ERROR, noiselevel=-1) + return False + openpgp_env = gemato.openpgp.OpenPGPEnvironment() else: - if status == 'B': - expl = 'bad signature' - elif status == 'X': - expl = 'expired signature' - elif status == 'Y': - expl = 'expired key' - elif status == 'R': - expl = 'revoked key' - elif status == 'E': - expl = 'unable to verify signature (missing key?)' - elif status == 'N': - expl = 'no signature' + openpgp_env = None + + try: + out = EOutput() + env = None + if openpgp_env is not None: + try: + out.einfo('Using keys from %s' % (self.repo.sync_openpgp_key_path,)) + with io.open(self.repo.sync_openpgp_key_path, 'rb') as f: + openpgp_env.import_key(f) + out.ebegin('Refreshing keys from keyserver') + openpgp_env.refresh_keys() + out.eend(0) + except GematoException as e: + writemsg_level("!!! Verification impossible due to keyring problem:\n%s\n" + % (e,), + level=logging.ERROR, noiselevel=-1) + return (1, False) + + env = os.environ.copy() + env['GNUPGHOME'] = openpgp_env.home + + rev_cmd = [self.bin_command, "log", "--pretty=format:%G?", "-1"] + try: + status = (portage._unicode_decode( + subprocess.check_output(rev_cmd, + cwd=portage._unicode_encode(self.repo.location), + env=env)) + .strip()) + except subprocess.CalledProcessError: + return False + + if status == 'G': # good signature is good + out.einfo('Trusted signature found on top commit') + return True + elif status == 'U': # untrusted + out.ewarn('Top commit signature is valid but not trusted') + return True else: - expl = 'unknown issue' - out.eerror('No valid signature found: %s' % (expl,)) - return False + if status == 'B': + expl = 'bad signature' + elif status == 'X': + expl = 'expired signature' + elif status == 'Y': + expl = 'expired key' + elif status == 'R': + expl = 'revoked key' + elif status == 'E': + expl = 'unable to verify signature (missing key?)' + elif status == 'N': + expl = 'no signature' + else: + expl = 'unknown issue' + out.eerror('No valid signature found: %s' % (expl,)) + return False + finally: + if openpgp_env is not None: + openpgp_env.close() def retrieve_head(self, **kwargs): '''Get information about the head commit'''