[Pkg-privacy-commits] [torbrowser-launcher] 01/28: Check that GnuPG key import was successful.

Ulrike Uhlig u-guest at moszumanska.debian.org
Sun Jul 10 21:18:15 UTC 2016


This is an automated email from the git hooks/post-receive script.

u-guest pushed a commit to branch debian/sid
in repository torbrowser-launcher.

commit b337b3de8aee9be537810d2d4f89810bedfa69cd
Author: Isis Lovecruft <isis at torproject.org>
Date:   Mon Oct 27 21:16:51 2014 +0000

    Check that GnuPG key import was successful.
    
    Rather than checking the GnuPG process exit code, a more robust way to
    handle determining whether or not a GnuPG process behaved as was
    intended is to check GnuPG's status-fd output. [0]
    
    In the case of key import, the particular status-fd flag we're looking
    for is `IMPORT_OK` followed by a "reason", then the expected
    fingerprint. [1]  Because the "reason"s are integers which may be ORed,
    and we are never expecting private keys to be within the file, we can
    assume the reason to be `[0, 15]` inclusive.
    
    While it's not strictly necessary to hardcode Erinn's key fingerprint
    within the code because the keyfiles are safely distributed along with
    the source code, doing so adds a simple defense-in-depth mechanism for
    the unlikely case that a user's torbrowser-launcher package/source
    download was compromised.  As such, and because it was a trivial
    addition which will also assist with checking that a signature was made
    by the key with the expected fingerprint [2], I've gone ahead and added
    a `common.fingerprints` dictionary whose keys match the names of the
    `common.paths` keyfile for their respective key (i.e. the fingerprint
    for `common.paths['erinn_key']` is stored at
    `common.fingerprints['erinn_key']`) in order to facilitate extensibility
    in the event that torbrowser-launcher should add new keyfiles in the
    future.  This may be removed, if undesirable.
    
     * ADD `common.gnupg_import_ok_pattern`, a compiled regex for
       determining if a key import was successful.
     * ADD new class attribute, `common.Common.fingerprints` for storing
       fingerprints.
     * ADD new method, `common.Common.import_key_and_check_status()`, which
       imports a GnuPG key, and then checks that the key was successfully
       imported.
     * CHANGE `common.Common.import_keys()` method to make adding
       new/additional keys easier.
     * FIXES https://github.com/micahflee/torbrowser-launcher/issues/137
    
    [0]: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;hb=HEAD#l323
    [1]: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;hb=HEAD#l713
    [2]: https://github.com/micahflee/torbrowser-launcher/issues/147
---
 torbrowser_launcher/common.py | 69 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 2 deletions(-)

diff --git a/torbrowser_launcher/common.py b/torbrowser_launcher/common.py
index c58a6fe..510706e 100644
--- a/torbrowser_launcher/common.py
+++ b/torbrowser_launcher/common.py
@@ -26,7 +26,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 """
 
-import os, sys, platform, subprocess, locale, pickle, psutil
+import os, sys, platform, subprocess, locale, pickle, psutil, re
 
 import pygtk
 pygtk.require('2.0')
@@ -40,6 +40,16 @@ gettext.install('torbrowser-launcher', os.path.join(SHARE, 'locale'))
 from twisted.internet import gtk2reactor
 gtk2reactor.install()
 
+
+# We're looking for output which:
+#
+#   1. The first portion must be `[GNUPG:] IMPORT_OK`
+#   2. The second must be an integer between [0, 15], inclusive
+#   3. The third must be an uppercased hex-encoded 160-bit fingerprint
+gnupg_import_ok_pattern = re.compile(
+    "(\[GNUPG\:\]) (IMPORT_OK) ([0-9]|[1]?[0-5]) ([A-F0-9]{40})")
+
+
 class Common:
 
     def __init__(self, tbl_version):
@@ -150,6 +160,12 @@ class Common:
                 },
             }
 
+        self.fingerprints = {}
+
+        # Add the expected fingerprint for imported keys:
+        if self.paths['erinn_key']:
+            self.fingerprints['erinn_key'] = '8738A680B84B3031A630F2DB416F061063FEE659'
+
     # create a directory
     @staticmethod
     def mkdir(path):
@@ -172,10 +188,59 @@ class Common:
             self.mkdir(self.paths['gnupg_homedir'])
         self.import_keys()
 
+    def import_key_and_check_status(self, key):
+        """Import a GnuPG key and check that the operation was successful.
+
+        :param str key: A string specifying the key's filepath from
+            ``Common.paths``, as well as its fingerprint in
+            ``Common.fingerprints``.
+        :rtype: bool
+        :returns: ``True`` if the key is now within the keyring (or was
+            previously and hasn't changed). ``False`` otherwise.
+        """
+        success = False
+
+        p = subprocess.Popen(['/usr/bin/gpg', '--status-fd', '2',
+                              '--homedir', self.paths['gnupg_homedir'],
+                              '--import', self.paths[key]],
+                             stderr=subprocess.PIPE)
+        p.wait()
+
+        output = p.stderr.read()
+        match = gnupg_import_ok_pattern.match(output)
+        if match:
+            # The output must match everything in the
+            # ``gnupg_import_ok_pattern``, as well as the expected fingerprint:
+            if match.group().find(self.fingerprints[key]) >= 0:
+                success = True
+
+        return success
+
     # import gpg keys
     def import_keys(self):
+        """Import all GnuPG keys.
+
+        :rtype: bool
+        :returns: ``True`` if all keys were successfully imported; ``False``
+            otherwise.
+        """
+        keys = ['erinn_key',]
+        all_imports_succeeded = True
+
         print _('Importing keys')
-        subprocess.Popen(['/usr/bin/gpg', '--homedir', self.paths['gnupg_homedir'], '--import', self.paths['erinn_key']]).wait()
+        for key in keys:
+            imported = self.import_key_and_check_status(key)
+            if not imported:
+                print _('Could not import key with fingerprint: %s.'
+                        % self.fingerprints[key])
+                all_imports_succeeded = False
+
+        if all_imports_succeeded:
+            print _('Successfully imported all keys.')
+        else:
+            print _('Not all keys were imported successfully!')
+
+        return all_imports_succeeded
 
     # load mirrors
     def load_mirrors(self):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/torbrowser-launcher.git



More information about the Pkg-privacy-commits mailing list