Commit 7c774efe authored by anarcat's avatar anarcat
Browse files

copy public keys for all secret keys found (Closes: #721599)

gpg.conf may specify another default key. instead of guessing around
what gpg thinks is the right secret key, let's just play it safe and
copy *all* the public key material associated with the secret keys we
find so that we can freely use any secret key we have through the
--secret-keyring flag.
parent eeb8b942
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -271,27 +271,26 @@ this should not interrupt the flow of the program, but must be visible to the us
we use --secret-keyring instead of copying the secret key material,
but we still need the public part in the temporary keyring for this to
work.

we copy all keys because we do not want to guess which keys gpg will
chose. it could vary based on default-key, for example, or some weird
ordering.
        """
        self.log(_('copying your private key to temporary keyring in %s') % self.tmpkeyring.homedir)
        # detect the proper uid
        if self.options.user is None:
            keys = self.keyring.get_keys(None, True, False)
        else:
        keys = self.keyring.get_keys(self.options.user, True, False)

        for fpr, key in keys.iteritems():
            self.log(_('found secret key: %s') % key)
            if not key.invalid and not key.disabled and not key.expired and not key.revoked:
                self.signing_key = key
                break
                # export public key material associated with all private keys
                # XXX: we should only do export-minimal here, but passing options down is a pain.
                if not self.tmpkeyring.import_data(self.keyring.export_data(key.fpr)):
                    self.warning(_('could not export public key material of private key %s') % key.fpr)

        if self.signing_key is None:
            self.abort(_('no default secret key found, abort!'))
        self.log(_('signing key chosen: %s') % self.signing_key.fpr)

        # export public key material associated with detected private
        if not self.tmpkeyring.import_data(self.keyring.export_data(self.signing_key.fpr)):
            self.abort(_('could not find public key material, do you have an OpenPGP key?'))
            self.abort(_('could not find public key material for any private key, do you have an OpenPGP key?'))

    def sign_key(self):
        """sign the key uids, as specified"""
+24 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import re
sys.path.insert(0, os.path.dirname(__file__) + '/..')

from monkeysign.ui import MonkeysignUi, EmailFactory
from monkeysign.gpg import TempKeyring
from monkeysign.gpg import TempKeyring, GpgRuntimeError

from test_lib import TestTimeLimit, AlarmException

@@ -158,6 +158,29 @@ this duplicates tests from the gpg code, but is necessary to test later function
        self.ui.sign_key()
        self.assertGreaterEqual(len(self.ui.signed_keys), 1)

    def test_multiple_secrets(self):
        """test if we pick the right key define in gpg.conf"""
        # configure gpg to use the second test key as a default key
        with open(os.path.join(self.ui.keyring.homedir, 'gpg.conf'), 'w') as f:
            f.write('default-key 323F39BD')
        # needed because we created a new gpg.conf
        self.ui.prepare()
        self.assertTrue(os.path.exists(os.path.join(self.ui.tmpkeyring.homedir, 'gpg.conf')))
        self.test_copy_secrets()
        # public key is missing, this should fail
        with self.assertRaises(GpgRuntimeError):
            self.ui.sign_key()
        self.ui.keyring.import_data(open(os.path.dirname(__file__) +
                                         '/323F39BD.asc').read())
        self.ui.keyring.import_data(open(os.path.dirname(__file__) +
                                         '/323F39BD-secret.asc').read())
        self.test_copy_secrets()
        self.ui.sign_key()
        self.ui.tmpkeyring.context.call_command(['list-sigs', '7B75921E'])
        # this is the primary test key, it shouldn't have signed this
        self.assertNotIn('sig:::1:86E4E70A96F47C6A:',
                         self.ui.tmpkeyring.context.stdout)

    def test_create_mail_multiple(self):
        """test if exported keys contain the right uid"""
        self.test_sign_key()