Control: severity 861198 important

On 2017-04-25, Vagrant Cascadian wrote:
>> Is there a different way to get a copy of the files in doc/ ? 
>
> At a quick glance, there is:
>
>   http://ftp.us.debian.org/debian/extrafiles
>
> Which has the added benefit of being signed, lists the files we want,
> with checksums.
>
> The code used to download debian-installer images based on the signed
> Release files in the distribution is similar to what's needed to parse
> extrafiles... e.g. download extrafiles, verify the signature, look for
> the files we want, download the individual files... so that code could
> be re-used, refactored, rewritten, etc. to support this.

Ok, I drafted up quick-and-dirty, cut-and-pasty, rough, untested,
conceptual code to handle downloading the individual files by matching
what's in the "extrafiles" file, much like how the debian-installer
files check against the Release files, to download the *SUMS files, to
then get a list of files to install.

Initially, it just switches to only using wget to fetch individual
files, which should be fairly easy to then switch to httplib or some
other native python library...

Having worked on this so infrequently... all simple-cdd code could
really use some refactoring once the proof-of-concept is done... *sigh*


live well,
  vagrant

diff --git a/simple_cdd/gnupg.py b/simple_cdd/gnupg.py
index 2a930db..ed17fe6 100644
--- a/simple_cdd/gnupg.py
+++ b/simple_cdd/gnupg.py
@@ -29,6 +29,18 @@ class Gnupg:
             self.import_keyring(keyring_file)
 
 
+    def extract_inline_contents(self, pathname, sigpathname):
+        args = ["gpg", "--no-default-keyring"]
+        for k in self.env.get("keyring"):
+            args.extend(("--keyring", k))
+        args.extend("--decrypt")
+        args.extend(sigpathname)
+        contents = subprocess.Popen([args], stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
+        x = open(pathname, 'rx')
+        for line in contents:
+            x.write(line)
+        x.close()
+
     def verify_detached_sig(self, pathname, sigpathname):
         args = ["gpg", "--no-default-keyring"]
         for k in self.env.get("keyring"):
@@ -38,6 +50,15 @@ class Gnupg:
         if retval != 0:
             raise Fail("Signature verification failed on %s", pathname)
 
+    def verify_inline_sig(self, pathname):
+        args = ["gpg", "--no-default-keyring"]
+        for k in self.env.get("keyring"):
+            args.extend(("--keyring", k))
+        args.extend(("--verify", pathname))
+        retval = run_command("verify gpg signature", args)
+        if retval != 0:
+            raise Fail("Signature verification failed on %s", pathname)
+
     def import_keyring(self, keyring_file):
         """
         Import a keyring into our keyring file
diff --git a/simple_cdd/tools/mirror_wget.py b/simple_cdd/tools/mirror_wget.py
index d822936..7248270 100644
--- a/simple_cdd/tools/mirror_wget.py
+++ b/simple_cdd/tools/mirror_wget.py
@@ -35,26 +35,51 @@ class ToolMirrorWget(Tool):
             baseurl = env.get("wget_debian_mirror")
             path_depth = urlparse(baseurl).path.strip("/").count("/") + 1
 
-            def _wget_many(urls):
-                args = ["wget", "--continue", "--timestamping", "--no-verbose",
-                        "--no-parent", "--no-host-directories", "--recursive", 
"--cut-dirs={}".format(path_depth),
-                        "--directory-prefix=" + env.get("MIRROR")]
-                args.extend(urls)
-                retval = run_command("wget {} files".format(len(urls)), args, 
logfd=logfd, env=wget_env)
-                if retval != 0:
-                    raise Fail("wget exited with code %s, see %s for full 
output log", retval, logfilename)
-
             def _wget_one(url, output):
+                os.makedirs(os.path.dirname(output))
                 args = ["wget", "-O", output, url]
                 retval = run_command("wget {}".format(url), args, logfd=logfd, 
env=wget_env)
                 if retval != 0:
                     raise Fail("wget exited with code %s, see %s for full 
output log", retval, logfilename)
 
+            if env.get("mirror_files"):
+                # Download the checksums present in the archive "extrafiles" 
and verify
+                extrafiles_file = os.path.join(env.get("simple_cdd_temp"), 
"extrafiles")
+                extrafiles_file_inlinesig = extrafiles_file + ".inlinesig"
+                download_extrafiles_file = 
os.path.join(env.get("wget_debian_mirror"), "extrafiles")
+                _wget_one(download_extrafiles_file, extrafiles_file_inlinesig)
+                self.gnupg.verify_inline_sig(extrafiles_file_inlinesig)
+                self.gnupg.extract_inline_contents(extrafiles_file, 
extrafiles_file_inlinesig)
+
+                # import checksums
+                extrafile_sums = Checksums()
+                extrafile_sums.parse_checksums_file(extrafiles_file, 'SHA256')
+
+                ef=open(extrafiles_file, 'r')
+                efile=ef.readlines()
+                ef.close()
+                ef_match = re.compile(env.get("mirror_files"))
+                ef_files = []
+                for line in efile:
+                    hashsum, relname=line.split()
+                    if not ef_match.search(relname): continue
+                    if relname.startswith(x):
+                        if filename == x or x.endswith('/'):
+                            ef_files.append({
+                                "absname": os.path.join(env.get("MIRROR"), 
relname),
+                                "relname": relname,
+                                "url": 
os.path.join(env.get("wget_debian_mirror"), relname),
+                            })
+
+                for x in ef_files:
+                    _wget_one(x["url"], x["absname"])
+                    extrafile_sums.verify_file(x["absname"], x["relname"])
+
+
             checksum_files = env.get("checksum_files")
 
             # Download files needed to build debian-installer image
             files = []
-            files.extend(env.get("mirror_files"))
             files.extend(checksum_files)
 
             # Build the environment for running reprepro
@@ -62,7 +87,10 @@ class ToolMirrorWget(Tool):
             for name, val, changed in self.env.export_iter():
                 wget_env[name] = str(val)
 
-            _wget_many([urljoin(baseurl, x) for x in files])
+            for x in files:
+                p = os.path.join(env.get("simple_cdd_temp"), x)
+                d = os.path.join(env.get("wget_debian_mirror"), x)
+                _wget_one(d, p)
 
             if checksum_files:
                 # Get the release file and verify that it is valid
@@ -110,13 +138,12 @@ class ToolMirrorWget(Tool):
                                 "url": 
os.path.join(env.get("wget_debian_mirror"), dirname, relname),
                             })
 
-                    # Download the extra files
-                    _wget_many([x["url"] for x in extra_files])
-
                     # Check downloaded files against their corresponding 
checksums.
                     file_sums = Checksums()
                     file_sums.parse_checksums_file(absname, hashtype)
                     for f in extra_files:
+                        # Download the extra files
+                        _wget_one([f["url"], f["absname"])
                         file_sums.verify_file(f["absname"], f["relname"])
 
 

Attachment: signature.asc
Description: PGP signature

Reply via email to