diff --git a/Core/manifest.mf b/Core/manifest.mf index 59baf3f8c2..683690ef1b 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 37 +OpenIDE-Module-Implementation-Version: 38 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 9adb1c7649..893ff6510e 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -85,8 +85,8 @@ file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSH file.reference.serializer-2.7.2.jar=release/modules/ext/serializer-2.7.2.jar file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar -file.reference.sleuthkit-4.12.0.jar=release/modules/ext/sleuthkit-4.12.0.jar -file.reference.sleuthkit-caseuco-4.12.0.jar=release/modules/ext/sleuthkit-caseuco-4.12.0.jar +file.reference.sleuthkit-4.12.1.jar=release/modules/ext/sleuthkit-4.12.1.jar +file.reference.sleuthkit-caseuco-4.12.1.jar=release/modules/ext/sleuthkit-caseuco-4.12.1.jar file.reference.slf4j-api-1.7.36.jar=release/modules/ext/slf4j-api-1.7.36.jar file.reference.snakeyaml-2.0.jar=release/modules/ext/snakeyaml-2.0.jar file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar @@ -107,4 +107,4 @@ license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true -spec.version.base=10.24 +spec.version.base=10.25 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 9b960955aa..754da003d9 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -718,12 +718,12 @@ release/modules/ext/sevenzipjbinding.jar - ext/sleuthkit-4.12.0.jar - release/modules/ext/sleuthkit-4.12.0.jar + ext/sleuthkit-4.12.1.jar + release/modules/ext/sleuthkit-4.12.1.jar - ext/sleuthkit-caseuco-4.12.0.jar - release/modules/ext/sleuthkit-caseuco-4.12.0.jar + ext/sleuthkit-caseuco-4.12.1.jar + release/modules/ext/sleuthkit-caseuco-4.12.1.jar ext/slf4j-api-1.7.36.jar 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 c358feec61..f21873f565 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java @@ -25,6 +25,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBeanResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; @@ -78,21 +79,22 @@ public class CTApiDAO { } public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException { - return getAuthToken(decrypted, false); + return getAuthToken(decrypted, null); } - public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, boolean fileUpload) throws CTCloudException { + public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, Long fileUploadSize) throws CTCloudException { AuthTokenRequest authTokenRequest = new AuthTokenRequest() .setAutopsyVersion(getAppVersion()) - .setRequestFileUpload(fileUpload) + .setRequestFileUpload(fileUploadSize != null && fileUploadSize > 0) + .setFileUploadSize(fileUploadSize != null && fileUploadSize > 0 ? fileUploadSize : null) .setBoostLicenseId(decrypted.getBoostLicenseId()) .setHostId(decrypted.getLicenseHostId()); return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class); } - public void uploadFile(String url, String fileName, InputStream fileIs) throws CTCloudException { - httpClient.doFileUploadPost(url, fileName, fileIs); + public void uploadFile(FileUploadRequest fileUploadRequest) throws CTCloudException { + httpClient.doFileUploadPut(fileUploadRequest); } public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException { 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 0a280c87e8..cf93d58307 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -18,6 +18,8 @@ */ package com.basistech.df.cybertriage.autopsy.ctapi; +import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException.ErrorCode; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -55,13 +57,14 @@ import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; -import org.apache.http.entity.mime.MultipartEntityBuilder; import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -155,16 +158,23 @@ class CTCloudHttpClient { // Parse Response if (classType != null) { HttpEntity entity = response.getEntity(); - String entityStr = EntityUtils.toString(entity); - O respObj = mapper.readValue(entityStr, classType); - return respObj; - } else { - return null; + if (entity != null) { + String entityStr = EntityUtils.toString(entity); + if (StringUtils.isNotBlank(entityStr)) { + O respObj = mapper.readValue(entityStr, classType); + return respObj; + } + } } + + return null; } else { LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine()); handleNonOKResponse(response, ""); } + // transform all non-CTCloudException's into a CTCloudException + } catch (CTCloudException ex) { + throw ex; } catch (Exception ex) { LOGGER.log(Level.WARNING, "Error when parsing response from CyberTriage Cloud", ex); throw new CTCloudException(CTCloudException.parseUnknownException(ex), ex); @@ -184,10 +194,23 @@ class CTCloudHttpClient { return null; } - public void doFileUploadPost(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException { - URI postUri; + public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudException { + if (fileUploadRequest == null) { + throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null")); + } + + String fullUrlPath = fileUploadRequest.getFullUrlPath(); + String fileName = fileUploadRequest.getFileName(); + InputStream fileInputStream = fileUploadRequest.getFileInputStream(); + Long contentLength = fileUploadRequest.getContentLength(); + + if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) { + throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0")); + } + + URI putUri; try { - postUri = new URI(fullUrlPath); + putUri = new URI(fullUrlPath); } catch (URISyntaxException ex) { LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex); throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); @@ -195,23 +218,13 @@ class CTCloudHttpClient { try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) { LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath); - HttpPost post = new HttpPost(postUri); - configureRequestTimeout(post); + HttpPut put = new HttpPut(putUri); + configureRequestTimeout(put); - post.addHeader("Connection", "keep-alive"); + put.addHeader("Connection", "keep-alive"); + put.setEntity(new InputStreamEntity(fileInputStream, contentLength, ContentType.APPLICATION_OCTET_STREAM)); - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.addBinaryBody( - "file", - fileIs, - ContentType.APPLICATION_OCTET_STREAM, - fileName - ); - - HttpEntity multipart = builder.build(); - post.setEntity(multipart); - - try (CloseableHttpResponse response = httpclient.execute(post)) { + try (CloseableHttpResponse response = httpclient.execute(put)) { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) { LOGGER.log(Level.INFO, "Response Received. - Status OK"); @@ -381,7 +394,7 @@ class CTCloudHttpClient { HttpClientBuilder builder; if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION - && StringUtils.isBlank(ProxySettings.getAuthenticationUsername()) + && StringUtils.isBlank(ProxySettings.getAuthenticationUsername()) && ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword()) && WinHttpClients.isWinAuthAvailable()) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java index 6a093fee8e..f137818346 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java @@ -34,6 +34,9 @@ public class AuthTokenRequest { @JsonProperty("requestFileUpload") private boolean requestFileUpload; + @JsonProperty("fileUploadSize") + private Long fileUploadSize; + @JsonProperty("host_id") private String hostId; @@ -64,6 +67,16 @@ public class AuthTokenRequest { return this; } + public Long getFileUploadSize() { + return fileUploadSize; + } + + public AuthTokenRequest setFileUploadSize(Long fileUploadSize) { + this.fileUploadSize = fileUploadSize; + return this; + } + + public String getHostId() { return hostId; } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java new file mode 100644 index 0000000000..48d8dc77b4 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java @@ -0,0 +1,69 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.ctapi.json; + +import java.io.InputStream; + +/** + * Data for a file upload request. + */ +public class FileUploadRequest { + + private String fullUrlPath; + private String fileName; + private InputStream fileInputStream; + private Long contentLength; + + public String getFullUrlPath() { + return fullUrlPath; + } + + public FileUploadRequest setFullUrlPath(String fullUrlPath) { + this.fullUrlPath = fullUrlPath; + return this; + } + + public String getFileName() { + return fileName; + } + + public FileUploadRequest setFileName(String fileName) { + this.fileName = fileName; + return this; + } + + public InputStream getFileInputStream() { + return fileInputStream; + } + + public FileUploadRequest setFileInputStream(InputStream fileInputStream) { + this.fileInputStream = fileInputStream; + return this; + } + + public Long getContentLength() { + return contentLength; + } + + public FileUploadRequest setContentLength(Long contentLength) { + this.contentLength = contentLength; + 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 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 class LicenseResponse { 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.PublicKey; 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.NoSuchPaddingException; 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 class LicenseDecryptorUtil { 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 class LicenseDecryptorUtil { * 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 class LicenseDecryptorUtil { } 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/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java index 83a4a9a51a..2b6cffe789 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java @@ -26,12 +26,12 @@ import java.beans.PropertyChangeListener; import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.JPanel; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; /** 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 3c86b5446d..44e71a4513 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 @@ -4,7 +4,7 @@ CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: -CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +CTLicenseDialog.licenseNumberTextField.text= CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= @@ -25,3 +25,4 @@ EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit +CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 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..d9876a8ed7 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 @@ -4,11 +4,11 @@ CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: -CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +CTLicenseDialog.licenseNumberTextField.text= CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= -CTLicenseDialog_verifyInput_licenseNumberError=Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' +CTLicenseDialog_verifyInput_licenseNumberError=Please enter a license number CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text= CTMalwareScannerOptionsPanel.countersResetLabel.text= CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text= @@ -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 @@ -63,3 +65,4 @@ EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit +CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form index e7cd2743a0..2ea57d43a8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form @@ -127,6 +127,9 @@ + + + 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 3bff998901..99fc749dd7 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 @@ -18,18 +18,20 @@ */ package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud; +import java.awt.Color; import java.util.regex.Pattern; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.corecomponents.TextPrompt; /** * License dialog */ class CTLicenseDialog extends javax.swing.JDialog { - private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$"); + private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9-_]+?\\s*$"); private String licenseString = null; /** @@ -38,6 +40,7 @@ class CTLicenseDialog extends javax.swing.JDialog { public CTLicenseDialog(java.awt.Frame parent, boolean modal) { super(parent, modal); initComponents(); + configureHintText(); this.licenseNumberTextField.getDocument().putProperty("filterNewlines", Boolean.TRUE); this.licenseNumberTextField.getDocument().addDocumentListener(new DocumentListener() { @Override @@ -56,13 +59,23 @@ class CTLicenseDialog extends javax.swing.JDialog { } }); } - + + private void configureHintText() { + TextPrompt textPrompt = new TextPrompt( + StringUtils.defaultString(this.licenseNumberTextField.getToolTipText()), + this.licenseNumberTextField); + + textPrompt.setForeground(Color.LIGHT_GRAY); + float alpha = 0.9f; // Mostly opaque + textPrompt.changeAlpha(alpha); + } + String getValue() { return licenseString; } @Messages({ - "CTLicenseDialog_verifyInput_licenseNumberError=Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'" + "CTLicenseDialog_verifyInput_licenseNumberError=Please enter a license number" }) private void verifyInput() { String licenseInput = StringUtils.defaultString(this.licenseNumberTextField.getText()); @@ -165,6 +178,7 @@ class CTLicenseDialog extends javax.swing.JDialog { getContentPane().add(cancelButton, gridBagConstraints); licenseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.text")); // NOI18N + licenseNumberTextField.setToolTipText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.toolTipText")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; @@ -177,7 +191,8 @@ class CTLicenseDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - this.licenseString = this.licenseNumberTextField.getText(); + String inputText = this.licenseNumberTextField.getText(); + this.licenseString = inputText == null ? null : inputText.trim(); this.dispose(); }//GEN-LAST:event_okButtonActionPerformed 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..deff21d423 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 @@ -40,7 +40,6 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; @@ -51,6 +50,7 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; /** * Options panel to be displayed in the CTOptionsPanel for settings regarding @@ -608,6 +608,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { @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 { @@ -629,10 +631,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { 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 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { 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); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties index ebde860d0b..48a2628742 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties @@ -12,3 +12,5 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. CTincidentImportOptionsPanel.instructionsTextLabel.text= CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: +CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: +CTIncidentImportOptionsPanel.importModuleDetected.text= diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED index ebde860d0b..dd406e6725 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED @@ -12,3 +12,7 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. CTincidentImportOptionsPanel.instructionsTextLabel.text= CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: +CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: +CTIncidentImportOptionsPanel.importModuleDetected.text= +CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected +CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form index 7382a2de2c..fd11f53ee8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form @@ -42,7 +42,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,7 +96,7 @@ - + @@ -86,7 +114,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java index bf018701ca..40a2c0fe3f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel; @@ -19,15 +24,20 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collection; import java.util.Collections; import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.stream.Stream; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.apache.commons.lang3.StringUtils; import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.Lookup; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.AutopsyContentProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.guiutils.JFileChooserFactory; @@ -41,6 +51,8 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { private static final String CT_IMPORTER_DOC_LINK = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html"; + private static final String CT_STANDARD_CONTENT_PROVIDER_NAME = "CTStandardContentProvider"; + private final JFileChooserFactory fileRepoChooserFactory = new JFileChooserFactory(); private final CTSettingsPersistence ctPersistence = CTSettingsPersistence.getInstance(); @@ -88,8 +100,23 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { public synchronized void loadSettings() { CTSettings ctSettings = ctPersistence.loadCTSettings(); setCTSettingsDisplay(ctSettings); + setModuleDetected(); setEnabledItems(Case.isCaseOpen()); } + + @Messages({ + "CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected", + "CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected" + }) + private void setModuleDetected() { + Collection contentProviders = Lookup.getDefault().lookupAll(AutopsyContentProvider.class); + boolean detected = ((Collection) (contentProviders != null ? contentProviders : Collections.emptyList())).stream() + .anyMatch(p -> p != null && StringUtils.defaultString(p.getName()).toUpperCase().startsWith(CT_STANDARD_CONTENT_PROVIDER_NAME.toUpperCase())); + + this.importModuleDetected.setText(detected + ? Bundle.CTIncidentImportOptionsPanel_setModuleDetected_detected() + : Bundle.CTIncidentImportOptionsPanel_setModuleDetected_notDetected()); + } private void setEnabledItems(boolean caseOpen) { this.caseOpenWarningLabel.setVisible(caseOpen); @@ -122,6 +149,8 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { incidentTextPanel = new javax.swing.JPanel(); incidentTextLabel = new javax.swing.JLabel(); + javax.swing.JLabel importModule = new javax.swing.JLabel(); + importModuleDetected = new javax.swing.JLabel(); instructionsPanel = new javax.swing.JPanel(); instructionsTextLabel = new javax.swing.JLabel(); instructionsLinkLabel = new javax.swing.JLabel(); @@ -140,10 +169,28 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); incidentTextPanel.add(incidentTextLabel, gridBagConstraints); + org.openide.awt.Mnemonics.setLocalizedText(importModule, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModule.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 3); + incidentTextPanel.add(importModule, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(importModuleDetected, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModuleDetected.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5); + incidentTextPanel.add(importModuleDetected, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; @@ -156,7 +203,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0); instructionsPanel.add(instructionsTextLabel, gridBagConstraints); instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:"); @@ -171,7 +218,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); instructionsPanel.add(instructionsLinkLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); @@ -278,6 +325,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { private javax.swing.JLabel caseOpenWarningLabel; private javax.swing.JButton fileRepoBrowseButton; private javax.swing.JTextField fileRepoPathField; + private javax.swing.JLabel importModuleDetected; private javax.swing.JLabel incidentTextLabel; private javax.swing.JPanel incidentTextPanel; private javax.swing.JLabel instructionsLinkLabel; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java index 35e2d108ea..d6427a641c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import java.io.IOException; @@ -19,35 +24,60 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.apache.commons.lang3.StringUtils; import org.openide.modules.Places; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** - * CT settings that don't include license information. This code must be kept in-sync with code in - * CT Autopsy Importer NBM. + * CT settings that don't include license information. This code must be kept + * in-sync with code in CT Autopsy Importer NBM. */ public class CTSettings { + private static final Logger LOGGER = Logger.getLogger(CTSettings.class.getCanonicalName()); private static final String DEFAULT_FILE_REPO_PATH = getAppDataLocalDirectory(); - // taken from com.basistech.df.cybertriage.utils.SystemProperties - private static String getAppDataLocalDirectory() { + private static final String CYBERTRIAGE_FOLDER = "cybertriage"; + private static final String CYBERTRIAGE_DOT_FOLDER = "." + CYBERTRIAGE_FOLDER; - Logger LOGGER = java.util.logging.Logger.getLogger(CTSettings.class.getCanonicalName()); + // based on com.basistech.df.cybertriage.utils.SystemProperties + private static String getAppDataLocalDirectory() { if (Objects.nonNull(Places.getUserDirectory()) && Places.getUserDirectory().getAbsolutePath().endsWith("testuserdir")) { // APP is in testing .. this should return the test path LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath()); return Places.getUserDirectory().getAbsolutePath(); - } else { - Path localAppPath = Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage"); + } + + // try to use LOCALAPPDATA on windows + String localDataStr = System.getenv("LOCALAPPDATA"); + if (StringUtils.isNotBlank(localDataStr)) { + Path localAppPath = Paths.get(localDataStr, CYBERTRIAGE_FOLDER); try { Files.createDirectories(localAppPath); LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString()); return localAppPath.toString(); } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "IO Error, defaulting to user dir", ex); - return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error + LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex); } } + + // try to use ~/.cybertriage anywhere else + if (!PlatformUtil.isWindowsOS()) { + String homePathStr = System.getenv("HOME"); + if (StringUtils.isNotBlank(homePathStr)) { + Path localAppPath = Paths.get(homePathStr, CYBERTRIAGE_DOT_FOLDER); + try { + Files.createDirectories(localAppPath); + LOGGER.log(Level.INFO, "Non-windows Application Data Path: " + localAppPath.toString()); + return localAppPath.toString(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex); + } + } + } + + // defer to user directory otherwise + return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error } public static String getDefaultFileRepoPath() { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java index be60813edd..e5e5b6838f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index bf395eb4b5..fee67fdff2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -23,6 +23,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; @@ -112,8 +113,10 @@ class MalwareScanIngestModule implements FileIngestModule { //minimum file uploads left before issuing warning private static final long LOW_UPLOADS_REMAINING = 25; + // min and max upload size in bytes private static final long MIN_UPLOAD_SIZE = 1; - private static final long MAX_UPLOAD_SIZE = 1_000_000_000; + private static final long MAX_UPLOAD_SIZE = 100_000_000; // 100MB + private static final int NUM_FILE_UPLOAD_RETRIES = 7; private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; @@ -131,8 +134,7 @@ class MalwareScanIngestModule implements FileIngestModule { "application/x-msdos-program"//NON-NLS ).collect(Collectors.toSet()); - private static final String MALWARE_TYPE_NAME = "TSK_MALWARE"; - private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; + private static final String MALWARE_CONFIG = ""; // NOTE: Adding a configuration complicates NTL branch UI private static final Logger logger = Logger.getLogger(MalwareScanIngestModule.class.getName()); @@ -232,18 +234,13 @@ class MalwareScanIngestModule implements FileIngestModule { // setup necessary variables for processing SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - BlackboardArtifact.Type malwareType = tskCase.getBlackboard().getOrAddArtifactType( - MALWARE_TYPE_NAME, - Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), - BlackboardArtifact.Category.ANALYSIS_RESULT); - return new IngestJobState( context, tskCase, new PathNormalizer(tskCase), new FileTypeDetector(), licenseInfoOpt.get(), - malwareType, + BlackboardArtifact.Type.TSK_MALWARE, uploadFiles, true ); @@ -640,7 +637,7 @@ class MalwareScanIngestModule implements FileIngestModule { } // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), true); + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), af.getSize()); if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { @@ -658,7 +655,13 @@ class MalwareScanIngestModule implements FileIngestModule { // upload bytes ReadContentInputStream fileInputStream = new ReadContentInputStream(af); - ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); + + ctApiDAO.uploadFile(new FileUploadRequest() + .setContentLength(af.getSize()) + .setFileInputStream(fileInputStream) + .setFileName(af.getName()) + .setFullUrlPath(authTokenResponse.getFileUploadUrl()) + ); // upload metadata MetadataUploadRequest metaRequest = new MetadataUploadRequest() @@ -700,6 +703,7 @@ class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title(), Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc() ); + logger.log(Level.INFO, "Begin polling for malware status of file uploads."); Map> remaining = new HashMap<>(ingestJobState.getUnidentifiedHashes()); @@ -735,6 +739,9 @@ class MalwareScanIngestModule implements FileIngestModule { // exponential backoff before trying again long waitMultiplier = ((long) Math.pow(2, retry)); + + logger.log(Level.INFO, MessageFormat.format("Waiting {0} milliseconds before polling again for malware status of file uploads.", (waitMultiplier * FILE_UPLOAD_RETRY_SLEEP_MILLIS))); + for (int i = 0; i < waitMultiplier; i++) { if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index cae89e41ce..92b64b840b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -66,8 +66,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the Case.open.msgDlg.updated.title=Case Database Schema Update Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ this case are missing. Would you like to search for them now?\n\ -Previously, the image was located at:\n\ -{0}\n\ +Previously, the image with host, {0}, was located at:\n\ +{1}\n\ Please note that you will still be able to browse directories and generate reports\n\ if you choose No, but you will not be able to view file content or run the ingest process. Case.checkImgExist.confDlg.doesntExist.title=Missing Image diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index dc96292d9a..ce1fb9aa70 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -253,8 +253,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the Case.open.msgDlg.updated.title=Case Database Schema Update Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ this case are missing. Would you like to search for them now?\n\ -Previously, the image was located at:\n\ -{0}\n\ +Previously, the image with host, {0}, was located at:\n\ +{1}\n\ Please note that you will still be able to browse directories and generate reports\n\ if you choose No, but you will not be able to view file content or run the ingest process. Case.checkImgExist.confDlg.doesntExist.title=Missing Image diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index b1d2f28c31..eb279febe7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -194,6 +194,8 @@ public class Case { private final SleuthkitEventListener sleuthkitEventListener; private CollaborationMonitor collaborationMonitor; private Services caseServices; + // matches something like '\\.\PHYSICALDRIVE0' + private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\PHYSICALDRIVE\\d*\\s*$"; private volatile boolean hasDataSource = false; private volatile boolean hasData = false; @@ -1303,9 +1305,18 @@ public class Case { for (Map.Entry entry : imgPaths.entrySet()) { long obj_id = entry.getKey(); String path = entry.getValue(); - boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); + boolean fileExists = (new File(path).exists()|| DriveUtils.driveExists(path)); if (!fileExists) { + // CT-7336: ignore relocating datasources if file provider is present and placeholder path is used. + if (newCurrentCase.getMetadata() != null + && !StringUtils.isBlank(newCurrentCase.getMetadata().getContentProviderName()) + && (path == null || path.matches(PLACEHOLDER_DS_PATH_REGEX))) { + continue; + } + try { + DataSource ds = newCurrentCase.getSleuthkitCase().getDataSource(obj_id); + String hostName = StringUtils.defaultString(ds.getHost() == null ? "" : ds.getHost().getName()); // Using invokeAndWait means that the dialog will // open on the EDT but this thread will wait for an // answer. Using invokeLater would cause this loop to @@ -1315,7 +1326,7 @@ public class Case { public void run() { int response = JOptionPane.showConfirmDialog( mainFrame, - NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), + NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", hostName, path), NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { @@ -1327,7 +1338,7 @@ public class Case { } }); - } catch (InterruptedException | InvocationTargetException ex) { + } catch (InterruptedException | InvocationTargetException | TskCoreException | TskDataException ex) { logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index a38383c183..4475b682c5 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -64,6 +64,7 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_IT import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_TL_EVENT; import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ASSOCIATED_OBJECT; import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_KEYWORD_HIT; +import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE; /** * Classes for creating nodes for BlackboardArtifacts. @@ -73,10 +74,6 @@ public class Artifacts { private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); - // this is currently a custom TSK artifact type, created in MalwareScanIngestModule - private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; - private static final String MALWARE_HITS = "TSK_MALWARE"; - /** * Base class for a parent node of artifacts. */ @@ -247,15 +244,6 @@ public class Artifacts { @SuppressWarnings("deprecation") private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) { - // Get the custom TSK_MALWARE artifact type from case database - if (MALWARE_ARTIFACT_TYPE == null) { - try { - MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS - } - } - int typeId = type.getTypeID(); if (TSK_EMAIL_MSG.getTypeID() == typeId) { EmailExtracted.RootNode emailNode = new EmailExtracted(skCase, dsObjId).new RootNode(); @@ -281,9 +269,9 @@ public class Artifacts { } else if (TSK_HASHSET_HIT.getTypeID() == typeId) { HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode(); return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT); - } else if (MALWARE_ARTIFACT_TYPE != null && MALWARE_ARTIFACT_TYPE.getTypeID() == typeId) { + } else if (TSK_MALWARE.getTypeID() == typeId) { MalwareHits.RootNode malwareHits = new MalwareHits(skCase, dsObjId).new RootNode(); - return new TypeNodeKey(malwareHits, MALWARE_ARTIFACT_TYPE); + return new TypeNodeKey(malwareHits, TSK_MALWARE); } else { return new TypeNodeKey(type, dsObjId); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java index c1761a7ad5..2524650178 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -44,12 +44,12 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode; import org.sleuthkit.datamodel.AnalysisResult; +import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE; import org.sleuthkit.datamodel.Score; /** @@ -57,9 +57,6 @@ import org.sleuthkit.datamodel.Score; */ public class MalwareHits implements AutopsyVisitableItem { - private static final String MALWARE_HITS = "TSK_MALWARE"; // this is currently a custom TSK artifact type, created in MalwareScanIngestModule - private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; - private static String DISPLAY_NAME; private static final Logger logger = Logger.getLogger(MalwareHits.class.getName()); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); @@ -126,20 +123,9 @@ public class MalwareHits implements AutopsyVisitableItem { return; } - // Get the custom TSK_MALWARE artifact type from case database - if (MALWARE_ARTIFACT_TYPE == null) { - try { - MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); - DISPLAY_NAME = MALWARE_ARTIFACT_TYPE.getDisplayName(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS - return; - } - } - String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS - + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() //NON-NLS + + "blackboard_artifacts.artifact_type_id=" + TSK_MALWARE.getTypeID() //NON-NLS + " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS @@ -182,7 +168,7 @@ public class MalwareHits implements AutopsyVisitableItem { * oldValue if the event is a remote event. */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); - if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == MALWARE_ARTIFACT_TYPE.getTypeID()) { + if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_MALWARE.getTypeID()) { malwareResults.update(); } } catch (NoCurrentCaseException notUsed) { @@ -248,13 +234,13 @@ public class MalwareHits implements AutopsyVisitableItem { public class RootNode extends UpdatableCountTypeNode { public RootNode() { - super(Children.create(new HitFactory(DISPLAY_NAME), true), - Lookups.singleton(DISPLAY_NAME), - DISPLAY_NAME, + super(Children.create(new HitFactory(TSK_MALWARE.getDisplayName()), true), + Lookups.singleton(TSK_MALWARE.getDisplayName()), + TSK_MALWARE.getDisplayName(), filteringDSObjId, - MALWARE_ARTIFACT_TYPE); + TSK_MALWARE); - super.setName(MALWARE_HITS); + super.setName(TSK_MALWARE.getTypeName()); // TODO make an icon this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png"); } @@ -297,7 +283,7 @@ public class MalwareHits implements AutopsyVisitableItem { */ @Override void updateDisplayName() { - super.setDisplayName(DISPLAY_NAME + " (" + malwareResults.getArtifactIds().size() + ")"); + super.setDisplayName(TSK_MALWARE.getDisplayName() + " (" + malwareResults.getArtifactIds().size() + ")"); } } diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf index 1d3168bf2c..9f684569fe 100644 --- a/CoreLibs/manifest.mf +++ b/CoreLibs/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 -OpenIDE-Module-Implementation-Version: 7 +OpenIDE-Module-Implementation-Version: 8 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties OpenIDE-Module-Specification-Version: 1.4 AutoUpdate-Show-In-Client: true diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 7760187c5e..79af40a112 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -144,7 +144,7 @@ 10 - 10.24 + 10.25 @@ -162,7 +162,7 @@ 6 - 6.6 + 6.7 diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 7a505d2ea6..d42fd1a08a 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -127,7 +127,7 @@ 10 - 10.24 + 10.25 diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf index 0e947e073b..f4abb2b2b9 100644 --- a/KeywordSearch/manifest.mf +++ b/KeywordSearch/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6 -OpenIDE-Module-Implementation-Version: 23 +OpenIDE-Module-Implementation-Version: 24 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties index baa7a10c98..16289e9e73 100644 --- a/KeywordSearch/nbproject/project.properties +++ b/KeywordSearch/nbproject/project.properties @@ -48,4 +48,4 @@ javac.compilerargs=-Xlint -Xlint:-serial license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/autopsy/ nbm.needs.restart=true -spec.version.base=6.6 +spec.version.base=6.7 diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index c1048f48ee..98a84faeb5 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -128,7 +128,7 @@ 10 - 10.24 + 10.25 diff --git a/NEWS.txt b/NEWS.txt index b8db91ca62..f6658a92ed 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -9,7 +9,7 @@ Library Updates Ingest Module Updates: - Recent Activity checks for malicious Chrome extensions from list provided by https://github.com/randomaccess3/detections - Keyword Search module now can search without needing to index text into Solr. -- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license) +- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license). https://www.cybertriage.com/autopsy-malware-module/ Add Data Source Updates: - Timestamps for logical files can be added. Issue https://github.com/sleuthkit/autopsy/issues/5852, https://github.com/sleuthkit/autopsy/issues/1788 @@ -24,7 +24,7 @@ Bugs: - Fix exporting of CSV files. Issue https://github.com/sleuthkit/autopsy/issues/6717 Misc: -- Added File Repository concept for data source files that are in a central location +- Added File Repository concept for data source files that are in a central location. Required for Cyber Triage import feature. - Added Spanish language support, contributor https://github.com/AburtoArielPM ---------------- VERSION 4.20.0 -------------- diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf index 03c6ce986b..6ab9cc4ccc 100644 --- a/RecentActivity/manifest.mf +++ b/RecentActivity/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6 -OpenIDE-Module-Implementation-Version: 19 +OpenIDE-Module-Implementation-Version: 20 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties OpenIDE-Module-Requires: diff --git a/TSKVersion.xml b/TSKVersion.xml index 087dac0912..7f6a1a8848 100644 --- a/TSKVersion.xml +++ b/TSKVersion.xml @@ -1,3 +1,3 @@ - + diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index c27ee220ec..cee5e3ed5b 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -47,7 +47,7 @@ 10 - 10.24 + 10.25 @@ -73,7 +73,7 @@ 6 - 6.6 + 6.7 diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index fa1dd6fb6b..ad875a270d 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -9,18 +9,23 @@ The Cyber Triage Malware Scanner module will use the malware scanning infrastruc This module requires a commercial license from Cyber Triage. -For more information on obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed. +For more information on what the module does or obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed. Configuration -======= +============== -Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. +You will need to first get a paid or eval license from the above URL. The code will come in via email. Example license formats include: +- AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070 +- b826a555-951f-42ca-86ce-439a81106688 -\image html Malware-scanner-global-options-panel-no-license.png +Once you have a license, you must add it on the Autopsy Options panel. +Choose the 'Cyber Triage' tab and choose 'Add License'. -After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. +\image html malware-scanner-global-options-panel-no-license.png + +After you enter the license number from your email, you will then need to review and agree to the license terms. The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. @@ -35,7 +40,7 @@ Using the Module Ingest Settings ------ -For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. +For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. Refer to the main [website](https://cybertriage.com/autopsy-malware-module) for details on what happens when files are uploaded. \image html malware-scanner-ingest-panel.png diff --git a/docs/doxygen-user/footer.html b/docs/doxygen-user/footer.html index d648961fdc..cfedffe82c 100644 --- a/docs/doxygen-user/footer.html +++ b/docs/doxygen-user/footer.html @@ -1,5 +1,5 @@
-

Copyright © 2012-2022 Basis Technology. Generated on $date
+

Copyright © 2012-2023 BasisTech. Generated on $date
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

diff --git a/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png b/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png deleted file mode 100644 index 09bb7d8344..0000000000 Binary files a/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png and /dev/null differ diff --git a/docs/doxygen-user/images/malware-artifact-tree.png b/docs/doxygen-user/images/malware-artifact-tree.png index 53b229751c..b47afb86c1 100644 Binary files a/docs/doxygen-user/images/malware-artifact-tree.png and b/docs/doxygen-user/images/malware-artifact-tree.png differ diff --git a/docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png b/docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png new file mode 100644 index 0000000000..de64843872 Binary files /dev/null and b/docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png differ diff --git a/docs/doxygen-user/images/malware-scanner-global-options-panel.png b/docs/doxygen-user/images/malware-scanner-global-options-panel.png index fd0b131832..b5a0ad4f3d 100644 Binary files a/docs/doxygen-user/images/malware-scanner-global-options-panel.png and b/docs/doxygen-user/images/malware-scanner-global-options-panel.png differ diff --git a/nbproject/project.properties b/nbproject/project.properties index e8d17eb3c8..d613ea09d4 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -4,7 +4,7 @@ app.title=Autopsy ### lowercase version of above app.name=${branding.token} ### if left unset, version will default to today's date -app.version=4.20.0 +app.version=4.21.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE build.type=DEVELOPMENT diff --git a/release_scripts/update_sleuthkit_version.pl b/release_scripts/update_sleuthkit_version.pl index 1d6bdc7e72..f197477c82 100755 --- a/release_scripts/update_sleuthkit_version.pl +++ b/release_scripts/update_sleuthkit_version.pl @@ -33,7 +33,7 @@ sub main { update_core_project_xml(); update_unix_setup(); - print "Files updated. You need to commit and push them\n"; + print "Files updated and added to git. You need to commit (no -a) and push.\n"; } diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 5c4fa0e042..abcccdc19c 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -54,7 +54,7 @@ 10 - 10.24 + 10.25 diff --git a/unix_setup.sh b/unix_setup.sh index d2572c9de2..ab2d1094f6 100644 --- a/unix_setup.sh +++ b/unix_setup.sh @@ -5,7 +5,7 @@ # NOTE: update_sleuthkit_version.pl updates this value and relies # on it keeping the same name and whitespace. Don't change it. -TSK_VERSION=4.12.0 +TSK_VERSION=4.12.1 usage() {