diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 8d04c4c6d6..93658c2057 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -22,14 +22,23 @@ import java.net.PasswordAuthentication; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.logging.Level; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; @@ -80,14 +89,8 @@ public class CTCloudHttpClient { private String hostName = null; private CTCloudHttpClient() { - SSLContext tmpSslContext; - try { - tmpSslContext = SSLContext.getInstance("TLSv1.2"); - } catch (NoSuchAlgorithmException ex) { - LOGGER.log(Level.WARNING, "Unable to setup ssl context instance", ex); - tmpSslContext = null; - } - this.sslContext = tmpSslContext; + // leave as null for now unless we want to customize this at a later date + this.sslContext = null; } private ProxySettingArgs getProxySettings() { @@ -100,12 +103,14 @@ public class CTCloudHttpClient { } int proxyPort = 0; - try { - proxyPort = Integer.parseInt(ProxySettings.getHttpsPort()); - } catch (NumberFormatException ex) { - LOGGER.log(Level.WARNING, "An exception occurred while converting port number to integer", ex); + if (StringUtils.isNotBlank(ProxySettings.getHttpPort())) { + try { + proxyPort = Integer.parseInt(ProxySettings.getHttpsPort()); + } catch (NumberFormatException ex) { + LOGGER.log(Level.WARNING, "Unable to convert port to integer"); + } } - + return new ProxySettingArgs( ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION, hostName, diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java index 3cc077c06d..29403ce7d4 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java @@ -13,12 +13,7 @@ ************************************************************************** */ package com.basistech.df.cybertriage.autopsy.ctapi; -import com.google.common.collect.ImmutableList; import java.net.URI; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; // TODO take out anything sensitive or not used final public class Constants { @@ -31,10 +26,13 @@ final public class Constants { public static final String SSLTEST_URL = "https://www2.cybertriage.com/ssl_test.html"; - public static final String CT_CLOUD_SERVER = "https://rep1.cybertriage.com"; + public static final String CT_CLOUD_DEV_SERVER = "https://cyber-triage-dev.appspot.com"; + // TODO put back + public static final String CT_CLOUD_SERVER = CT_CLOUD_DEV_SERVER; //"https://rep1.cybertriage.com"; + /** * Link to watch demo video * @since 3.1.0 diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java index f7b5e75147..061f8a83e0 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java @@ -36,7 +36,8 @@ public class CTApiDAO { private static final String LICENSE_REQUEST_PATH = "/_ah/api/license/v1/activate"; private static final String AUTH_TOKEN_REQUEST_PATH = "/_ah/api/auth/v2/generate_token"; private static final String CTCLOUD_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE"; - + private static final String AUTOPSY_PRODUCT = "AUTOPSY"; + private static final CTApiDAO instance = new CTApiDAO(); @@ -48,7 +49,7 @@ public class CTApiDAO { } private static String getAppVersion() { - return Version.getName() + " " + Version.getVersion(); + return Version.getVersion(); } private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance(); @@ -58,7 +59,7 @@ public class CTApiDAO { LicenseRequest licenseRequest = new LicenseRequest() .setBoostLicenseCode(licenseString) .setHostId(CTHostIDGenerationUtil.generateLicenseHostID()) - .setProduct(getAppVersion()); + .setProduct(AUTOPSY_PRODUCT); return httpClient.doPost(LICENSE_REQUEST_PATH, licenseRequest, LicenseResponse.class); @@ -89,8 +90,4 @@ public class CTApiDAO { ? Collections.emptyList() : resp.getItems(); } - - public enum ResultType { - OK, SERVER_ERROR, NOT_AUTHORIZED - } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java index ec9e74a2ed..79ef4350d5 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java @@ -13,8 +13,12 @@ ************************************************************************** */ package com.basistech.df.cybertriage.autopsy.ctapi.json; +import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.InstantEpochMillisDeserializer; +import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.MDYDateDeserializer; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.time.Instant; import java.time.ZonedDateTime; /** @@ -27,7 +31,7 @@ public class DecryptedLicenseResponse { private final ZonedDateTime expirationDate; private final Long hashLookups; private final Long fileUploads; - private final ZonedDateTime activationTime; + private final Instant activationTime; private final String product; private final String limitType; @@ -35,12 +39,17 @@ public class DecryptedLicenseResponse { public DecryptedLicenseResponse( @JsonProperty("boostLicenseId") String boostLicenseId, @JsonProperty("licenseHostId") String licenseHostId, + @JsonDeserialize(using=MDYDateDeserializer.class) @JsonProperty("expirationDate") ZonedDateTime expirationDate, @JsonProperty("hashLookups") Long hashLookups, @JsonProperty("fileUploads") Long fileUploads, - @JsonProperty("activationTime") ZonedDateTime activationTime, + @JsonDeserialize(using=InstantEpochMillisDeserializer.class) + @JsonProperty("activationTime") Instant activationTime, @JsonProperty("product") String product, - @JsonProperty("limitType") String limitType + @JsonProperty("limitType") String limitType, + + @JsonProperty("l4jLicenseId") String l4jlicenseId, + @JsonProperty("ctLicenseId") String ctLicenseId ) { this.boostLicenseId = boostLicenseId; this.licenseHostId = licenseHostId; @@ -68,7 +77,7 @@ public class DecryptedLicenseResponse { return fileUploads; } - public ZonedDateTime getActivationTime() { + public Instant getActivationTime() { return activationTime; } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java index efa91afd8d..8276b8a55a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java @@ -87,9 +87,9 @@ public class LicenseDecryptorUtil { } DecryptedLicenseResponse decryptedLicense = objectMapper.readValue(decryptedJsonResponse, DecryptedLicenseResponse.class); - if (!"CYBERTRIAGE".equalsIgnoreCase(decryptedLicense.getProduct())) { + if (!"AUTOPSY".equalsIgnoreCase(decryptedLicense.getProduct())) { // license file is expected to contain product of "CYBERTRIAGE" - throw new InvalidLicenseException("Not a valid Cyber Triage license"); + throw new InvalidLicenseException("Not a valid Autopsy license"); } return decryptedLicense; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/ObjectMapperUtil.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/ObjectMapperUtil.java index 79098ce650..4a5ecd7925 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/ObjectMapperUtil.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/ObjectMapperUtil.java @@ -13,8 +13,19 @@ ************************************************************************** */ package com.basistech.df.cybertriage.autopsy.ctapi.util; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.IOException; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; /** * Creates default ObjectMapper @@ -33,9 +44,41 @@ public class ObjectMapperUtil { public ObjectMapper getDefaultObjectMapper() { ObjectMapper defaultMapper = new ObjectMapper(); - defaultMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); +// defaultMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); defaultMapper.registerModule(new JavaTimeModule()); return defaultMapper; } + public static class MDYDateDeserializer extends JsonDeserializer { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("MMM dd, yyyy"); + @Override + public ZonedDateTime deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException { + JsonNode node = jp.getCodec().readTree(jp); + String nodeText = node.asText(); + try { + return ZonedDateTime.parse(nodeText, FORMATTER); + } catch (DateTimeParseException ex) { + return null; + } + } + + } + + public static class InstantEpochMillisDeserializer extends JsonDeserializer { + + @Override + public Instant deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException { + JsonNode node = jp.getCodec().readTree(jp); + if (!node.isNumber()) { + return null; + } else { + try { + long millis = node.asLong(); + return Instant.ofEpochMilli(millis); + } catch (DateTimeException ex) { + return null; + } + } + } + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index 5df431e10c..9b875b95c9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -2,7 +2,7 @@ # Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template - +CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX CTLicenseDialog.cancelButton.text=Cancel @@ -21,3 +21,4 @@ CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text= CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 6eaa730072..4819107a24 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -2,7 +2,7 @@ # Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template - +CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX CTLicenseDialog.cancelButton.text=Cancel @@ -22,6 +22,7 @@ CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text= CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= + CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number: CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License... CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java index 8af5795517..4a32bc2c40 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java @@ -24,8 +24,9 @@ import org.openide.util.NbBundle.Messages; */ public class CTLicenseDialog extends javax.swing.JDialog { - private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}\\s*$"); + //private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}\\s*$"); + private static final Pattern LICENSE_PATTERN = Pattern.compile("\\s*[a-zA-Z0-9\\-]+?\\s*"); private String licenseString = null; /** diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java index 8f9d61a79e..a77b537e24 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java @@ -49,6 +49,7 @@ public class CTLicensePersistence { if (licenseResponse != null) { File licenseFile = getCTLicenseFile(); try { + licenseFile.getParentFile().mkdirs(); objectMapper.writeValue(licenseFile, licenseResponse); return true; } catch (IOException ex) { @@ -62,7 +63,7 @@ public class CTLicensePersistence { public synchronized Optional loadLicenseResponse() { Optional toRet = Optional.empty(); File licenseFile = getCTLicenseFile(); - if (licenseFile.isFile()) { + if (licenseFile.exists() && licenseFile.isFile()) { try { toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class)); } catch (IOException ex) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 6ff5e74edc..97e0f0ccee 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -162,11 +162,14 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.authTokenFetcher.cancel(true); } - setMalwareScansDisplay(null, Bundle.CTOPtionsPanel_loadMalwareScansInfo_loading()); - if (licenseInfo == null || licenseInfo.getDecryptedLicense() == null) { + setMalwareScansDisplay(null, null); return; } + + setMalwareScansDisplay(null, Bundle.CTOPtionsPanel_loadMalwareScansInfo_loading()); + + this.authTokenFetcher = new AuthTokenFetcher(licenseInfo.getDecryptedLicense().getBoostLicenseId()); this.authTokenFetcher.execute(); @@ -388,7 +391,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.licenseInfoUserLabel.setVisible(false); } else { this.licenseInfoExpiresLabel.setVisible(true); - this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(LICENSE_EXPIRES_FORMAT.format(this.licenseInfo.getDecryptedLicense().getExpirationDate()))); + this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(this.licenseInfo.getDecryptedLicense().getExpirationDate() == null ? "" : LICENSE_EXPIRES_FORMAT.format(this.licenseInfo.getDecryptedLicense().getExpirationDate()))); this.licenseInfoIdLabel.setVisible(true); this.licenseInfoIdLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_id(this.licenseInfo.getDecryptedLicense().getBoostLicenseId())); this.licenseInfoUserLabel.setVisible(true); @@ -412,7 +415,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.maxFileUploadsLabel.setVisible(true); this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(this.authTokenResponse.getFileUploadLimit())); this.countersResetLabel.setVisible(true); - this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getExpiration()))); + this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(this.authTokenResponse.getExpiration() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getExpiration()))); this.hashLookupsRemainingLabel.setVisible(true); this.hashLookupsRemainingLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining(remaining(this.authTokenResponse.getHashLookupLimit(), this.authTokenResponse.getHashLookupCount()))); this.fileUploadsRemainingLabel.setVisible(true); diff --git a/CoreLibs/nbproject/project.xml b/CoreLibs/nbproject/project.xml index b2f08dc42b..ff5e70f4e8 100644 --- a/CoreLibs/nbproject/project.xml +++ b/CoreLibs/nbproject/project.xml @@ -64,6 +64,10 @@ com.fasterxml.jackson.databind.util com.fasterxml.jackson.dataformat.csv com.fasterxml.jackson.datatype.jsr310 + com.fasterxml.jackson.datatype.jsr310.deser + com.fasterxml.jackson.datatype.jsr310.deser.key + com.fasterxml.jackson.datatype.jsr310.ser + com.fasterxml.jackson.datatype.jsr310.ser.key com.fasterxml.jackson.datatype.jsr310.util com.github.lgooddatepicker.components com.github.lgooddatepicker.optionalusertools diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index f8cea13909..4973262834 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 20 Jul 2023 14:02:30 -0400 +#Thu, 20 Jul 2023 19:55:04 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 2387b67597..a6687c35a0 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 20 Jul 2023 14:02:30 -0400 +#Thu, 20 Jul 2023 19:55:04 -0400 CTL_MainWindow_Title=Autopsy 4.20.0 CTL_MainWindow_Title_No_Project=Autopsy 4.20.0