From ed444f466141c70f552ae0591b1ad99fbdeb7a58 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro <gregd@basistech.com> Date: Thu, 24 Aug 2023 15:22:40 -0400 Subject: [PATCH] better feedback on unsuccessful license --- .../autopsy/ctapi/json/LicenseResponse.java | 9 +++++- .../ctapi/util/LicenseDecryptorUtil.java | 19 ++++++++--- .../ctcloud/Bundle.properties-MERGED | 2 ++ .../ctcloud/CTMalwareScannerOptionsPanel.java | 32 ++++++++++++++++--- 4 files changed, 53 insertions(+), 9 deletions(-) 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 a3a8247884..5a85778b60 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 @@ -32,18 +32,21 @@ public class LicenseResponse { private final Boolean hostChanged; private final Long hostChangesRemaining; private final BoostLicenseResponse boostLicense; + private final String errorMsg; @JsonCreator public LicenseResponse( @JsonProperty("success") Boolean success, @JsonProperty("hostChanged") Boolean hostChanged, @JsonProperty("hostChangesRemaining") Long hostChangesRemaining, - @JsonProperty("boostLicense") BoostLicenseResponse boostLicense + @JsonProperty("boostLicense") BoostLicenseResponse boostLicense, + @JsonProperty("errorMsg") String errorMsg ) { this.success = success; this.hostChanged = hostChanged; this.hostChangesRemaining = hostChangesRemaining; this.boostLicense = boostLicense; + this.errorMsg = errorMsg; } public Boolean isSuccess() { @@ -61,4 +64,8 @@ public Long getHostChangesRemaining() { public BoostLicenseResponse getBoostLicense() { return boostLicense; } + + public String getErrorMsg() { + return errorMsg; + } } 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 f62b57d795..26ebe793a4 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 @@ -34,6 +34,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.X509EncodedKeySpec; +import java.text.MessageFormat; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -42,6 +43,7 @@ import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.lang3.ObjectUtils; /** * Decrypts the payload of boost license. @@ -58,12 +60,12 @@ public static LicenseDecryptorUtil getInstance() { private LicenseDecryptorUtil() { } - + public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException { - if (licenseResponse == null || licenseResponse.getBoostLicense() == null) { - throw new InvalidLicenseException("License or boost license are null"); + if (licenseResponse == null) { + throw new InvalidLicenseException("License is null"); } - + DecryptedLicenseResponse decrypted = parseLicenseJSON(licenseResponse.getBoostLicense()); return new LicenseInfo(licenseResponse, decrypted); } @@ -78,6 +80,9 @@ public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws Jso * com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException */ public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException { + if (licenseResponse == null) { + throw new InvalidLicenseException("Boost license is null"); + } String decryptedJsonResponse; try { @@ -101,6 +106,12 @@ public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseRes } private String decryptLicenseString(String encryptedJson, String ivBase64, String encryptedKey, String version) throws IOException, GeneralSecurityException, InvalidLicenseException { + if (ObjectUtils.anyNull(encryptedJson, ivBase64, encryptedKey, version)) { + throw new InvalidLicenseException(MessageFormat.format( + "encryptedJson: {0}, iv: {1}, encryptedKey: {2}, version: {3} must all be non-null", + encryptedJson, ivBase64, encryptedKey, version)); + } + if (!"1.0".equals(version)) { throw new InvalidLicenseException("Unexpected file version: " + version); } 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 0e888c7fac..8dd673e2d7 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 @@ -31,6 +31,8 @@ CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Alr CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_desc=Please verify that license number is of format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_title=Invalid License Number CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error +# {0} - licenseCode +CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0} CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later. CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error # {0} - expiresDate 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 375943188c..735be72afc 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 @@ -608,6 +608,8 @@ private void acceptEula(LicenseResponse licenseResponse) { @NbBundle.Messages({ "CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error", "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error", + "# {0} - licenseCode", + "CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}", "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.",}) private class LicenseFetcher extends SwingWorker<LicenseResponse, Void> { @@ -629,10 +631,9 @@ protected LicenseResponse doInBackground() throws Exception { protected void done() { try { LicenseResponse licenseResponse = get(); - if (licenseResponse != null && licenseResponse.isSuccess()) { - SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); - } else { - logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful"); + // if no result, show unauthorized + if (licenseResponse == null) { + logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch returned no result."); JOptionPane.showMessageDialog( CTMalwareScannerOptionsPanel.this, CTCloudException.ErrorCode.UN_AUTHORIZED.getDescription(), @@ -640,7 +641,30 @@ protected void done() { JOptionPane.ERROR_MESSAGE); setLicenseDisplay(licenseInfo, null); loadMalwareScansInfo(licenseInfo); + return; + } + + // if not successful response + if (!Boolean.TRUE.equals(licenseResponse.isSuccess())) { + logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful"); + // use default message unless error message specified + String message = Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc(licenseText); + if (!StringUtils.isBlank(licenseResponse.getErrorMsg())) { + message = licenseResponse.getErrorMsg(); + } + JOptionPane.showMessageDialog( + CTMalwareScannerOptionsPanel.this, + message, + Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(), + JOptionPane.ERROR_MESSAGE); + setLicenseDisplay(licenseInfo, null); + loadMalwareScansInfo(licenseInfo); + return; } + + // otherwise, load + SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); + } catch (InterruptedException | CancellationException ex) { // ignore cancellation; just load current license setLicenseDisplay(licenseInfo, null); -- GitLab