summaryrefslogtreecommitdiff
path: root/apt
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2012-10-15 10:58:42 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2012-10-15 10:58:42 +0200
commit2e754964b0570ff72c82aa012142adf504e01f0e (patch)
treea6cf324f43fe5fd11a5651c6f8186a987a1da922 /apt
parent43d87e1b14719750585412ab1d15fc30e280b7d0 (diff)
parent7bd938dd78ab27ec23ffd84811dbdfa5dd83593a (diff)
downloadpython-apt-2e754964b0570ff72c82aa012142adf504e01f0e.tar.gz
merge from the debian-sid branch
Diffstat (limited to 'apt')
-rw-r--r--apt/auth.py97
-rw-r--r--apt/debfile.py1
-rw-r--r--apt/progress/base.py2
3 files changed, 88 insertions, 12 deletions
diff --git a/apt/auth.py b/apt/auth.py
index 5d4b1cd6..eff13b1a 100644
--- a/apt/auth.py
+++ b/apt/auth.py
@@ -27,13 +27,19 @@
import atexit
import os
import os.path
+import shutil
import subprocess
+import sys
import tempfile
import apt_pkg
from apt_pkg import gettext as _
+class AptKeyError(Exception):
+ pass
+
+
class TrustedKey(object):
"""Represents a trusted key."""
@@ -69,7 +75,7 @@ def _call_apt_key_script(*args, **kwargs):
proc = subprocess.Popen(cmd, env=env, universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
+ stderr=subprocess.PIPE)
content = kwargs.get("stdin", None)
if isinstance(content, unicode):
@@ -77,12 +83,15 @@ def _call_apt_key_script(*args, **kwargs):
output, stderr = proc.communicate(content)
- assert stderr == None
-
if proc.returncode:
- raise SystemError("The apt-key script failed with return code %s:\n"
- "%s\n%s" % (proc.returncode, " ".join(cmd),
- output))
+ raise AptKeyError("The apt-key script failed with return code %s:\n"
+ "%s\n"
+ "stdout: %s\n"
+ "stderr: %s" % (proc.returncode, " ".join(cmd),
+ output,stderr))
+ elif stderr:
+ sys.stderr.write(stderr) # Forward stderr
+
return output.strip()
finally:
if conf is not None:
@@ -95,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
diff --git a/apt/progress/base.py b/apt/progress/base.py
index ab57dd82..2c80ae29 100644
--- a/apt/progress/base.py
+++ b/apt/progress/base.py
@@ -65,7 +65,7 @@ class AcquireProgress(object):
def media_change(self, media, drive):
"""Prompt the user to change the inserted removable media.
- The parameter 'media' decribes the name of the the media type that
+ The parameter 'media' decribes the name of the media type that
should be changed, whereas the parameter 'drive' should be the
identifying name of the drive whose media should be changed.