You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ma...@apache.org on 2019/12/10 19:45:27 UTC
[netbeans] branch master updated (1f0916a -> 4bb8e4c)
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git.
from 1f0916a [NETBEANS-3559] Corrected compiler warnings in Bootstrap project.
new c1f912a Ensure only safe redirects are followed and simplify connection handling
new d09dc3a Require NBMs to be fully signed
new 58ded71 Base certificate validation in UpdateCenter on KeyStore and not on trust to the embedded certpath
new 03a4c48 Expose modified/damaged Plugins in verification GUI
new 8e4916e Add option to provide a message digest in update center
new 2982cf4 Problem Panel shows plain text - ensure, that that is correctly displayed
new cf4a7da Allow marking an AutoupdateCatalogProvider as trusted
new d92aeb8 Include message digest into generate update center (SHA-512)
new 4bb8e4c Merge branch 'improve_updatecenter_wip'
The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../modules/updatecenters/resources/mf-layer.xml | 1 +
.../org/netbeans/nbbuild/MakeUpdateDesc.java | 92 +++++-
platform/autoupdate.services/apichanges.xml | 41 +++
platform/autoupdate.services/build.xml | 40 +++
.../libsrc/org/netbeans/updater/XMLUtil.java | 2 +
.../updater/resources/autoupdate-catalog-2_8.dtd | 96 ++++++
platform/autoupdate.services/manifest.mf | 2 +-
.../api/autoupdate/UpdateUnitProvider.java | 23 ++
.../autoupdate/services/InstallSupportImpl.java | 106 +++++-
.../autoupdate/services/MessageDigestChecker.java | 152 +++++++++
.../autoupdate/services/UpdateElementImpl.java | 29 +-
.../autoupdate/services/UpdateUnitFactory.java | 11 +-
.../services/UpdateUnitProviderImpl.java | 43 ++-
.../modules/autoupdate/services/Utilities.java | 359 +++++++++++++--------
.../updateprovider/AutoupdateCatalogCache.java | 2 +-
.../updateprovider/AutoupdateCatalogFactory.java | 7 +
.../updateprovider/AutoupdateCatalogParser.java | 25 +-
.../updateprovider/AutoupdateCatalogProvider.java | 13 +
.../updateprovider/MessageDigestValue.java | 79 +++++
.../autoupdate/updateprovider/NetworkAccess.java | 134 +++-----
.../autoupdate/updateprovider/UpdateItemImpl.java | 20 ++
.../netbeans/spi/autoupdate/KeyStoreProvider.java | 45 ++-
.../services/MessageDigestCheckerTest.java | 48 +++
.../autoupdate/services/VerifyFileTest.java | 58 +++-
platform/autoupdate.ui/manifest.mf | 2 +-
platform/autoupdate.ui/nbproject/project.xml | 12 +-
.../modules/autoupdate/ui/Bundle.properties | 1 +
.../modules/autoupdate/ui/ProblemPanel.form | 19 +-
.../modules/autoupdate/ui/ProblemPanel.java | 12 +-
.../modules/autoupdate/ui/SettingsTab.java | 5 +-
.../autoupdate/ui/UpdateUnitProviderPanel.form | 27 +-
.../autoupdate/ui/UpdateUnitProviderPanel.java | 24 +-
.../autoupdate/ui/wizards/Bundle.properties | 3 +-
.../ui/wizards/ValidationWarningPanel.form | 78 +++--
.../ui/wizards/ValidationWarningPanel.java | 90 ++++--
35 files changed, 1354 insertions(+), 347 deletions(-)
create mode 100644 platform/autoupdate.services/libsrc/org/netbeans/updater/resources/autoupdate-catalog-2_8.dtd
create mode 100644 platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/MessageDigestChecker.java
create mode 100644 platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/MessageDigestValue.java
create mode 100644 platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/MessageDigestCheckerTest.java
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 02/09: Require NBMs to be fully signed
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit d09dc3a37f84efcde3d276697db15ac4ffddb596
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Sat Nov 2 22:27:44 2019 +0100
Require NBMs to be fully signed
After this change every file contained in a NBM is checked and required
to be signed. Partitial/inconsistent signatures will be reported as a
modified package.
---
platform/autoupdate.services/build.xml | 12 ++
.../autoupdate/services/InstallSupportImpl.java | 50 +++++--
.../modules/autoupdate/services/Utilities.java | 155 ++++++++++++++++-----
.../autoupdate/services/VerifyFileTest.java | 37 ++++-
4 files changed, 202 insertions(+), 52 deletions(-)
diff --git a/platform/autoupdate.services/build.xml b/platform/autoupdate.services/build.xml
index 8e0f1ed..971c989 100644
--- a/platform/autoupdate.services/build.xml
+++ b/platform/autoupdate.services/build.xml
@@ -53,6 +53,7 @@
<target name="do-unit-test-build" depends="projectized.do-unit-test-build">
<touch file="${build.dir}/Dummy.class" />
+ <touch file="${build.dir}/Dummy2.class" />
<jar destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-signed.jar">
<zipfileset prefix="dummy/" file="${build.dir}/Dummy.class"/>
</jar>
@@ -71,6 +72,17 @@
keystore="${test.unit.src.dir}/org/netbeans/api/autoupdate/data/test-keystore.jks"
storepass="password"
alias="test-two" />
+ <jar destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-partial-signed.jar">
+ <zipfileset prefix="dummy/" file="${build.dir}/Dummy.class"/>
+ </jar>
+ <signjar jar="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-partial-signed.jar"
+ keystore="${test.unit.src.dir}/org/netbeans/api/autoupdate/data/test-keystore.jks"
+ storepass="password"
+ alias="test-one" />
+ <zip destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-partial-signed.jar"
+ update="true">
+ <zipfileset prefix="dummy/" file="${build.dir}/Dummy2.class" />
+ </zip>
</target>
</project>
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 1644392..43e7f84 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -30,11 +30,11 @@ import java.net.URLConnection;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.KeyStoreException;
+import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
@@ -66,6 +66,8 @@ import org.openide.util.NbBundle;
import org.openide.util.NbCollections;
import org.xml.sax.SAXException;
+import static org.netbeans.modules.autoupdate.services.Utilities.VERIFICATION_RESULT_COMPARATOR;
+
/**
*
* @author Jiri Rechtacek
@@ -1050,29 +1052,55 @@ public class InstallSupportImpl {
}
private int verifyNbm (UpdateElement el, File nbmFile, ProgressHandle progress, int verified) throws OperationException {
- String res;
+ String res = null;
try {
// get trusted certificates
- List<Certificate> trustedCerts = new ArrayList<Certificate> ();
+ Set<Certificate> trustedCerts = new HashSet<> ();
for (KeyStore ks : Utilities.getKeyStore ()) {
- trustedCerts.addAll (Utilities.getCertificates (ks));
+ trustedCerts.addAll(Utilities.getCertificates(ks));
}
// load user certificates
KeyStore ks = Utilities.loadKeyStore ();
if (ks != null) {
- trustedCerts.addAll (Utilities.getCertificates (ks));
+ trustedCerts.addAll(Utilities.getCertificates(ks));
}
-
+
verified += el.getDownloadSize ();
if (progress != null) {
progress.progress (el.getDisplayName (), verified < wasDownloaded ? verified : wasDownloaded);
}
- Collection<Certificate> nbmCerts = Utilities.getNbmCertificates (nbmFile);
- if (nbmCerts != null && nbmCerts.size () > 0) {
- certs.put (el, nbmCerts);
- }
- res = Utilities.verifyCertificates(nbmCerts, trustedCerts);
+
UpdateElementImpl impl = Trampoline.API.impl(el);
+
+ try {
+ Collection<CertPath> nbmCerts = Utilities.getNbmCertificates(nbmFile);
+ if(nbmCerts == null) {
+ res = Utilities.N_A;
+ } else if (nbmCerts.isEmpty()) {
+ res = Utilities.UNSIGNED;
+ } else {
+ // Iterate all certpaths that can be considered for the NBM
+ // choose the certpath, that has the highest trust level
+ // TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED
+ // or comes first
+ for(CertPath cp: nbmCerts) {
+ String localRes = Utilities.verifyCertificates(cp, trustedCerts);
+ // If there is no previous result or if the local
+ // verification yielded a better result than the
+ // previous result, replace it
+ if (res == null
+ || VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
+ res = localRes;
+ certs.put(el, (List<Certificate>) cp.getCertificates());
+ }
+ }
+ }
+ } catch (SecurityException ex) {
+ LOG.log(Level.INFO, "The content of the jar/nbm has been modified or certificate paths were inconsistent - " + ex.getMessage(), ex);
+ res = Utilities.MODIFIED;
+ modified.add(impl);
+ }
+
if (res != null) {
switch (res) {
case Utilities.MODIFIED:
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
index f5d886b..fcd3139 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
@@ -22,6 +22,7 @@ package org.netbeans.modules.autoupdate.services;
import java.io.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
+import java.security.CodeSigner;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -46,6 +47,7 @@ import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
+import java.util.regex.Pattern;
import org.netbeans.Module;
import org.netbeans.ModuleManager;
import org.netbeans.api.autoupdate.UpdateElement;
@@ -104,10 +106,9 @@ public class Utilities {
private static final String KS_USER_PASSWORD = "open4user";
private static Lookup.Result<KeyStoreProvider> result;
private static final Logger err = Logger.getLogger(Utilities.class.getName ());
-
-
+
public static Collection<KeyStore> getKeyStore () {
- if (result == null) {
+ if (result == null) {
result = Lookup.getDefault ().lookupResult (KeyStoreProvider.class);
result.addLookupListener (new KeyStoreProviderListener ());
}
@@ -115,27 +116,32 @@ public class Utilities {
if (c == null || c.isEmpty ()) {
return Collections.emptyList ();
}
- List<KeyStore> kss = new ArrayList<>();
-
+
+ List<KeyStore> kss = new ArrayList<>();
for (KeyStoreProvider provider : c) {
KeyStore ks = provider.getKeyStore ();
if (ks != null) {
kss.add (ks);
}
}
-
+
return kss;
}
-
- public static String verifyCertificates(Collection<Certificate> archiveCertificates, Collection<Certificate> trustedCertificates) {
- if (archiveCertificates == null) {
- return N_A;
- }
+
+ /**
+ *
+ * @param archiveCertPath
+ * @param trustedCertificates
+ * @return
+ */
+ public static String verifyCertificates(CertPath archiveCertPath, Collection<? extends Certificate> trustedCertificates) {
+ assert archiveCertPath != null;
+ List<? extends Certificate> archiveCertificates = archiveCertPath.getCertificates();
if (!archiveCertificates.isEmpty()) {
Collection<Certificate> c = new HashSet<>(trustedCertificates);
c.retainAll(archiveCertificates);
- if (c.isEmpty()) {
- Map<Principal, X509Certificate> certSubjectsMap = new HashMap<>();
+ if (c.isEmpty()) {
+ Map<Principal, X509Certificate> certSubjectsMap = new HashMap<>();
Set<Principal> certIssuersSet = new HashSet<>();
for (Certificate cert : archiveCertificates) {
if (cert != null) {
@@ -146,17 +152,15 @@ public class Utilities {
}
}
}
-
Map<X509Certificate, X509Certificate> candidates = new HashMap<>();
-
for (Principal p : certSubjectsMap.keySet()) {
// cert chain may not be ordered - trust anchor could before certificate itself
if (certIssuersSet.contains(p)) {
continue;
}
-
+
X509Certificate cert = certSubjectsMap.get(p);
-
+
Principal tap = cert.getIssuerDN();
if (tap != null) {
X509Certificate tempTrustAnchor = certSubjectsMap.get(tap);
@@ -164,12 +168,12 @@ public class Utilities {
candidates.put(cert, tempTrustAnchor);
}
}
- }
+ }
// TRUSTED = 2
// SIGNATURE_VERIFIED = 1
// SIGNATURE_UNVERIFIED = 0
- int res = 0;
+ int res = 0;
for (X509Certificate cert : candidates.keySet()) {
X509Certificate trustCert = candidates.get(cert);
PKIXCertPathValidatorResult validResult = null;
@@ -196,9 +200,9 @@ public class Utilities {
err.log(Level.INFO, "Cannot validate certificate path - " + ex.getMessage(), ex);
//SIGNATURE_UNVERIFIED - result = 0;
} catch (SecurityException ex) {
- // When jar/nbm correctly signed, but content modified
+ // When jar/nbm correctly signed, but content modified
err.log(Level.INFO, "The content of the jar/nbm has been modified - " + ex.getMessage(), ex);
- return MODIFIED;
+ return MODIFIED;
}
if (validResult != null) {
@@ -209,17 +213,17 @@ public class Utilities {
break;
} else {
res = 1;
- }
+ }
}
}
-
+
switch (res) {
case 2:
return TRUSTED;
case 1:
return SIGNATURE_VERIFIED;
default:
- return SIGNATURE_UNVERIFIED;
+ return SIGNATURE_UNVERIFIED;
}
} else {
// signed by trusted certificate stored in user's keystore od ide.ks
@@ -228,7 +232,43 @@ public class Utilities {
}
return UNSIGNED;
}
-
+
+ /**
+ * Establishes an order for verificication result strings. Only the values
+ * <ul>
+ * <li>{@code null}</li>
+ * <li>{@link #UNSIGNED}</li>
+ * <li>{@link #SIGNATURE_UNVERIFIED}</li>
+ * <li>{@link #SIGNATURE_VERIFIED}</li>
+ * <li>{@link #TRUSTED}</li>
+ * </ul>
+ *
+ * @param verificationResult1
+ * @param verificationResult2
+ * @return
+ */
+ public static final Comparator<String> VERIFICATION_RESULT_COMPARATOR = new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ int i1 = mapVerificationResultToInt(o1);
+ int i2 = mapVerificationResultToInt(o2);
+ return i1 - i2;
+ }
+ };
+
+ private static int mapVerificationResultToInt(String input) {
+ if(input == null) {
+ return 0;
+ }
+ switch(input) {
+ case UNSIGNED: return 1;
+ case SIGNATURE_UNVERIFIED: return 2;
+ case SIGNATURE_VERIFIED: return 3;
+ case TRUSTED: return 4;
+ default: throw new IllegalArgumentException("Unmappable value: " + input);
+ }
+ }
+
public static Collection<Certificate> getCertificates (KeyStore keyStore) throws KeyStoreException {
Set<Certificate> certs = new HashSet<Certificate> ();
for (String alias: Collections.list (keyStore.aliases ())) {
@@ -240,33 +280,72 @@ public class Utilities {
}
return certs;
}
-
- public static Collection<Certificate> getNbmCertificates (File nbmFile) throws IOException {
- Set<Certificate> certs = new HashSet<Certificate>();
- JarFile jf = new JarFile(nbmFile);
+
+ /**
+ * Get the certpaths that were used to sign the NBM content.
+ *
+ * @param nbmFile
+ * @return collection of CertPaths, that were used to sign the non-signature
+ * entries of the NBM
+ * @throws IOException
+ * @throws SecurityException if JAR was tampered with or if the certificate
+ * chains are not consistent
+ */
+ public static Collection<CertPath> getNbmCertificates (File nbmFile) throws IOException, SecurityException {
+ Set<CertPath> certs = null;
+
+ // Empty means only the MANIFEST.MF is present - special cased to be in
+ // line with established behaviour
boolean empty = true;
- try {
+
+ // The idea:
+ // - iterate over all JAR entries
+ // - read each entry (as required by the JarFile specificiation for verification)
+ // - extract the certificate paths, that were used to sign the
+ // entry
+ // - compare it with the previously read entries. If they are not
+ // identical, raise a SecurityException.
+ //
+ // Excluded from the above algorithm are:
+ // - directory entries
+ // - files that are part of the signature (each entry in META-INF, that
+ // ends with .SF, .DSA, .RSA or .EC
+ try (JarFile jf = new JarFile(nbmFile)) {
for (JarEntry entry : Collections.list(jf.entries())) {
verifyEntry(jf, entry);
- if (!entry.getName().startsWith("META-INF/")) {
- empty = false;
- if (entry.getCertificates() != null) {
- certs.addAll(Arrays.asList(entry.getCertificates()));
+ if ((! entry.isDirectory()) && (! isSignatureEntry(entry))) {
+ if(! entry.getName().equals("META-INF/MANIFEST.MF")) {
+ empty = false;
+ }
+ Set<CertPath> entryCerts = new HashSet<>();
+ CodeSigner[] codeSigners = entry.getCodeSigners();
+ if (codeSigners != null) {
+ for (CodeSigner cs : entry.getCodeSigners()) {
+ entryCerts.add(cs.getSignerCertPath());
+ }
+ }
+ if(certs == null) {
+ certs = entryCerts;
+ } else if (! certs.equals(entryCerts)) {
+ throw new SecurityException("Inconsistent certificate paths used for signing");
}
}
}
- } finally {
- jf.close();
}
return empty ? null : certs;
}
-
+
+ private static final Pattern SIGNATURE_PATTERN = Pattern.compile("META-INF/([^/]+)\\.(SF|DSA|RSA|EC)");
+ private static boolean isSignatureEntry(JarEntry je) {
+ return SIGNATURE_PATTERN.matcher(je.getName()).matches();
+ }
+
/**
* @throws SecurityException
*/
@SuppressWarnings("empty-statement")
- private static void verifyEntry (JarFile jf, JarEntry je) throws IOException {
+ private static void verifyEntry (JarFile jf, JarEntry je) throws IOException, SecurityException {
InputStream is = null;
try {
is = jf.getInputStream (je);
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
index 9b6da19..b55e48f 100644
--- a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
@@ -27,6 +27,7 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
+import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.util.Collection;
import java.util.logging.Level;
@@ -34,6 +35,8 @@ import java.util.logging.Logger;
import org.netbeans.api.autoupdate.TestUtils;
import org.netbeans.junit.NbTestCase;
+import static org.netbeans.modules.autoupdate.services.Utilities.VERIFICATION_RESULT_COMPARATOR;
+
public class VerifyFileTest extends NbTestCase {
private static final Logger LOG = Logger.getLogger(VerifyFileTest.class.getName());
@@ -58,9 +61,33 @@ public class VerifyFileTest extends NbTestCase {
assertNotNull(urlToFile);
File jar = org.openide.util.Utilities.toFile(urlToFile.toURI());
assertTrue(jar.exists());
- Collection<Certificate> nbmCertificates = Utilities.getNbmCertificates(jar);
- Collection<Certificate> trustedCertificates = Utilities.getCertificates(ks);
- return Utilities.verifyCertificates(nbmCertificates, trustedCertificates);
+ String res = null;
+ try {
+ Collection<CertPath> nbmCerts = Utilities.getNbmCertificates(jar);
+ Collection<Certificate> trustedCerts = Utilities.getCertificates(ks);
+ if (nbmCerts == null) {
+ res = Utilities.N_A;
+ } else if (nbmCerts.isEmpty()) {
+ res = Utilities.UNSIGNED;
+ } else {
+ // Iterate all certpaths that can be considered for the NBM
+ // choose the certpath, that has the highest trust level
+ // TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED -> UNSIGNED
+ // or comes first
+ for (CertPath cp : nbmCerts) {
+ String localRes = Utilities.verifyCertificates(cp, trustedCerts);
+ if (res == null
+ || VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
+ res = localRes;
+ }
+ }
+ }
+ } catch (SecurityException ex) {
+ LOG.log(Level.INFO, "The content of the jar/nbm has been modified or certificate paths were inconsistent - " + ex.getMessage(), ex);
+ res = Utilities.MODIFIED;
+ }
+
+ return res;
}
@SuppressWarnings("unchecked")
@@ -86,6 +113,10 @@ public class VerifyFileTest extends NbTestCase {
assertEquals(Utilities.TRUSTED, doVerification("data/dummy-signed-twice.jar"));
}
+ public void testUnsignedPartiallySigned() throws MalformedURLException, URISyntaxException, IOException, KeyStoreException {
+ assertEquals(Utilities.MODIFIED, doVerification("data/dummy-partial-signed.jar"));
+ }
+
private static KeyStore getKeyStore(File file, String password) {
if (file == null) {
return null;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 06/09: Problem Panel shows plain text - ensure,
that that is correctly displayed
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 2982cf4498fd3f1561bbd01ee03b66032012a183
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Mon Nov 11 21:48:25 2019 +0100
Problem Panel shows plain text - ensure, that that is correctly displayed
---
.../netbeans/modules/autoupdate/ui/ProblemPanel.form | 19 ++++++++-----------
.../netbeans/modules/autoupdate/ui/ProblemPanel.java | 12 +++++-------
2 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.form b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.form
index dce5dfb..bc654d7 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.form
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.form
@@ -22,6 +22,11 @@
-->
<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <Properties>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[700, 400]"/>
+ </Property>
+ </Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties" key="NetworkProblemPanel_ACD" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
@@ -42,16 +47,16 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cbShowAgain" alignment="1" max="32767" attributes="0"/>
- <Component id="jScrollPane1" alignment="0" pref="425" max="32767" attributes="0"/>
+ <Component id="jScrollPane1" alignment="0" pref="682" max="32767" attributes="0"/>
<Component id="jScrollPane2" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
- <Component id="jScrollPane2" pref="106" max="32767" attributes="0"/>
+ <Component id="jScrollPane2" pref="140" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
- <Component id="jScrollPane1" pref="169" max="32767" attributes="0"/>
+ <Component id="jScrollPane1" pref="201" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="cbShowAgain" min="-2" max="-2" attributes="0"/>
</Group>
@@ -79,11 +84,7 @@
<Component class="javax.swing.JTextPane" name="tpMessage">
<Properties>
<Property name="editable" type="boolean" value="false"/>
- <Property name="contentType" type="java.lang.String" value="text/html" noResource="true"/>
<Property name="opaque" type="boolean" value="false"/>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[400, 100]"/>
- </Property>
</Properties>
</Component>
</SubComponents>
@@ -98,11 +99,7 @@
<Component class="javax.swing.JTextPane" name="taTitle">
<Properties>
<Property name="editable" type="boolean" value="false"/>
- <Property name="contentType" type="java.lang.String" value="text/html" noResource="true"/>
<Property name="opaque" type="boolean" value="false"/>
- <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
- <Dimension value="[200, 100]"/>
- </Property>
</Properties>
</Component>
</SubComponents>
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.java b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.java
index 6876782..cc4ab13 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.java
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/ProblemPanel.java
@@ -176,6 +176,8 @@ public class ProblemPanel extends javax.swing.JPanel {
jScrollPane2 = new javax.swing.JScrollPane();
taTitle = new javax.swing.JTextPane();
+ setPreferredSize(new java.awt.Dimension(700, 400));
+
org.openide.awt.Mnemonics.setLocalizedText(cbShowAgain, org.openide.util.NbBundle.getMessage(ProblemPanel.class, "ProblemPanel.cbShowAgain.text")); // NOI18N
cbShowAgain.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -184,15 +186,11 @@ public class ProblemPanel extends javax.swing.JPanel {
});
tpMessage.setEditable(false);
- tpMessage.setContentType("text/html"); // NOI18N
tpMessage.setOpaque(false);
- tpMessage.setPreferredSize(new java.awt.Dimension(400, 100));
jScrollPane1.setViewportView(tpMessage);
taTitle.setEditable(false);
- taTitle.setContentType("text/html"); // NOI18N
taTitle.setOpaque(false);
- taTitle.setPreferredSize(new java.awt.Dimension(200, 100));
jScrollPane2.setViewportView(taTitle);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@@ -200,15 +198,15 @@ public class ProblemPanel extends javax.swing.JPanel {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cbShowAgain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 425, Short.MAX_VALUE)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 682, Short.MAX_VALUE)
.addComponent(jScrollPane2)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
- .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 169, Short.MAX_VALUE)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cbShowAgain))
);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 09/09: Merge branch 'improve_updatecenter_wip'
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 4bb8e4cd7bbf48f28ebba606083228ebf0d2dde3
Merge: 1f0916a d92aeb8
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Tue Dec 10 20:03:48 2019 +0100
Merge branch 'improve_updatecenter_wip'
Review on private@netbeans.apache.org - References:
https://lists.apache.org/thread.html/3313fe7ecab7d861356f2a2d218041ee97aafec588120ade4e7480d3%40%3Cprivate.netbeans.apache.org%3E
https://lists.apache.org/thread.html/3313fe7ecab7d861356f2a2d218041ee97aafec588120ade4e7480d3%40%3Cprivate.netbeans.apache.org%3E
https://lists.apache.org/thread.html/4b628153ef6ce965d757608926e2a6dae1ebee3a6ba9ee630c4d7c6d%40%3Cprivate.netbeans.apache.org%3E
.../modules/updatecenters/resources/mf-layer.xml | 1 +
.../org/netbeans/nbbuild/MakeUpdateDesc.java | 92 +++++-
platform/autoupdate.services/apichanges.xml | 41 +++
platform/autoupdate.services/build.xml | 40 +++
.../libsrc/org/netbeans/updater/XMLUtil.java | 2 +
.../updater/resources/autoupdate-catalog-2_8.dtd | 96 ++++++
platform/autoupdate.services/manifest.mf | 2 +-
.../api/autoupdate/UpdateUnitProvider.java | 23 ++
.../autoupdate/services/InstallSupportImpl.java | 106 +++++-
.../autoupdate/services/MessageDigestChecker.java | 152 +++++++++
.../autoupdate/services/UpdateElementImpl.java | 29 +-
.../autoupdate/services/UpdateUnitFactory.java | 11 +-
.../services/UpdateUnitProviderImpl.java | 43 ++-
.../modules/autoupdate/services/Utilities.java | 359 +++++++++++++--------
.../updateprovider/AutoupdateCatalogCache.java | 2 +-
.../updateprovider/AutoupdateCatalogFactory.java | 7 +
.../updateprovider/AutoupdateCatalogParser.java | 25 +-
.../updateprovider/AutoupdateCatalogProvider.java | 13 +
.../updateprovider/MessageDigestValue.java | 79 +++++
.../autoupdate/updateprovider/NetworkAccess.java | 134 +++-----
.../autoupdate/updateprovider/UpdateItemImpl.java | 20 ++
.../netbeans/spi/autoupdate/KeyStoreProvider.java | 45 ++-
.../services/MessageDigestCheckerTest.java | 48 +++
.../autoupdate/services/VerifyFileTest.java | 58 +++-
platform/autoupdate.ui/manifest.mf | 2 +-
platform/autoupdate.ui/nbproject/project.xml | 12 +-
.../modules/autoupdate/ui/Bundle.properties | 1 +
.../modules/autoupdate/ui/ProblemPanel.form | 19 +-
.../modules/autoupdate/ui/ProblemPanel.java | 12 +-
.../modules/autoupdate/ui/SettingsTab.java | 5 +-
.../autoupdate/ui/UpdateUnitProviderPanel.form | 27 +-
.../autoupdate/ui/UpdateUnitProviderPanel.java | 24 +-
.../autoupdate/ui/wizards/Bundle.properties | 3 +-
.../ui/wizards/ValidationWarningPanel.form | 78 +++--
.../ui/wizards/ValidationWarningPanel.java | 90 ++++--
35 files changed, 1354 insertions(+), 347 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 04/09: Expose modified/damaged Plugins in verification
GUI
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 03a4c48ef8db3684e3ed635a701bb67bb8a21a47
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Tue Nov 5 18:53:06 2019 +0100
Expose modified/damaged Plugins in verification GUI
UpdateItems, that failed validation, where not reported in the
Plugin Manager GUI, but still blocked installation. This changeset adds
a new node into the certificate validation dialog which lists the
"Modified/Damaged" Plugins. This allows the user to see the plugins,
which block installation.
---
.../autoupdate/services/InstallSupportImpl.java | 10 ++-
.../autoupdate/ui/wizards/Bundle.properties | 3 +-
.../ui/wizards/ValidationWarningPanel.form | 78 ++++++++++++-------
.../ui/wizards/ValidationWarningPanel.java | 90 +++++++++++++++-------
4 files changed, 121 insertions(+), 60 deletions(-)
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 5db31b9..28263fc 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -1056,6 +1056,13 @@ public class InstallSupportImpl {
}
private int verifyNbm (UpdateElement el, File nbmFile, ProgressHandle progress, int verified) throws OperationException {
+ UpdateElementImpl impl = Trampoline.API.impl(el);
+
+ modified.remove(impl);
+ trusted.remove(impl);
+ signedVerified.remove(impl);
+ signedUnverified.remove(impl);
+
String res = null;
try {
// get trusted certificates
@@ -1086,8 +1093,6 @@ public class InstallSupportImpl {
progress.progress (el.getDisplayName (), verified < wasDownloaded ? verified : wasDownloaded);
}
- UpdateElementImpl impl = Trampoline.API.impl(el);
-
try {
Collection<CodeSigner> nbmCerts = Utilities.getNbmCertificates(nbmFile);
if(nbmCerts == null) {
@@ -1114,7 +1119,6 @@ public class InstallSupportImpl {
} catch (SecurityException ex) {
LOG.log(Level.INFO, "The content of the jar/nbm has been modified or certificate paths were inconsistent - " + ex.getMessage(), ex);
res = Utilities.MODIFIED;
- modified.add(impl);
}
if (res != null) {
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties
index e0f4999..7086f1f 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties
@@ -164,4 +164,5 @@ InstallStep_DownloadProblem=There were some problems while storing {0}.\nCause:
InstallStep_DownloadProblem_SomePlugins=selected plugins
LicenseApprovalPanel.lbPlugins.text=Plugins:
OperationDescriptionStep_NoteCachesNotBuilt=<br><hr><br>\
- <b>Note:</b> Missing modules may be published on Update Centers. Please run "<b>Check for Newest</b>" from the "<b>Available Plugins</b>" tab.
\ No newline at end of file
+ <b>Note:</b> Missing modules may be published on Update Centers. Please run "<b>Check for Newest</b>" from the "<b>Available Plugins</b>" tab.
+ValidationWarningPanel.taError.text=Error: There were plugins, that were modified or damaged, Installation can't continue.
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.form b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.form
index 70d3f6c..09ee81d 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.form
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.form
@@ -22,6 +22,20 @@
-->
<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <Properties>
+ <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+ <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
+ <EmptyBorder bottom="6" left="6" right="6" top="6"/>
+ </Border>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[480, 400]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[480, 400]"/>
+ </Property>
+ <Property name="requestFocusEnabled" type="boolean" value="false"/>
+ </Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties" key="ValidationWarningPanel_ACD" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
@@ -36,36 +50,10 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,4,29,0,0,1,-30"/>
</AuxValues>
- <Layout>
- <DimensionLayout dim="0">
- <Group type="103" groupAlignment="0" attributes="0">
- <Group type="102" attributes="0">
- <EmptySpace min="-2" max="-2" attributes="0"/>
- <Group type="103" groupAlignment="0" attributes="0">
- <Component id="spPlugins" alignment="0" max="32767" attributes="0"/>
- <Component id="taHead" alignment="0" max="32767" attributes="2"/>
- <Component id="taWarning" alignment="1" max="32767" attributes="2"/>
- </Group>
- <EmptySpace min="-2" max="-2" attributes="0"/>
- </Group>
- </Group>
- </DimensionLayout>
- <DimensionLayout dim="1">
- <Group type="103" groupAlignment="0" attributes="0">
- <Group type="102" alignment="0" attributes="0">
- <EmptySpace min="-2" max="-2" attributes="0"/>
- <Component id="taHead" min="-2" pref="57" max="-2" attributes="0"/>
- <EmptySpace min="-2" max="-2" attributes="0"/>
- <Component id="spPlugins" pref="196" max="32767" attributes="0"/>
- <EmptySpace min="-2" max="-2" attributes="0"/>
- <Component id="taWarning" pref="58" max="32767" attributes="0"/>
- <EmptySpace min="-2" max="-2" attributes="0"/>
- </Group>
- </Group>
- </DimensionLayout>
- </Layout>
+ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="taHead">
<Properties>
@@ -82,8 +70,37 @@
<ResourceString bundle="org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties" key="ValidationWarningPanel_taHead_ACN" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
</Property>
</AccessibilityProperties>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ <Component class="javax.swing.JTextArea" name="taError">
+ <Properties>
+ <Property name="editable" type="boolean" value="false"/>
+ <Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+ <Color blue="12" green="0" red="cc" type="rgb"/>
+ </Property>
+ <Property name="lineWrap" type="boolean" value="true"/>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties" key="ValidationWarningPanel.taError.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ <Property name="wrapStyleWord" type="boolean" value="true"/>
+ <Property name="opaque" type="boolean" value="false"/>
+ </Properties>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="512" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
</Component>
<Container class="javax.swing.JScrollPane" name="spPlugins">
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
+ </Constraint>
+ </Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
@@ -114,6 +131,11 @@
<ResourceString bundle="org/netbeans/modules/autoupdate/ui/wizards/Bundle.properties" key="ValidationWarningPanel_taWarning_Text_ACD" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
</Property>
</AccessibilityProperties>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="512" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
</Component>
</SubComponents>
</Form>
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.java b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.java
index a60b35d..e413163 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.java
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/wizards/ValidationWarningPanel.java
@@ -44,6 +44,8 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
taHead.setBorder(BorderFactory.createEmptyBorder());
taWarning.setBackground( new Color(0,0,0,0) );
taWarning.setBorder(BorderFactory.createEmptyBorder());
+ taError.setVisible(! modified.isEmpty());
+ taHead.setVisible(modified.isEmpty());
postInitComponents (signedVerified, signedUnverified, unsigned, modified, total);
}
@@ -51,6 +53,7 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
DefaultMutableTreeNode signedAndValidNode = new DefaultMutableTreeNode("Signed and Valid (" + signedVerified.size() + ")");
DefaultMutableTreeNode selfSignedNode = new DefaultMutableTreeNode("Self signed (" + signedUnverified.size() + ")");
DefaultMutableTreeNode unsignedNode = new DefaultMutableTreeNode("Unsigned (" + unsigned.size() + ")");
+ DefaultMutableTreeNode modifiedNode = new DefaultMutableTreeNode("Modified/Damaged (" + modified.size() + ")");
for (UpdateElement el : signedVerified) {
signedAndValidNode.add(new DefaultMutableTreeNode(el.getDisplayName()));
@@ -66,7 +69,12 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
unsignedNode.add(new DefaultMutableTreeNode(el.getDisplayName()));
}
pluginModelRoot.add(unsignedNode);
-
+
+ for (UpdateElement el : modified) {
+ modifiedNode.add(new DefaultMutableTreeNode(el.getDisplayName()));
+ }
+ pluginModelRoot.add(modifiedNode);
+
pluginsModel.reload();
int requiresAttention = signedVerified.size() + signedUnverified.size() + unsigned.size();
@@ -78,6 +86,10 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
taHead.setText(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taHead_NotTrustedTextSg",
requiresAttention, total));
}
+
+ if(modified.size() > 0) {
+
+ }
}
public String getSelectedNode() {
@@ -96,52 +108,73 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
taHead = new javax.swing.JTextArea();
+ taError = new javax.swing.JTextArea();
spPlugins = new javax.swing.JScrollPane();
tPlugins = new javax.swing.JTree();
taWarning = new javax.swing.JTextArea();
+ setBorder(javax.swing.BorderFactory.createEmptyBorder(6, 6, 6, 6));
+ setMinimumSize(new java.awt.Dimension(480, 400));
+ setPreferredSize(new java.awt.Dimension(480, 400));
+ setRequestFocusEnabled(false);
+ setLayout(new java.awt.GridBagLayout());
+
taHead.setEditable(false);
taHead.setLineWrap(true);
taHead.setWrapStyleWord(true);
taHead.setOpaque(false);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 3, 0);
+ add(taHead, gridBagConstraints);
+ taHead.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taHead_ACN")); // NOI18N
+ taHead.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taHead_ACN")); // NOI18N
+
+ taError.setEditable(false);
+ taError.setForeground(new java.awt.Color(204, 0, 18));
+ taError.setLineWrap(true);
+ taError.setText(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel.taError.text")); // NOI18N
+ taError.setWrapStyleWord(true);
+ taError.setOpaque(false);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE_LEADING;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 3, 0);
+ add(taError, gridBagConstraints);
tPlugins.setModel(pluginsModel);
spPlugins.setViewportView(tPlugins);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.weighty = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
+ add(spPlugins, gridBagConstraints);
+
taWarning.setEditable(false);
taWarning.setLineWrap(true);
taWarning.setText(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taWarning_Text")); // NOI18N
taWarning.setWrapStyleWord(true);
taWarning.setOpaque(false);
-
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
- this.setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addContainerGap()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(spPlugins, javax.swing.GroupLayout.DEFAULT_SIZE, 398, Short.MAX_VALUE)
- .addComponent(taHead)
- .addComponent(taWarning, javax.swing.GroupLayout.Alignment.TRAILING))
- .addContainerGap())
- );
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(taHead, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(spPlugins, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(taWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 58, Short.MAX_VALUE)
- .addContainerGap())
- );
-
- taHead.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taHead_ACN")); // NOI18N
- taHead.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taHead_ACN")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 3;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.BASELINE_LEADING;
+ gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0);
+ add(taWarning, gridBagConstraints);
taWarning.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taWarning_Text_ACN")); // NOI18N
taWarning.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ValidationWarningPanel.class, "ValidationWarningPanel_taWarning_Text_ACD")); // NOI18N
@@ -152,6 +185,7 @@ public class ValidationWarningPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane spPlugins;
private javax.swing.JTree tPlugins;
+ private javax.swing.JTextArea taError;
private javax.swing.JTextArea taHead;
private javax.swing.JTextArea taWarning;
// End of variables declaration//GEN-END:variables
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 07/09: Allow marking an AutoupdateCatalogProvider as
trusted
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit cf4a7da15d780197b87beab6ef3ce59eb1122e46
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Fri Nov 15 20:53:37 2019 +0100
Allow marking an AutoupdateCatalogProvider as trusted
When an AutoupdateCatalogProvider is marked as trusted and the Auto Update
Service can make a connection between the catalog and the update item,
the update item will also be trusted. The connection can for example be
established if the catalog provides checksums/hashes/message digests for
the referenced items.
---
.../modules/updatecenters/resources/mf-layer.xml | 1 +
platform/autoupdate.services/apichanges.xml | 18 +++++++
platform/autoupdate.services/manifest.mf | 2 +-
.../api/autoupdate/UpdateUnitProvider.java | 23 +++++++++
.../autoupdate/services/InstallSupportImpl.java | 60 ++++++++++++----------
.../autoupdate/services/UpdateElementImpl.java | 13 ++++-
.../autoupdate/services/UpdateUnitFactory.java | 11 ++--
.../services/UpdateUnitProviderImpl.java | 43 +++++++++++++++-
.../updateprovider/AutoupdateCatalogFactory.java | 7 +++
.../updateprovider/AutoupdateCatalogProvider.java | 13 +++++
.../autoupdate/updateprovider/UpdateItemImpl.java | 9 ++++
platform/autoupdate.ui/manifest.mf | 2 +-
platform/autoupdate.ui/nbproject/project.xml | 12 ++---
.../modules/autoupdate/ui/Bundle.properties | 1 +
.../modules/autoupdate/ui/SettingsTab.java | 5 +-
.../autoupdate/ui/UpdateUnitProviderPanel.form | 27 +++++++++-
.../autoupdate/ui/UpdateUnitProviderPanel.java | 24 +++++++--
17 files changed, 221 insertions(+), 50 deletions(-)
diff --git a/nb/updatecenters/src/org/netbeans/modules/updatecenters/resources/mf-layer.xml b/nb/updatecenters/src/org/netbeans/modules/updatecenters/resources/mf-layer.xml
index de190a3..b57d7a8 100644
--- a/nb/updatecenters/src/org/netbeans/modules/updatecenters/resources/mf-layer.xml
+++ b/nb/updatecenters/src/org/netbeans/modules/updatecenters/resources/mf-layer.xml
@@ -31,6 +31,7 @@
<attr name="url" bundlevalue="org.netbeans.modules.updatecenters.resources.Bundle#URL_Distribution"/>
<attr name="category" stringvalue="STANDARD"/>
<attr name="enabled" boolvalue="true"/>
+ <attr name="trusted" boolvalue="true"/>
<attr name="instanceOf" stringvalue="org.netbeans.spi.autoupdate.UpdateProvider" />
<attr name="instanceCreate" methodvalue="org.netbeans.modules.autoupdate.updateprovider.AutoupdateCatalogFactory.createUpdateProvider"/>
</file>
diff --git a/platform/autoupdate.services/apichanges.xml b/platform/autoupdate.services/apichanges.xml
index 350a3a2..a51099c 100644
--- a/platform/autoupdate.services/apichanges.xml
+++ b/platform/autoupdate.services/apichanges.xml
@@ -33,6 +33,24 @@
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
+ <change id="enable-trusted-update-centers">
+ <api name="general"/>
+ <summary>KeyStoreProviders can now report which trustlevel they intent to supply</summary>
+ <version major="1" minor="62"/>
+ <date day="4" month="11" year="2019"/>
+ <author login="matthiasblaesing"/>
+ <compatibility addition="yes" binary="compatible" deletion="no" deprecation="no" semantic="compatible" source="compatible"/>
+ <description>
+ <p>
+ The UpdateUnitProvider can now be declared trusted. If
+ UpdateItems are provided by a trusted UpdateUnitProvider
+ and can be linked to it (for example because the provider provides
+ checksums in the catalog), they are considered trusted by the Autoupdate
+ mechanism and will not trigger certificate warnings.
+ </p>
+ </description>
+ <class package="org.netbeans.api.autoupdate" name="OperationContainer"/>
+ </change>
<change id="keystores-for-validation">
<api name="general"/>
<summary>KeyStoreProviders can now report which trustlevel they intent to supply</summary>
diff --git a/platform/autoupdate.services/manifest.mf b/platform/autoupdate.services/manifest.mf
index f664430..c9df2d4 100644
--- a/platform/autoupdate.services/manifest.mf
+++ b/platform/autoupdate.services/manifest.mf
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.autoupdate.services
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/services/resources/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.61
+OpenIDE-Module-Specification-Version: 1.62
OpenIDE-Module-Layer: org/netbeans/modules/autoupdate/services/resources/layer.xml
AutoUpdate-Show-In-Client: false
AutoUpdate-Essential-Module: true
diff --git a/platform/autoupdate.services/src/org/netbeans/api/autoupdate/UpdateUnitProvider.java b/platform/autoupdate.services/src/org/netbeans/api/autoupdate/UpdateUnitProvider.java
index 80d17d2..92f2e8c 100644
--- a/platform/autoupdate.services/src/org/netbeans/api/autoupdate/UpdateUnitProvider.java
+++ b/platform/autoupdate.services/src/org/netbeans/api/autoupdate/UpdateUnitProvider.java
@@ -193,4 +193,27 @@ public final class UpdateUnitProvider {
public String toString() {
return super.toString() + "[" + impl + "]";
}
+
+ /** Sets the trusted flag.
+ *
+ * @see #isTrusted
+ * @param trusted
+ * @since 1.62
+ */
+ public void setTrusted (boolean trusted) {
+ impl.setTrusted(trusted);
+ }
+
+ /** Returns <code>true</code> if the provider is considered to be trusted.
+ * If {@link UpdateItem} are provided by a trusted {@code UpdateUnitProvider}
+ * and can be linked to it (for example because the provider provides
+ * checksums in the catalog), they are considered trusted by the Autoupdate
+ * mechanism and will not trigger certificate warnings.
+ *
+ * @return trusted flag
+ * @since 1.62
+ */
+ public boolean isTrusted () {
+ return impl.isTrusted();
+ }
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 7a37748..61f7ba9 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -1093,34 +1093,6 @@ public class InstallSupportImpl {
progress.progress (el.getDisplayName (), verified < wasDownloaded ? verified : wasDownloaded);
}
- try {
- Collection<CodeSigner> nbmCerts = Utilities.getNbmCertificates(nbmFile);
- if(nbmCerts == null) {
- res = Utilities.N_A;
- } else if (nbmCerts.isEmpty()) {
- res = Utilities.UNSIGNED;
- } else {
- // Iterate all certpaths that can be considered for the NBM
- // choose the certpath, that has the highest trust level
- // TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED
- // or comes first
- for(CodeSigner cs: nbmCerts) {
- String localRes = Utilities.verifyCertificates(cs, trustedCerts, trustedCACerts, validationCerts, validationCACerts);
- // If there is no previous result or if the local
- // verification yielded a better result than the
- // previous result, replace it
- if (res == null
- || VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
- res = localRes;
- certs.put(el, (List<Certificate>) cs.getSignerCertPath().getCertificates());
- }
- }
- }
- } catch (SecurityException ex) {
- LOG.log(Level.INFO, "The content of the jar/nbm has been modified or certificate paths were inconsistent - " + ex.getMessage(), ex);
- res = Utilities.MODIFIED;
- }
-
{
MessageDigestChecker mdChecker = new MessageDigestChecker(impl.getMessageDigests());
byte[] buffer = new byte[102400];
@@ -1141,6 +1113,38 @@ public class InstallSupportImpl {
});
}
res = Utilities.MODIFIED;
+ } else if (mdChecker.isDigestAvailable() && impl.isCatalogTrusted()) {
+ res = Utilities.TRUSTED;
+ }
+ }
+
+ if(res == null) {
+ try {
+ Collection<CodeSigner> nbmCerts = Utilities.getNbmCertificates(nbmFile);
+ if (nbmCerts == null) {
+ res = Utilities.N_A;
+ } else if (nbmCerts.isEmpty()) {
+ res = Utilities.UNSIGNED;
+ } else {
+ // Iterate all certpaths that can be considered for the NBM
+ // choose the certpath, that has the highest trust level
+ // TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED
+ // or comes first
+ for (CodeSigner cs : nbmCerts) {
+ String localRes = Utilities.verifyCertificates(cs, trustedCerts, trustedCACerts, validationCerts, validationCACerts);
+ // If there is no previous result or if the local
+ // verification yielded a better result than the
+ // previous result, replace it
+ if (res == null
+ || VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
+ res = localRes;
+ certs.put(el, (List<Certificate>) cs.getSignerCertPath().getCertificates());
+ }
+ }
+ }
+ } catch (SecurityException ex) {
+ LOG.log(Level.INFO, "The content of the jar/nbm has been modified or certificate paths were inconsistent - " + ex.getMessage(), ex);
+ res = Utilities.MODIFIED;
}
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
index d2ba5dd..31a2688 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
@@ -38,11 +38,13 @@ public abstract class UpdateElementImpl extends Object {
private UpdateUnit unit;
private UpdateElement element;
private List<MessageDigestValue> messageDigests = new ArrayList<>();
-
+ private boolean catalogTrusted = false;
+
public UpdateElementImpl (UpdateItemImpl item, String providerName) {
if(item.getMessageDigests() != null) {
messageDigests.addAll(item.getMessageDigests());
}
+ this.catalogTrusted = item.isCatalogTrusted();
}
public UpdateUnit getUpdateUnit () {
@@ -113,4 +115,13 @@ public abstract class UpdateElementImpl extends Object {
public void setMessageDigests(List<MessageDigestValue> messageDigests) {
this.messageDigests = messageDigests;
}
+
+ public boolean isCatalogTrusted() {
+ return catalogTrusted;
+ }
+
+ public void setCatalogTrusted(boolean catalogTrusted) {
+ this.catalogTrusted = catalogTrusted;
+ }
+
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitFactory.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitFactory.java
index 646df0a..529ada0 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitFactory.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitFactory.java
@@ -113,7 +113,7 @@ public class UpdateUnitFactory {
for (UpdateUnitProvider up : updates) {
UpdateUnitProviderImpl impl = Trampoline.API.impl (up);
-
+
// append units from provider
mappedImpl = appendUpdateItems (mappedImpl, impl.getUpdateProvider ());
reportRunTime ("AppendUpdateItems for " + impl.getUpdateProvider ().getDisplayName ());
@@ -126,7 +126,7 @@ public class UpdateUnitFactory {
//TODO: this call should be forced not to be called from AWT
//assert !SwingUtilities.isEventDispatchThread();
resetRunTime ("Measuring UpdateUnitFactory.getUpdateUnits (" + provider.getDisplayName () + ")"); // NOI18N
-
+
// append units from provider
Map<String, UpdateUnit> temp = appendUpdateItems (new HashMap<String, UpdateUnit> (), provider);
reportRunTime ("Get appendUpdateItems for " + provider.getDisplayName ());
@@ -143,6 +143,8 @@ public class UpdateUnitFactory {
Map<String, UpdateUnit> appendUpdateItems (Map<String, UpdateUnit> originalUnits, UpdateProvider provider) {
assert originalUnits != null : "Map of original UnitImpl cannot be null";
+ boolean trusted = UpdateUnitProviderImpl.loadTrusted(provider);
+
Map<String, UpdateItem> items;
try {
items = provider.getUpdateItems ();
@@ -155,7 +157,7 @@ public class UpdateUnitFactory {
// append updates
for (String simpleItemId : items.keySet ()) {
-
+
UpdateElement updateEl = null;
try {
@@ -204,6 +206,7 @@ public class UpdateUnitFactory {
// add element to map
if (updateEl != null) {
+ Trampoline.API.impl(updateEl).setCatalogTrusted(trusted);
addElement (originalUnits, updateEl, provider);
}
}
@@ -282,7 +285,7 @@ public class UpdateUnitFactory {
// set UpdateUnit into element
elImpl.setUpdateUnit (unit);
-
+
}
private UpdateUnit mergeInstalledUpdateUnit (UpdateUnit uu) {
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitProviderImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitProviderImpl.java
index 102ee99..adc8f20 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitProviderImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateUnitProviderImpl.java
@@ -31,6 +31,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
@@ -68,6 +69,7 @@ public final class UpdateUnitProviderImpl {
private static final String URL = "url";
private static final String DISPLAY_NAME = "displayName";
private static final String ENABLED = "enabled";
+ private static final String TRUSTED = "trusted";
private static final String CATEGORY_NAME = "categoryName";
private static final LookupListenerImpl UPDATE_PROVIDERS = new LookupListenerImpl();
@@ -133,7 +135,15 @@ public final class UpdateUnitProviderImpl {
public void setProviderURL (URL url) {
storeUrl (getUpdateProvider (), url);
}
-
+
+ public boolean isTrusted() {
+ return loadTrusted(getUpdateProvider());
+ }
+
+ public void setTrusted(Boolean trusted) {
+ storeTrusted(getUpdateProvider(), trusted);
+ }
+
public List<UpdateUnit> getUpdateUnits (UpdateManager.TYPE... types) {
return UpdateManagerImpl.getUpdateUnits (getUpdateProvider (), types);
}
@@ -343,6 +353,7 @@ public final class UpdateUnitProviderImpl {
String toUrl = providerPreferences.get (URL, providerPreferences.get (AutoupdateCatalogFactory.ORIGINAL_URL, null));
String displayName = providerPreferences.get (DISPLAY_NAME, providerPreferences.get (AutoupdateCatalogFactory.ORIGINAL_DISPLAY_NAME, codeName));
String categoryName = providerPreferences.get (CATEGORY_NAME, providerPreferences.get (AutoupdateCatalogFactory.ORIGINAL_CATEGORY_NAME, CATEGORY.COMMUNITY.name()));
+ Boolean trusted = providerPreferences.getBoolean(TRUSTED, providerPreferences.getBoolean(AutoupdateCatalogFactory.ORIGINAL_TRUSTED, false));
CATEGORY c;
try {
c = CATEGORY.valueOf(categoryName);
@@ -368,7 +379,9 @@ public final class UpdateUnitProviderImpl {
} catch (MalformedURLException mue) {
assert false : mue;
}
- return new AutoupdateCatalogProvider (codeName, displayName, url, pc);
+ AutoupdateCatalogProvider acp = new AutoupdateCatalogProvider (codeName, displayName, url, pc);
+ acp.setTrusted(trusted);
+ return acp;
}
private static boolean loadState (String codename) {
@@ -461,6 +474,32 @@ public final class UpdateUnitProviderImpl {
}
}
+ static boolean loadTrusted (UpdateProvider p) {
+ Preferences providerPreferences = getPreferences ().node (p.getName ());
+ assert providerPreferences != null : "Preferences node " + p.getName () + " found.";
+
+ Boolean trusted = null;
+ if (p instanceof AutoupdateCatalogProvider) {
+ trusted = ((AutoupdateCatalogProvider) p).isTrusted();
+ }
+ if(trusted == null) {
+ trusted = false;
+ }
+ return providerPreferences.getBoolean(TRUSTED, trusted);
+ }
+
+ private static void storeTrusted (UpdateProvider p, Boolean trusted) {
+ Preferences providerPreferences = getPreferences ().node (p.getName ());
+ assert providerPreferences != null : "Preferences node " + p.getName () + " found.";
+
+ // store only if differs
+ if (trusted == null) {
+ providerPreferences.remove (TRUSTED);
+ } else {
+ providerPreferences.putBoolean(TRUSTED, trusted);
+ }
+ }
+
private static class LookupListenerImpl implements LookupListener {
final Lookup.Result<UpdateProvider> result = Lookup.getDefault ().lookupResult(UpdateProvider.class);
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogFactory.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogFactory.java
index ae134a1..1f0ec51 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogFactory.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogFactory.java
@@ -62,6 +62,7 @@ public class AutoupdateCatalogFactory {
public static final String ORIGINAL_ENABLED = "originalEnabled"; // NOI18N
public static final String ORIGINAL_CATEGORY_NAME = "originalCategoryName"; // NOI18N
public static final String ORIGINAL_CATEGORY_ICON_BASE = "originalCategoryIconBase"; // NOI18N
+ public static final String ORIGINAL_TRUSTED = "originalTrusted"; // NOI18N
public static UpdateProvider createUpdateProvider (FileObject fo) {
String sKey = (String) fo.getAttribute ("url_key"); // NOI18N
@@ -143,6 +144,12 @@ public class AutoupdateCatalogFactory {
providerPreferences.putBoolean (ORIGINAL_ENABLED, en);
}
+ Boolean trusted = (Boolean) fo.getAttribute("trusted"); // NOI18N
+ if(trusted != null) {
+ au_catalog.setTrusted(trusted);
+ providerPreferences.putBoolean(ORIGINAL_TRUSTED, trusted);
+ }
+
return au_catalog;
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogProvider.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogProvider.java
index a9ea300..326fd11 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogProvider.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogProvider.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.autoupdate.UpdateUnitProvider.CATEGORY;
+import org.netbeans.modules.autoupdate.services.Trampoline;
import org.netbeans.spi.autoupdate.UpdateItem;
import org.netbeans.spi.autoupdate.UpdateProvider;
import org.openide.util.Parameters;
@@ -45,6 +46,7 @@ public class AutoupdateCatalogProvider implements UpdateProvider {
private ProviderCategory category;
private String contentDescription;
private boolean contentDescriptionInitialized;
+ private boolean trusted;
public AutoupdateCatalogProvider (String name, String displayName, URL updateCenter) {
this(name, displayName, updateCenter, ProviderCategory.forValue(CATEGORY.COMMUNITY));
@@ -117,6 +119,9 @@ public class AutoupdateCatalogProvider implements UpdateProvider {
synchronized(cache.getLock(toParse)) {
map = AutoupdateCatalogParser.getUpdateItems (toParse, this);
}
+ for(UpdateItem ui: map.values()) {
+ UpdateItemImpl impl = Trampoline.SPI.impl(ui);
+ }
descriptionInitialized = true;
return map;
}
@@ -158,4 +163,12 @@ public class AutoupdateCatalogProvider implements UpdateProvider {
public ProviderCategory getProviderCategory() {
return category;
}
+
+ public boolean isTrusted() {
+ return trusted;
+ }
+
+ public void setTrusted(boolean trusted) {
+ this.trusted = trusted;
+ }
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
index bb4497c..30d410c 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
@@ -31,6 +31,7 @@ import org.netbeans.spi.autoupdate.UpdateItem;
public abstract class UpdateItemImpl {
private UpdateItem originalUpdateItem;
private List<MessageDigestValue> messageDigests = new ArrayList<>();
+ private boolean catalogTrusted = false;
/** Creates a new instance of UpdateItemImpl */
UpdateItemImpl () {
@@ -75,4 +76,12 @@ public abstract class UpdateItemImpl {
public void setMessageDigests(List<MessageDigestValue> messageDigests) {
this.messageDigests = new ArrayList<>(messageDigests);
}
+
+ public boolean isCatalogTrusted() {
+ return catalogTrusted;
+ }
+
+ public void setCatalogTrusted(boolean catalogTrusted) {
+ this.catalogTrusted = catalogTrusted;
+ }
}
diff --git a/platform/autoupdate.ui/manifest.mf b/platform/autoupdate.ui/manifest.mf
index 40be84a..d55d1d8 100644
--- a/platform/autoupdate.ui/manifest.mf
+++ b/platform/autoupdate.ui/manifest.mf
@@ -2,6 +2,6 @@ Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.autoupdate.ui
OpenIDE-Module-Install: org/netbeans/modules/autoupdate/ui/actions/Installer.class
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/ui/resources/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.52
+OpenIDE-Module-Specification-Version: 1.53
AutoUpdate-Show-In-Client: false
AutoUpdate-Essential-Module: true
diff --git a/platform/autoupdate.ui/nbproject/project.xml b/platform/autoupdate.ui/nbproject/project.xml
index 8615fb5..d09a3ce 100644
--- a/platform/autoupdate.ui/nbproject/project.xml
+++ b/platform/autoupdate.ui/nbproject/project.xml
@@ -56,7 +56,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
- <specification-version>1.57</specification-version>
+ <specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@@ -101,7 +101,7 @@
</run-dependency>
</dependency>
<dependency>
- <code-name-base>org.openide.util.ui</code-name-base>
+ <code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
@@ -109,19 +109,19 @@
</run-dependency>
</dependency>
<dependency>
- <code-name-base>org.openide.util</code-name-base>
+ <code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
- <specification-version>9.3</specification-version>
+ <specification-version>8.0</specification-version>
</run-dependency>
</dependency>
<dependency>
- <code-name-base>org.openide.util.lookup</code-name-base>
+ <code-name-base>org.openide.util.ui</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
- <specification-version>8.0</specification-version>
+ <specification-version>9.3</specification-version>
</run-dependency>
</dependency>
<dependency>
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties
index af27211..e718266 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/Bundle.properties
@@ -211,3 +211,4 @@ Unit_InternalUpdates_Version=(Internal Updates)
Unit_InternalUpdates_Title=Internal Updates
ProblemPanel.cbShowAgain.text=&Don't show this message again
SettingsTab.lLocation.text=Plugin &Install Location:
+UpdateUnitProviderPanel.cbTrusted.text=&Trust update center fully and allow automatic installations
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/SettingsTab.java b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/SettingsTab.java
index 40e33dd..49024ee 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/SettingsTab.java
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/SettingsTab.java
@@ -512,6 +512,7 @@ private void bProxyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:
}
provider.setEnable (panel.isActive ());
+ provider.setTrusted(panel.isTrusted());
if (panel.isActive ()) {
// was not enabled and will be -> add it to model and read its content
refreshProvider (provider, forceRead);
@@ -566,7 +567,8 @@ private void bProxyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:
final UpdateUnitProviderPanel panel = new UpdateUnitProviderPanel(provider.isEnabled(),
provider.getDisplayName(), // display name
provider.getProviderURL().toExternalForm(), // URL
- true); // editing
+ true, // editing
+ provider.isTrusted());
DialogDescriptor descriptor = getCustomizerDescriptor(panel);
panel.getOKButton().addActionListener(new ActionListener(){
@Override
@@ -628,6 +630,7 @@ private void bProxyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:
final UpdateUnitProviderPanel panel = new UpdateUnitProviderPanel(true,
NbBundle.getMessage(SettingsTab.class, "SettingsTab_NewProviderName"), // NOI18N
NbBundle.getMessage(SettingsTab.class, "SettingsTab_NewProviderURL"), // NOI18N
+ false,
false);
DialogDescriptor descriptor = getCustomizerDescriptor(panel);
panel.getOKButton().addActionListener(new ActionListener(){
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.form b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.form
index bf2d7c3..495a23c 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.form
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.form
@@ -49,7 +49,13 @@
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tfURL" alignment="0" pref="474" max="32767" attributes="0"/>
<Component id="tfName" pref="474" max="32767" attributes="0"/>
- <Component id="cbActive" alignment="0" min="-2" max="-2" attributes="0"/>
+ <Group type="102" attributes="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Component id="cbTrusted" min="-2" max="-2" attributes="0"/>
+ <Component id="cbActive" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+ </Group>
</Group>
</Group>
</Group>
@@ -72,7 +78,9 @@
<Component id="lURL" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="tfURL" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
- <EmptySpace pref="20" max="32767" attributes="0"/>
+ <EmptySpace type="separate" max="-2" attributes="0"/>
+ <Component id="cbTrusted" min="-2" max="-2" attributes="0"/>
+ <EmptySpace max="32767" attributes="0"/>
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -142,5 +150,20 @@
</Component>
<Component class="javax.swing.JLabel" name="errorLabel">
</Component>
+ <Component class="javax.swing.JCheckBox" name="cbTrusted">
+ <Properties>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/autoupdate/ui/Bundle.properties" key="UpdateUnitProviderPanel.cbTrusted.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+ <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
+ <EmptyBorder bottom="0" left="0" right="0" top="0"/>
+ </Border>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+ </AuxValues>
+ </Component>
</SubComponents>
</Form>
diff --git a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.java b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.java
index 98e2dc1..c419202 100644
--- a/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.java
+++ b/platform/autoupdate.ui/src/org/netbeans/modules/autoupdate/ui/UpdateUnitProviderPanel.java
@@ -50,7 +50,7 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
private final Icon errorIcon = ImageUtilities.loadImageIcon("org/netbeans/modules/autoupdate/ui/resources/error.png", false);
/** Creates new form UpdateUnitProviderPanel */
- public UpdateUnitProviderPanel(boolean isActive, String name, String url, boolean editing) {
+ public UpdateUnitProviderPanel(boolean isActive, String name, String url, boolean editing, boolean isTrusted) {
isEdit = editing;
originalName = name;
initComponents();
@@ -58,6 +58,7 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
tfURL.setText(url);
tfName.setText(name);
cbActive.setSelected(isActive);
+ cbTrusted.setSelected(isTrusted);
getAccessibleContext().setAccessibleName("ACN_UpdateCenterCustomizer");
getAccessibleContext().setAccessibleDescription("ACD_UpdateCenterCustomizer");
}
@@ -239,7 +240,11 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
public String getProviderURL() {
return tfURL.getText().trim();
}
-
+
+ public boolean isTrusted() {
+ return cbTrusted.isSelected();
+ }
+
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
@@ -254,6 +259,7 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
tfURL = new javax.swing.JTextField();
cbActive = new javax.swing.JCheckBox();
errorLabel = new javax.swing.JLabel();
+ cbTrusted = new javax.swing.JCheckBox();
lName.setLabelFor(tfName);
org.openide.awt.Mnemonics.setLocalizedText(lName, org.openide.util.NbBundle.getMessage(UpdateUnitProviderPanel.class, "UpdateUnitProviderPanel.lName.text")); // NOI18N
@@ -264,6 +270,9 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
org.openide.awt.Mnemonics.setLocalizedText(cbActive, org.openide.util.NbBundle.getMessage(UpdateUnitProviderPanel.class, "UpdateUnitProviderPanel.cbActive.text")); // NOI18N
cbActive.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ org.openide.awt.Mnemonics.setLocalizedText(cbTrusted, org.openide.util.NbBundle.getMessage(UpdateUnitProviderPanel.class, "UpdateUnitProviderPanel.cbTrusted.text")); // NOI18N
+ cbTrusted.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@@ -280,7 +289,11 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tfURL, javax.swing.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE)
.addComponent(tfName, javax.swing.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE)
- .addComponent(cbActive))))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(cbTrusted)
+ .addComponent(cbActive))
+ .addGap(0, 0, Short.MAX_VALUE)))))
.addContainerGap())
);
layout.setVerticalGroup(
@@ -296,7 +309,9 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lURL)
.addComponent(tfURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
+ .addGap(18, 18, 18)
+ .addComponent(cbTrusted)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(errorLabel)
.addContainerGap())
);
@@ -309,6 +324,7 @@ public class UpdateUnitProviderPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox cbActive;
+ private javax.swing.JCheckBox cbTrusted;
private javax.swing.JLabel errorLabel;
private javax.swing.JLabel lName;
private javax.swing.JLabel lURL;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 01/09: Ensure only safe redirects are followed and
simplify connection handling
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit c1f912a501e2cf102416ad4561b940016c612ad8
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Fri Nov 1 23:20:37 2019 +0100
Ensure only safe redirects are followed and simplify connection handling
NetBeans did follow redirects even if a protocol change happened. In
this case the user is not aware, that a download potentially drops from
https to http. Instead protocol changes are only allowed, if the
originating URL is insecure (http).
Instead of trying to handle the SSL/TLS trust internally, the default
JDK mechanisms for handling SSL/TLS connections are now used and the
connection configuration code was centralized.
---
.../autoupdate/services/InstallSupportImpl.java | 5 +-
.../updateprovider/AutoupdateCatalogCache.java | 2 +-
.../autoupdate/updateprovider/NetworkAccess.java | 134 ++++++++-------------
3 files changed, 53 insertions(+), 88 deletions(-)
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 5098c28..1644392 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -924,9 +924,10 @@ public class InstallSupportImpl {
String label) throws MalformedURLException, IOException {
OpenConnectionListener listener = new OpenConnectionListener(source);
- final Task task = NetworkAccess.createNetworkAcessTask(source,
+ final Task task = NetworkAccess.createNetworkAccessTask(source,
AutoupdateSettings.getOpenConnectionTimeout(),
- listener);
+ listener,
+ false);
new Thread(new Runnable() {
@SuppressWarnings("SleepWhileInLoop")
@Override
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogCache.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogCache.java
index ab94735..ba81ccd 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogCache.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogCache.java
@@ -216,7 +216,7 @@ public final class AutoupdateCatalogCache {
DownloadListener nwl = new DownloadListener(sourceUrl, temp, allowZeroSize);
- NetworkAccess.Task task = NetworkAccess.createNetworkAcessTask (sourceUrl, AutoupdateSettings.getOpenConnectionTimeout (), nwl);
+ NetworkAccess.Task task = NetworkAccess.createNetworkAccessTask (sourceUrl, AutoupdateSettings.getOpenConnectionTimeout (), nwl, true);
task.waitFinished ();
nwl.notifyException ();
synchronized(getLock(cache)) {
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/NetworkAccess.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/NetworkAccess.java
index c79154a..1560eda 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/NetworkAccess.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/NetworkAccess.java
@@ -24,10 +24,6 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
@@ -40,12 +36,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
@@ -63,19 +53,20 @@ public class NetworkAccess {
private NetworkAccess () {}
- public static Task createNetworkAcessTask (URL url, int timeout, NetworkListener networkAcesssListener) {
- return new Task (url, timeout, networkAcesssListener);
+ public static Task createNetworkAccessTask (URL url, int timeout, NetworkListener networkAccessListener, boolean disableInsecureRedirects) {
+ return new Task (url, timeout, networkAccessListener, disableInsecureRedirects);
}
public static class Task implements Cancellable {
+ private final ExecutorService es = Executors.newSingleThreadExecutor();
+ private final boolean disableInsecureRedirects;
private URL url;
private int timeout;
private NetworkListener listener;
- private final ExecutorService es = Executors.newSingleThreadExecutor ();
private Future<InputStream> connect = null;
private RequestProcessor.Task rpTask = null;
- private Task (URL url, int timeout, NetworkListener listener) {
+ private Task (URL url, int timeout, NetworkListener listener, boolean disableInsecureRedirects) {
if (url == null) {
throw new IllegalArgumentException ("URL cannot be null.");
}
@@ -85,6 +76,7 @@ public class NetworkAccess {
this.url = url;
this.timeout = timeout;
this.listener = listener;
+ this.disableInsecureRedirects = disableInsecureRedirects;
postTask ();
}
@@ -146,11 +138,7 @@ public class NetworkAccess {
@Override
public InputStream call () throws Exception {
URLConnection conn = url.openConnection ();
- conn.setConnectTimeout (timeout);
- conn.setReadTimeout(timeout);
- if(conn instanceof HttpsURLConnection){
- NetworkAccess.initSSL((HttpsURLConnection) conn);
- }
+ configureConnection(conn, timeout);
// handle redirection here
int redirCount = 0;
@@ -181,13 +169,52 @@ public class NetworkAccess {
}
};
}
-
+
@Override
public boolean cancel () {
- return connect.cancel (true);
+ return connect.cancel(true);
+ }
+
+ private URLConnection checkRedirect(URLConnection conn, int timeout) throws IOException {
+ if (conn instanceof HttpURLConnection) {
+ conn.connect();
+ int code = ((HttpURLConnection) conn).getResponseCode();
+ boolean isInsecure = "http".equalsIgnoreCase(conn.getURL().getProtocol());
+ if (code == HttpURLConnection.HTTP_MOVED_TEMP
+ || code == HttpURLConnection.HTTP_MOVED_PERM) {
+ // in case of redirection, try to obtain new URL
+ String redirUrl = conn.getHeaderField("Location"); //NOI18N
+ if (null != redirUrl && !redirUrl.isEmpty()) {
+ //create connection to redirected url and substitute original connection
+ URL redirectedUrl = new URL(redirUrl);
+ if (disableInsecureRedirects && (!isInsecure) && (!redirectedUrl.getProtocol().equalsIgnoreCase(conn.getURL().getProtocol()))) {
+ throw new IOException(String.format(
+ "Redirect from secure URL '%s' to '%s' blocked.",
+ conn.getURL().toExternalForm(),
+ redirectedUrl.toExternalForm()
+ ));
+ }
+ URLConnection connRedir = redirectedUrl.openConnection();
+ connRedir.setRequestProperty("User-Agent", "NetBeans"); // NOI18N
+ connRedir.setConnectTimeout(timeout);
+ connRedir.setReadTimeout(timeout);
+ return connRedir;
+ }
+ }
+ }
+ return conn;
+ }
+
+ private static void configureConnection(URLConnection conn, int timeout) {
+ if (conn instanceof HttpURLConnection) {
+ ((HttpURLConnection) conn).setInstanceFollowRedirects(false);
+ }
+ conn.setRequestProperty("User-Agent", "NetBeans");
+ conn.setConnectTimeout(timeout);
+ conn.setReadTimeout(timeout);
}
-
}
+
private interface SizedConnection extends Callable<InputStream> {
public int getContentLength();
}
@@ -197,67 +224,4 @@ public class NetworkAccess {
public void accessTimeOut ();
public void notifyException (Exception x);
}
-
- public static void initSSL(HttpURLConnection httpCon) throws IOException {
- if (httpCon instanceof HttpsURLConnection) {
- HttpsURLConnection https = (HttpsURLConnection) httpCon;
-
- try {
- TrustManager[] trustAllCerts = new TrustManager[]{
- new X509TrustManager() {
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] certs, String authType) {
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] certs, String authType) {
- }
- }};
- SSLContext sslContext = SSLContext.getInstance("SSL"); // NOI18N
- sslContext.init(null, trustAllCerts, new SecureRandom());
- https.setHostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- return true;
- }
- });
- https.setSSLSocketFactory(sslContext.getSocketFactory());
- } catch (KeyManagementException ex) {
- throw new IOException(ex);
- } catch (NoSuchAlgorithmException ex) {
- throw new IOException(ex);
- }
- }
- }
-
- private static URLConnection checkRedirect(URLConnection conn, int timeout) throws IOException {
- if (conn instanceof HttpURLConnection) {
- conn.connect();
- int code = ((HttpURLConnection) conn).getResponseCode();
- if (code == HttpURLConnection.HTTP_MOVED_TEMP
- || code == HttpURLConnection.HTTP_MOVED_PERM) {
- // in case of redirection, try to obtain new URL
- String redirUrl = conn.getHeaderField("Location"); //NOI18N
- if (null != redirUrl && !redirUrl.isEmpty()) {
- //create connection to redirected url and substitute original conn
- URL redirectedUrl = new URL(redirUrl);
- URLConnection connRedir = redirectedUrl.openConnection();
- // XXX is this neede
- connRedir.setRequestProperty("User-Agent", "NetBeans"); // NOI18N
- connRedir.setConnectTimeout(timeout);
- connRedir.setReadTimeout(timeout);
- if (connRedir instanceof HttpsURLConnection) {
- NetworkAccess.initSSL((HttpsURLConnection) connRedir);
- }
- return connRedir;
- }
- }
- }
- return conn;
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 05/09: Add option to provide a message digest in update
center
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 8e4916ec3d16ce8d38c8939bd84897e34f55ab44
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Sun Nov 10 17:51:35 2019 +0100
Add option to provide a message digest in update center
The idea is, that an update center can provide message digests/hashes
for the modules it provides. This way, the NetBeans Platform can verify
a download of a module by checking the hash, even if the download
happens over an insecure link (http).
If a download does not yield the same digest, installation will be
blocked, just as if certification validation failed with a
SecurityException.
---
.../libsrc/org/netbeans/updater/XMLUtil.java | 2 +
.../updater/resources/autoupdate-catalog-2_8.dtd | 96 +++++++++++++
.../autoupdate/services/InstallSupportImpl.java | 29 +++-
.../autoupdate/services/MessageDigestChecker.java | 152 +++++++++++++++++++++
.../autoupdate/services/UpdateElementImpl.java | 16 ++-
.../updateprovider/AutoupdateCatalogParser.java | 25 +++-
.../updateprovider/MessageDigestValue.java | 79 +++++++++++
.../autoupdate/updateprovider/UpdateItemImpl.java | 11 ++
.../services/MessageDigestCheckerTest.java | 48 +++++++
9 files changed, 450 insertions(+), 8 deletions(-)
diff --git a/platform/autoupdate.services/libsrc/org/netbeans/updater/XMLUtil.java b/platform/autoupdate.services/libsrc/org/netbeans/updater/XMLUtil.java
index 7ce7088..b0e7560 100644
--- a/platform/autoupdate.services/libsrc/org/netbeans/updater/XMLUtil.java
+++ b/platform/autoupdate.services/libsrc/org/netbeans/updater/XMLUtil.java
@@ -183,6 +183,8 @@ public final class XMLUtil extends Object {
return new InputSource(XMLUtil.class.getResource("resources/autoupdate-catalog-2_7.dtd").toString()); // NOI18N
} else if ("-//NetBeans//DTD Autoupdate Module Info 2.7//EN".equals(publicID)) { // NOI18N
return new InputSource(XMLUtil.class.getResource("resources/autoupdate-info-2_7.dtd").toString()); // NOI18N
+ } else if ("-//NetBeans//DTD Autoupdate Catalog 2.8//EN".equals(publicID)) { // NOI18N
+ return new InputSource(XMLUtil.class.getResource("resources/autoupdate-catalog-2_8.dtd").toString()); // NOI18N
} else {
if (systemID.endsWith(".dtd")) { // NOI18N
return new InputSource(new ByteArrayInputStream(new byte[0]));
diff --git a/platform/autoupdate.services/libsrc/org/netbeans/updater/resources/autoupdate-catalog-2_8.dtd b/platform/autoupdate.services/libsrc/org/netbeans/updater/resources/autoupdate-catalog-2_8.dtd
new file mode 100644
index 0000000..074e636
--- /dev/null
+++ b/platform/autoupdate.services/libsrc/org/netbeans/updater/resources/autoupdate-catalog-2_8.dtd
@@ -0,0 +1,96 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<!-- -//NetBeans//DTD Autoupdate Catalog 2.8//EN -->
+<!-- XML representation of Autoupdate Modules/Updates Catalog -->
+
+<!ELEMENT module_updates ((notification?, content_description?, (module_group|module)*, license*)|error)>
+<!ATTLIST module_updates timestamp CDATA #REQUIRED>
+
+<!ELEMENT module_group ((module_group|module)*)>
+<!ATTLIST module_group name CDATA #REQUIRED>
+
+<!ELEMENT notification (#PCDATA)>
+<!ATTLIST notification url CDATA #IMPLIED>
+
+<!ELEMENT content_description (#PCDATA)>
+<!ATTLIST content_description url CDATA #IMPLIED>
+
+<!ELEMENT module (description?, module_notification?, external_package*, (manifest | l10n), message_digest* )>
+<!ATTLIST module codenamebase CDATA #REQUIRED
+ homepage CDATA #IMPLIED
+ distribution CDATA #REQUIRED
+ license CDATA #IMPLIED
+ downloadsize CDATA #REQUIRED
+ needsrestart (true|false) #IMPLIED
+ moduleauthor CDATA #IMPLIED
+ releasedate CDATA #IMPLIED
+ global (true|false) #IMPLIED
+ targetcluster CDATA #IMPLIED
+ preferredupdate (true|false) #IMPLIED
+ eager (true|false) #IMPLIED
+ autoload (true|false) #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT module_notification (#PCDATA)>
+
+<!ELEMENT external_package EMPTY>
+<!ATTLIST external_package
+ name CDATA #REQUIRED
+ target_name CDATA #REQUIRED
+ start_url CDATA #REQUIRED
+ description CDATA #IMPLIED>
+
+<!ELEMENT manifest EMPTY>
+<!ATTLIST manifest OpenIDE-Module CDATA #REQUIRED
+ OpenIDE-Module-Name CDATA #REQUIRED
+ OpenIDE-Module-Specification-Version CDATA #REQUIRED
+ OpenIDE-Module-Implementation-Version CDATA #IMPLIED
+ OpenIDE-Module-Module-Dependencies CDATA #IMPLIED
+ OpenIDE-Module-Package-Dependencies CDATA #IMPLIED
+ OpenIDE-Module-Java-Dependencies CDATA #IMPLIED
+ OpenIDE-Module-IDE-Dependencies CDATA #IMPLIED
+ OpenIDE-Module-Short-Description CDATA #IMPLIED
+ OpenIDE-Module-Long-Description CDATA #IMPLIED
+ OpenIDE-Module-Display-Category CDATA #IMPLIED
+ OpenIDE-Module-Provides CDATA #IMPLIED
+ OpenIDE-Module-Requires CDATA #IMPLIED
+ OpenIDE-Module-Recommends CDATA #IMPLIED
+ OpenIDE-Module-Needs CDATA #IMPLIED
+ AutoUpdate-Show-In-Client (true|false) #IMPLIED
+ AutoUpdate-Essential-Module (true|false) #IMPLIED
+ OpenIDE-Module-Fragment-Host CDATA #IMPLIED>
+
+<!ELEMENT l10n EMPTY>
+<!ATTLIST l10n langcode CDATA #IMPLIED
+ brandingcode CDATA #IMPLIED
+ module_spec_version CDATA #IMPLIED
+ module_major_version CDATA #IMPLIED
+ OpenIDE-Module-Name CDATA #IMPLIED
+ OpenIDE-Module-Long-Description CDATA #IMPLIED>
+
+<!ELEMENT license (#PCDATA)>
+<!ATTLIST license name CDATA #REQUIRED
+ url CDATA #IMPLIED>
+
+<!ELEMENT message_digest EMPTY>
+<!ATTLIST message_digest algorithm CDATA #REQUIRED
+ value CDATA #REQUIRED>
\ No newline at end of file
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 28263fc..7a37748 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -31,10 +31,8 @@ import java.net.UnknownHostException;
import java.security.CodeSigner;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.TrustAnchor;
-import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
@@ -51,6 +49,7 @@ import org.netbeans.api.autoupdate.OperationContainer.OperationInfo;
import org.netbeans.api.autoupdate.OperationSupport.Restarter;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.modules.autoupdate.updateprovider.AutoupdateInfoParser;
+import org.netbeans.modules.autoupdate.updateprovider.MessageDigestValue;
import org.netbeans.modules.autoupdate.updateprovider.ModuleItem;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess.Task;
@@ -1017,7 +1016,7 @@ public class InstallSupportImpl {
// + ") of is equal to estimatedSize (" + estimatedSize + ").";
if (estimatedSize != increment) {
LOG.log (Level.FINEST, "Increment (" + increment + ") of is not equal to estimatedSize (" + estimatedSize + ").");
- }
+ }
} catch (IOException ioe) {
LOG.log (Level.INFO, "Writing content of URL " + source + " failed.", ioe);
} finally {
@@ -1029,6 +1028,7 @@ public class InstallSupportImpl {
LOG.log (Level.INFO, ioe.getMessage (), ioe);
}
}
+
if (contentLength != -1 && increment != contentLength) {
if(canceled) {
LOG.log(Level.INFO, "Download of " + source + " was cancelled");
@@ -1121,6 +1121,29 @@ public class InstallSupportImpl {
res = Utilities.MODIFIED;
}
+ {
+ MessageDigestChecker mdChecker = new MessageDigestChecker(impl.getMessageDigests());
+ byte[] buffer = new byte[102400];
+ int read;
+ try(FileInputStream fis = new FileInputStream(nbmFile)) {
+ while((read = fis.read(buffer)) > 0) {
+ mdChecker.update(buffer, 0, read);
+ }
+ }
+ if(!mdChecker.validate()) {
+ for (String algorithm : mdChecker.getFailingHashes()) {
+ LOG.log(Level.INFO,
+ "Failed to validate message digest for ''{0}'' expected ''{1}'' got ''{2}''",
+ new Object[]{
+ nbmFile.getAbsolutePath(),
+ mdChecker.getExpectedHashAsString(algorithm),
+ mdChecker.getCalculatedHashAsString(algorithm)
+ });
+ }
+ res = Utilities.MODIFIED;
+ }
+ }
+
if (res != null) {
switch (res) {
case Utilities.MODIFIED:
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/MessageDigestChecker.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/MessageDigestChecker.java
new file mode 100644
index 0000000..53d3eaf
--- /dev/null
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/MessageDigestChecker.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.autoupdate.services;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.modules.autoupdate.updateprovider.MessageDigestValue;
+
+public class MessageDigestChecker {
+
+ private static final Logger LOG = Logger.getLogger(MessageDigestChecker.class.getName());
+
+ private final Map<String,MessageDigest> messageDigest = new HashMap<>();
+ private final Map<String,byte[]> exptectedResult = new HashMap<>();
+ private final Map<String,byte[]> calculatedResult = new HashMap<>();
+ private Boolean overallValid = null;
+
+ public MessageDigestChecker(Collection<MessageDigestValue> referenceHashes) {
+ if (referenceHashes != null) {
+ for (MessageDigestValue h : referenceHashes) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(h.getAlgorithm());
+ messageDigest.put(h.getAlgorithm(), md);
+ exptectedResult.put(h.getAlgorithm(), hexDecode(h.getValue()));
+ } catch (NoSuchAlgorithmException ex) {
+ LOG.log(Level.FINE, "Unsupported Hash Algorithm: {0}", h.getAlgorithm());
+ }
+ }
+ }
+ }
+
+ public void update(byte[] data) {
+ ensureValidateNotCalled();
+ for(MessageDigest md: messageDigest.values()) {
+ md.update(data);
+ }
+ }
+
+ public void update(byte[] data, int offset, int len) {
+ ensureValidateNotCalled();
+ for(MessageDigest md: messageDigest.values()) {
+ md.update(data, offset, len);
+ }
+ }
+
+ public void update(byte data) {
+ ensureValidateNotCalled();
+ for(MessageDigest md: messageDigest.values()) {
+ md.update(data);
+ }
+ }
+
+ private void ensureValidateNotCalled() throws IllegalStateException {
+ if(overallValid != null) {
+ throw new IllegalStateException("update must not be called after validate is invoked");
+ }
+ }
+
+ private void ensureValidateCalled() throws IllegalStateException {
+ if(overallValid == null) {
+ throw new IllegalStateException("This method must not be called before validate is invoked");
+ }
+ }
+
+ public boolean isDigestAvailable() {
+ return ! messageDigest.isEmpty();
+ }
+
+ public boolean validate() throws IOException {
+ if (overallValid == null) {
+ overallValid = true;
+ for (Entry<String, MessageDigest> e : messageDigest.entrySet()) {
+ String algorithm = e.getKey();
+ calculatedResult.put(algorithm, e.getValue().digest());
+ boolean localValid = Arrays.equals(
+ exptectedResult.get(algorithm),
+ calculatedResult.get(algorithm));
+ overallValid &= localValid;
+ }
+ }
+ return overallValid;
+ }
+
+ public List<String> getFailingHashes() {
+ ensureValidateCalled();
+ List<String> result = new ArrayList<>();
+ for(String algorithm: messageDigest.keySet()) {
+ if(! Arrays.equals(
+ exptectedResult.get(algorithm),
+ calculatedResult.get(algorithm))) {
+ result.add(algorithm);
+ }
+ }
+ return result;
+ }
+
+ public String getExpectedHashAsString(String algorithm) {
+ ensureValidateCalled();
+ return hexEncode(exptectedResult.get(algorithm));
+ }
+
+ public String getCalculatedHashAsString(String algorithm) {
+ ensureValidateCalled();
+ return hexEncode(calculatedResult.get(algorithm));
+ }
+
+ public static String hexEncode(byte[] input) {
+ StringBuilder sb = new StringBuilder(input.length * 2);
+ for(byte b: input) {
+ sb.append(Character.forDigit((b & 0xF0) >> 4, 16));
+ sb.append(Character.forDigit((b & 0x0F), 16));
+ }
+ return sb.toString();
+ }
+
+ public static byte[] hexDecode(String input) {
+ int length = input.length() / 2;
+ byte[] result = new byte[length];
+ for(int i = 0; i < length; i++) {
+ int b = Character.digit(input.charAt(i * 2), 16) << 4;
+ b |= Character.digit(input.charAt(i * 2 + 1), 16);
+ result[i] = (byte) (b & 0xFF);
+ }
+ return result;
+ }
+}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
index 7cc580c..d2ba5dd 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/UpdateElementImpl.java
@@ -19,10 +19,12 @@
package org.netbeans.modules.autoupdate.services;
+import java.util.ArrayList;
import java.util.List;
import org.netbeans.api.autoupdate.UpdateElement;
import org.netbeans.api.autoupdate.UpdateManager;
import org.netbeans.api.autoupdate.UpdateUnit;
+import org.netbeans.modules.autoupdate.updateprovider.MessageDigestValue;
import org.netbeans.modules.autoupdate.updateprovider.InstallInfo;
import org.netbeans.modules.autoupdate.updateprovider.UpdateItemImpl;
import org.openide.modules.ModuleInfo;
@@ -35,8 +37,13 @@ import org.openide.modules.SpecificationVersion;
public abstract class UpdateElementImpl extends Object {
private UpdateUnit unit;
private UpdateElement element;
+ private List<MessageDigestValue> messageDigests = new ArrayList<>();
- public UpdateElementImpl (UpdateItemImpl item, String providerName) {}
+ public UpdateElementImpl (UpdateItemImpl item, String providerName) {
+ if(item.getMessageDigests() != null) {
+ messageDigests.addAll(item.getMessageDigests());
+ }
+ }
public UpdateUnit getUpdateUnit () {
return unit;
@@ -99,4 +106,11 @@ public abstract class UpdateElementImpl extends Object {
// XXX: try to rid of this
public abstract InstallInfo getInstallInfo ();
+ public List<MessageDigestValue> getMessageDigests() {
+ return messageDigests;
+ }
+
+ public void setMessageDigests(List<MessageDigestValue> messageDigests) {
+ this.messageDigests = messageDigests;
+ }
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
index d95e1b4..a6d737f 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/AutoupdateCatalogParser.java
@@ -34,7 +34,6 @@ import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.netbeans.Module;
import org.netbeans.modules.autoupdate.services.Trampoline;
import org.netbeans.modules.autoupdate.services.UpdateLicenseImpl;
import org.netbeans.modules.autoupdate.services.Utilities;
@@ -52,6 +51,7 @@ public class AutoupdateCatalogParser extends DefaultHandler {
private final AutoupdateCatalogProvider provider;
private final EntityResolver entityResolver;
private final URI baseUri;
+ private final List<MessageDigestValue> messageDigestsBuffer = new ArrayList<>();
private AutoupdateCatalogParser (Map<String, UpdateItem> items, AutoupdateCatalogProvider provider, URI base) {
this.items = items;
@@ -111,7 +111,7 @@ public class AutoupdateCatalogParser extends DefaultHandler {
private static enum ELEMENTS {
module_updates, module_group, notification, content_description, module, description,
- module_notification, external_package, manifest, l10n, license
+ module_notification, external_package, manifest, l10n, license, message_digest
}
private static final String MODULE_UPDATES_ATTR_TIMESTAMP = "timestamp"; // NOI18N
@@ -149,7 +149,10 @@ public class AutoupdateCatalogParser extends DefaultHandler {
private static final String L10N_ATTR_MODULE_MAJOR_VERSION = "module_major_version"; // NOI18N
private static final String L10N_ATTR_LOCALIZED_MODULE_NAME = "OpenIDE-Module-Name"; // NOI18N
private static final String L10N_ATTR_LOCALIZED_MODULE_DESCRIPTION = "OpenIDE-Module-Long-Description"; // NOI18N
-
+
+ private static final String MESSAGE_DIGEST_ATTR_ALGORITHM = "algorithm"; // NOI18N
+ private static final String MESSAGE_DIGEST_ATTR_VALUE = "value"; // NOI18N
+
private static String GZIP_EXTENSION = ".gz"; // NOI18N
private static String XML_EXTENSION = ".xml"; // NOI18N
private static String GZIP_MIME_TYPE = "application/x-gzip"; // NOI18N
@@ -359,6 +362,8 @@ public class AutoupdateCatalogParser extends DefaultHandler {
currentLicense.pop ();
break;
+ case message_digest:
+ break;
default:
ERR.warning ("Unknown element " + qName);
}
@@ -454,6 +459,16 @@ public class AutoupdateCatalogParser extends DefaultHandler {
map.put(attributes.getValue (LICENSE_ATTR_NAME), attributes.getValue (LICENSE_ATTR_URL));
currentLicense.push (map);
break;
+ case message_digest:
+ ModuleDescriptor desc2 = currentModule.peek ();
+ // At this point the manifest element must have been seen
+ UpdateItem ui = items.get (desc2.getId ());
+ UpdateItemImpl uiImpl = Trampoline.SPI.impl (ui);
+ uiImpl.getMessageDigests().add(new MessageDigestValue(
+ attributes.getValue(MESSAGE_DIGEST_ATTR_ALGORITHM),
+ attributes.getValue(MESSAGE_DIGEST_ATTR_VALUE)
+ ));
+ break;
default:
ERR.warning ("Unknown element " + qName);
}
@@ -511,6 +526,8 @@ public class AutoupdateCatalogParser extends DefaultHandler {
private String catalogDate;
private String fragmentHost;
+
+ private List<MessageDigestValue> hashes;
private static ModuleDescriptor md = null;
@@ -608,7 +625,7 @@ public class AutoupdateCatalogParser extends DefaultHandler {
return res;
}
- private void cleanUp (){
+ public void cleanUp (){
this.specVersion = null;
this.mf = null;
this.notification = null;
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/MessageDigestValue.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/MessageDigestValue.java
new file mode 100644
index 0000000..1351ef9
--- /dev/null
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/MessageDigestValue.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.autoupdate.updateprovider;
+
+import java.util.Objects;
+
+public class MessageDigestValue {
+ private String algorithm;
+ private String value;
+
+ public MessageDigestValue() {
+ }
+
+ public MessageDigestValue(String algorithm, String value) {
+ this.algorithm = algorithm;
+ this.value = value;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public void setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 53 * hash + Objects.hashCode(this.algorithm);
+ hash = 53 * hash + Objects.hashCode(this.value);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final MessageDigestValue other = (MessageDigestValue) obj;
+ if (!Objects.equals(this.algorithm, other.algorithm)) {
+ return false;
+ }
+ if (!Objects.equals(this.value, other.value)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
index 0f639dd..bb4497c 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/updateprovider/UpdateItemImpl.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.autoupdate.updateprovider;
+import java.util.ArrayList;
+import java.util.List;
import org.netbeans.modules.autoupdate.services.UpdateLicenseImpl;
import org.netbeans.spi.autoupdate.UpdateItem;
@@ -28,6 +30,7 @@ import org.netbeans.spi.autoupdate.UpdateItem;
*/
public abstract class UpdateItemImpl {
private UpdateItem originalUpdateItem;
+ private List<MessageDigestValue> messageDigests = new ArrayList<>();
/** Creates a new instance of UpdateItemImpl */
UpdateItemImpl () {
@@ -64,4 +67,12 @@ public abstract class UpdateItemImpl {
public String getFragmentHost() {
return null;
}
+
+ public List<MessageDigestValue> getMessageDigests() {
+ return messageDigests;
+ }
+
+ public void setMessageDigests(List<MessageDigestValue> messageDigests) {
+ this.messageDigests = new ArrayList<>(messageDigests);
+ }
}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/MessageDigestCheckerTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/MessageDigestCheckerTest.java
new file mode 100644
index 0000000..79af4ab
--- /dev/null
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/MessageDigestCheckerTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.autoupdate.services;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class MessageDigestCheckerTest {
+
+ public MessageDigestCheckerTest() {
+ }
+
+ @Test
+ public void testHexEncode() throws NoSuchAlgorithmException {
+ MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
+ byte[] hash = sha512.digest(new byte[] {});
+ assertEquals(
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+ MessageDigestChecker.hexEncode(hash));
+ }
+
+ @Test
+ public void testHexDecode() throws NoSuchAlgorithmException {
+ MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
+ byte[] hash = sha512.digest(new byte[] {});
+ assertArrayEquals(
+ hash,
+ MessageDigestChecker.hexDecode("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 08/09: Include message digest into generate update
center (SHA-512)
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit d92aeb8b2d667c635cf90a675134a5b1754357c2
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Sun Nov 17 14:33:21 2019 +0100
Include message digest into generate update center (SHA-512)
---
.../org/netbeans/nbbuild/MakeUpdateDesc.java | 92 +++++++++++++++++++++-
1 file changed, 90 insertions(+), 2 deletions(-)
diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java b/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
index 825ffba..90a30e0 100644
--- a/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
@@ -28,6 +28,7 @@ import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.DirectoryScanner;
import java.io.File;
import java.io.FileFilter;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -36,17 +37,22 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.text.Collator;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map.Entry;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TimeZone;
@@ -55,8 +61,11 @@ import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Path;
@@ -105,6 +114,19 @@ public class MakeUpdateDesc extends MatchingTask {
private List<Group> groups = new ArrayList<>();
private List<FileSet> filesets = new ArrayList<>();
+ private List<String> includeMessageDigests = Arrays.asList("SHA-512");
+
+ public String getIncludeMessageDigests() {
+ return includeMessageDigests.stream().collect(Collectors.joining(" "));
+ }
+
+ public void setIncludeMessageDigests(String includeMessageDigests) {
+ if(includeMessageDigests == null) {
+ includeMessageDigests = "";
+ }
+ this.includeMessageDigests = Arrays.asList(includeMessageDigests.split(" "));
+ }
+
private File desc;
/** Description file to create. */
@@ -301,7 +323,9 @@ public class MakeUpdateDesc extends MatchingTask {
}
File desc_ent = new File(ent_name);
desc_ent.delete();
- if (isPreferredUpdateDefined || (contentDescription != null && ! contentDescription.isEmpty())) {
+ if (includeMessageDigests != null && (! includeMessageDigests.isEmpty())) {
+ pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.8//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_8.dtd\" [");
+ } else if (isPreferredUpdateDefined || (contentDescription != null && ! contentDescription.isEmpty())) {
pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.7//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_7.dtd\" [");
} else if (useLicenseUrl) {
pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.6//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_6.dtd\" [");
@@ -339,7 +363,9 @@ public class MakeUpdateDesc extends MatchingTask {
pw.println ();
} else {
- if (isPreferredUpdateDefined || (contentDescription != null && ! contentDescription.isEmpty())) {
+ if (includeMessageDigests != null && (! includeMessageDigests.isEmpty())) {
+ pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.8//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_8.dtd\">");
+ } else if (isPreferredUpdateDefined || (contentDescription != null && ! contentDescription.isEmpty())) {
pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.7//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_7.dtd\">");
} else if (useLicenseUrl) {
pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.6//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_6.dtd\">");
@@ -642,6 +668,15 @@ public class MakeUpdateDesc extends MatchingTask {
}
}
}
+
+ Map<String,String> messageDigests = createMessageDigests(n_file);
+ for(Entry<String,String> messageDigest: messageDigests.entrySet()) {
+ Element messageDigestElement = m.xml.getOwnerDocument().createElement("message_digest");
+ messageDigestElement.setAttribute("algorithm", messageDigest.getKey());
+ messageDigestElement.setAttribute("value", messageDigest.getValue());
+ m.xml.appendChild(messageDigestElement);
+ }
+
moduleCollection.add(m);
}
} catch (BuildException x) {
@@ -882,4 +917,57 @@ public class MakeUpdateDesc extends MatchingTask {
return sb;
}
+ private Map<String,String> createMessageDigests(File targetFile) {
+ if(includeMessageDigests.isEmpty()) {
+ return Collections.<String,String>emptyMap();
+ }
+
+ Map<String,MessageDigest> digests = new HashMap<>(includeMessageDigests.size());
+
+ for(String messageDigest: includeMessageDigests) {
+ try {
+ digests.put(messageDigest, MessageDigest.getInstance(messageDigest));
+ } catch (NoSuchAlgorithmException ex) {
+ throw new BuildException("Failed to load requested messageDigest: " + messageDigest, ex);
+ }
+ }
+
+ try(FileInputStream fis = new FileInputStream(targetFile)) {
+ byte[] buffer = new byte[102400];
+ int read;
+ while((read = fis.read(buffer)) >= 0) {
+ for(MessageDigest md: digests.values()) {
+ md.update(buffer, 0, read);
+ }
+ }
+ } catch (IOException ex) {
+ Logger.getLogger(MakeUpdateDesc.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ Map<String,String> result = new HashMap<>();
+ for(Entry<String,MessageDigest> md: digests.entrySet()) {
+ result.put(md.getKey(), hexEncode(md.getValue().digest()));
+ }
+ return result;
+ }
+
+ private static String hexEncode(byte[] input) {
+ StringBuilder sb = new StringBuilder(input.length * 2);
+ for(byte b: input) {
+ sb.append(Character.forDigit((b & 0xF0) >> 4, 16));
+ sb.append(Character.forDigit((b & 0x0F), 16));
+ }
+ return sb.toString();
+ }
+
+ private static byte[] hexDecode(String input) {
+ int length = input.length() / 2;
+ byte[] result = new byte[length];
+ for(int i = 0; i < length; i++) {
+ int b = Character.digit(input.charAt(i * 2), 16) << 4;
+ b |= Character.digit(input.charAt(i * 2 + 1), 16);
+ result[i] = (byte) (b & 0xFF);
+ }
+ return result;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
[netbeans] 03/09: Base certificate validation in UpdateCenter on
KeyStore and not on trust to the embedded certpath
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 58ded7130bee8c57c84c12457fb34badcd468939
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Sun Nov 3 15:47:07 2019 +0100
Base certificate validation in UpdateCenter on KeyStore and not on trust to the embedded certpath
Instead of trusting the provided chain embedded in a NBM, validity of a
signature is now checked against a TrustStore, as is already done to
establish trust.
The KeyStoreProvider SPI was extended to allow to specify a level
of trust. This way a module can provide trusted and/or validation
certificates.
---
platform/autoupdate.services/apichanges.xml | 23 ++
platform/autoupdate.services/build.xml | 28 +++
platform/autoupdate.services/manifest.mf | 2 +-
.../autoupdate/services/InstallSupportImpl.java | 26 ++-
.../modules/autoupdate/services/Utilities.java | 236 +++++++++++----------
.../netbeans/spi/autoupdate/KeyStoreProvider.java | 45 +++-
.../autoupdate/services/VerifyFileTest.java | 29 ++-
7 files changed, 262 insertions(+), 127 deletions(-)
diff --git a/platform/autoupdate.services/apichanges.xml b/platform/autoupdate.services/apichanges.xml
index 9cee0f7..350a3a2 100644
--- a/platform/autoupdate.services/apichanges.xml
+++ b/platform/autoupdate.services/apichanges.xml
@@ -33,6 +33,29 @@
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
+ <change id="keystores-for-validation">
+ <api name="general"/>
+ <summary>KeyStoreProviders can now report which trustlevel they intent to supply</summary>
+ <version major="1" minor="61"/>
+ <date day="4" month="11" year="2019"/>
+ <author login="matthiasblaesing"/>
+ <compatibility addition="yes" binary="compatible" deletion="no" deprecation="no" semantic="compatible" source="compatible"/>
+ <description>
+ <p>
+ The validation of signatures of NBMs was done by checking if at least a partial certificate chain was present
+ and if that chain was valid (i.e. not expired, not revoked). Instead of relying on this partial check this
+ version bases the verification on a list of trusted certificates, similar to the existing KeyStoreProvider.
+ </p>
+ <p>
+ The existing KeyStoreProviders provide Certificates, that are fully trusted. The new getTrustLevel method
+ allows a KeyStoreProvider to provide certificate for the new, lower trusted level. In addition to the to
+ levels TRUST and VALIDATE, two variants: TRUST_CA and VALIDATE_CA are introduced. Certificates provided with
+ that level are expected to be CA certificates and they are only trusted if a `CertPathValidator` validates
+ the chain.
+ </p>
+ </description>
+ <class package="org.netbeans.api.autoupdate" name="OperationContainer"/>
+ </change>
<change id="missing-elements">
<api name="general"/>
<summary>Report parts of a feature which is not installed yet</summary>
diff --git a/platform/autoupdate.services/build.xml b/platform/autoupdate.services/build.xml
index 971c989..33f8799 100644
--- a/platform/autoupdate.services/build.xml
+++ b/platform/autoupdate.services/build.xml
@@ -52,6 +52,20 @@
<target name="netbeans-extra" depends="jar-updater"/>
<target name="do-unit-test-build" depends="projectized.do-unit-test-build">
+ <property name="validation-store" value="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/test-validate-keystore.jks" />
+ <delete file="${validation-store}" />
+ <genkey
+ keystore="${validation-store}"
+ alias="demo-key" storepass="password"
+ dname="CN=Demo Key, OU=NetBeans, O=Apache.org, C=US"
+ />
+ <property name="unvalidation-store" value="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/test-unvalidate-keystore.jks" />
+ <delete file="${unvalidation-store}" />
+ <genkey
+ keystore="${unvalidation-store}"
+ alias="demo-key-unvalidated" storepass="password"
+ dname="CN=Demo Key (unvalidated), OU=NetBeans, O=Apache.org, C=US"
+ />
<touch file="${build.dir}/Dummy.class" />
<touch file="${build.dir}/Dummy2.class" />
<jar destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-signed.jar">
@@ -83,6 +97,20 @@
update="true">
<zipfileset prefix="dummy/" file="${build.dir}/Dummy2.class" />
</zip>
+ <jar destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-validated.jar">
+ <zipfileset prefix="dummy/" file="${build.dir}/Dummy.class"/>
+ </jar>
+ <signjar jar="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-validated.jar"
+ keystore="${validation-store}"
+ storepass="password"
+ alias="demo-key" />
+ <jar destfile="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-unvalidated.jar">
+ <zipfileset prefix="dummy/" file="${build.dir}/Dummy.class"/>
+ </jar>
+ <signjar jar="${build.test.unit.classes.dir}/org/netbeans/api/autoupdate/data/dummy-unvalidated.jar"
+ keystore="${unvalidation-store}"
+ storepass="password"
+ alias="demo-key-unvalidated" />
</target>
</project>
diff --git a/platform/autoupdate.services/manifest.mf b/platform/autoupdate.services/manifest.mf
index 0948f17..f664430 100644
--- a/platform/autoupdate.services/manifest.mf
+++ b/platform/autoupdate.services/manifest.mf
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.autoupdate.services
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/autoupdate/services/resources/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.60
+OpenIDE-Module-Specification-Version: 1.61
OpenIDE-Module-Layer: org/netbeans/modules/autoupdate/services/resources/layer.xml
AutoUpdate-Show-In-Client: false
AutoUpdate-Essential-Module: true
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
index 43e7f84..5db31b9 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/InstallSupportImpl.java
@@ -28,10 +28,13 @@ import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
+import java.security.CodeSigner;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
@@ -52,6 +55,7 @@ import org.netbeans.modules.autoupdate.updateprovider.ModuleItem;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess;
import org.netbeans.modules.autoupdate.updateprovider.NetworkAccess.Task;
import org.netbeans.modules.autoupdate.updateprovider.UpdateItemImpl;
+import org.netbeans.spi.autoupdate.KeyStoreProvider;
import org.netbeans.spi.autoupdate.UpdateItem;
import org.netbeans.updater.ModuleDeactivator;
import org.netbeans.updater.ModuleUpdater;
@@ -1056,9 +1060,21 @@ public class InstallSupportImpl {
try {
// get trusted certificates
Set<Certificate> trustedCerts = new HashSet<> ();
- for (KeyStore ks : Utilities.getKeyStore ()) {
+ Set<Certificate> validationCerts = new HashSet<>();
+ Set<TrustAnchor> trustedCACerts = new HashSet<>();
+ Set<TrustAnchor> validationCACerts = new HashSet<>();
+ for (KeyStore ks : Utilities.getKeyStore (KeyStoreProvider.TrustLevel.TRUST)) {
trustedCerts.addAll(Utilities.getCertificates(ks));
}
+ for (KeyStore ks : Utilities.getKeyStore (KeyStoreProvider.TrustLevel.VALIDATE)) {
+ validationCerts.addAll(Utilities.getCertificates(ks));
+ }
+ for (KeyStore ks : Utilities.getKeyStore (KeyStoreProvider.TrustLevel.TRUST_CA)) {
+ trustedCACerts.addAll(Utilities.getTrustAnchor(ks));
+ }
+ for (KeyStore ks : Utilities.getKeyStore (KeyStoreProvider.TrustLevel.VALIDATE_CA)) {
+ validationCACerts.addAll(Utilities.getTrustAnchor(ks));
+ }
// load user certificates
KeyStore ks = Utilities.loadKeyStore ();
if (ks != null) {
@@ -1073,7 +1089,7 @@ public class InstallSupportImpl {
UpdateElementImpl impl = Trampoline.API.impl(el);
try {
- Collection<CertPath> nbmCerts = Utilities.getNbmCertificates(nbmFile);
+ Collection<CodeSigner> nbmCerts = Utilities.getNbmCertificates(nbmFile);
if(nbmCerts == null) {
res = Utilities.N_A;
} else if (nbmCerts.isEmpty()) {
@@ -1083,15 +1099,15 @@ public class InstallSupportImpl {
// choose the certpath, that has the highest trust level
// TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED
// or comes first
- for(CertPath cp: nbmCerts) {
- String localRes = Utilities.verifyCertificates(cp, trustedCerts);
+ for(CodeSigner cs: nbmCerts) {
+ String localRes = Utilities.verifyCertificates(cs, trustedCerts, trustedCACerts, validationCerts, validationCACerts);
// If there is no previous result or if the local
// verification yielded a better result than the
// previous result, replace it
if (res == null
|| VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
res = localRes;
- certs.put(el, (List<Certificate>) cp.getCertificates());
+ certs.put(el, (List<Certificate>) cs.getSignerCertPath().getCertificates());
}
}
}
diff --git a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
index fcd3139..fdef5f2 100644
--- a/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
+++ b/platform/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java
@@ -27,16 +27,13 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.Security;
-import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.PKIXRevocationChecker.Option;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.text.ParseException;
@@ -60,6 +57,7 @@ import org.netbeans.modules.autoupdate.updateprovider.DummyModuleInfo;
import org.netbeans.modules.autoupdate.updateprovider.InstalledModuleProvider;
import org.netbeans.modules.autoupdate.updateprovider.UpdateItemImpl;
import org.netbeans.spi.autoupdate.KeyStoreProvider;
+import org.netbeans.spi.autoupdate.KeyStoreProvider.TrustLevel;
import org.netbeans.spi.autoupdate.UpdateItem;
import org.netbeans.updater.ModuleDeactivator;
import org.netbeans.updater.ModuleUpdater;
@@ -104,28 +102,38 @@ public class Utilities {
private static final String USER_KS_KEY = "userKS";
private static final String USER_KS_FILE_NAME = "user.ks";
private static final String KS_USER_PASSWORD = "open4user";
- private static Lookup.Result<KeyStoreProvider> result;
+ private static Lookup.Result<KeyStoreProvider> keyStoreLookupResult;
+ private static Map<TrustLevel,List<KeyStore>> keystoreCache = Collections.synchronizedMap(new HashMap<>());
private static final Logger err = Logger.getLogger(Utilities.class.getName ());
- public static Collection<KeyStore> getKeyStore () {
- if (result == null) {
- result = Lookup.getDefault ().lookupResult (KeyStoreProvider.class);
- result.addLookupListener (new KeyStoreProviderListener ());
- }
- Collection<? extends KeyStoreProvider> c = result.allInstances ();
- if (c == null || c.isEmpty ()) {
- return Collections.emptyList ();
+ public static Collection<KeyStore> getKeyStore (TrustLevel trustLevel) {
+ if (keyStoreLookupResult == null) {
+ keyStoreLookupResult = Lookup.getDefault().lookupResult(KeyStoreProvider.class);
+ keyStoreLookupResult.addLookupListener(new KeyStoreProviderListener());
}
- List<KeyStore> kss = new ArrayList<>();
- for (KeyStoreProvider provider : c) {
- KeyStore ks = provider.getKeyStore ();
- if (ks != null) {
- kss.add (ks);
+ List<KeyStore> result = keystoreCache.get(trustLevel);
+
+ if (result == null) {
+ Collection<? extends KeyStoreProvider> c = keyStoreLookupResult.allInstances();
+ if (c == null || c.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<KeyStore> kss = new ArrayList<>();
+
+ for (KeyStoreProvider provider : c) {
+ KeyStore ks = provider.getKeyStore();
+ if (ks != null) {
+ kss.add(ks);
+ }
}
+
+ result = Collections.unmodifiableList(kss);
+
+ keystoreCache.put(trustLevel, result);
}
- return kss;
+ return result;
}
/**
@@ -134,103 +142,80 @@ public class Utilities {
* @param trustedCertificates
* @return
*/
- public static String verifyCertificates(CertPath archiveCertPath, Collection<? extends Certificate> trustedCertificates) {
+ public static String verifyCertificates(CodeSigner archiveCertPath,
+ Collection<Certificate> trustedCertificates,
+ Set<TrustAnchor> trustedCACertificates,
+ Collection<Certificate> validateCertificates,
+ Set<TrustAnchor> validationCACertificates) {
assert archiveCertPath != null;
- List<? extends Certificate> archiveCertificates = archiveCertPath.getCertificates();
- if (!archiveCertificates.isEmpty()) {
- Collection<Certificate> c = new HashSet<>(trustedCertificates);
- c.retainAll(archiveCertificates);
- if (c.isEmpty()) {
- Map<Principal, X509Certificate> certSubjectsMap = new HashMap<>();
- Set<Principal> certIssuersSet = new HashSet<>();
- for (Certificate cert : archiveCertificates) {
- if (cert != null) {
- X509Certificate x509Cert = (X509Certificate) cert;
- certSubjectsMap.put(x509Cert.getSubjectDN(), x509Cert);
- if (x509Cert.getIssuerDN() != null) {
- certIssuersSet.add(x509Cert.getIssuerDN());
- }
- }
- }
- Map<X509Certificate, X509Certificate> candidates = new HashMap<>();
- for (Principal p : certSubjectsMap.keySet()) {
- // cert chain may not be ordered - trust anchor could before certificate itself
- if (certIssuersSet.contains(p)) {
- continue;
- }
- X509Certificate cert = certSubjectsMap.get(p);
+ List<? extends Certificate> archiveCertificates = archiveCertPath.getSignerCertPath().getCertificates();
- Principal tap = cert.getIssuerDN();
- if (tap != null) {
- X509Certificate tempTrustAnchor = certSubjectsMap.get(tap);
- if (tempTrustAnchor != null) {
- candidates.put(cert, tempTrustAnchor);
- }
- }
- }
+ if(archiveCertificates.isEmpty()) {
+ return UNSIGNED;
+ }
- // TRUSTED = 2
- // SIGNATURE_VERIFIED = 1
- // SIGNATURE_UNVERIFIED = 0
- int res = 0;
- for (X509Certificate cert : candidates.keySet()) {
- X509Certificate trustCert = candidates.get(cert);
- PKIXCertPathValidatorResult validResult = null;
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- List certList = new ArrayList();
- certList.add(cert);
- CertPath cp = cf.generateCertPath(certList);
- TrustAnchor trustAnchor = new TrustAnchor(trustCert, null);
- PKIXParameters params = new PKIXParameters(Collections.singleton(trustAnchor));
- params.setRevocationEnabled(true);
- Security.setProperty("ocsp.enable", "true");
- System.setProperty("com.sun.security.enableCRLDP", "true"); // CRL fallback
- CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
- validResult = (PKIXCertPathValidatorResult) cpv.validate(cp, params);
- } catch (CertificateException | InvalidAlgorithmParameterException | NoSuchAlgorithmException ex) {
- // CertificateException - Should not get here - "X.509" is proper certificate type
- // InvalidAlgorithmParameterException - Should not get here - trustAnchor cannot be null -> collection cannot be empty
- // NoSuchAlgorithmException - Should not get here - "PKIX" is proper algorythm
- err.log(Level.SEVERE, "Certificate verification failed - " + ex.getMessage(), ex);
- //SIGNATURE_UNVERIFIED - result = 0;
- } catch (CertPathValidatorException ex) {
- // CertPath cannot be validated
- err.log(Level.INFO, "Cannot validate certificate path - " + ex.getMessage(), ex);
- //SIGNATURE_UNVERIFIED - result = 0;
- } catch (SecurityException ex) {
- // When jar/nbm correctly signed, but content modified
- err.log(Level.INFO, "The content of the jar/nbm has been modified - " + ex.getMessage(), ex);
- return MODIFIED;
- }
+ // Case 1: We have direct trust into one of the certificates of the
+ // certificate chain
+ if(isChainTrusted(archiveCertificates, trustedCertificates)) {
+ return TRUSTED;
+ }
- if (validResult != null) {
- String certDNName = cert.getSubjectDN().getName();
- if (certDNName.contains("CN=\"Oracle America, Inc.\"")
- && (certDNName.contains("OU=Software Engineering") || certDNName.contains("OU=Code Signing Bureau"))) {
- res = 2;
- break;
- } else {
- res = 1;
- }
- }
- }
+ // Case 2: We trust the CA, that issued a certificate - do the
+ // normal CertPathValidation
+ if(verifyCACertificatePath(trustedCACertificates, archiveCertPath)) {
+ return TRUSTED;
+ }
- switch (res) {
- case 2:
- return TRUSTED;
- case 1:
- return SIGNATURE_VERIFIED;
- default:
- return SIGNATURE_UNVERIFIED;
- }
- } else {
- // signed by trusted certificate stored in user's keystore od ide.ks
- return TRUSTED;
+ // Case 3: We have a list of certificates, that we directly mark as
+ // valid
+ if(isChainTrusted(archiveCertificates, validateCertificates)) {
+ return SIGNATURE_VERIFIED;
+ }
+
+ // Case 4: We trust the CA to do validation
+ if (verifyCACertificatePath(validationCACertificates, archiveCertPath)) {
+ return SIGNATURE_VERIFIED;
+ }
+
+ // Case 5: File is not signed
+ return SIGNATURE_UNVERIFIED;
+ }
+
+ private static boolean verifyCACertificatePath(Set<TrustAnchor> trustedCACertificates, CodeSigner archiveCertPath) {
+ if(trustedCACertificates.isEmpty()) {
+ return false;
+ }
+ try {
+ CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ PKIXParameters verificationParameters = new PKIXParameters(trustedCACertificates);
+ PKIXRevocationChecker rc = (PKIXRevocationChecker) cpv.getRevocationChecker();
+ rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
+ verificationParameters.addCertPathChecker(rc);
+ if (archiveCertPath.getTimestamp() != null) {
+ cpv.validate(archiveCertPath.getSignerCertPath(), verificationParameters);
+ verificationParameters.setDate(archiveCertPath.getTimestamp().getTimestamp());
}
+ // validate raises a CertPathValidatorException if validation failed
+ cpv.validate(archiveCertPath.getSignerCertPath(), verificationParameters);
+ return true;
+ } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException ex) {
+ // InvalidAlgorithmParameterException - Should not get here - trustAnchor cannot be null -> collection cannot be empty
+ // NoSuchAlgorithmException - Should not get here - "PKIX" is proper algorythm
+ err.log(Level.SEVERE, "Certificate verification failed - " + ex.getMessage(), ex);
+ //SIGNATURE_UNVERIFIED - result = 0;
+ } catch (CertPathValidatorException ex) {
+ // CertPath cannot be validated
+ err.log(Level.INFO, "Cannot validate certificate path - " + ex.getMessage(), ex);
+ //SIGNATURE_UNVERIFIED - result = 0;
}
- return UNSIGNED;
+ return false;
+ }
+
+ private static boolean isChainTrusted(Collection<? extends Certificate> archiveCertificates, Collection<? extends Certificate> trustedCertificates) {
+ Collection<Certificate> c = new HashSet(trustedCertificates);
+ c.retainAll(archiveCertificates);
+ return ! c.isEmpty();
}
/**
@@ -270,7 +255,7 @@ public class Utilities {
}
public static Collection<Certificate> getCertificates (KeyStore keyStore) throws KeyStoreException {
- Set<Certificate> certs = new HashSet<Certificate> ();
+ Set<Certificate> certs = new HashSet<> ();
for (String alias: Collections.list (keyStore.aliases ())) {
Certificate[] certificateChain = keyStore.getCertificateChain(alias);
if (certificateChain != null) {
@@ -281,18 +266,37 @@ public class Utilities {
return certs;
}
+ public static Collection<TrustAnchor> getTrustAnchor (KeyStore keyStore) throws KeyStoreException {
+ Set<TrustAnchor> certs = new HashSet<> ();
+ for (String alias: Collections.list (keyStore.aliases ())) {
+ Certificate[] certificateChain = keyStore.getCertificateChain(alias);
+ if (certificateChain != null) {
+ for(Certificate cert: certificateChain) {
+ if(cert instanceof X509Certificate) {
+ certs.add(new TrustAnchor((X509Certificate) cert, null));
+ }
+ }
+ }
+ Certificate aliasCert = keyStore.getCertificate(alias);
+ if(aliasCert instanceof X509Certificate) {
+ certs.add(new TrustAnchor((X509Certificate) aliasCert, null));
+ }
+ }
+ return certs;
+ }
+
/**
* Get the certpaths that were used to sign the NBM content.
*
* @param nbmFile
- * @return collection of CertPaths, that were used to sign the non-signature
+ * @return collection of CodeSigners, that were used to sign the non-signature
* entries of the NBM
* @throws IOException
* @throws SecurityException if JAR was tampered with or if the certificate
* chains are not consistent
*/
- public static Collection<CertPath> getNbmCertificates (File nbmFile) throws IOException, SecurityException {
- Set<CertPath> certs = null;
+ public static Collection<CodeSigner> getNbmCertificates (File nbmFile) throws IOException, SecurityException {
+ Set<CodeSigner> certs = null;
// Empty means only the MANIFEST.MF is present - special cased to be in
// line with established behaviour
@@ -317,11 +321,11 @@ public class Utilities {
if(! entry.getName().equals("META-INF/MANIFEST.MF")) {
empty = false;
}
- Set<CertPath> entryCerts = new HashSet<>();
+ Set<CodeSigner> entryCerts = new HashSet<>();
CodeSigner[] codeSigners = entry.getCodeSigners();
if (codeSigners != null) {
for (CodeSigner cs : entry.getCodeSigners()) {
- entryCerts.add(cs.getSignerCertPath());
+ entryCerts.add(cs);
}
}
if(certs == null) {
@@ -362,7 +366,7 @@ public class Utilities {
@Override
public void resultChanged (LookupEvent ev) {
- result = null;
+ keystoreCache.clear();
}
}
diff --git a/platform/autoupdate.services/src/org/netbeans/spi/autoupdate/KeyStoreProvider.java b/platform/autoupdate.services/src/org/netbeans/spi/autoupdate/KeyStoreProvider.java
index 5f2b3ad..e94fb1d 100644
--- a/platform/autoupdate.services/src/org/netbeans/spi/autoupdate/KeyStoreProvider.java
+++ b/platform/autoupdate.services/src/org/netbeans/spi/autoupdate/KeyStoreProvider.java
@@ -29,9 +29,52 @@ import java.security.KeyStore;
* @author Jiri Rechtacek
*/
public interface KeyStoreProvider {
-
+ /**
+ * TrustLevel describes the level of trust, that a {@link KeyStoreProvider}
+ * assigns to the provided keystore.
+ *
+ * @since 1.61
+ */
+ public enum TrustLevel {
+ /**
+ * Unlimited trust - modules signed with certificates in this store
+ * will be installed without further user requests. This level is by
+ * default used for the update centers of the IDE itself.
+ */
+ TRUST,
+ /**
+ * Unlimited trust - modules signed with certificates in this store
+ * will be installed without further user requests. This level is by
+ * default used for the update centers of the IDE itself. It differes
+ * from {@link TRUST} in that, these certificates are subject to a
+ * {@code CertPathValidator}
+ */
+ TRUST_CA,
+ /**
+ * Plugins signed with certificates from this store will show up as
+ * "Signed and valid".
+ */
+ VALIDATE,
+ /**
+ * Plugins signed with certificates created by these certificates
+ * will show up as "Signed and valid". While certificates provided by
+ * {@link VALIDATE} not subject to PKIX checking, these certificates
+ * are run through a {@code CertPathValidator}.
+ */
+ VALIDATE_CA
+ }
+
/**
* @return KeyStore
*/
public KeyStore getKeyStore ();
+
+ /**
+ * @return TrustLevel that is provided by the keystore this
+ * {@link KeyStoreProvider} provides
+ * @since 1.61
+ */
+ default TrustLevel getTrustLevel() {
+ return TrustLevel.TRUST;
+ }
}
diff --git a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
index b55e48f..7813bc5 100644
--- a/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
+++ b/platform/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/VerifyFileTest.java
@@ -25,11 +25,15 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
+import java.security.CodeSigner;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.cert.CertPath;
import java.security.cert.Certificate;
+import java.security.cert.TrustAnchor;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.autoupdate.TestUtils;
@@ -42,6 +46,7 @@ public class VerifyFileTest extends NbTestCase {
private static final Logger LOG = Logger.getLogger(VerifyFileTest.class.getName());
private KeyStore ks;
+ private KeyStore validateKs;
public VerifyFileTest(String testName) {
super(testName);
@@ -51,9 +56,14 @@ public class VerifyFileTest extends NbTestCase {
protected void setUp() throws Exception {
URL urlToKS = TestUtils.class.getResource("data/test-keystore.jks");
assertNotNull(urlToKS);
+ URL urlToValidateKS = TestUtils.class.getResource("data/test-validate-keystore.jks");
+ assertNotNull(urlToValidateKS);
File ksFile = org.openide.util.Utilities.toFile(urlToKS.toURI());
assertTrue(ksFile.exists());
+ File validateKsFile = org.openide.util.Utilities.toFile(urlToValidateKS.toURI());
+ assertTrue(validateKsFile.exists());
ks = getKeyStore(ksFile, "password");
+ validateKs = getKeyStore(validateKsFile, "password");
}
private String doVerification(String path) throws URISyntaxException, IOException, KeyStoreException {
@@ -63,8 +73,11 @@ public class VerifyFileTest extends NbTestCase {
assertTrue(jar.exists());
String res = null;
try {
- Collection<CertPath> nbmCerts = Utilities.getNbmCertificates(jar);
+ Collection<CodeSigner> nbmCerts = Utilities.getNbmCertificates(jar);
Collection<Certificate> trustedCerts = Utilities.getCertificates(ks);
+ Set<TrustAnchor> trustedCACerts = Collections.EMPTY_SET;
+ Collection<Certificate> validationAnchors = new HashSet<>(Utilities.getCertificates(validateKs));
+ Set<TrustAnchor> validationCACerts = Collections.EMPTY_SET;
if (nbmCerts == null) {
res = Utilities.N_A;
} else if (nbmCerts.isEmpty()) {
@@ -74,8 +87,8 @@ public class VerifyFileTest extends NbTestCase {
// choose the certpath, that has the highest trust level
// TRUSTED -> SIGNATURE_VERIFIED -> SIGNATURE_UNVERIFIED -> UNSIGNED
// or comes first
- for (CertPath cp : nbmCerts) {
- String localRes = Utilities.verifyCertificates(cp, trustedCerts);
+ for (CodeSigner cp : nbmCerts) {
+ String localRes = Utilities.verifyCertificates(cp, trustedCerts, trustedCACerts, validationAnchors, validationCACerts);
if (res == null
|| VERIFICATION_RESULT_COMPARATOR.compare(res, localRes) > 0) {
res = localRes;
@@ -113,6 +126,14 @@ public class VerifyFileTest extends NbTestCase {
assertEquals(Utilities.TRUSTED, doVerification("data/dummy-signed-twice.jar"));
}
+ public void testValidatedSigned() throws MalformedURLException, URISyntaxException, IOException, KeyStoreException {
+ assertEquals(Utilities.SIGNATURE_VERIFIED, doVerification("data/dummy-validated.jar"));
+ }
+
+ public void testUnvalidatedSigned() throws MalformedURLException, URISyntaxException, IOException, KeyStoreException {
+ assertEquals(Utilities.SIGNATURE_UNVERIFIED, doVerification("data/dummy-unvalidated.jar"));
+ }
+
public void testUnsignedPartiallySigned() throws MalformedURLException, URISyntaxException, IOException, KeyStoreException {
assertEquals(Utilities.MODIFIED, doVerification("data/dummy-partial-signed.jar"));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists