From 4f04c1d3f0617676b2f0b49a5d022b8c3f6860a0 Mon Sep 17 00:00:00 2001 From: "eugene.livis" <elivis@basistech.com> Date: Tue, 31 Oct 2023 11:37:18 -0400 Subject: [PATCH] Verifying Postgres SSL certificates --- .../datamodel/CaseDatabaseFactory.java | 16 +++++++--- .../datamodel/CaseDbConnectionInfo.java | 16 ++++++++-- .../sleuthkit/datamodel/SleuthkitCase.java | 32 +++++++++++++------ 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java index 6e3ffe683..a81349108 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java @@ -714,11 +714,17 @@ Connection getConnection(String databaseName) throws TskCoreException { .append(encodedDbName); if (info.isSslEnabled()) { - // ssl=true: enables SSL encryption. - // NonValidatingFactory avoids hostname verification. - // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can�t be encrypted. - // In this mode, the JDBC driver accepts all server certificates. - url.append("?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"); + // ssl=true: enables SSL encryption. + if (info.isSslVerify()) { + // DefaultJavaSSLFactory: uses Java's default truststore to validate server certificate. + // sslmode=verify-ca: verifies that the server we are connecting to is trusted by CA. + url.append("?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca"); + } else { + // NonValidatingFactory avoids hostname verification. + // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can't be encrypted. + // In this mode, the JDBC driver accepts all server certificates, including self-signed ones. + url.append("?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"); + } } Connection conn; diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java index 2fc9d3ec4..4cf918dfe 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java +++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java @@ -1,7 +1,7 @@ /* * Sleuth Kit Data Model * - * Copyright 2011-2015 Basis Technology Corp. + * Copyright 2011-2023 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,6 +35,7 @@ public class CaseDbConnectionInfo { private String password; private DbType dbType; private boolean sslEnabled = false; + private boolean sslVerify = false; /** * The intent of this class is to hold any information needed to connect to @@ -56,6 +57,7 @@ public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userN this.userName = userName; this.password = password; this.sslEnabled = false; + this.sslVerify = false; if (dbType == DbType.SQLITE) { throw new IllegalArgumentException("SQLite database type invalid for CaseDbConnectionInfo. CaseDbConnectionInfo should be used only for remote database types."); } @@ -77,13 +79,15 @@ public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userN * @param password the password * @param dbType the database type * @param sslEnabled a flag whether SSL is enabled + * @param sslVerify 'true' if SSL certificate needs to be CA verified. 'false' if self-signed certificates should be accepted. */ - public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userName, String password, DbType dbType, boolean sslEnabled) { + public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userName, String password, DbType dbType, boolean sslEnabled, boolean sslVerify) { this.hostNameOrIP = hostNameOrIP; this.portNumber = portNumber; this.userName = userName; this.password = password; this.sslEnabled = sslEnabled; + this.sslVerify = sslVerify; if (dbType == DbType.SQLITE) { throw new IllegalArgumentException("SQLite database type invalid for CaseDbConnectionInfo. CaseDbConnectionInfo should be used only for remote database types."); } @@ -137,4 +141,12 @@ public boolean isSslEnabled() { public void setSslEnabled(boolean sslEnabled) { this.sslEnabled = sslEnabled; } + + public boolean isSslVerify() { + return sslVerify; + } + + public void setSslVerify(boolean sslVerify) { + this.sslVerify = sslVerify; + } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 01e59f885..95257a63f 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -295,11 +295,17 @@ public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException Class.forName("org.postgresql.Driver"); //NON-NLS String connectionURL = "jdbc:postgresql://" + info.getHost() + ":" + info.getPort() + "/postgres"; if (info.isSslEnabled()) { - // ssl=true: enables SSL encryption. - // NonValidatingFactory avoids hostname verification. - // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can�t be encrypted. - // In this mode, the JDBC driver accepts all server certificates. - connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"; + // ssl=true: enables SSL encryption. + if (info.isSslVerify()) { + // DefaultJavaSSLFactory: uses Java's default truststore to validate server certificate. + // sslmode=verify-ca: verifies that the server we are connecting to is trusted by CA. + connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca"; + } else { + // NonValidatingFactory avoids hostname verification. + // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can't be encrypted. + // In this mode, the JDBC driver accepts all server certificates, including self-signed ones. + connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"; + } } Connection conn = DriverManager.getConnection(connectionURL, info.getUserName(), info.getPassword()); //NON-NLS if (conn != null) { @@ -13406,11 +13412,17 @@ private final class PostgreSQLConnections extends ConnectionPool { String connectionURL = "jdbc:postgresql://" + info.getHost() + ":" + Integer.valueOf(info.getPort()) + "/" + URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString()); if (info.isSslEnabled()) { - // ssl=true: enables SSL encryption. - // NonValidatingFactory avoids hostname verification. - // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can�t be encrypted. - // In this mode, the JDBC driver accepts all server certificates. - connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"; + // ssl=true: enables SSL encryption. + if (info.isSslVerify()) { + // DefaultJavaSSLFactory: uses Java's default truststore to validate server certificate. + // sslmode=verify-ca: verifies that the server we are connecting to is trusted by CA. + connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca"; + } else { + // NonValidatingFactory avoids hostname verification. + // sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can't be encrypted. + // In this mode, the JDBC driver accepts all server certificates, including self-signed ones. + connectionURL += "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require"; + } } comboPooledDataSource.setJdbcUrl(connectionURL); comboPooledDataSource.setUser(info.getUserName()); -- GitLab