summaryrefslogtreecommitdiff
path: root/apt
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2012-10-17 10:08:36 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2012-10-17 10:08:36 +0200
commit718409afe561f7dfc7407214685ccbfacdf31631 (patch)
tree837b8b6e1539c1bb976137012ca2c12350dc5150 /apt
parent5384546c17c80b809791ef95ac357bc017be83f9 (diff)
parent7bd938dd78ab27ec23ffd84811dbdfa5dd83593a (diff)
downloadpython-apt-718409afe561f7dfc7407214685ccbfacdf31631.tar.gz
merged debian-sid branch
Diffstat (limited to 'apt')
-rw-r--r--apt/auth.py83
-rw-r--r--apt/debfile.py1
2 files changed, 78 insertions, 6 deletions
diff --git a/apt/auth.py b/apt/auth.py
index e088ae85..eff13b1a 100644
--- a/apt/auth.py
+++ b/apt/auth.py
@@ -27,6 +27,7 @@
import atexit
import os
import os.path
+import shutil
import subprocess
import sys
import tempfile
@@ -35,6 +36,10 @@ import apt_pkg
from apt_pkg import gettext as _
+class AptKeyError(Exception):
+ pass
+
+
class TrustedKey(object):
"""Represents a trusted key."""
@@ -79,7 +84,7 @@ def _call_apt_key_script(*args, **kwargs):
output, stderr = proc.communicate(content)
if proc.returncode:
- raise SystemError("The apt-key script failed with return code %s:\n"
+ raise AptKeyError("The apt-key script failed with return code %s:\n"
"%s\n"
"stdout: %s\n"
"stderr: %s" % (proc.returncode, " ".join(cmd),
@@ -99,20 +104,86 @@ def add_key_from_file(filename):
filename -- the absolute path to the public GnuPG key file
"""
if not os.path.abspath(filename):
- raise SystemError("An absolute path is required: %s" % filename)
+ raise AptKeyError("An absolute path is required: %s" % filename)
if not os.access(filename, os.R_OK):
- raise SystemError("Key file cannot be accessed: %s" % filename)
+ raise AptKeyError("Key file cannot be accessed: %s" % filename)
_call_apt_key_script("add", filename)
def add_key_from_keyserver(keyid, keyserver):
"""Import a GnuPG key file to trust repositores signed by it.
Keyword arguments:
- keyid -- the identifier of the key, e.g. 0x0EB12DSA
+ keyid -- the long keyid (fingerprint) of the key, e.g.
+ A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553
keyserver -- the URL or hostname of the key server
"""
- _call_apt_key_script("adv", "--quiet", "--keyserver", keyserver,
- "--recv", keyid)
+ tmp_keyring_dir = tempfile.mkdtemp()
+ try:
+ _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir)
+ except:
+ raise
+ finally:
+ shutil.rmtree(tmp_keyring_dir)
+
+def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
+ if len(keyid) < 160/8:
+ raise AptKeyError("Only long keyids (v4, 160bit) are supported")
+ # create a temp keyring dir
+ tmp_secret_keyring = os.path.join(tmp_keyring_dir, "secring.gpg")
+ tmp_keyring = os.path.join(tmp_keyring_dir, "pubring.gpg")
+ # default options for gpg
+ gpg_default_options = [
+ "gpg",
+ "--no-default-keyring", "--no-options",
+ "--homedir", tmp_keyring_dir,
+ ]
+ # download the key to a temp keyring first
+ res = subprocess.call(gpg_default_options + [
+ "--secret-keyring", tmp_secret_keyring,
+ "--keyring", tmp_keyring,
+ "--keyserver", keyserver,
+ "--recv", keyid,
+ ])
+ if res != 0:
+ raise AptKeyError("recv from '%s' failed for '%s'" % (
+ keyserver, keyid))
+ # now export again using the long key id (to ensure that there is
+ # really only this one key in our keyring) and not someone MITM us
+ tmp_export_keyring = os.path.join(tmp_keyring_dir, "export-keyring.gpg")
+ res = subprocess.call(gpg_default_options + [
+ "--keyring", tmp_keyring,
+ "--output", tmp_export_keyring,
+ "--export", keyid,
+ ])
+ if res != 0:
+ raise AptKeyError("export of '%s' failed", keyid)
+ # now verify the fingerprint, this is probably redundant as we
+ # exported by the fingerprint in the previous command but its
+ # still good paranoia
+ output = subprocess.Popen(
+ gpg_default_options + [
+ "--keyring", tmp_export_keyring,
+ "--fingerprint",
+ "--batch",
+ "--with-colons",
+ ],
+ stdout=subprocess.PIPE,
+ universal_newlines=True).communicate()[0]
+ got_fingerprint=None
+ for line in output.splitlines():
+ if line.startswith("fpr:"):
+ got_fingerprint = line.split(":")[9]
+ # stop after the first to ensure no subkey trickery
+ break
+ # strip the leading "0x" is there is one and uppercase (as this is
+ # what gnupg is using)
+ signing_key_fingerprint = keyid.replace("0x", "").upper()
+ if got_fingerprint != signing_key_fingerprint:
+ raise AptKeyError(
+ "Fingerprints do not match, not importing: '%s' != '%s'" % (
+ signing_key_fingerprint, got_fingerprint))
+ # finally add it
+ add_key_from_file(tmp_export_keyring)
def add_key(content):
"""Import a GnuPG key to trust repositores signed by it.
diff --git a/apt/debfile.py b/apt/debfile.py
index 2eb807b8..1ebbea32 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -104,6 +104,7 @@ class DebPackage(object):
elif self._cache.is_virtual_package(pkgname):
return pkgname
elif (pkgname in self._cache and
+ self._cache[pkgname].candidate and
self._cache[pkgname].candidate.architecture == "all"):
return pkgname
# now do the real multiarch checking