[linux-signed] 04/09: debian/bin/sign.py: Implement secure downloads
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Sat Apr 16 01:04:20 UTC 2016
This is an automated email from the git hooks/post-receive script.
benh pushed a commit to branch master
in repository linux-signed.
commit 6533d86ba0cce37a7f60aa68e13e135b5f0d8634
Author: Ben Hutchings <ben at decadent.org.uk>
Date: Sat Apr 16 00:11:05 2016 +0100
debian/bin/sign.py: Implement secure downloads
Download and validate InRelease, Packages.gz and binary packages in
turn.
---
debian/bin/sign.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++----
debian/rules | 2 +-
debian/rules.defs | 3 ++
3 files changed, 93 insertions(+), 8 deletions(-)
diff --git a/debian/bin/sign.py b/debian/bin/sign.py
index 7322024..f46e245 100755
--- a/debian/bin/sign.py
+++ b/debian/bin/sign.py
@@ -4,21 +4,102 @@ import sys
sys.path.append(sys.argv[1] + "/lib/python")
import os, os.path, shutil, subprocess, tempfile
+import deb822, codecs, gzip, hashlib, io, re, struct, urllib.parse, urllib.request
from debian_linux.config import ConfigCoreDump
from debian_linux.debian import VersionLinux
-def get_package(name, version, arch):
+_release_data = {}
+
+def get_release_data(mirror, suite):
+ if not _release_data:
+ url = urllib.parse.urljoin(mirror, 'dists/%s/InRelease' % suite)
+ print('I: Fetching %s' % url)
+ with urllib.request.urlopen(url) as req:
+ release_raw = req.read()
+
+ # Validate against keyring. deb822.Release seems to expect
+ # detached signatures so call gpgv directly.
+ with tempfile.NamedTemporaryFile() as release_file:
+ release_file.write(release_raw)
+ output = subprocess.check_output(
+ ['gpgv', '--status-fd', '1',
+ '--keyring', '/usr/share/keyrings/debian-archive-keyring.gpg',
+ '--ignore-time-conflict', release_file.name])
+ if not re.search(r'^\[GNUPG:\]\s+VALIDSIG\s', codecs.decode(output),
+ re.MULTILINE):
+ os.write(2, output) # bytes not str!
+ raise Exception('gpgv rejected %s' % url)
+
+ release_stream = io.TextIOWrapper(io.BytesIO(release_raw), 'utf-8')
+
+ # Make a dictionary of per-file data
+ for file_data in deb822.Release(release_stream)['SHA256']:
+ _release_data[file_data['name']] = file_data
+
+ return _release_data
+
+_packages_data = {}
+
+def get_packages_data(mirror, suite, arch):
+ if arch not in _packages_data:
+ release_data = get_release_data(mirror, suite)
+
+ path = 'main/binary-%s/Packages.gz' % arch
+ file_data = release_data[path]
+ url = urllib.parse.urljoin(mirror, 'dists/%s/%s' % (suite, path))
+ print('I: Fetching %s' % url)
+ with urllib.request.urlopen(url) as req:
+ packages_raw = req.read()
+
+ # Validate against Release file
+ if len(packages_raw) != int(file_data['size']):
+ raise Exception('%s has wrong size' % url)
+ h = hashlib.sha256()
+ h.update(packages_raw)
+ if h.digest() != bytes.fromhex(file_data['sha256']):
+ raise Exception('%s has wrong checksum' % url)
+
+ packages_stream = io.TextIOWrapper(
+ io.BytesIO(gzip.decompress(packages_raw)), 'utf-8')
+
+ # Make a dictionary of per-package data
+ _packages_data[arch] = data = {}
+ for package_data in deb822.Packages.iter_paragraphs(packages_stream):
+ data[package_data['Package']] = package_data
+
+ return _packages_data[arch]
+
+def get_package(mirror, suite, name, version, arch):
packages_dir = 'debian/localpackages/'
package_file = '%s/%s_%s_%s.deb' % (packages_dir, name, version, arch)
unpack_dir = '%s/%s_%s_%s' % (packages_dir, name, version, arch)
- # FIXME Need a way to download for any architecture with signature
- # verification
os.makedirs(packages_dir, exist_ok=True)
+
if not os.path.isfile(package_file):
- subprocess.check_call(['debsnap', '-d', packages_dir, '-f', '--binary',
- '-a', arch, name, str(version)])
+ packages_data = get_packages_data(mirror, suite, arch)
+ if name not in packages_data:
+ raise Exception('package %s is not available' % name)
+ package_data = packages_data[name]
+ if package_data['Version'] != version:
+ raise Exception('package %s version %s is not available; only version %s' %
+ (name, version, package_data['Version']))
+ url = urllib.parse.urljoin(mirror, package_data['Filename'])
+ print('I: Fetching %s' % url)
+ with urllib.request.urlopen(url) as req:
+ package = req.read()
+
+ # Validate against Packages file
+ if len(package) != int(package_data['Size']):
+ raise Exception('%s has wrong size' % url)
+ h = hashlib.sha256()
+ h.update(package)
+ if h.digest() != bytes.fromhex(package_data['SHA256']):
+ raise Exception('%s has wrong checksum' % url)
+
+ with open(package_file, 'wb') as f:
+ f.write(package)
if not os.path.isdir(unpack_dir):
# Unpack to a temporary directory before moving into place, so we
@@ -73,7 +154,7 @@ def sign_image_efi(image_name, signature_name, privkey_name, cert_name):
raise Exception('sbsign failed')
def sign(config_name, imageversion_str, modules_privkey_name, modules_cert_name,
- image_privkey_name, image_cert_name):
+ image_privkey_name, image_cert_name, mirror_url, suite):
config = ConfigCoreDump(fp=open(config_name, 'rb'))
assert config['version',]['source'] == imageversion_str
abiname = config['version',]['abiname']
@@ -100,7 +181,8 @@ def sign(config_name, imageversion_str, modules_privkey_name, modules_cert_name,
flavour)
package_name = 'linux-image-' + kernelversion
- package_dir = get_package(package_name, imageversion, arch)
+ package_dir = get_package(mirror_url, suite,
+ package_name, imageversion_str, arch)
signature_dir = os.path.join('debian/signatures', package_name)
os.makedirs(signature_dir)
diff --git a/debian/rules b/debian/rules
index 683359e..e73fc09 100755
--- a/debian/rules
+++ b/debian/rules
@@ -67,6 +67,6 @@ maintainerclean: clean
rm -rf $(filter-out %.config %.postinst %.templates %.NEWS, $(wildcard debian/linux-*))
sign:
- $(SIGN) /usr/src/linux-support-$(KERNEL_ABINAME) "$(KERNEL_IMAGE_VERSION)" "$(KERNEL_MODULES_PRIVKEY)" "$(KERNEL_MODULES_CERT)" "$(KERNEL_IMAGE_PRIVKEY)" "$(KERNEL_IMAGE_CERT)"
+ $(SIGN) /usr/src/linux-support-$(KERNEL_ABINAME) "$(KERNEL_IMAGE_VERSION)" "$(KERNEL_MODULES_PRIVKEY)" "$(KERNEL_MODULES_CERT)" "$(KERNEL_IMAGE_PRIVKEY)" "$(KERNEL_IMAGE_CERT)" "$(MIRROR_URL)" "$(SUITE)"
.PHONY: build build-arch build-indep clean binary binary-arch binary-indep binary-arch-all maintainerclean sign
diff --git a/debian/rules.defs b/debian/rules.defs
index e9ef10a..f358ff8 100644
--- a/debian/rules.defs
+++ b/debian/rules.defs
@@ -3,6 +3,9 @@ STAMPS_DIR = debian/stamps
TEMPLATES_DIR = debian/templates
KERNEL_ABINAME := 4.5.0-1
KERNEL_IMAGE_VERSION := 4.5.1-1
+SUITE = unstable
+
+MIRROR_URL = http://httpredir.debian.org/debian/
# For initial testing - to be replaced with HSM
KERNEL_SIGNER := benh at debian.org
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux-signed.git
More information about the Kernel-svn-changes
mailing list