From 122c78648adb7fe8b71cda0839d5e3ea0e311128 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 21 May 2017 18:04:26 -0400 Subject: [PATCH] updated code to better handle TLS errors --- .../dependencycheck/analyzer/NspAnalyzer.java | 25 ++-- .../dependencycheck/data/nsp/NspSearch.java | 111 ++++++++++-------- .../org/owasp/dependencycheck/EngineIT.java | 31 +++-- .../data/nsp/NspSearchTest.java | 17 ++- 4 files changed, 108 insertions(+), 76 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java index 2bdac7f7a..0cdf6fca6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java @@ -50,10 +50,11 @@ import javax.json.JsonReader; import javax.json.JsonString; import javax.json.JsonValue; import org.owasp.dependencycheck.exception.InitializationException; +import org.owasp.dependencycheck.utils.URLConnectionFailureException; /** - * Used to analyze Node Package Manager (npm) package.json files via - * Node Security Platform (nsp). + * Used to analyze Node Package Manager (npm) package.json files via Node + * Security Platform (nsp). * * @author Steve Springett */ @@ -161,7 +162,7 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { // Submits the package payload to the nsp check service final List advisories = searcher.submitPackage(nspPayload); - for (Advisory advisory: advisories) { + for (Advisory advisory : advisories) { /* * Create a new vulnerability out of the advisory returned by nsp. */ @@ -247,23 +248,27 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { addToEvidence(packageJson, vendorEvidence, "author"); addToEvidence(packageJson, dependency.getVersionEvidence(), "version"); dependency.setDisplayFileName(String.format("%s/%s", file.getParentFile().getName(), file.getName())); - + } catch (URLConnectionFailureException e) { + this.setEnabled(false); + throw new AnalysisException(e.getMessage(), e); } catch (IOException e) { - LOGGER.debug("Error reading dependency or connecting to Node Security Platform /check API", e); + LOGGER.debug("Error reading dependency or connecting to Node Security Platform - check API", e); + this.setEnabled(false); + throw new AnalysisException(e.getMessage(), e); } catch (JsonException e) { - LOGGER.warn("Failed to parse package.json file.", e); + throw new AnalysisException(String.format("Failed to parse %s file.", file.getPath()), e); } } /** - * Processes a part of package.json (as defined by JsobObject) and - * update the specified dependency with relevant info. + * Processes a part of package.json (as defined by JsobObject) and update + * the specified dependency with relevant info. * * @param dependency the Dependency to update * @param jsonObject the jsonObject to parse */ private void processPackage(Dependency dependency, JsonObject jsonObject, String depType) { - for (int i=0; i entry : jsonObject.entrySet()) { /* * Create identifies that include the npm module and version. Since these are defined, @@ -273,7 +278,7 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { moduleName.setConfidence(Confidence.HIGHEST); String version = ""; if (entry.getValue() != null && entry.getValue().getValueType() == JsonValue.ValueType.STRING) { - version = ((JsonString)entry.getValue()).getString(); + version = ((JsonString) entry.getValue()).getString(); } final Identifier moduleVersion = new Identifier("npm", "Version", null, version); moduleVersion.setConfidence(Confidence.HIGHEST); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java index c59830a4c..d78ecfb34 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java @@ -35,6 +35,7 @@ import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonReader; +import org.owasp.dependencycheck.utils.URLConnectionFailureException; /** * Class of methods to search via Node Security Platform. @@ -75,70 +76,80 @@ public class NspSearch { } /** - * Submits the package.json file to the NSP public /check API and returns - * a list of zero or more Advisories. + * Submits the package.json file to the NSP public /check API and returns a + * list of zero or more Advisories. * * @param packageJson the package.json file retrieved from the Dependency * @return a List of zero or more Advisory object * @throws IOException if it's unable to connect to Node Security Platform */ public List submitPackage(JsonObject packageJson) throws IOException { - List result = new ArrayList<>(); - byte[] packageDatabytes = packageJson.toString().getBytes(StandardCharsets.UTF_8); + try { + List result = new ArrayList<>(); + byte[] packageDatabytes = packageJson.toString().getBytes(StandardCharsets.UTF_8); - final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(nspCheckUrl, useProxy); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - conn.setRequestProperty("X-NSP-VERSION", "2.6.2"); - conn.setRequestProperty("Content-Type", "application/json"); - conn.setRequestProperty("Content-Length", Integer.toString(packageDatabytes.length)); - conn.connect(); + final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(nspCheckUrl, useProxy); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + conn.setRequestProperty("X-NSP-VERSION", "2.6.2"); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setRequestProperty("Content-Length", Integer.toString(packageDatabytes.length)); + conn.connect(); - try (OutputStream os = new BufferedOutputStream(conn.getOutputStream())) { - os.write(packageDatabytes); - os.flush(); - } + try (OutputStream os = new BufferedOutputStream(conn.getOutputStream())) { + os.write(packageDatabytes); + os.flush(); + } - if (conn.getResponseCode() == 200) { - try (InputStream in = new BufferedInputStream(conn.getInputStream())) { - JsonReader jsonReader = Json.createReader(in); - JsonArray array = jsonReader.readArray(); - if (array != null) { - for (int i=0; i stringPath = new ArrayList<>(); - for (int j=0; j stringPath = new ArrayList<>(); + for (int j = 0; j < jsonPath.size(); j++) { + stringPath.add(jsonPath.getString(j)); + } + advisory.setPath(stringPath.toArray(new String[stringPath.size()])); + + result.add(advisory); } - advisory.setPath(stringPath.toArray(new String[stringPath.size()])); - - result.add(advisory); } } + } else { + LOGGER.debug("Could not connect to Node Security Platform. Received response code: {} {}", + conn.getResponseCode(), conn.getResponseMessage()); + throw new IOException("Could not connect to Node Security Platform"); } - } else { - LOGGER.debug("Could not connect to Node Security Platform. Received response code: {} {}", - conn.getResponseCode(), conn.getResponseMessage()); - throw new IOException("Could not connect to Node Security Platform"); + return result; + } catch (IOException ex) { + if (ex instanceof javax.net.ssl.SSLHandshakeException + && ex.getMessage().contains("unable to find valid certification path to requested target")) { + final String msg = String.format("Unable to connect to '%s' - the Java trust store does not contain a trusted root for the cert. " + + " Please see https://github.com/jeremylong/InstallCert for one method of updating the trusted certificates.", nspCheckUrl); + throw new URLConnectionFailureException(msg, ex); + } + throw ex; } - return result; } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java index dd81bf828..1df3dc7cf 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java @@ -18,6 +18,8 @@ package org.owasp.dependencycheck; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -58,18 +60,23 @@ public class EngineIT extends BaseDBTestCase { try { instance.analyzeDependencies(); } catch (ExceptionCollection ex) { - if (ex.getExceptions().size() == 1 - && (ex.getExceptions().get(0).getMessage().contains("bundle-audit") - || ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer"))) { - //this is fine to ignore - } else if (ex.getExceptions().size() == 2 - && ((ex.getExceptions().get(0).getMessage().contains("bundle-audit") - && ex.getExceptions().get(1).getMessage().contains("AssemblyAnalyzer")) - || (ex.getExceptions().get(1).getMessage().contains("bundle-audit") - && ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer")))) { - //this is fine to ignore - } else { - throw ex; + Set allowedMessages = new HashSet<>(); + allowedMessages.add("bundle-audit"); + allowedMessages.add("AssemblyAnalyzer"); + //allowedMessages.add("Unable to connect to"); + for (Throwable t : ex.getExceptions()) { + boolean isOk = false; + if (t.getMessage()!=null) { + for (String msg : allowedMessages) { + if (t.getMessage().contains(msg)) { + isOk=true; + break; + } + } + } + if (!isOk) { + throw ex; + } } } DatabaseProperties prop = null; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nsp/NspSearchTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nsp/NspSearchTest.java index a39f37899..f93c6afbc 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nsp/NspSearchTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nsp/NspSearchTest.java @@ -32,6 +32,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.List; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; +import org.owasp.dependencycheck.utils.URLConnectionFailureException; public class NspSearchTest extends BaseTest { @@ -45,8 +48,7 @@ public class NspSearchTest extends BaseTest { searcher = new NspSearch(new URL(url)); } - //@Test - //todo: this test does not work in Java 7 - UNABLE TO FIND VALID CERTIFICATION PATH TO REQUESTED TARGET + @Test public void testNspSearchPositive() throws Exception { InputStream in = BaseTest.getResourceAsStream(this, "nsp/package.json"); try (JsonReader jsonReader = Json.createReader(in)) { @@ -56,17 +58,24 @@ public class NspSearchTest extends BaseTest { final JsonObject nspPayload = builder.add("package", sanitizedJson).build(); final List advisories = searcher.submitPackage(nspPayload); Assert.assertTrue(advisories.size() > 0); + } catch (Exception ex) { + assumeFalse(ex instanceof URLConnectionFailureException + && ex.getMessage().contains("Unable to connect to ")); + throw ex; } } - //@Test(expected = IOException.class) - //todo: this test does not work in Java 7 - UNABLE TO FIND VALID CERTIFICATION PATH TO REQUESTED TARGET + @Test public void testNspSearchNegative() throws Exception { InputStream in = BaseTest.getResourceAsStream(this, "nsp/package.json"); try (JsonReader jsonReader = Json.createReader(in)) { final JsonObject packageJson = jsonReader.readObject(); final JsonObject sanitizedJson = SanitizePackage.sanitize(packageJson); searcher.submitPackage(sanitizedJson); + } catch (Exception ex) { + assumeFalse(ex instanceof URLConnectionFailureException + && ex.getMessage().contains("Unable to connect to ")); + throw ex; } }