From 1bc994ec866b25f33d1f5ea32b69145253068413 Mon Sep 17 00:00:00 2001 From: Mattia Bertorello Date: Wed, 3 Jul 2019 18:02:49 +0200 Subject: [PATCH] Use verifyDomain also for the library index --- .../DownloadableContributionsDownloader.java | 21 ++- .../libraries/LibraryInstaller.java | 27 ++-- .../arduino/utils/network/CacheControl.java | 153 +----------------- 3 files changed, 33 insertions(+), 168 deletions(-) diff --git a/arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java b/arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java index e669f0eb7..a0b811ba1 100644 --- a/arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java +++ b/arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java @@ -160,11 +160,8 @@ public class DownloadableContributionsDownloader { try { // Download package index download(packageIndexUrl, packageIndexTemp, progress, statusText, progressListener, true); - final List domain = new LinkedList<>(PreferencesData.getCollection("http.signature_verify_domains")); - // Default domain - domain.add("downloads.arduino.cc"); - if (domain.contains(packageIndexUrl.getHost())) { + if (verifyDomain(packageIndexUrl)) { URL signatureUrl = new URL(packageIndexUrl.toString() + ".sig"); if (checkSignature(progress, downloadedFilesAccumulator, signatureUrl, progressListener, signatureVerifier, statusText, packageIndexTemp)) { @@ -173,7 +170,7 @@ public class DownloadableContributionsDownloader { downloadedFilesAccumulator.remove(packageIndex.getName()); } } else { - log.info("The domain is not selected to verify the signature. domain list: {}, packageIndex: {}", domain, packageIndexUrl); + log.info("The domain is not selected to verify the signature. packageIndex: {}", packageIndexUrl); } } catch (Exception e) { downloadedFilesAccumulator.remove(packageIndex.getName()); @@ -184,6 +181,20 @@ public class DownloadableContributionsDownloader { } } + public boolean verifyDomain(URL url) { + final List domain = new LinkedList<>(PreferencesData.getCollection("http.signature_verify_domains")); + if (domain.size() == 0) { + // Default domain + domain.add("downloads.arduino.cc"); + } + if (domain.contains(url.getHost())) { + return true; + } else { + log.info("The domain is not selected to verify the signature. domain list: {}, url: {}", domain, url); + return false; + } + } + public boolean checkSignature(MultiStepProgress progress, List downloadedFilesAccumulator, URL signatureUrl, ProgressListener progressListener, SignatureVerifier signatureVerifier, String statusText, File fileToVerify) throws Exception { File packageIndexSignatureTemp = File.createTempFile(signatureUrl.getPath(), ".tmp"); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java b/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java index cdde5b20b..3f28204cc 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java @@ -87,20 +87,25 @@ public class LibraryInstaller { progress.stepDone(); URL signatureUrl = new URL(libraryURL.toString() + ".sig"); - if (downloader.checkSignature(progress, downloadedFilesAccumulator, signatureUrl, progressListener, signatureVerifier, statusText, libraryIndexTemp)) { - // Replace old index with the updated one - if (libraryIndexTemp.length() > 0) { - Files.move(libraryIndexTemp.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + if (downloader.verifyDomain(signatureUrl)) { + if (downloader.checkSignature(progress, downloadedFilesAccumulator, signatureUrl, progressListener, signatureVerifier, statusText, libraryIndexTemp)) { + // Replace old index with the updated one + if (libraryIndexTemp.length() > 0) { + Files.move(libraryIndexTemp.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + // Step 2: Parse index + BaseNoGui.librariesIndexer.parseIndex(); + + // Step 3: Rescan index + rescanLibraryIndex(progress, progressListener); + } else { + log.error("Fail to verify the signature of {}", libraryURL); } - - // Step 2: Parse index - BaseNoGui.librariesIndexer.parseIndex(); - - // Step 3: Rescan index - rescanLibraryIndex(progress, progressListener); } else { - log.error("Fail to verify the signature of {}", libraryURL); + log.info("The domain is not selected to verify the signature. library index: {}", signatureUrl); } + } public synchronized void install(ContributedLibrary lib, Optional mayReplacedLib, ProgressListener progressListener) throws Exception { diff --git a/arduino-core/src/cc/arduino/utils/network/CacheControl.java b/arduino-core/src/cc/arduino/utils/network/CacheControl.java index 432624356..4dc679a27 100644 --- a/arduino-core/src/cc/arduino/utils/network/CacheControl.java +++ b/arduino-core/src/cc/arduino/utils/network/CacheControl.java @@ -3,99 +3,22 @@ package cc.arduino.utils.network; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** - * Represents a HTTP Cache-Control response header and parses it from string. - * - *

Note: This class ignores 1#field-name parameter for - * private and no-cache directive and cache extensions.

- * - * @see HTTP/1.1 section 14.9 - */ public class CacheControl { - // copied from org.apache.abdera.protocol.util.CacheControlUtil + // see org.apache.abdera.protocol.util.CacheControlUtil private static final Pattern PATTERN = Pattern.compile("\\s*([\\w\\-]+)\\s*(=)?\\s*(\\-?\\d+|\\\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)+\\\")?\\s*"); - /** - * Corresponds to the max-age cache control directive. - * The default value is -1, i.e. not specified. - * - * @see HTTP/1.1 section 14.9.3 - */ private int maxAge = -1; - /** - * Corresponds to the s-maxage cache control directive. - * The default value is -1, i.e. not specified. - * - * @see HTTP/1.1 section 14.9.3 - */ - private int sMaxAge = -1; - - /** - * Whether the must-revalidate directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.4 - */ private boolean isMustRevalidate = false; - /** - * Whether the no-cache directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.1 - */ private boolean isNoCache = false; - /** - * Whether the no-store directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.2 - */ private boolean isNoStore = false; - /** - * Whether the no-transform directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.5 - */ - private boolean isNoTransform = false; - /** - * Whether the private directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.1 - */ - private boolean isPrivate = false; - - /** - * Whether the public directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.1 - */ - private boolean isPublic = false; - - /** - * Whether the proxy-revalidate directive is specified. - * The default value is false. - * - * @see HTTP/1.1 section 14.9.4 - */ - private boolean isProxyRevalidate = false; - - - /** - * Creates a new instance of CacheControl by parsing the supplied string. - * - * @param value A value the Cache-Control header. - */ public static CacheControl valueOf(String value) { CacheControl cc = new CacheControl(); @@ -105,22 +28,12 @@ public class CacheControl { switch (matcher.group(1).toLowerCase()) { case "max-age": cc.setMaxAge(Integer.parseInt(matcher.group(3))); break; - case "s-maxage": - cc.setSMaxAge(Integer.parseInt(matcher.group(3))); break; case "must-revalidate": cc.setMustRevalidate(true); break; case "no-cache": cc.setNoCache(true); break; case "no-store": cc.setNoStore(true); break; - case "no-transform": - cc.setNoTransform(true); break; - case "private": - cc.setPrivate(true); break; - case "public": - cc.setPublic(true); break; - case "proxy-revalidate": - cc.setProxyRevalidate(true); break; default: //ignore } } @@ -128,25 +41,6 @@ public class CacheControl { return cc; } - /** - * Returns max-age, or s-maxage according to whether - * considering a shared cache, or a private cache. If shared cache and the - * s-maxage is negative (i.e. not set), then returns - * max-age instead. - * - * @param sharedCache true for a shared cache, - * or false for a private cache - * @return A {@link #maxAge}, or {@link #sMaxAge} according to the given - * sharedCache argument. - */ - public int getMaxAge(boolean sharedCache) { - if (sharedCache) { - return sMaxAge >= 0 ? sMaxAge : maxAge; - } else { - return maxAge; - } - } - public void setMaxAge(int maxAge) { this.maxAge = maxAge; } @@ -155,14 +49,6 @@ public class CacheControl { return maxAge; } - public int getSMaxAge() { - return sMaxAge; - } - - public void setSMaxAge(int sMaxAge) { - this.sMaxAge = sMaxAge; - } - public boolean isMustRevalidate() { return isMustRevalidate; } @@ -187,50 +73,13 @@ public class CacheControl { isNoStore = noStore; } - public boolean isNoTransform() { - return isNoTransform; - } - - public void setNoTransform(boolean noTransform) { - isNoTransform = noTransform; - } - - public boolean isPrivate() { - return isPrivate; - } - - public void setPrivate(boolean aPrivate) { - isPrivate = aPrivate; - } - - public boolean isPublic() { - return isPublic; - } - - public void setPublic(boolean aPublic) { - isPublic = aPublic; - } - - public boolean isProxyRevalidate() { - return isProxyRevalidate; - } - - public void setProxyRevalidate(boolean proxyRevalidate) { - isProxyRevalidate = proxyRevalidate; - } - @Override public String toString() { return "CacheControl{" + "maxAge=" + maxAge + - ", sMaxAge=" + sMaxAge + ", isMustRevalidate=" + isMustRevalidate + ", isNoCache=" + isNoCache + ", isNoStore=" + isNoStore + - ", isNoTransform=" + isNoTransform + - ", isPrivate=" + isPrivate + - ", isPublic=" + isPublic + - ", isProxyRevalidate=" + isProxyRevalidate + '}'; } }