summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhackademix <giorgio@maone.net>2016-11-09 19:21:38 +0100
committerhackademix <giorgio@maone.net>2016-11-09 19:21:38 +0100
commit9ecc8b0569e4b9a69c21b7def3ef72b5f6c46dac (patch)
tree5d7ca1ecb3b339811387f2d4902de21820768a13
parent8ce21c4a899572524a7edd528f83f8b6f842e2d2 (diff)
Feature #10859 - remove any test/sample entry from config.json
-rw-r--r--build.sh11
-rw-r--r--tails-download-and-verify/.jpmignore4
-rw-r--r--tails-download-and-verify/bootstrap.js11
-rw-r--r--tails-download-and-verify/conf.json9
-rw-r--r--tails-download-and-verify/conf.json.sample39
-rw-r--r--tails-download-and-verify/install.rdf26
-rw-r--r--tails-download-and-verify/lib/mirror-dispatcher.js232
-rw-r--r--tails-download-and-verify/package.json2
-rw-r--r--www/dave.xpibin23179 -> 23412 bytes
-rw-r--r--www/download.html2
10 files changed, 322 insertions, 14 deletions
diff --git a/build.sh b/build.sh
index 231b711..35dc938 100644
--- a/build.sh
+++ b/build.sh
@@ -10,12 +10,17 @@ pushd "$dir" >/dev/null 2>&1 || (
echo -n "Removing old XPIs... "
rm -f *.xpi >/dev/null && echo "done."
ver=$(egrep '"version": "[0-9]+\.[^"]+"' package.json | sed -re 's/.*"([0-9]+\.[^"]+)".*/\1/')
-echo "Importing mirror-dispatcher.js library"
-[ -f "$mirror_dispatcher_file" ] || curl \
+
+if [ -f "$mirror_dispatcher_file" ]; then
+ echo "$mirror_dispatcher_file exists, won't download it (erase the local file to update from the $mirror_dispatcher_url)."
+else
+ echo "Importing $mirror_dispatcher_file from $mirror_dispatcher_url ..."
+ curl \
--proto -all,https \
--tlsv1 \
--output "$mirror_dispatcher_file" \
"$mirror_dispatcher_url"
+fi
echo "Building extension version $ver"
jpm xpi || exit 2
popd
@@ -23,7 +28,7 @@ echo "Copying "*.xpi" to $base/www/dave.xpi..."
cp "$dir/"*.xpi "$base/www/dave.xpi" >/dev/null
ver_page="$base/www/download.html"
ver_line=$(egrep '<[a-z][^>]+id="extension-version"[^>]*>[0-9]' $ver_page)
-if [ "$ver_line" ] && ! echo "$ver_line" | fgrep "$ver" ; then
+if [ "$ver_line" ] && ! echo "$ver_line" | grep -F "$ver" ; then
echo "Updating download.html to version $ver..."
sed -re 's/(<[a-z][^>]+id="extension-version"[^>]*>)[0-9\.rcba]+/\1'$ver'/' $ver_page > $ver_page.upd && mv $ver_page.upd $ver_page
fi
diff --git a/tails-download-and-verify/.jpmignore b/tails-download-and-verify/.jpmignore
new file mode 100644
index 0000000..d0c3bb8
--- /dev/null
+++ b/tails-download-and-verify/.jpmignore
@@ -0,0 +1,4 @@
+*.sample
+*.zip
+*.xpi
+.*
diff --git a/tails-download-and-verify/bootstrap.js b/tails-download-and-verify/bootstrap.js
new file mode 100644
index 0000000..4866564
--- /dev/null
+++ b/tails-download-and-verify/bootstrap.js
@@ -0,0 +1,11 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { utils: Cu } = Components;
+const rootURI = __SCRIPT_URI_SPEC__.replace("bootstrap.js", "");
+const COMMONJS_URI = "resource://gre/modules/commonjs";
+const { require } = Cu.import(COMMONJS_URI + "/toolkit/require.js", {});
+const { Bootstrap } = require(COMMONJS_URI + "/sdk/addon/bootstrap.js");
+const { startup, shutdown, install, uninstall } = new Bootstrap(rootURI);
diff --git a/tails-download-and-verify/conf.json b/tails-download-and-verify/conf.json
index 35e89d5..a62f785 100644
--- a/tails-download-and-verify/conf.json
+++ b/tails-download-and-verify/conf.json
@@ -8,18 +8,9 @@
"tails.boum.org": {
"certs": null,
"issuers": ["Let's Encrypt", "Gandi"]
- },
- "labs.riseup.net": {
- "issuers": ["Let's Encrypt", "Gandi"]
}
},
"certs": {
- "*.boum.org": {
- "subjectName":"CN=*.boum.org,OU=Gandi Standard Wildcard SSL,OU=Domain Control Validated",
- "issuerOrganization":"Gandi",
- "sha256Fingerprint":"FB:89:1F:85:61:8D:6F:62:EA:A6:6E:92:4D:3A:FC:80:17:03:D6:FB:D5:F4:B0:31:E7:D7:5A:7F:55:06:74:2D",
- "serialNumber":"00:84:A7:E7:40:C4:D4:54:54:64:E4:35:22:38:F0:29:53"
- },
"Gandi": {
"subjectName":"CN=Gandi Standard SSL CA 2,O=Gandi,L=Paris,ST=Paris,C=FR",
"issuerOrganization":"The USERTRUST Network",
diff --git a/tails-download-and-verify/conf.json.sample b/tails-download-and-verify/conf.json.sample
new file mode 100644
index 0000000..35e89d5
--- /dev/null
+++ b/tails-download-and-verify/conf.json.sample
@@ -0,0 +1,39 @@
+{
+ "descriptor": "https://tails.boum.org/install/v1/Tails/i386/stable/latest.yml",
+ "fallback_download_url_prefix": "http://dl.amnesia.boum.org/tails",
+ "mirror_pool_url": "https://tails.boum.org/mirrors.json",
+ "pinGlobally": true,
+ "pins": {
+ "domains": {
+ "tails.boum.org": {
+ "certs": null,
+ "issuers": ["Let's Encrypt", "Gandi"]
+ },
+ "labs.riseup.net": {
+ "issuers": ["Let's Encrypt", "Gandi"]
+ }
+ },
+ "certs": {
+ "*.boum.org": {
+ "subjectName":"CN=*.boum.org,OU=Gandi Standard Wildcard SSL,OU=Domain Control Validated",
+ "issuerOrganization":"Gandi",
+ "sha256Fingerprint":"FB:89:1F:85:61:8D:6F:62:EA:A6:6E:92:4D:3A:FC:80:17:03:D6:FB:D5:F4:B0:31:E7:D7:5A:7F:55:06:74:2D",
+ "serialNumber":"00:84:A7:E7:40:C4:D4:54:54:64:E4:35:22:38:F0:29:53"
+ },
+ "Gandi": {
+ "subjectName":"CN=Gandi Standard SSL CA 2,O=Gandi,L=Paris,ST=Paris,C=FR",
+ "issuerOrganization":"The USERTRUST Network",
+ "sha256Fingerprint":"B9:F2:16:43:23:63:8D:CE:0B:92:21:8B:43:C4:1C:1B:2B:26:96:38:93:29:DB:19:F5:CF:7A:D4:9B:5C:B3:72",
+ "serialNumber":"05:E4:DC:3B:94:38:AB:3B:85:97:CB:A6:A1:98:50:E3"
+ },
+ "Let's Encrypt": {
+ "subjectName":"CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US",
+ "commonName":"Let's Encrypt Authority X3",
+ "issuerOrganization":"Digital Signature Trust Co.",
+ "organization":"Let's Encrypt",
+ "sha256Fingerprint":"25:84:7D:66:8E:B4:F0:4F:DD:40:B1:2B:6B:07:40:C5:67:DA:7D:02:43:08:EB:6C:2C:96:FE:41:D9:DE:21:8D",
+ "serialNumber":"0A:01:41:42:00:00:01:53:85:73:6A:0B:85:EC:A7:08"
+ }
+ }
+ }
+}
diff --git a/tails-download-and-verify/install.rdf b/tails-download-and-verify/install.rdf
new file mode 100644
index 0000000..3bc8981
--- /dev/null
+++ b/tails-download-and-verify/install.rdf
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>dave@tails.boum.org</em:id>
+ <em:type>2</em:type>
+ <em:bootstrap>true</em:bootstrap>
+ <em:unpack>false</em:unpack>
+ <em:version>0.2.9rc1</em:version>
+ <em:name>Tails Download and Verify</em:name>
+ <em:description>A browser extension to download and verify Tails ISO images</em:description>
+ <em:creator>Giorgio Maone</em:creator>
+ <em:homepageURL>https://tails.boum.org</em:homepageURL>
+ <em:multiprocessCompatible>true</em:multiprocessCompatible>
+
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>38.0a1</em:minVersion>
+ <em:maxVersion>39.0</em:maxVersion>
+</Description>
+</em:targetApplication>
+
+
+ </Description>
+
+</RDF>
diff --git a/tails-download-and-verify/lib/mirror-dispatcher.js b/tails-download-and-verify/lib/mirror-dispatcher.js
new file mode 100644
index 0000000..ab467b2
--- /dev/null
+++ b/tails-download-and-verify/lib/mirror-dispatcher.js
@@ -0,0 +1,232 @@
+/*
+@licstart
+Copyright (C) 2015-2016 Tails Developers
+
+ The JavaScript code in this page is free software: you can
+ redistribute it and/or modify it under the terms of the GNU
+ General Public License (GNU GPL) as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option)
+ any later version. The code is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
+
+ As additional permission under GNU GPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally requestuired by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+@licend
+*/
+
+'use strict';
+
+/*
+ * To enable console logging in production set DEBUG to true
+ */
+
+var DEBUG = false;
+// Allow debugging through the JS console
+if(DEBUG === false) {
+ var console = { log: function() {} };
+}
+
+/*
+ * Some versions of IE do not support logging to the console.
+ * When we set ALERTFALLBACK to true, we can log to alert.
+ * In any case, if console function does not exist, we do not want to log
+ * nor throw an error, thus disabling console.log.
+ */
+
+var ALERTFALLBACK = false;
+if (typeof console === "undefined" || typeof console.log === "undefined") {
+ console = {};
+ if (ALERTFALLBACK) {
+ console.log = function(msg) {
+ alert(msg);
+ };
+ } else {
+ console.log = function() {};
+ }
+}
+
+function get(path, callback) {
+
+ var max_expected_filelength = 8 * Math.pow(2,10);
+
+ // Do the usual request stuff
+ var request = new XMLHttpRequest();
+ request.open('GET', path);
+
+ // Handle network errors
+ request.onerror = function() {
+ console.log("Network Error");
+ return false;
+ };
+
+ request.onreadystatechange = function() {
+ // Check the status
+ // 4 = Headers and responseText have been loaded.
+ if (request.readyState === 4) {
+ // console.log(request.getAllResponseHeaders());
+ // check filesize is not too big
+ if(request.responseText.length > max_expected_filelength) {
+ console.log("Retrieved content too big. Response length: " + request.responseText.length + " max_expected_filelength: " + max_expected_filelength);
+ request.abort();
+ return false;
+ }
+ // Check TLS
+ if(!/^https:\/\//.test(request.responseURL)) {
+ console.log("File not served over TLS.");
+ request.abort();
+ return false;
+ }
+ // empty string = text responseType
+ if(request.responseType != "") {
+ console.log("Expected responseType is text.");
+ request.abort();
+ return false;
+ }
+
+ // 200 = The request has succeeded.
+ if (request.status === 200) {
+ var data = request.responseText;
+ console.log("data = request.responseText: " + data);
+ if (callback) {
+ callback(data);
+ }
+ } else {
+ console.log(request.statusText);
+ request.abort();
+ return false;
+ }
+ }
+ };
+
+ // Make the request
+ request.send();
+}
+
+/*
+ * Choose a random mirror, based on weight.
+ * weight="0" - this mirror is not active.
+ * There is no max weight.
+ * @params: JSON mirror data, formatted like this:
+ - schema: https://git-tails.immerda.ch/mirror-pool/tree/schema.json
+ - example: https://git-tails.immerda.ch/mirror-pool/tree/example-mirrors.json
+ * @returns false or one randomly chosen host URL prefix
+ */
+function getRandomMirrorUrlPrefix(data) {
+ if (data.mirrors.length > 0) {
+ var end_of_last_range = 0,
+ i,
+ mirrors = [],
+ picked_value,
+ ranges_end = [];
+
+ // Build a "compressed" version of the array that would contain N times each
+ // mirror, with N being its weight. We "compress" it by only storing, for
+ // each mirror, the index of the last element it would occupy in the
+ // uncompressed version of the array.
+ for (i = 0; i < data.mirrors.length; i++) {
+ ranges_end[i]
+ = end_of_last_range
+ = end_of_last_range + data.mirrors[i].weight;
+ }
+
+ // If we were using the "uncompressed" version of the aforementioned array,
+ // we would do something like Math.random() * uncompressed_array.length,
+ // and the result would be the mirror we want. But here we are using
+ // a "compressed" version of this array, so the result we get instead is
+ // the minimum *weight* of the mirror we pick randomly.
+ picked_value = Math.floor(Math.random() * end_of_last_range) + 1;
+
+ // Pick the first mirror that would occupy a range that ends at or after
+ // uncompressed_array[picked_value] in the "uncompressed" version
+ // of the array. I.e. once converted to the "compressed" optimization:
+ // the one whose ranges_end[i] is bigger or equal to picked_value.
+ for (i = 0; i < data.mirrors.length; i++) {
+ if (picked_value <= ranges_end[i]) {
+ if(isValidURL(data.mirrors[i].url_prefix)) {
+ return data.mirrors[i].url_prefix;
+ }
+ }
+ }
+ } else {
+ return false;
+ }
+}
+
+/*
+ * Returns true if url is a valid URL pattern
+ */
+function isValidURL(url) {
+ var url_pattern = new RegExp('^(http|https):\/\/[a-z0-9\-_]+(\.[a-z0-9\-_]+)+([a-z0-9\-_\.,@\?^=%&;:/~\+#]*[a-z0-9\-\_#@\?^=%&;/~\+])?$', 'i');
+ var test = url_pattern.test(url)
+ console.log("Tested URL: " + url + " " + test);
+ return(test);
+}
+
+/*
+ * This is the main function call, to be called by our website
+ */
+function replaceUrlPrefixWithRandomMirror(linkelements) {
+ var data, index, max_expected_linkelements, url_current, fallback_download_url_prefix, url_new, url_prefix;
+
+ max_expected_linkelements = 15;
+ if(linkelements.length > max_expected_linkelements) {
+ console.log(linkelements.length + " exceeds number of expected elements: " + max_expected_linkelements);
+ return false;
+ }
+
+ fallback_download_url_prefix = "http://dl.amnesia.boum.org/tails/";
+
+ return get('/mirrors.json', function(data){
+ if( data !== "undefined" ) {
+ data = JSON.parse(data);
+
+ // pick a random mirror
+ url_prefix = getRandomMirrorUrlPrefix(data);
+ console.log("Random URL prefix: " + url_prefix);
+
+ if(url_prefix) {
+ // replace the default prefix with the newly picked one,
+ // in the href of each linkelement
+ for (index = 0; index < linkelements.length; index++) {
+ // remove possible URL whitespaces and line breaks as created by ikiwiki
+ url_current = linkelements[index].getAttribute('href');
+ url_current = url_current.trim();
+ if (url_current !== 'undefined' && isValidURL(url_current)) {
+ url_new = url_prefix +
+ url_current.slice(fallback_download_url_prefix.length);
+ console.log("index: "+ index + " url_current: " + url_current + " --> url_new:" + url_new);
+ linkelements[index].setAttribute('href', url_new)
+ } else {
+ console.log(url_current + " appears to be malformed.");
+ }
+ }
+ } else {
+ console.log("Could not determine url_prefix.");
+ }
+ }
+ });
+}
+
+/* This function is used by DAVE instead of
+ * replaceUrlPrefixWithRandomMirror().
+ * Use mirror pool configuration and select a random mirror.
+ */
+function transformURL(url, fallback_download_url_prefix, mirrors) {
+ return getRandomMirrorUrlPrefix(mirrors) +
+ url.slice(fallback_download_url_prefix.length);
+}
+
+/*
+ * Assign transformURL to exports, so that it can be used
+ * by tails-transform-mirror-url via nodejs.
+ * Will return target object.
+ */
+
+if(typeof exports !== 'undefined') {
+ // Now we know that we're not running in the browser
+ module.exports.transformURL = transformURL;
+}
diff --git a/tails-download-and-verify/package.json b/tails-download-and-verify/package.json
index c386f3d..441addd 100644
--- a/tails-download-and-verify/package.json
+++ b/tails-download-and-verify/package.json
@@ -3,7 +3,7 @@
"id": "dave@tails.boum.org",
"name": "tails-download-and-verify",
"homepage": "https://tails.boum.org",
- "version": "0.2.8rc2",
+ "version": "0.2.9rc1",
"description": "A browser extension to download and verify Tails ISO images",
"main": "index.js",
"permissions": {
diff --git a/www/dave.xpi b/www/dave.xpi
index 514a043..0d3e7be 100644
--- a/www/dave.xpi
+++ b/www/dave.xpi
Binary files differ
diff --git a/www/download.html b/www/download.html
index 3695d06..ab58443 100644
--- a/www/download.html
+++ b/www/download.html
@@ -250,7 +250,7 @@ For your security, it is very important to also verify your download. We propose
two techniques to do this verification automatically.</p>
<div id="download-and-verify" class="chrome-unsupported">
- <div id="extension-version">0.2.8rc2</div>
+ <div id="extension-version">0.2.9rc1</div>
<div id="undetected-browser">
<p>We failed to detect your browser vendor, maybe because JavaScript is disabled.</p>