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 73fd1e96ab..fa35dd7dbb 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java @@ -20,7 +20,6 @@ package com.basistech.df.cybertriage.autopsy.ctapi; import java.net.URI; -// TODO take out anything sensitive or not used final public class Constants { public static final String CYBER_TRIAGE = "CyberTriage"; 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 927cc10cbe..b8883df4b2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java @@ -35,6 +35,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Version; /** @@ -69,7 +70,8 @@ public class CTApiDAO { LicenseRequest licenseRequest = new LicenseRequest() .setBoostLicenseCode(licenseString) .setHostId(CTHostIDGenerationUtil.generateLicenseHostID()) - .setProduct(AUTOPSY_PRODUCT); + .setProduct(AUTOPSY_PRODUCT) + .setTimeZoneId(UserPreferences.getInferredUserTimeZone()); return httpClient.doPost(LICENSE_REQUEST_PATH, licenseRequest, LicenseResponse.class); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenResponse.java index d23e14289a..d4ac70e16c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenResponse.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenResponse.java @@ -18,6 +18,7 @@ */ 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.InstantEpochSecsDeserializer; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -39,6 +40,7 @@ public class AuthTokenResponse { private final Instant expiration; private final String token; private final String apiKey; + private final Instant resetDate; @JsonCreator public AuthTokenResponse( @@ -50,7 +52,9 @@ public class AuthTokenResponse { @JsonProperty("fileUploadCount") Long fileUploadCount, @JsonProperty("fileUploadUrl") String fileUploadUrl, @JsonDeserialize(using = InstantEpochSecsDeserializer.class) - @JsonProperty("expiration") Instant expiration + @JsonProperty("expiration") Instant expiration, + @JsonDeserialize(using = InstantEpochMillisDeserializer.class) + @JsonProperty("resetDate") Instant resetDate ) { this.token = token; this.apiKey = apiKey; @@ -60,6 +64,7 @@ public class AuthTokenResponse { this.fileUploadCount = fileUploadCount; this.fileUploadUrl = fileUploadUrl; this.expiration = expiration; + this.resetDate = resetDate; } public Long getHashLookupCount() { @@ -94,4 +99,7 @@ public class AuthTokenResponse { return apiKey; } + public Instant getResetDate() { + return resetDate; + } } 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 bc10ec7703..5be0996a9e 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 @@ -19,13 +19,11 @@ 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.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.time.Instant; -import java.time.ZonedDateTime; /** * POJO for after encrypted boost license has been decrypted. @@ -35,27 +33,29 @@ public class DecryptedLicenseResponse { private final String boostLicenseId; private final String licenseHostId; - private final ZonedDateTime expirationDate; + private final Instant expirationDate; private final Long hashLookups; private final Long fileUploads; private final Instant activationTime; private final String product; private final String limitType; + private final String timezone; + private final String customerEmail; @JsonCreator public DecryptedLicenseResponse( @JsonProperty("boostLicenseId") String boostLicenseId, @JsonProperty("licenseHostId") String licenseHostId, - @JsonDeserialize(using = MDYDateDeserializer.class) - @JsonProperty("expirationDate") ZonedDateTime expirationDate, + @JsonDeserialize(using = InstantEpochMillisDeserializer.class) + @JsonProperty("expirationDate") Instant expirationDate, @JsonProperty("hashLookups") Long hashLookups, @JsonProperty("fileUploads") Long fileUploads, @JsonDeserialize(using = InstantEpochMillisDeserializer.class) @JsonProperty("activationTime") Instant activationTime, @JsonProperty("product") String product, - @JsonProperty("limitType") String limitType - // @JsonProperty("l4jLicenseId") String l4jlicenseId, - // @JsonProperty("ctLicenseId") String ctLicenseId + @JsonProperty("limitType") String limitType, + @JsonProperty("timezone") String timezone, + @JsonProperty("customerEmail") String customerEmail ) { this.boostLicenseId = boostLicenseId; this.licenseHostId = licenseHostId; @@ -65,6 +65,8 @@ public class DecryptedLicenseResponse { this.activationTime = activationTime; this.product = product; this.limitType = limitType; + this.timezone = timezone; + this.customerEmail = customerEmail; } public String getBoostLicenseId() { @@ -95,8 +97,15 @@ public class DecryptedLicenseResponse { return limitType; } - public ZonedDateTime getExpirationDate() { + public Instant getExpirationDate() { return expirationDate; } + public String getTimezone() { + return timezone; + } + + public String getCustomerEmail() { + return customerEmail; + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseInfo.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseInfo.java index 1ee8112105..127df9987d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseInfo.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseInfo.java @@ -37,14 +37,4 @@ public class LicenseInfo { public DecryptedLicenseResponse getDecryptedLicense() { return decryptedLicense; } - - // TODO - public String getUser() { - return "TBD"; - } - - // TODO - public String getEmail() { - return "TBD"; - } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseRequest.java index 4abda508f5..18a1b1c4bf 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseRequest.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseRequest.java @@ -32,6 +32,9 @@ public class LicenseRequest { @JsonProperty("product") private String product; + + @JsonProperty("time_zone_id") + private String timeZoneId; public String getHostId() { return hostId; @@ -59,6 +62,16 @@ public class LicenseRequest { this.product = product; return this; } + + public String getTimeZoneId() { + return timeZoneId; + } + + public LicenseRequest setTimeZoneId(String timeZoneId) { + this.timeZoneId = timeZoneId; + return this; + } + } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java index 4d68f86e5e..a3a8247884 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java @@ -27,6 +27,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; */ @JsonIgnoreProperties(ignoreUnknown = true) public class LicenseResponse { + private final Boolean success; private final Boolean hostChanged; private final Long hostChangesRemaining; @@ -34,9 +35,9 @@ public class LicenseResponse { @JsonCreator public LicenseResponse( - @JsonProperty("success") Boolean success, - @JsonProperty("hostChanged") Boolean hostChanged, - @JsonProperty("hostChangesRemaining") Long hostChangesRemaining, + @JsonProperty("success") Boolean success, + @JsonProperty("hostChanged") Boolean hostChanged, + @JsonProperty("hostChangesRemaining") Long hostChangesRemaining, @JsonProperty("boostLicense") BoostLicenseResponse boostLicense ) { this.success = success; @@ -60,7 +61,4 @@ public class LicenseResponse { public BoostLicenseResponse getBoostLicense() { return boostLicense; } - - - } 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 ac6fe958ab..d6412fff67 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 @@ -57,11 +57,11 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private static final DateTimeFormatter LICENSE_EXPIRES_FORMAT = DateTimeFormatter .ofPattern("MMMM d, YYYY") - .withZone(ZoneId.of(UserPreferences.getTimeZoneForDisplays())); + .withZone(ZoneId.of(UserPreferences.getInferredUserTimeZone())); private static final DateTimeFormatter MALWARE_SCANS_RESET_FORMAT = DateTimeFormatter .ofPattern("MMM d, YYYY' at 'h:mma") - .withZone(ZoneId.of(UserPreferences.getTimeZoneForDisplays())); + .withZone(ZoneId.of(UserPreferences.getInferredUserTimeZone())); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance(); @@ -406,11 +406,16 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.licenseInfoUserLabel.setVisible(false); } else { this.licenseInfoExpiresLabel.setVisible(true); - this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(this.licenseInfo.getDecryptedLicense().getExpirationDate() == null ? "" : 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); - this.licenseInfoUserLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_userInfo(this.licenseInfo.getUser(), this.licenseInfo.getEmail())); + this.licenseInfoUserLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_userInfo( + "TBD", + this.licenseInfo.getDecryptedLicense().getCustomerEmail())); } this.malwareScansPanel.setVisible(StringUtils.isNotBlank(this.authTokenMessage) || authTokenResponse != null); @@ -430,7 +435,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(this.authTokenResponse.getExpiration() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getExpiration()))); + this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(this.authTokenResponse.getResetDate() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getResetDate()))); 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/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index cee09547a3..da9e2629f1 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Paths; +import java.time.ZoneId; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -385,6 +386,30 @@ public final class UserPreferences { public static String getTimeZoneForDisplays() { return viewPreferences.get(TIME_ZONE_FOR_DISPLAYS, TimeZone.GMT_ZONE.getID()); } + + /** + * Returns the inferred preferred time zone deriving in order: + * 1) Starts with user preference if set + * 2) Gets system time zone if can be determined + * 3) Otherwise uses GMT + * + * @return Returns preferred time zone id. + */ + public static String getInferredUserTimeZone() { + String timeZonePref = viewPreferences.get(TIME_ZONE_FOR_DISPLAYS, null); + if (StringUtils.isBlank(timeZonePref)) { + ZoneId systemZoneId = ZoneId.systemDefault(); + if (systemZoneId != null) { + timeZonePref = systemZoneId.getId(); + } + } + + if (StringUtils.isBlank(timeZonePref)) { + timeZonePref = TimeZone.GMT_ZONE.getID(); + } + + return timeZonePref; + } public static void setTimeZoneForDisplays(String timeZone) { viewPreferences.put(TIME_ZONE_FOR_DISPLAYS, timeZone);