commit:     726789b64dd713a761ebdc78abb3d64fff2a7984
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Mon Jul 23 04:10:40 2018 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sat Jul 28 05:53:06 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=726789b6

webrsync: support sync-openpgp-key-path (bug 661838)

Add repos.conf sync-webrsync-verify-signature = true|false setting that
enables sync-openpgp-key-path support like in the rsync and git sync
modules. This is disabled by default, in order to avoid interference
with legacy manual PORTAGE_GPG_DIR configuration.

When sync-webrsync-verify-signature = true is set in repos.conf,
if the PORTAGE_GPG_DIR has not been exported, emerge-webrsync will
assume that it has been called directly and it will output an error
message advising the user to instead call emerge --sync or emaint sync.

Bug: https://bugs.gentoo.org/661838
Reviewed-by: Brian Dolbec <dolsen <AT> gentoo.org>

 bin/emerge-webrsync                           | 16 +++++-
 lib/portage/sync/modules/webrsync/__init__.py |  4 +-
 lib/portage/sync/modules/webrsync/webrsync.py | 74 +++++++++++++++++++++++----
 man/portage.5                                 |  5 ++
 4 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index b135567b7..f622dde3e 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -10,7 +10,14 @@
 #  - all output should prob be converted to e* funcs
 #  - add support for ROOT
 
+# repos.conf configuration for use with emerge --sync and emaint sync
+# using keyring from app-crypt/openpgp-keys-gentoo-release:
+# [gentoo]
+# sync-type = webrsync
+# sync-webrsync-verify-signature = true
+# sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
 #
+# Alternative (legacy) PORTAGE_GPG_DIR configuration:
 # gpg key import
 # KEY_ID=0x96D8BF6D
 # gpg --homedir /etc/portage/gnupg --keyserver subkeys.pgp.net --recv-keys 
$KEY_ID
@@ -67,7 +74,14 @@ do_verbose=0
 do_debug=0
 keep=false
 
-if has webrsync-gpg ${FEATURES} ; then
+if has $(__repo_attr "${repo_name}" sync-webrsync-verify-signature | \
+       LC_ALL=C tr '[:upper:]' '[:lower:]') true yes; then
+       if [[ ! -d ${PORTAGE_GPG_DIR} ]]; then
+               eecho "Do not call ${argv0##*/} directly, instead call emerge 
--sync or emaint sync."
+               exit 1
+       fi
+       WEBSYNC_VERIFY_SIGNATURE=1
+elif has webrsync-gpg ${FEATURES}; then
        WEBSYNC_VERIFY_SIGNATURE=1
 else
        WEBSYNC_VERIFY_SIGNATURE=0

diff --git a/lib/portage/sync/modules/webrsync/__init__.py 
b/lib/portage/sync/modules/webrsync/__init__.py
index dc7def20c..1e09d1a47 100644
--- a/lib/portage/sync/modules/webrsync/__init__.py
+++ b/lib/portage/sync/modules/webrsync/__init__.py
@@ -45,7 +45,9 @@ module_spec = {
                                        'exists and is a valid repository',
                        },
                        'validate_config': CheckSyncConfig,
-                       'module_specific_options': (),
+                       'module_specific_options': (
+                               'sync-webrsync-verify-signature',
+                       ),
                },
        }
 }

diff --git a/lib/portage/sync/modules/webrsync/webrsync.py 
b/lib/portage/sync/modules/webrsync/webrsync.py
index 3d79f4557..1b4c08e65 100644
--- a/lib/portage/sync/modules/webrsync/webrsync.py
+++ b/lib/portage/sync/modules/webrsync/webrsync.py
@@ -1,17 +1,25 @@
 
 '''WebRsync module for portage'''
 
+import io
 import logging
 
 import portage
 from portage import os
 from portage.util import writemsg_level
+from portage.util.futures import asyncio
 from portage.output import create_color_func
 good = create_color_func("GOOD")
 bad = create_color_func("BAD")
 warn = create_color_func("WARN")
 from portage.sync.syncbase import SyncBase
 
+try:
+       from gemato.exceptions import GematoException
+       import gemato.openpgp
+except ImportError:
+       gemato = None
+
 
 class WebRsync(SyncBase):
        '''WebRSync sync class'''
@@ -39,15 +47,63 @@ class WebRsync(SyncBase):
                for var in ['uid', 'gid', 'groups']:
                        self.spawn_kwargs.pop(var, None)
 
-               exitcode = portage.process.spawn_bash("%s" % \
-                       (self.bin_command),
-                       **self.spawn_kwargs)
-               if exitcode != os.EX_OK:
-                       msg = "!!! emerge-webrsync error in %s" % 
self.repo.location
-                       self.logger(self.xterm_titles, msg)
-                       writemsg_level(msg + "\n", level=logging.ERROR, 
noiselevel=-1)
-                       return (exitcode, False)
-               return (exitcode, True)
+               verbose = '--verbose' in self.options['emerge_config'].opts
+               quiet = '--quiet' in self.options['emerge_config'].opts
+               openpgp_env = None
+               try:
+                       if self.repo.module_specific_options.get(
+                               'sync-webrsync-verify-signature', 
'false').lower() in ('true', 'yes'):
+
+                               if not self.repo.sync_openpgp_key_path:
+                                       writemsg_level("!!! 
sync-openpgp-key-path is not set\n",
+                                               level=logging.ERROR, 
noiselevel=-1)
+                                       return (1, False)
+
+                               if not 
os.path.isfile(self.repo.sync_openpgp_key_path):
+                                       writemsg_level("!!! 
sync-openpgp-key-path file not found: %s\n" %
+                                               
self.repo.sync_openpgp_key_path, level=logging.ERROR, noiselevel=-1)
+                                       return (1, False)
+
+                               if gemato is None:
+                                       writemsg_level("!!! Verifying against 
specified key requires gemato-11.0+ installed\n",
+                                               level=logging.ERROR, 
noiselevel=-1)
+                                       return (1, False)
+
+                               openpgp_env = 
gemato.openpgp.OpenPGPEnvironment()
+
+                               out = portage.output.EOutput(quiet=quiet)
+                               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)
+                                       self._refresh_keys(openpgp_env)
+                                       
self.spawn_kwargs["env"]["PORTAGE_GPG_DIR"] = openpgp_env.home
+                               except (GematoException, asyncio.TimeoutError) 
as e:
+                                       writemsg_level("!!! Verification 
impossible due to keyring problem:\n%s\n"
+                                                       % (e,),
+                                                       level=logging.ERROR, 
noiselevel=-1)
+                                       return (1, False)
+
+                       webrsync_cmd = [self.bin_command]
+                       if verbose:
+                               webrsync_cmd.append('-v')
+                       elif quiet:
+                               webrsync_cmd.append('-q')
+
+                       if self.repo.module_specific_options.get(
+                               'sync-webrsync-keep-snapshots', 
'false').lower() in ('true', 'yes'):
+                               webrsync_cmd.append('-k')
+
+                       exitcode = portage.process.spawn(webrsync_cmd, 
**self.spawn_kwargs)
+                       if exitcode != os.EX_OK:
+                               msg = "!!! emerge-webrsync error in %s" % 
self.repo.location
+                               self.logger(self.xterm_titles, msg)
+                               writemsg_level(msg + "\n", level=logging.ERROR, 
noiselevel=-1)
+                               return (exitcode, False)
+                       return (exitcode, True)
+               finally:
+                       if openpgp_env is not None:
+                               openpgp_env.close()
 
 
 class PyWebRsync(SyncBase):

diff --git a/man/portage.5 b/man/portage.5
index a57531d44..8ebf980f5 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -1127,6 +1127,11 @@ when 0. Defaults to disabled.
 .B sync\-rsync\-verify\-metamanifest = yes|no
 Require the repository to contain a signed MetaManifest and verify
 it using \fBapp\-portage/gemato\fR. Defaults to no.
+.TP
+.B sync\-webrsync\-verify\-signature = true|false
+Require the detached tarball signature to contain a good OpenPGP
+signature. This uses the OpenPGP key(ring) specified by the
+sync\-openpgp\-key\-path setting. Defaults to false.
 
 .RE
 

Reply via email to