mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-08 22:29:33 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into moduleoutputfix
This commit is contained in:
commit
fccd4e01cb
13
Core/ivy.xml
13
Core/ivy.xml
@ -1,3 +1,6 @@
|
|||||||
|
<!DOCTYPE ivy-module [
|
||||||
|
<!ENTITY httpcomponents.version "4.5.14">
|
||||||
|
]>
|
||||||
<ivy-module version="2.0">
|
<ivy-module version="2.0">
|
||||||
<info organisation="org.sleuthkit.autopsy" module="core"/>
|
<info organisation="org.sleuthkit.autopsy" module="core"/>
|
||||||
<configurations >
|
<configurations >
|
||||||
@ -72,6 +75,15 @@
|
|||||||
<!-- annotations like guarded by -->
|
<!-- annotations like guarded by -->
|
||||||
<dependency conf="core->default" org="com.github.spotbugs" name="spotbugs-annotations" rev="4.6.0"/>
|
<dependency conf="core->default" org="com.github.spotbugs" name="spotbugs-annotations" rev="4.6.0"/>
|
||||||
|
|
||||||
|
<dependency conf="core->default" org="com.license4j" name="license4j-runtime-library" rev="4.7.1"/>
|
||||||
|
|
||||||
|
<dependency conf="core->default" org="org.apache.httpcomponents" name="httpclient" rev="&httpcomponents.version;"/>
|
||||||
|
<dependency conf="core->default" org="org.apache.httpcomponents" name="httpmime" rev="&httpcomponents.version;"/>
|
||||||
|
<dependency conf="core->default" org="org.apache.httpcomponents" name="httpclient-win" rev="&httpcomponents.version;">
|
||||||
|
<exclude name="jna" />
|
||||||
|
<exclude name="jna-platform" />
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<override org="org.apache.zookeeper" module="zookeeper" rev="3.8.0"/>
|
<override org="org.apache.zookeeper" module="zookeeper" rev="3.8.0"/>
|
||||||
<override org="org.apache.zookeeper" module="zookeeper-jute" rev="3.8.0"/>
|
<override org="org.apache.zookeeper" module="zookeeper-jute" rev="3.8.0"/>
|
||||||
|
|
||||||
@ -84,5 +96,6 @@
|
|||||||
<override org="org.bouncycastle" module="bcprov-ext-jdk15on" rev="1.70"/>
|
<override org="org.bouncycastle" module="bcprov-ext-jdk15on" rev="1.70"/>
|
||||||
<override org="org.bouncycastle" module="bcprov-jdk15on" rev="1.70"/>
|
<override org="org.bouncycastle" module="bcprov-jdk15on" rev="1.70"/>
|
||||||
<override org="org.bouncycastle" module="bcpkix-jdk15on" rev="1.70"/>
|
<override org="org.bouncycastle" module="bcpkix-jdk15on" rev="1.70"/>
|
||||||
|
<override org="junit" module="junit" rev="4.13.2"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</ivy-module>
|
</ivy-module>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<chain name="main">
|
<chain name="main">
|
||||||
<ibiblio name="central" root="https://repo1.maven.org/maven2" m2compatible="true"/>
|
<ibiblio name="central" root="https://repo1.maven.org/maven2" m2compatible="true"/>
|
||||||
<ibiblio name="maven.restlet.org" root="http://maven.restlet.com" m2compatible="true" />
|
<ibiblio name="maven.restlet.org" root="http://maven.restlet.com" m2compatible="true" />
|
||||||
|
<ibiblio name="license4j.com" root="http://www.license4j.com/maven/" m2compatible="true" />
|
||||||
</chain>
|
</chain>
|
||||||
</resolvers>
|
</resolvers>
|
||||||
<property name="packaging.type" value="jar" />
|
<property name="packaging.type" value="jar" />
|
||||||
|
@ -18,6 +18,7 @@ file.reference.bcprov-jdk15on-1.70.jar=release/modules/ext/bcprov-jdk15on-1.70.j
|
|||||||
file.reference.bcutil-jdk15on-1.70.jar=release/modules/ext/bcutil-jdk15on-1.70.jar
|
file.reference.bcutil-jdk15on-1.70.jar=release/modules/ext/bcutil-jdk15on-1.70.jar
|
||||||
file.reference.c3p0-0.9.5.5.jar=release/modules/ext/c3p0-0.9.5.5.jar
|
file.reference.c3p0-0.9.5.5.jar=release/modules/ext/c3p0-0.9.5.5.jar
|
||||||
file.reference.checker-qual-3.33.0.jar=release/modules/ext/checker-qual-3.33.0.jar
|
file.reference.checker-qual-3.33.0.jar=release/modules/ext/checker-qual-3.33.0.jar
|
||||||
|
file.reference.commons-codec-1.11.jar=release/modules/ext/commons-codec-1.11.jar
|
||||||
file.reference.commons-dbcp2-2.9.0.jar=release/modules/ext/commons-dbcp2-2.9.0.jar
|
file.reference.commons-dbcp2-2.9.0.jar=release/modules/ext/commons-dbcp2-2.9.0.jar
|
||||||
file.reference.commons-io-2.11.0.jar=release/modules/ext/commons-io-2.11.0.jar
|
file.reference.commons-io-2.11.0.jar=release/modules/ext/commons-io-2.11.0.jar
|
||||||
file.reference.commons-lang3-3.10.jar=release/modules/ext/commons-lang3-3.10.jar
|
file.reference.commons-lang3-3.10.jar=release/modules/ext/commons-lang3-3.10.jar
|
||||||
@ -31,6 +32,10 @@ file.reference.decodetect-core-0.3.jar=release/modules/ext/decodetect-core-0.3.j
|
|||||||
file.reference.error_prone_annotations-2.18.0.jar=release/modules/ext/error_prone_annotations-2.18.0.jar
|
file.reference.error_prone_annotations-2.18.0.jar=release/modules/ext/error_prone_annotations-2.18.0.jar
|
||||||
file.reference.failureaccess-1.0.1.jar=release/modules/ext/failureaccess-1.0.1.jar
|
file.reference.failureaccess-1.0.1.jar=release/modules/ext/failureaccess-1.0.1.jar
|
||||||
file.reference.guava-32.0.1-jre.jar=release/modules/ext/guava-32.0.1-jre.jar
|
file.reference.guava-32.0.1-jre.jar=release/modules/ext/guava-32.0.1-jre.jar
|
||||||
|
file.reference.httpclient-4.5.14.jar=release/modules/ext/httpclient-4.5.14.jar
|
||||||
|
file.reference.httpclient-win-4.5.14.jar=release/modules/ext/httpclient-win-4.5.14.jar
|
||||||
|
file.reference.httpcore-4.4.16.jar=release/modules/ext/httpcore-4.4.16.jar
|
||||||
|
file.reference.httpmime-4.5.14.jar=release/modules/ext/httpmime-4.5.14.jar
|
||||||
file.reference.icepdf-core-6.2.2.jar=release/modules/ext/icepdf-core-6.2.2.jar
|
file.reference.icepdf-core-6.2.2.jar=release/modules/ext/icepdf-core-6.2.2.jar
|
||||||
file.reference.icepdf-viewer-6.2.2.jar=release/modules/ext/icepdf-viewer-6.2.2.jar
|
file.reference.icepdf-viewer-6.2.2.jar=release/modules/ext/icepdf-viewer-6.2.2.jar
|
||||||
file.reference.istack-commons-runtime-3.0.11.jar=release/modules/ext/istack-commons-runtime-3.0.11.jar
|
file.reference.istack-commons-runtime-3.0.11.jar=release/modules/ext/istack-commons-runtime-3.0.11.jar
|
||||||
@ -46,6 +51,7 @@ file.reference.javax.activation-api-1.2.0.jar=release/modules/ext/javax.activati
|
|||||||
file.reference.javax.ws.rs-api-2.1.1.jar=release/modules/ext/javax.ws.rs-api-2.1.1.jar
|
file.reference.javax.ws.rs-api-2.1.1.jar=release/modules/ext/javax.ws.rs-api-2.1.1.jar
|
||||||
file.reference.jaxb-api-2.3.1.jar=release/modules/ext/jaxb-api-2.3.1.jar
|
file.reference.jaxb-api-2.3.1.jar=release/modules/ext/jaxb-api-2.3.1.jar
|
||||||
file.reference.jaxb-runtime-2.3.3.jar=release/modules/ext/jaxb-runtime-2.3.3.jar
|
file.reference.jaxb-runtime-2.3.3.jar=release/modules/ext/jaxb-runtime-2.3.3.jar
|
||||||
|
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar
|
||||||
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
|
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
|
||||||
file.reference.jfreechart-1.5.3.jar=release/modules/ext/jfreechart-1.5.3.jar
|
file.reference.jfreechart-1.5.3.jar=release/modules/ext/jfreechart-1.5.3.jar
|
||||||
file.reference.jgraphx-4.2.2.jar=release/modules/ext/jgraphx-4.2.2.jar
|
file.reference.jgraphx-4.2.2.jar=release/modules/ext/jgraphx-4.2.2.jar
|
||||||
@ -55,6 +61,7 @@ file.reference.jutf7-1.0.0.jar=release/modules/ext/jutf7-1.0.0.jar
|
|||||||
file.reference.jxmapviewer2-2.6.jar=release/modules/ext/jxmapviewer2-2.6.jar
|
file.reference.jxmapviewer2-2.6.jar=release/modules/ext/jxmapviewer2-2.6.jar
|
||||||
file.reference.jython-standalone-2.7.2.jar=release/modules/ext/jython-standalone-2.7.2.jar
|
file.reference.jython-standalone-2.7.2.jar=release/modules/ext/jython-standalone-2.7.2.jar
|
||||||
file.reference.libphonenumber-8.12.45.jar=release/modules/ext/libphonenumber-8.12.45.jar
|
file.reference.libphonenumber-8.12.45.jar=release/modules/ext/libphonenumber-8.12.45.jar
|
||||||
|
file.reference.license4j-runtime-library-4.7.1.jar=release/modules/ext/license4j-runtime-library-4.7.1.jar
|
||||||
file.reference.listenablefuture-1.0.jar=release/modules/ext/listenablefuture-1.0.jar
|
file.reference.listenablefuture-1.0.jar=release/modules/ext/listenablefuture-1.0.jar
|
||||||
file.reference.logback-classic-1.2.10.jar=release/modules/ext/logback-classic-1.2.10.jar
|
file.reference.logback-classic-1.2.10.jar=release/modules/ext/logback-classic-1.2.10.jar
|
||||||
file.reference.logback-core-1.2.10.jar=release/modules/ext/logback-core-1.2.10.jar
|
file.reference.logback-core-1.2.10.jar=release/modules/ext/logback-core-1.2.10.jar
|
||||||
|
@ -66,6 +66,14 @@
|
|||||||
<implementation-version/>
|
<implementation-version/>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<code-name-base>org.netbeans.modules.keyring</code-name-base>
|
||||||
|
<build-prerequisite/>
|
||||||
|
<compile-dependency/>
|
||||||
|
<run-dependency>
|
||||||
|
<specification-version>1.41</specification-version>
|
||||||
|
</run-dependency>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<code-name-base>org.netbeans.modules.options.api</code-name-base>
|
<code-name-base>org.netbeans.modules.options.api</code-name-base>
|
||||||
<build-prerequisite/>
|
<build-prerequisite/>
|
||||||
@ -165,14 +173,6 @@
|
|||||||
<specification-version>9.29</specification-version>
|
<specification-version>9.29</specification-version>
|
||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- <dependency>
|
|
||||||
<code-name-base>org.openide.filesystems.compat8</code-name-base>
|
|
||||||
<build-prerequisite/>
|
|
||||||
<compile-dependency/>
|
|
||||||
<run-dependency>
|
|
||||||
<specification-version>9.26</specification-version>
|
|
||||||
</run-dependency>
|
|
||||||
</dependency> -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<code-name-base>org.openide.filesystems.nb</code-name-base>
|
<code-name-base>org.openide.filesystems.nb</code-name-base>
|
||||||
<build-prerequisite/>
|
<build-prerequisite/>
|
||||||
@ -323,6 +323,7 @@
|
|||||||
</test-type>
|
</test-type>
|
||||||
</test-dependencies>
|
</test-dependencies>
|
||||||
<public-packages>
|
<public-packages>
|
||||||
|
<package>com.basistech.df.cybertriage.autopsy.ctoptions.subpanel</package>
|
||||||
<package>net.sf.sevenzipjbinding</package>
|
<package>net.sf.sevenzipjbinding</package>
|
||||||
<package>net.sf.sevenzipjbinding.impl</package>
|
<package>net.sf.sevenzipjbinding.impl</package>
|
||||||
<package>net.sf.sevenzipjbinding.simple</package>
|
<package>net.sf.sevenzipjbinding.simple</package>
|
||||||
@ -448,6 +449,10 @@
|
|||||||
<runtime-relative-path>ext/checker-qual-3.33.0.jar</runtime-relative-path>
|
<runtime-relative-path>ext/checker-qual-3.33.0.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/checker-qual-3.33.0.jar</binary-origin>
|
<binary-origin>release/modules/ext/checker-qual-3.33.0.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/commons-codec-1.11.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/commons-codec-1.11.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-dbcp2-2.9.0.jar</runtime-relative-path>
|
<runtime-relative-path>ext/commons-dbcp2-2.9.0.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/commons-dbcp2-2.9.0.jar</binary-origin>
|
<binary-origin>release/modules/ext/commons-dbcp2-2.9.0.jar</binary-origin>
|
||||||
@ -500,6 +505,22 @@
|
|||||||
<runtime-relative-path>ext/guava-32.0.1-jre.jar</runtime-relative-path>
|
<runtime-relative-path>ext/guava-32.0.1-jre.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/guava-32.0.1-jre.jar</binary-origin>
|
<binary-origin>release/modules/ext/guava-32.0.1-jre.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/httpclient-4.5.14.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/httpclient-4.5.14.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/httpclient-win-4.5.14.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/httpclient-win-4.5.14.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/httpcore-4.4.16.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/httpcore-4.4.16.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/httpmime-4.5.14.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/httpmime-4.5.14.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/icepdf-core-6.2.2.jar</runtime-relative-path>
|
<runtime-relative-path>ext/icepdf-core-6.2.2.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/icepdf-core-6.2.2.jar</binary-origin>
|
<binary-origin>release/modules/ext/icepdf-core-6.2.2.jar</binary-origin>
|
||||||
@ -560,6 +581,10 @@
|
|||||||
<runtime-relative-path>ext/jaxb-runtime-2.3.3.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jaxb-runtime-2.3.3.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jaxb-runtime-2.3.3.jar</binary-origin>
|
<binary-origin>release/modules/ext/jaxb-runtime-2.3.3.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jdom-2.0.5.jar</binary-origin>
|
<binary-origin>release/modules/ext/jdom-2.0.5.jar</binary-origin>
|
||||||
@ -596,6 +621,10 @@
|
|||||||
<runtime-relative-path>ext/libphonenumber-8.12.45.jar</runtime-relative-path>
|
<runtime-relative-path>ext/libphonenumber-8.12.45.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/libphonenumber-8.12.45.jar</binary-origin>
|
<binary-origin>release/modules/ext/libphonenumber-8.12.45.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/license4j-runtime-library-4.7.1.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/license4j-runtime-library-4.7.1.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/listenablefuture-1.0.jar</runtime-relative-path>
|
<runtime-relative-path>ext/listenablefuture-1.0.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/listenablefuture-1.0.jar</binary-origin>
|
<binary-origin>release/modules/ext/listenablefuture-1.0.jar</binary-origin>
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenRequest;
|
||||||
|
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.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.LicenseRequest;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.CTHostIDGenerationUtil;
|
||||||
|
import java.util.Collections;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Data access layer for handling the CT api.
|
||||||
|
*/
|
||||||
|
public class CTApiDAO {
|
||||||
|
|
||||||
|
private static final String LICENSE_REQUEST_PATH = "/_ah/api/license/v1/activate";
|
||||||
|
private static final String AUTH_TOKEN_REQUEST_PATH = "/_ah/api/auth/v2/generate_token";
|
||||||
|
private static final String CTCLOUD_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE";
|
||||||
|
private static final String AUTOPSY_PRODUCT = "AUTOPSY";
|
||||||
|
|
||||||
|
private static final CTApiDAO instance = new CTApiDAO();
|
||||||
|
|
||||||
|
private CTApiDAO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CTApiDAO getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getAppVersion() {
|
||||||
|
return Version.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance();
|
||||||
|
|
||||||
|
public LicenseResponse getLicenseInfo(String licenseString) throws CTCloudException {
|
||||||
|
LicenseRequest licenseRequest = new LicenseRequest()
|
||||||
|
.setBoostLicenseCode(licenseString)
|
||||||
|
.setHostId(CTHostIDGenerationUtil.generateLicenseHostID())
|
||||||
|
.setProduct(AUTOPSY_PRODUCT)
|
||||||
|
.setTimeZoneId(UserPreferences.getInferredUserTimeZone());
|
||||||
|
|
||||||
|
return httpClient.doPost(LICENSE_REQUEST_PATH, licenseRequest, LicenseResponse.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException {
|
||||||
|
AuthTokenRequest authTokenRequest = new AuthTokenRequest()
|
||||||
|
.setAutopsyVersion(getAppVersion())
|
||||||
|
.setRequestFileUpload(false)
|
||||||
|
.setBoostLicenseId(decrypted.getBoostLicenseId())
|
||||||
|
.setHostId(decrypted.getLicenseHostId());
|
||||||
|
|
||||||
|
return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> getAuthParams(AuthenticatedRequestData authenticatedRequestData) {
|
||||||
|
return new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("api_key", authenticatedRequestData.getApiKey());
|
||||||
|
put("token", authenticatedRequestData.getToken());
|
||||||
|
put("host_id", authenticatedRequestData.getHostId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CTCloudBean> getReputationResults(AuthenticatedRequestData authenticatedRequestData, List<String> md5Hashes) throws CTCloudException {
|
||||||
|
if (CollectionUtils.isEmpty(md5Hashes)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReputationRequest fileRepReq = new FileReputationRequest()
|
||||||
|
.setHashes(md5Hashes);
|
||||||
|
|
||||||
|
CTCloudBeanResponse resp = httpClient.doPost(
|
||||||
|
CTCLOUD_SERVER_HASH_PATH,
|
||||||
|
getAuthParams(authenticatedRequestData),
|
||||||
|
fileRepReq,
|
||||||
|
CTCloudBeanResponse.class
|
||||||
|
);
|
||||||
|
|
||||||
|
return resp == null || resp.getItems() == null
|
||||||
|
? Collections.emptyList()
|
||||||
|
: resp.getItems();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception thrown due to an error that occurs while making a CT Cloud REST
|
||||||
|
* API request.
|
||||||
|
*/
|
||||||
|
public class CTCloudException extends Exception{
|
||||||
|
private final ErrorCode errorCode;
|
||||||
|
|
||||||
|
public enum ErrorCode {
|
||||||
|
BAD_REQUEST("CT-400", "Unknown or Bad request. Please contact Basis support at " + Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM + " for help diagnosing the problem."),
|
||||||
|
INVALID_KEY("CT-401", "An invalid license ID was used to access CyberTriage Cloud Service. Please contact Basis support " + Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM + " for help diagnosing the problem."),
|
||||||
|
GATEWAY_TIMEOUT("CT-504", "Request to CyberTriage Cloud Service timed out. Please retry after some time. If issue persists, please contact Basis support at " + Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM + " for assistance."),
|
||||||
|
UN_AUTHORIZED("CT-403", "An authorization error occurred. Please contact Basis support " + Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM + " for help diagnosing the problem."),
|
||||||
|
PROXY_UNAUTHORIZED("CT-407", "Proxy authentication failed. Please validate the connection settings from the Options panel Proxy Settings."),
|
||||||
|
TEMP_UNAVAILABLE("CT-500", "CyberTriage Cloud Service temporarily unavailable; please try again later. If this problem persists, contact Basis support at " + Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM),
|
||||||
|
UNKNOWN("CT-080", "Unknown error while communicating with CyberTriage Cloud Service. If this problem persists, contact Basis support at "+ Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM +" for assistance."),
|
||||||
|
UNKNOWN_HOST("CT-081", "Unknown host error. If this problem persists, contact Basis support at "+ Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM +" for assistance."),
|
||||||
|
NETWORK_ERROR("CT-015", "Error connecting to CyberTriage Cloud.\n"
|
||||||
|
+ "Check your firewall or proxy settings.\n"
|
||||||
|
+ "Contact Support (support@cybertriage.com) for further assistance");
|
||||||
|
private final String errorcode;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
private ErrorCode(String errorcode, String description) {
|
||||||
|
this.errorcode = errorcode;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return errorcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTCloudException(CTCloudException.ErrorCode errorCode) {
|
||||||
|
super(errorCode.name());
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTCloudException(CTCloudException.ErrorCode errorCode, Throwable throwable) {
|
||||||
|
super(errorCode.name(), throwable);
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorCode getErrorCode() {
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorDetails() {
|
||||||
|
if(getErrorCode() == CTCloudException.ErrorCode.UNKNOWN && Objects.nonNull(getCause())){
|
||||||
|
return String.format("Malware scan error %s occurred. Please try \"Re Scan\" from the dashboard to attempt Malware scaning again. "
|
||||||
|
+ "\nPlease contact Basis support at %s for help if the problem presists.",
|
||||||
|
StringUtils.isNotBlank(getCause().getLocalizedMessage()) ? "("+getCause().getLocalizedMessage()+")": "(Unknown)",
|
||||||
|
Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM );
|
||||||
|
}else {
|
||||||
|
return getErrorCode().getDescription();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempts to find a more specific error code than "Unknown" for the given exception.
|
||||||
|
*/
|
||||||
|
public static ErrorCode parseUnknownException(Throwable throwable) {
|
||||||
|
|
||||||
|
String stackTrace = ExceptionUtils.getStackTrace(throwable);
|
||||||
|
if (stackTrace.contains("UnknownHostException")) {
|
||||||
|
return ErrorCode.UNKNOWN_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,409 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Authenticator;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.PasswordAuthentication;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.net.ssl.KeyManager;
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.auth.AuthScope;
|
||||||
|
import org.apache.http.auth.NTCredentials;
|
||||||
|
import org.apache.http.client.CredentialsProvider;
|
||||||
|
import org.apache.http.client.config.AuthSchemes;
|
||||||
|
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.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.StringEntity;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.impl.client.SystemDefaultCredentialsProvider;
|
||||||
|
import org.apache.http.impl.client.WinHttpClients;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the http requests to CT cloud.
|
||||||
|
*/
|
||||||
|
public class CTCloudHttpClient {
|
||||||
|
|
||||||
|
private static final CTCloudHttpClient instance = new CTCloudHttpClient();
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName());
|
||||||
|
private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER;
|
||||||
|
|
||||||
|
private static final List<String> DEFAULT_SCHEME_PRIORITY
|
||||||
|
= new ArrayList<>(Arrays.asList(
|
||||||
|
AuthSchemes.SPNEGO,
|
||||||
|
AuthSchemes.KERBEROS,
|
||||||
|
AuthSchemes.NTLM,
|
||||||
|
AuthSchemes.CREDSSP,
|
||||||
|
AuthSchemes.DIGEST,
|
||||||
|
AuthSchemes.BASIC));
|
||||||
|
|
||||||
|
private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec
|
||||||
|
|
||||||
|
public static CTCloudHttpClient getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ObjectMapper mapper = ObjectMapperUtil.getInstance().getDefaultObjectMapper();
|
||||||
|
private final SSLContext sslContext;
|
||||||
|
private String hostName = null;
|
||||||
|
|
||||||
|
private CTCloudHttpClient() {
|
||||||
|
// leave as null for now unless we want to customize this at a later date
|
||||||
|
this.sslContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProxySettingArgs getProxySettings() {
|
||||||
|
if (StringUtils.isBlank(hostName)) {
|
||||||
|
try {
|
||||||
|
hostName = InetAddress.getLocalHost().getCanonicalHostName();
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "An error occurred while fetching the hostname", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int proxyPort = 0;
|
||||||
|
if (StringUtils.isNotBlank(ProxySettings.getHttpPort())) {
|
||||||
|
try {
|
||||||
|
proxyPort = Integer.parseInt(ProxySettings.getHttpsPort());
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Unable to convert port to integer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProxySettingArgs(
|
||||||
|
ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION,
|
||||||
|
hostName,
|
||||||
|
ProxySettings.getHttpsHost(),
|
||||||
|
proxyPort,
|
||||||
|
ProxySettings.getAuthenticationUsername(),
|
||||||
|
ProxySettings.getAuthenticationPassword(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <O> O doPost(String urlPath, Object jsonBody, Class<O> classType) throws CTCloudException {
|
||||||
|
return doPost(urlPath, Collections.emptyMap(), jsonBody, classType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <O> O doPost(String urlPath, Map<String, String> urlReqParams, Object jsonBody, Class<O> classType) throws CTCloudException {
|
||||||
|
String url = HOST_URL + urlPath;
|
||||||
|
try {
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, "initiating http connection to ctcloud server");
|
||||||
|
try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) {
|
||||||
|
URIBuilder builder = new URIBuilder(url);
|
||||||
|
|
||||||
|
if (!MapUtils.isEmpty(urlReqParams)) {
|
||||||
|
for (Entry<String, String> e : urlReqParams.entrySet()) {
|
||||||
|
String key = e.getKey();
|
||||||
|
String value = e.getValue();
|
||||||
|
if (StringUtils.isNotBlank(key) || StringUtils.isNotBlank(value)) {
|
||||||
|
builder.addParameter(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
URI postURI = builder.build();
|
||||||
|
HttpPost postRequest = new HttpPost(postURI);
|
||||||
|
|
||||||
|
|
||||||
|
configureRequestTimeout(postRequest);
|
||||||
|
postRequest.setHeader("Content-type", "application/json");
|
||||||
|
|
||||||
|
if (jsonBody != null) {
|
||||||
|
String requestBody = mapper.writeValueAsString(jsonBody);
|
||||||
|
if (StringUtils.isNotBlank(requestBody)) {
|
||||||
|
HttpEntity entity = new StringEntity(requestBody, "UTF-8");
|
||||||
|
postRequest.setEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + postRequest.getURI());
|
||||||
|
try (CloseableHttpResponse response = httpclient.execute(postRequest)) {
|
||||||
|
|
||||||
|
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||||
|
LOGGER.log(Level.INFO, "Response Received. - Status OK");
|
||||||
|
// Parse Response
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
String entityStr = EntityUtils.toString(entity);
|
||||||
|
O respObj = mapper.readValue(entityStr, classType);
|
||||||
|
return respObj;
|
||||||
|
} else {
|
||||||
|
LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine());
|
||||||
|
handleNonOKResponse(response, "");
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Error when parsing response from CyberTriage Cloud", ex);
|
||||||
|
throw new CTCloudException(CTCloudException.parseUnknownException(ex), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + url, ex);
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + url, ex);
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic way to handle the HTTP response - when the response code is NOT
|
||||||
|
* 200 OK.
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @param fileName - used only for logging.
|
||||||
|
* @throws MalwareScannerException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void handleNonOKResponse(CloseableHttpResponse response, String fileName) throws CTCloudException, IOException {
|
||||||
|
LOGGER.log(Level.WARNING, MessageFormat.format(
|
||||||
|
"Response code {0}. Message Body {1}",
|
||||||
|
response.getStatusLine().getStatusCode(),
|
||||||
|
EntityUtils.toString(response.getEntity())));
|
||||||
|
|
||||||
|
switch (response.getStatusLine().getStatusCode()) {
|
||||||
|
|
||||||
|
case HttpStatus.SC_BAD_REQUEST:
|
||||||
|
//400: Bad request => Unsupported HTTP method or invalid http request (e.g., empty body).
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.BAD_REQUEST);
|
||||||
|
case HttpStatus.SC_UNAUTHORIZED:
|
||||||
|
//401 Invalid API key => An invalid API key, or no API key, has been provided
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.INVALID_KEY);
|
||||||
|
case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
|
||||||
|
// 407 Proxy server authentication required.
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.PROXY_UNAUTHORIZED);
|
||||||
|
case HttpStatus.SC_FORBIDDEN:
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.UN_AUTHORIZED);
|
||||||
|
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
|
||||||
|
//500 Internal error Server temporarily unavailable; please try again later. If the issue persists, please contact RL.
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.TEMP_UNAVAILABLE);
|
||||||
|
case HttpStatus.SC_SERVICE_UNAVAILABLE:
|
||||||
|
//503 Server is too busy. Try again later.
|
||||||
|
//503 Failed to request scan. Try again later. The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. If the issue persists, please contact RL.
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.TEMP_UNAVAILABLE);
|
||||||
|
case HttpStatus.SC_GATEWAY_TIMEOUT:
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.GATEWAY_TIMEOUT);
|
||||||
|
default:
|
||||||
|
String returnData = EntityUtils.toString(response.getEntity());
|
||||||
|
LOGGER.log(Level.WARNING, MessageFormat.format("upload response content for {0}:\n {1}", fileName, returnData));
|
||||||
|
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE That this is not a perfect solution as timeouts set this way does
|
||||||
|
* not terminate a connection forcefully after a specified interval. so if
|
||||||
|
* there is data streaming in from the server at a small speed the
|
||||||
|
* connection will be kept open.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
private void configureRequestTimeout(HttpRequestBase request) {
|
||||||
|
RequestConfig config = RequestConfig.custom()
|
||||||
|
.setConnectionRequestTimeout(CONNECTION_TIMEOUT_MS)
|
||||||
|
.setConnectTimeout(CONNECTION_TIMEOUT_MS)
|
||||||
|
.setSocketTimeout(CONNECTION_TIMEOUT_MS)
|
||||||
|
.build();
|
||||||
|
request.setConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a connection to CT Cloud with the given arguments.
|
||||||
|
* @param proxySettings The network proxy settings.
|
||||||
|
* @param sslContext The ssl context or null.
|
||||||
|
* @return The connection to CT Cloud.
|
||||||
|
*/
|
||||||
|
private static CloseableHttpClient createConnection(ProxySettingArgs proxySettings, SSLContext sslContext) {
|
||||||
|
HttpClientBuilder builder = getHttpClientBuilder(proxySettings);
|
||||||
|
|
||||||
|
if (sslContext != null) {
|
||||||
|
builder.setSSLContext(sslContext);
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpClientBuilder getHttpClientBuilder(ProxySettingArgs proxySettings) {
|
||||||
|
|
||||||
|
if (proxySettings.isSystemOrManualProxy()) {
|
||||||
|
|
||||||
|
Authenticator.setDefault(new Authenticator() {
|
||||||
|
@Override
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
LOGGER.info("Requesting Password Authentication...");
|
||||||
|
return super.getPasswordAuthentication();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpClientBuilder builder = null;
|
||||||
|
HttpHost proxyHost = null;
|
||||||
|
CredentialsProvider proxyCredsProvider = null;
|
||||||
|
RequestConfig config = null;
|
||||||
|
|
||||||
|
if (Objects.nonNull(proxySettings.getProxyHostname()) && proxySettings.getProxyPort() > 0) {
|
||||||
|
proxyHost = new HttpHost(proxySettings.getProxyHostname(), proxySettings.getProxyPort());
|
||||||
|
|
||||||
|
proxyCredsProvider = getProxyCredentialsProvider(proxySettings);
|
||||||
|
if (StringUtils.isNotBlank(proxySettings.getAuthScheme())) {
|
||||||
|
if (!DEFAULT_SCHEME_PRIORITY.get(0).equalsIgnoreCase(proxySettings.getAuthScheme())) {
|
||||||
|
DEFAULT_SCHEME_PRIORITY.removeIf(s -> s.equalsIgnoreCase(proxySettings.getAuthScheme()));
|
||||||
|
DEFAULT_SCHEME_PRIORITY.add(0, proxySettings.getAuthScheme());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config = RequestConfig.custom().setProxyPreferredAuthSchemes(DEFAULT_SCHEME_PRIORITY).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Objects.isNull(proxyCredsProvider) && WinHttpClients.isWinAuthAvailable()) {
|
||||||
|
builder = WinHttpClients.custom();
|
||||||
|
builder.useSystemProperties();
|
||||||
|
LOGGER.log(Level.WARNING, "Using Win HTTP Client");
|
||||||
|
} else {
|
||||||
|
builder = HttpClients.custom();
|
||||||
|
builder.setDefaultRequestConfig(config);
|
||||||
|
if (Objects.nonNull(proxyCredsProvider)) { // make sure non null proxycreds before setting it
|
||||||
|
builder.setDefaultCredentialsProvider(proxyCredsProvider);
|
||||||
|
}
|
||||||
|
LOGGER.log(Level.WARNING, "Using default http client");
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(proxyHost)) {
|
||||||
|
builder.setProxy(proxyHost);
|
||||||
|
LOGGER.log(Level.WARNING, MessageFormat.format("Using proxy {0}", proxyHost));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
} else {
|
||||||
|
return HttpClients.custom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a CredentialsProvider for proxy, if one is configured.
|
||||||
|
*
|
||||||
|
* @return CredentialsProvider, if a proxy is configured with credentials,
|
||||||
|
* null otherwise
|
||||||
|
*/
|
||||||
|
private static CredentialsProvider getProxyCredentialsProvider(ProxySettingArgs proxySettings) {
|
||||||
|
CredentialsProvider proxyCredsProvider = null;
|
||||||
|
if (proxySettings.isSystemOrManualProxy()) {
|
||||||
|
if (StringUtils.isNotBlank(proxySettings.getProxyUserId())) {
|
||||||
|
if (null != proxySettings.getProxyPassword() && proxySettings.getProxyPassword().length > 0) { // Password will be blank for KERBEROS / NEGOTIATE schemes.
|
||||||
|
proxyCredsProvider = new SystemDefaultCredentialsProvider();
|
||||||
|
String userId = proxySettings.getProxyUserId();
|
||||||
|
String domain = null;
|
||||||
|
if (userId.contains("\\")) {
|
||||||
|
domain = userId.split("\\\\")[0];
|
||||||
|
userId = userId.split("\\\\")[1];
|
||||||
|
}
|
||||||
|
String workStation = proxySettings.getHostName();
|
||||||
|
proxyCredsProvider.setCredentials(new AuthScope(proxySettings.getProxyHostname(), proxySettings.getProxyPort()),
|
||||||
|
new NTCredentials(userId, new String(proxySettings.getProxyPassword()), workStation, domain));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyCredsProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProxySettingArgs {
|
||||||
|
|
||||||
|
private final boolean systemOrManualProxy;
|
||||||
|
private final String hostName;
|
||||||
|
private final String proxyHostname;
|
||||||
|
private final int proxyPort;
|
||||||
|
private final String proxyUserId;
|
||||||
|
private final char[] proxyPassword;
|
||||||
|
private final String authScheme;
|
||||||
|
|
||||||
|
ProxySettingArgs(boolean systemOrManualProxy, String hostName, String proxyHostname, int proxyPort, String proxyUserId, char[] proxyPassword, String authScheme) {
|
||||||
|
this.systemOrManualProxy = systemOrManualProxy;
|
||||||
|
this.hostName = hostName;
|
||||||
|
this.proxyHostname = proxyHostname;
|
||||||
|
this.proxyPort = proxyPort;
|
||||||
|
this.proxyUserId = proxyUserId;
|
||||||
|
this.proxyPassword = proxyPassword;
|
||||||
|
this.authScheme = authScheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSystemOrManualProxy() {
|
||||||
|
return systemOrManualProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getHostName() {
|
||||||
|
return hostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getProxyHostname() {
|
||||||
|
return proxyHostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getProxyPort() {
|
||||||
|
return proxyPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getProxyUserId() {
|
||||||
|
return proxyUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] getProxyPassword() {
|
||||||
|
return proxyPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthScheme() {
|
||||||
|
return authScheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants regarding connections to cyber triage cloud.
|
||||||
|
*/
|
||||||
|
final public class Constants {
|
||||||
|
|
||||||
|
public static final String CYBER_TRIAGE = "CyberTriage";
|
||||||
|
|
||||||
|
public static final String IS_MEMORY_IMAGE = "IS_MEMORY_IMAGE";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String SSLTEST_URL = "https://www2.cybertriage.com/ssl_test.html";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static final String CT_CLOUD_DEV_SERVER = "https://cyber-triage-dev.appspot.com";
|
||||||
|
|
||||||
|
public static final String CT_CLOUD_SERVER = "https://rep1.cybertriage.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to watch demo video
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public static final String DEMO_VIDEO_URL = "https://www.cybertriage.com/video/cyber-triage-demo-video/?utm_source=Cyber+Triage+Tool&utm_campaign=Eval+Demo+Video";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link request quote
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public static final String REQUEST_QUOTE_URL = "https://www.cybertriage.com/request-quote/?utm_source=Cyber+Triage+Tool&utm_campaign=Eval+Quote";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Latest help document URL
|
||||||
|
* @since 3.2.0
|
||||||
|
*/
|
||||||
|
public static final URI USER_GUIDE_LATEST_URL = URI.create("https://docs.cybertriage.com/en/latest/?utm_source=Cyber+Triage+Tool&utm_campaign=Help+Docs");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit website URL
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public static final String VISIT_WEBSITE_URL ="https://www.cybertriage.com/eval_data_202109/?utm_source=Cyber+Triage+Tool&utm_campaign=Eval+Data+Button";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL for visiting the website after the data is ingested on the dashboard.
|
||||||
|
*/
|
||||||
|
public static final String EVAL_WEBSITE_AUTO_URL = "https://www.cybertriage.com/eval_data_202109_auto/?utm_source=Cyber+Triage+Tool&utm_campaign=Eval+Data+Auto/"; //CT-4045
|
||||||
|
|
||||||
|
|
||||||
|
public static final String SUPPORT_AT_CYBERTRIAGE_DOT_COM = "support@cybertriage.com";
|
||||||
|
|
||||||
|
public static final String SALES_AT_CYBERTRIAGE_DOT_COM = "sales@cybertriage.com";
|
||||||
|
|
||||||
|
public final static String AUTODETECT = "Auto Detect";
|
||||||
|
|
||||||
|
public final static int RESTAPI_PORT = 9443;
|
||||||
|
|
||||||
|
public static final String INVALID_HOSTNAME_REQUEST = "Request rejected. Invalid host name. Hostname contains characters that are not allowed. \n"
|
||||||
|
+ "Characters that are not allowed include `~!@#$&^*(){}[]\\\\|;'\",<>/? \n"
|
||||||
|
+ "You may input the host IP address if the name is not resolving.";
|
||||||
|
public static final String INVALID_HOSTNAME_UI = "Invalid host name. Hostname contains characters that are not allowed. \n"
|
||||||
|
+ "Characters that are not allowed include `~!@#$&^*(){}[]\\\\|;'\",<>/?";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,446 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.prefs.PreferenceChangeListener;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
import org.netbeans.api.keyring.Keyring;
|
||||||
|
import org.openide.util.*;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taken from https://raw.githubusercontent.com/apache/netbeans/master/platform/o.n.core/src/org/netbeans/core/ProxySettings.java
|
||||||
|
* @author Jiri Rechtacek
|
||||||
|
*/
|
||||||
|
public class ProxySettings {
|
||||||
|
|
||||||
|
public static final String PROXY_HTTP_HOST = "proxyHttpHost"; // NOI18N
|
||||||
|
public static final String PROXY_HTTP_PORT = "proxyHttpPort"; // NOI18N
|
||||||
|
public static final String PROXY_HTTPS_HOST = "proxyHttpsHost"; // NOI18N
|
||||||
|
public static final String PROXY_HTTPS_PORT = "proxyHttpsPort"; // NOI18N
|
||||||
|
public static final String PROXY_SOCKS_HOST = "proxySocksHost"; // NOI18N
|
||||||
|
public static final String PROXY_SOCKS_PORT = "proxySocksPort"; // NOI18N
|
||||||
|
public static final String NOT_PROXY_HOSTS = "proxyNonProxyHosts"; // NOI18N
|
||||||
|
public static final String PROXY_TYPE = "proxyType"; // NOI18N
|
||||||
|
public static final String USE_PROXY_AUTHENTICATION = "useProxyAuthentication"; // NOI18N
|
||||||
|
public static final String PROXY_AUTHENTICATION_USERNAME = "proxyAuthenticationUsername"; // NOI18N
|
||||||
|
public static final String PROXY_AUTHENTICATION_PASSWORD = "proxyAuthenticationPassword"; // NOI18N
|
||||||
|
public static final String USE_PROXY_ALL_PROTOCOLS = "useProxyAllProtocols"; // NOI18N
|
||||||
|
public static final String DIRECT = "DIRECT"; // NOI18N
|
||||||
|
public static final String PAC = "PAC"; // NOI18N
|
||||||
|
|
||||||
|
public static final String SYSTEM_PROXY_HTTP_HOST = "systemProxyHttpHost"; // NOI18N
|
||||||
|
public static final String SYSTEM_PROXY_HTTP_PORT = "systemProxyHttpPort"; // NOI18N
|
||||||
|
public static final String SYSTEM_PROXY_HTTPS_HOST = "systemProxyHttpsHost"; // NOI18N
|
||||||
|
public static final String SYSTEM_PROXY_HTTPS_PORT = "systemProxyHttpsPort"; // NOI18N
|
||||||
|
public static final String SYSTEM_PROXY_SOCKS_HOST = "systemProxySocksHost"; // NOI18N
|
||||||
|
public static final String SYSTEM_PROXY_SOCKS_PORT = "systemProxySocksPort"; // NOI18N
|
||||||
|
public static final String SYSTEM_NON_PROXY_HOSTS = "systemProxyNonProxyHosts"; // NOI18N
|
||||||
|
public static final String SYSTEM_PAC = "systemPAC"; // NOI18N
|
||||||
|
|
||||||
|
// Only for testing purpose (Test connection in General options panel)
|
||||||
|
public static final String TEST_SYSTEM_PROXY_HTTP_HOST = "testSystemProxyHttpHost"; // NOI18N
|
||||||
|
public static final String TEST_SYSTEM_PROXY_HTTP_PORT = "testSystemProxyHttpPort"; // NOI18N
|
||||||
|
public static final String HTTP_CONNECTION_TEST_URL = "https://netbeans.apache.org";// NOI18N
|
||||||
|
|
||||||
|
private static String presetNonProxyHosts;
|
||||||
|
|
||||||
|
/** No proxy is used to connect. */
|
||||||
|
public static final int DIRECT_CONNECTION = 0;
|
||||||
|
|
||||||
|
/** Proxy setting is automatically detect in OS. */
|
||||||
|
public static final int AUTO_DETECT_PROXY = 1; // as default
|
||||||
|
|
||||||
|
/** Manually set proxy host and port. */
|
||||||
|
public static final int MANUAL_SET_PROXY = 2;
|
||||||
|
|
||||||
|
/** Proxy PAC file automatically detect in OS. */
|
||||||
|
public static final int AUTO_DETECT_PAC = 3;
|
||||||
|
|
||||||
|
/** Proxy PAC file manually set. */
|
||||||
|
public static final int MANUAL_SET_PAC = 4;
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(ProxySettings.class.getName());
|
||||||
|
|
||||||
|
private static Preferences getPreferences() {
|
||||||
|
return NbPreferences.forModule (ProxySettings.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getHttpHost () {
|
||||||
|
return normalizeProxyHost (getPreferences ().get (PROXY_HTTP_HOST, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHttpPort () {
|
||||||
|
return getPreferences ().get (PROXY_HTTP_PORT, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHttpsHost () {
|
||||||
|
if (useProxyAllProtocols ()) {
|
||||||
|
return getHttpHost ();
|
||||||
|
} else {
|
||||||
|
return getPreferences ().get (PROXY_HTTPS_HOST, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHttpsPort () {
|
||||||
|
if (useProxyAllProtocols ()) {
|
||||||
|
return getHttpPort ();
|
||||||
|
} else {
|
||||||
|
return getPreferences ().get (PROXY_HTTPS_PORT, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSocksHost () {
|
||||||
|
if (useProxyAllProtocols ()) {
|
||||||
|
return getHttpHost ();
|
||||||
|
} else {
|
||||||
|
return getPreferences ().get (PROXY_SOCKS_HOST, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSocksPort () {
|
||||||
|
if (useProxyAllProtocols ()) {
|
||||||
|
return getHttpPort ();
|
||||||
|
} else {
|
||||||
|
return getPreferences ().get (PROXY_SOCKS_PORT, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getNonProxyHosts () {
|
||||||
|
String hosts = getPreferences ().get (NOT_PROXY_HOSTS, getDefaultUserNonProxyHosts ());
|
||||||
|
return compactNonProxyHosts(hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getProxyType () {
|
||||||
|
int type = getPreferences ().getInt (PROXY_TYPE, AUTO_DETECT_PROXY);
|
||||||
|
if (AUTO_DETECT_PROXY == type) {
|
||||||
|
type = ProxySettings.getSystemPac() != null ? AUTO_DETECT_PAC : AUTO_DETECT_PROXY;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getSystemHttpHost() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_HTTP_HOST, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemHttpPort() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_HTTP_PORT, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemHttpsHost() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_HTTPS_HOST, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemHttpsPort() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_HTTPS_PORT, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemSocksHost() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_SOCKS_HOST, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemSocksPort() {
|
||||||
|
return getPreferences().get(SYSTEM_PROXY_SOCKS_PORT, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemNonProxyHosts() {
|
||||||
|
return getPreferences().get(SYSTEM_NON_PROXY_HOSTS, getModifiedNonProxyHosts(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSystemPac() {
|
||||||
|
return getPreferences().get(SYSTEM_PAC, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getTestSystemHttpHost() {
|
||||||
|
return getPreferences().get(TEST_SYSTEM_PROXY_HTTP_HOST, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getTestSystemHttpPort() {
|
||||||
|
return getPreferences().get(TEST_SYSTEM_PROXY_HTTP_PORT, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean useAuthentication () {
|
||||||
|
return getPreferences ().getBoolean (USE_PROXY_AUTHENTICATION, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean useProxyAllProtocols () {
|
||||||
|
return getPreferences ().getBoolean (USE_PROXY_ALL_PROTOCOLS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAuthenticationUsername () {
|
||||||
|
return getPreferences ().get (PROXY_AUTHENTICATION_USERNAME, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char[] getAuthenticationPassword () {
|
||||||
|
String old = getPreferences().get(PROXY_AUTHENTICATION_PASSWORD, null);
|
||||||
|
if (old != null) {
|
||||||
|
getPreferences().remove(PROXY_AUTHENTICATION_PASSWORD);
|
||||||
|
setAuthenticationPassword(old.toCharArray());
|
||||||
|
}
|
||||||
|
char[] pwd = Keyring.read(PROXY_AUTHENTICATION_PASSWORD);
|
||||||
|
return pwd != null ? pwd : new char[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAuthenticationPassword(char[] password) {
|
||||||
|
Keyring.save(ProxySettings.PROXY_AUTHENTICATION_PASSWORD, password,
|
||||||
|
// XXX consider including getHttpHost and/or getHttpsHost
|
||||||
|
NbBundle.getMessage(ProxySettings.class, "ProxySettings.password.description")); // NOI18N
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addPreferenceChangeListener (PreferenceChangeListener l) {
|
||||||
|
getPreferences ().addPreferenceChangeListener (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removePreferenceChangeListener (PreferenceChangeListener l) {
|
||||||
|
getPreferences ().removePreferenceChangeListener (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPresetNonProxyHosts () {
|
||||||
|
if (presetNonProxyHosts == null) {
|
||||||
|
presetNonProxyHosts = System.getProperty ("http.nonProxyHosts", ""); // NOI18N
|
||||||
|
}
|
||||||
|
return presetNonProxyHosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDefaultUserNonProxyHosts () {
|
||||||
|
return getModifiedNonProxyHosts (getSystemNonProxyHosts ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String concatProxies(String... proxies) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String n : proxies) {
|
||||||
|
if (n == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = n.trim();
|
||||||
|
if (n.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '|') { // NOI18N
|
||||||
|
if (!n.startsWith("|")) { // NOI18N
|
||||||
|
sb.append('|'); // NOI18N
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(n);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getModifiedNonProxyHosts (String systemPreset) {
|
||||||
|
String fromSystem = systemPreset.replace (";", "|").replace (",", "|"); //NOI18N
|
||||||
|
String fromUser = getPresetNonProxyHosts () == null ? "" : getPresetNonProxyHosts ().replace (";", "|").replace (",", "|"); //NOI18N
|
||||||
|
if (Utilities.isWindows ()) {
|
||||||
|
fromSystem = addReguralToNonProxyHosts (fromSystem);
|
||||||
|
}
|
||||||
|
final String staticNonProxyHosts = NbBundle.getMessage(ProxySettings.class, "StaticNonProxyHosts"); // NOI18N
|
||||||
|
String nonProxy = concatProxies(fromUser, fromSystem, staticNonProxyHosts); // NOI18N
|
||||||
|
String localhost;
|
||||||
|
try {
|
||||||
|
localhost = InetAddress.getLocalHost().getHostName();
|
||||||
|
if (!"localhost".equals(localhost)) { // NOI18N
|
||||||
|
nonProxy = nonProxy + "|" + localhost; // NOI18N
|
||||||
|
} else {
|
||||||
|
// Avoid this error when hostname == localhost:
|
||||||
|
// Error in http.nonProxyHosts system property: sun.misc.REException: localhost is a duplicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnknownHostException e) {
|
||||||
|
// OK. Sometimes a hostname is assigned by DNS, but a computer
|
||||||
|
// is later pulled off the network. It may then produce a bogus
|
||||||
|
// name for itself which can't actually be resolved. Normally
|
||||||
|
// "localhost" is aliased to 127.0.0.1 anyway.
|
||||||
|
}
|
||||||
|
/* per Milan's agreement it's removed. See issue #89868
|
||||||
|
try {
|
||||||
|
String localhost2 = InetAddress.getLocalHost().getCanonicalHostName();
|
||||||
|
if (!"localhost".equals(localhost2) && !localhost2.equals(localhost)) { // NOI18N
|
||||||
|
nonProxy = nonProxy + "|" + localhost2; // NOI18N
|
||||||
|
} else {
|
||||||
|
// Avoid this error when hostname == localhost:
|
||||||
|
// Error in http.nonProxyHosts system property: sun.misc.REException: localhost is a duplicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnknownHostException e) {
|
||||||
|
// OK. Sometimes a hostname is assigned by DNS, but a computer
|
||||||
|
// is later pulled off the network. It may then produce a bogus
|
||||||
|
// name for itself which can't actually be resolved. Normally
|
||||||
|
// "localhost" is aliased to 127.0.0.1 anyway.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return compactNonProxyHosts (nonProxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// avoid duplicate hosts
|
||||||
|
private static String compactNonProxyHosts (String hosts) {
|
||||||
|
StringTokenizer st = new StringTokenizer(hosts, ","); //NOI18N
|
||||||
|
StringBuilder nonProxyHosts = new StringBuilder();
|
||||||
|
while (st.hasMoreTokens()) {
|
||||||
|
String h = st.nextToken().trim();
|
||||||
|
if (h.length() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nonProxyHosts.length() > 0) {
|
||||||
|
nonProxyHosts.append("|"); // NOI18N
|
||||||
|
}
|
||||||
|
nonProxyHosts.append(h);
|
||||||
|
}
|
||||||
|
st = new StringTokenizer (nonProxyHosts.toString(), "|"); //NOI18N
|
||||||
|
Set<String> set = new HashSet<String> ();
|
||||||
|
StringBuilder compactedProxyHosts = new StringBuilder();
|
||||||
|
while (st.hasMoreTokens ()) {
|
||||||
|
String t = st.nextToken ();
|
||||||
|
if (set.add (t.toLowerCase (Locale.US))) {
|
||||||
|
if (compactedProxyHosts.length() > 0) {
|
||||||
|
compactedProxyHosts.append('|'); // NOI18N
|
||||||
|
}
|
||||||
|
compactedProxyHosts.append(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compactedProxyHosts.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String addReguralToNonProxyHosts (String nonProxyHost) {
|
||||||
|
StringTokenizer st = new StringTokenizer (nonProxyHost, "|"); // NOI18N
|
||||||
|
StringBuilder reguralProxyHosts = new StringBuilder();
|
||||||
|
while (st.hasMoreTokens ()) {
|
||||||
|
String t = st.nextToken ();
|
||||||
|
if (t.indexOf ('*') == -1) { //NOI18N
|
||||||
|
t = t + '*'; //NOI18N
|
||||||
|
}
|
||||||
|
if (reguralProxyHosts.length() > 0)
|
||||||
|
reguralProxyHosts.append('|'); // NOI18N
|
||||||
|
reguralProxyHosts.append(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reguralProxyHosts.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String normalizeProxyHost (String proxyHost) {
|
||||||
|
if (proxyHost.toLowerCase (Locale.US).startsWith ("http://")) { // NOI18N
|
||||||
|
return proxyHost.substring (7, proxyHost.length ());
|
||||||
|
} else {
|
||||||
|
return proxyHost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InetSocketAddress analyzeProxy(URI uri) {
|
||||||
|
Parameters.notNull("uri", uri); // NOI18N
|
||||||
|
List<Proxy> proxies = ProxySelector.getDefault().select(uri);
|
||||||
|
assert proxies != null : "ProxySelector cannot return null for " + uri; // NOI18N
|
||||||
|
assert !proxies.isEmpty() : "ProxySelector cannot return empty list for " + uri; // NOI18N
|
||||||
|
String protocol = uri.getScheme();
|
||||||
|
Proxy p = proxies.get(0);
|
||||||
|
if (Proxy.Type.DIRECT == p.type()) {
|
||||||
|
// return null for DIRECT proxy
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (protocol == null
|
||||||
|
|| ((protocol.startsWith("http") || protocol.equals("ftp")) && Proxy.Type.HTTP == p.type()) // NOI18N
|
||||||
|
|| !(protocol.startsWith("http") || protocol.equals("ftp"))) { // NOI18N
|
||||||
|
if (p.address() instanceof InetSocketAddress) {
|
||||||
|
// check is
|
||||||
|
//assert ! ((InetSocketAddress) p.address()).isUnresolved() : p.address() + " must be resolved address.";
|
||||||
|
return (InetSocketAddress) p.address();
|
||||||
|
} else {
|
||||||
|
LOGGER.log(Level.INFO, p.address() + " is not instanceof InetSocketAddress but " + p.address().getClass()); // NOI18N
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reload() {
|
||||||
|
Reloader reloader = Lookup.getDefault().lookup(Reloader.class);
|
||||||
|
reloader.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ServiceProvider(service = NetworkSettings.ProxyCredentialsProvider.class, position = 1000)
|
||||||
|
public static class NbProxyCredentialsProvider extends NetworkSettings.ProxyCredentialsProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProxyHost(URI u) {
|
||||||
|
if (getPreferences() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InetSocketAddress sa = analyzeProxy(u);
|
||||||
|
return sa == null ? null : sa.getHostName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProxyPort(URI u) {
|
||||||
|
if (getPreferences() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InetSocketAddress sa = analyzeProxy(u);
|
||||||
|
return sa == null ? null : Integer.toString(sa.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getProxyUserName(URI u) {
|
||||||
|
if (getPreferences() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ProxySettings.getAuthenticationUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected char[] getProxyPassword(URI u) {
|
||||||
|
if (getPreferences() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ProxySettings.getAuthenticationPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isProxyAuthentication(URI u) {
|
||||||
|
if (getPreferences() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getPreferences().getBoolean(USE_PROXY_AUTHENTICATION, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A bridge between <code>o.n.core</code> and <code>core.network</code>.
|
||||||
|
* An implementation of this class brings a facility to reload Network Proxy Settings
|
||||||
|
* from underlying OS.
|
||||||
|
* The module <code>core.network</code> provides a implementation which may be accessible
|
||||||
|
* via <code>Lookup.getDefault()</code>. It's not guaranteed any implementation is found on all distribution.
|
||||||
|
*
|
||||||
|
* @since 3.40
|
||||||
|
*/
|
||||||
|
public abstract static class Reloader {
|
||||||
|
|
||||||
|
/** Reloads Network Proxy Settings from underlying system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract void reload();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for an auth token request.
|
||||||
|
*/
|
||||||
|
public class AuthTokenRequest {
|
||||||
|
|
||||||
|
@JsonProperty("autopsy_version")
|
||||||
|
private String autopsyVersion;
|
||||||
|
|
||||||
|
@JsonProperty("boost_license_id")
|
||||||
|
private String boostLicenseId;
|
||||||
|
|
||||||
|
@JsonProperty("requestFileUpload")
|
||||||
|
private boolean requestFileUpload;
|
||||||
|
|
||||||
|
@JsonProperty("host_id")
|
||||||
|
private String hostId;
|
||||||
|
|
||||||
|
public String getAutopsyVersion() {
|
||||||
|
return autopsyVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenRequest setAutopsyVersion(String autopsyVersion) {
|
||||||
|
this.autopsyVersion = autopsyVersion;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBoostLicenseId() {
|
||||||
|
return boostLicenseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenRequest setBoostLicenseId(String boostLicenseId) {
|
||||||
|
this.boostLicenseId = boostLicenseId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequestFileUpload() {
|
||||||
|
return requestFileUpload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenRequest setRequestFileUpload(boolean requestFileUpload) {
|
||||||
|
this.requestFileUpload = requestFileUpload;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenRequest setHostId(String hostId) {
|
||||||
|
this.hostId = hostId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 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;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for an auth token response.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class AuthTokenResponse {
|
||||||
|
|
||||||
|
private final Long hashLookupCount;
|
||||||
|
private final Long hashLookupLimit;
|
||||||
|
private final Long fileUploadLimit;
|
||||||
|
private final Long fileUploadCount;
|
||||||
|
private final String fileUploadUrl;
|
||||||
|
private final Instant expiration;
|
||||||
|
private final String token;
|
||||||
|
private final String apiKey;
|
||||||
|
private final Instant resetDate;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public AuthTokenResponse(
|
||||||
|
@JsonProperty("token") String token,
|
||||||
|
@JsonProperty("api_key") String apiKey,
|
||||||
|
@JsonProperty("hashLookupCount") Long hashLookupCount,
|
||||||
|
@JsonProperty("hashLookupLimit") Long hashLookupLimit,
|
||||||
|
@JsonProperty("fileUploadLimit") Long fileUploadLimit,
|
||||||
|
@JsonProperty("fileUploadCount") Long fileUploadCount,
|
||||||
|
@JsonProperty("fileUploadUrl") String fileUploadUrl,
|
||||||
|
@JsonDeserialize(using = InstantEpochSecsDeserializer.class)
|
||||||
|
@JsonProperty("expiration") Instant expiration,
|
||||||
|
@JsonDeserialize(using = InstantEpochMillisDeserializer.class)
|
||||||
|
@JsonProperty("resetDate") Instant resetDate
|
||||||
|
) {
|
||||||
|
this.token = token;
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
this.hashLookupCount = hashLookupCount;
|
||||||
|
this.hashLookupLimit = hashLookupLimit;
|
||||||
|
this.fileUploadLimit = fileUploadLimit;
|
||||||
|
this.fileUploadCount = fileUploadCount;
|
||||||
|
this.fileUploadUrl = fileUploadUrl;
|
||||||
|
this.expiration = expiration;
|
||||||
|
this.resetDate = resetDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getHashLookupCount() {
|
||||||
|
return hashLookupCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getHashLookupLimit() {
|
||||||
|
return hashLookupLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getFileUploadLimit() {
|
||||||
|
return fileUploadLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getFileUploadCount() {
|
||||||
|
return fileUploadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileUploadUrl() {
|
||||||
|
return fileUploadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApiKey() {
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getResetDate() {
|
||||||
|
return resetDate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data required for an authenticated request.
|
||||||
|
*/
|
||||||
|
public class AuthenticatedRequestData {
|
||||||
|
|
||||||
|
private final String token;
|
||||||
|
private final String apiKey;
|
||||||
|
private final String hostId;
|
||||||
|
|
||||||
|
public AuthenticatedRequestData(DecryptedLicenseResponse decrypted, AuthTokenResponse authResp) {
|
||||||
|
this(authResp.getToken(), authResp.getApiKey(), decrypted.getLicenseHostId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatedRequestData(String token, String apiKey, String hostId) {
|
||||||
|
this.token = token;
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
this.hostId = hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApiKey() {
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for a boost license response object that is a part of the license
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class BoostLicenseResponse {
|
||||||
|
|
||||||
|
private final String version;
|
||||||
|
private final String iv;
|
||||||
|
private final String encryptedKey;
|
||||||
|
private final String encryptedJson;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public BoostLicenseResponse(
|
||||||
|
@JsonProperty("version") String version,
|
||||||
|
@JsonProperty("iv") String iv,
|
||||||
|
@JsonProperty("encryptedKey") String encryptedKey,
|
||||||
|
@JsonProperty("encryptedJson") String encryptedJson) {
|
||||||
|
|
||||||
|
this.version = version;
|
||||||
|
this.iv = iv;
|
||||||
|
this.encryptedKey = encryptedKey;
|
||||||
|
this.encryptedJson = encryptedJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIv() {
|
||||||
|
return iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncryptedKey() {
|
||||||
|
return encryptedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncryptedJson() {
|
||||||
|
return encryptedJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class CTCloudBean {
|
||||||
|
|
||||||
|
public static enum Status {
|
||||||
|
FOUND,
|
||||||
|
NOT_FOUND,
|
||||||
|
ERROR,
|
||||||
|
LIMITS_EXCEEDED,
|
||||||
|
BEING_SCANNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@JsonProperty("malware")
|
||||||
|
private MalwareResultBean malwareResult;
|
||||||
|
|
||||||
|
@JsonProperty("correlation")
|
||||||
|
private CorrelationResultBean correlationResult;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@JsonProperty("md5_hash")
|
||||||
|
private String md5HashValue;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty("sha1_hash")
|
||||||
|
private String sha1HashValue;
|
||||||
|
|
||||||
|
public String getMd5HashValue() {
|
||||||
|
return md5HashValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSha1HashValue() {
|
||||||
|
return sha1HashValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMd5HashValue(String md5HashValue) {
|
||||||
|
this.md5HashValue = md5HashValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSha1HashValue(String sha1HashValue) {
|
||||||
|
this.sha1HashValue = sha1HashValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MalwareResultBean getMalwareResult() {
|
||||||
|
return malwareResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMalwareResult(MalwareResultBean malwareResult) {
|
||||||
|
this.malwareResult = malwareResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CorrelationResultBean getCorrelationResult() {
|
||||||
|
return correlationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCorrelationResult(CorrelationResultBean correlationResult) {
|
||||||
|
this.correlationResult = correlationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CTCloudBean{"
|
||||||
|
+ "status=" + malwareResult.getStatus()
|
||||||
|
+ ", malwareDescription=" + malwareResult.getMalwareDescription()
|
||||||
|
+ ", score=" + malwareResult.getCTScore()
|
||||||
|
+ ", md5HashValue=" + md5HashValue
|
||||||
|
+ ", sha1HashValue=" + sha1HashValue
|
||||||
|
+ ", firstSeen=" + malwareResult.getFirstAnalyzedDate()
|
||||||
|
+ ", lastSeen=" + malwareResult.getLastAnalyzedDate()
|
||||||
|
+ ", statusDescription=" + malwareResult.getStatusDescription()
|
||||||
|
+ ", metadata=" + malwareResult.getMetadata()
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for file reputation result list response.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class CTCloudBeanResponse {
|
||||||
|
|
||||||
|
private final List<CTCloudBean> items;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public CTCloudBeanResponse(
|
||||||
|
@JsonProperty("items") List<CTCloudBean> items
|
||||||
|
) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CTCloudBean> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class CTCloudCorrelationResultBean {
|
||||||
|
|
||||||
|
@JsonProperty("correlation")
|
||||||
|
private CorrelationResultBean correlationResult;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@JsonProperty("signature")
|
||||||
|
private String signature;
|
||||||
|
|
||||||
|
public CorrelationResultBean getCorrelationResult() {
|
||||||
|
return correlationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCorrelationResult(CorrelationResultBean correlationResult) {
|
||||||
|
this.correlationResult = correlationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(String signature) {
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CTCloudCorrelationResultBean{"
|
||||||
|
+ "correlationResult=" + correlationResult
|
||||||
|
+ ", signature=" + signature
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
class CTCloudCostBean {
|
||||||
|
|
||||||
|
private final String provider;
|
||||||
|
|
||||||
|
private final Integer units;
|
||||||
|
|
||||||
|
public CTCloudCostBean(@JsonProperty("provider") String provider, @JsonProperty("units") Integer units) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.units = units;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getUnits() {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.google.common.base.MoreObjects;
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import org.sleuthkit.datamodel.Score;
|
||||||
|
import org.sleuthkit.datamodel.Score.Priority;
|
||||||
|
import org.sleuthkit.datamodel.Score.Significance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Score class represents a conclusion and the relative confidence in the conclusion about
|
||||||
|
* a subject. A subject may be an Item, a category/analysis result etc.
|
||||||
|
* @since 1.7.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum CTScore {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Enum names without method defaults to AUTO
|
||||||
|
NOTABLE -> NOTABLE
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unknown None
|
||||||
|
UNKNOWN(new Score(Significance.UNKNOWN, Priority.NORMAL)),
|
||||||
|
// GOOD_MEDIUM
|
||||||
|
LIKELY_NONE(new Score(Significance.LIKELY_NONE, Priority.NORMAL)),
|
||||||
|
// SUSPICIOUS_HIGH / BAD_MEDIUM
|
||||||
|
LIKELY_NOTABLE(new Score(Significance.LIKELY_NOTABLE, Priority.NORMAL)),
|
||||||
|
// GOOD_HIGH
|
||||||
|
NONE(new Score(Significance.NONE, Priority.NORMAL)),
|
||||||
|
// BAD_HIGH
|
||||||
|
NOTABLE(new Score(Significance.NOTABLE, Priority.NORMAL)),
|
||||||
|
// SUSPICIOUS (User flagged)
|
||||||
|
LIKELY_NOTABLE_MANUAL(new Score(Significance.LIKELY_NOTABLE, Priority.OVERRIDE)),
|
||||||
|
// Good (User flagged)
|
||||||
|
NONE_MANUAL(new Score(Significance.NONE, Priority.OVERRIDE)),
|
||||||
|
// Bad (User flagged)
|
||||||
|
NOTABLE_MANUAL(new Score(Significance.NOTABLE, Priority.OVERRIDE));
|
||||||
|
|
||||||
|
|
||||||
|
private final Score tskScore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a CTScore instance based on score
|
||||||
|
* @param tskScore
|
||||||
|
*/
|
||||||
|
private CTScore(Score tskScore) {
|
||||||
|
|
||||||
|
checkArgument(tskScore.getSignificance() == Significance.UNKNOWN ? tskScore.getPriority() == Priority.NORMAL : true, "Unknown Conclusions expects no (NORMAL) priority");
|
||||||
|
this.tskScore = tskScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Score getTskCore() {
|
||||||
|
return tskScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("Method Category", tskScore.getPriority())
|
||||||
|
.add("Significance", tskScore.getSignificance()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
public enum CorrelationFrequency {
|
||||||
|
UNIQUE,
|
||||||
|
RARE,
|
||||||
|
COMMON;
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
public class CorrelationResultBean {
|
||||||
|
|
||||||
|
@JsonProperty("frequency")
|
||||||
|
private CorrelationFrequency frequency;
|
||||||
|
|
||||||
|
@JsonProperty("frequency_description")
|
||||||
|
private String frequencyDescription;
|
||||||
|
|
||||||
|
public CorrelationFrequency getFrequency() {
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrequencyDescription() {
|
||||||
|
return frequencyDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrequency(CorrelationFrequency frequency) {
|
||||||
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrequencyDescription(String frequencyDescription) {
|
||||||
|
this.frequencyDescription = frequencyDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.InstantEpochMillisDeserializer;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for after encrypted boost license has been decrypted.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class DecryptedLicenseResponse {
|
||||||
|
|
||||||
|
private final String boostLicenseId;
|
||||||
|
private final String licenseHostId;
|
||||||
|
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;
|
||||||
|
private final String customerName;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public DecryptedLicenseResponse(
|
||||||
|
@JsonProperty("boostLicenseId") String boostLicenseId,
|
||||||
|
@JsonProperty("licenseHostId") String licenseHostId,
|
||||||
|
@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("timezone") String timezone,
|
||||||
|
@JsonProperty("customerEmail") String customerEmail,
|
||||||
|
@JsonProperty("customerName") String customerName
|
||||||
|
) {
|
||||||
|
this.boostLicenseId = boostLicenseId;
|
||||||
|
this.licenseHostId = licenseHostId;
|
||||||
|
this.expirationDate = expirationDate;
|
||||||
|
this.hashLookups = hashLookups;
|
||||||
|
this.fileUploads = fileUploads;
|
||||||
|
this.activationTime = activationTime;
|
||||||
|
this.product = product;
|
||||||
|
this.limitType = limitType;
|
||||||
|
this.timezone = timezone;
|
||||||
|
this.customerEmail = customerEmail;
|
||||||
|
this.customerName = customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBoostLicenseId() {
|
||||||
|
return boostLicenseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLicenseHostId() {
|
||||||
|
return licenseHostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getHashLookups() {
|
||||||
|
return hashLookups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getFileUploads() {
|
||||||
|
return fileUploads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getActivationTime() {
|
||||||
|
return activationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProduct() {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLimitType() {
|
||||||
|
return limitType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getExpirationDate() {
|
||||||
|
return expirationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimezone() {
|
||||||
|
return timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomerEmail() {
|
||||||
|
return customerEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomerName() {
|
||||||
|
return customerName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request for file reputation results.
|
||||||
|
*/
|
||||||
|
public class FileReputationRequest {
|
||||||
|
|
||||||
|
@JsonProperty("hashes")
|
||||||
|
private List<String> hashes;
|
||||||
|
|
||||||
|
public List<String> getHashes() {
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileReputationRequest setHashes(List<String> hashes) {
|
||||||
|
this.hashes = hashes;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains license info and decrypted boost license.
|
||||||
|
*/
|
||||||
|
public class LicenseInfo {
|
||||||
|
private final LicenseResponse licenseResponse;
|
||||||
|
private final DecryptedLicenseResponse decryptedLicense;
|
||||||
|
|
||||||
|
public LicenseInfo(LicenseResponse licenseResponse, DecryptedLicenseResponse decryptedLicense) {
|
||||||
|
this.licenseResponse = licenseResponse;
|
||||||
|
this.decryptedLicense = decryptedLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseResponse getLicenseResponse() {
|
||||||
|
return licenseResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecryptedLicenseResponse getDecryptedLicense() {
|
||||||
|
return decryptedLicense;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for license request information.
|
||||||
|
*/
|
||||||
|
public class LicenseRequest {
|
||||||
|
@JsonProperty("host_id")
|
||||||
|
private String hostId;
|
||||||
|
|
||||||
|
@JsonProperty("boost_license_code")
|
||||||
|
private String boostLicenseCode;
|
||||||
|
|
||||||
|
@JsonProperty("product")
|
||||||
|
private String product;
|
||||||
|
|
||||||
|
@JsonProperty("time_zone_id")
|
||||||
|
private String timeZoneId;
|
||||||
|
|
||||||
|
public String getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseRequest setHostId(String hostId) {
|
||||||
|
this.hostId = hostId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBoostLicenseCode() {
|
||||||
|
return boostLicenseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseRequest setBoostLicenseCode(String boostLicenseCode) {
|
||||||
|
this.boostLicenseCode = boostLicenseCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProduct() {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseRequest setProduct(String product) {
|
||||||
|
this.product = product;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimeZoneId() {
|
||||||
|
return timeZoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LicenseRequest setTimeZoneId(String timeZoneId) {
|
||||||
|
this.timeZoneId = timeZoneId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response POJO for request for license.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class LicenseResponse {
|
||||||
|
|
||||||
|
private final Boolean success;
|
||||||
|
private final Boolean hostChanged;
|
||||||
|
private final Long hostChangesRemaining;
|
||||||
|
private final BoostLicenseResponse boostLicense;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public LicenseResponse(
|
||||||
|
@JsonProperty("success") Boolean success,
|
||||||
|
@JsonProperty("hostChanged") Boolean hostChanged,
|
||||||
|
@JsonProperty("hostChangesRemaining") Long hostChangesRemaining,
|
||||||
|
@JsonProperty("boostLicense") BoostLicenseResponse boostLicense
|
||||||
|
) {
|
||||||
|
this.success = success;
|
||||||
|
this.hostChanged = hostChanged;
|
||||||
|
this.hostChangesRemaining = hostChangesRemaining;
|
||||||
|
this.boostLicense = boostLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isHostChanged() {
|
||||||
|
return hostChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getHostChangesRemaining() {
|
||||||
|
return hostChangesRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoostLicenseResponse getBoostLicense() {
|
||||||
|
return boostLicense;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.ZonedDateTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
public class MalwareResultBean {
|
||||||
|
|
||||||
|
public static enum Status {
|
||||||
|
FOUND,
|
||||||
|
NOT_FOUND,
|
||||||
|
ERROR,
|
||||||
|
LIMITS_EXCEEDED,
|
||||||
|
BEING_SCANNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty("malware_description")
|
||||||
|
private String malwareDescription;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@JsonProperty("status")
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@JsonProperty("score")
|
||||||
|
private String score;
|
||||||
|
|
||||||
|
private CTScore ctScore;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty("first_scan_date")
|
||||||
|
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
|
||||||
|
private ZonedDateTime firstAnalyzedDate;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty("last_scan_date")
|
||||||
|
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
|
||||||
|
private ZonedDateTime lastAnalyzedDate;
|
||||||
|
|
||||||
|
@JsonProperty("metadata")
|
||||||
|
private List<MetadataLabel> metadata;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty("status_description")
|
||||||
|
private String statusDescription;
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@JsonProperty
|
||||||
|
private List<CTCloudCostBean> cost;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public CTScore getCTScore() {
|
||||||
|
return ctScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime getFirstAnalyzedDate() {
|
||||||
|
return firstAnalyzedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime getLastAnalyzedDate() {
|
||||||
|
return lastAnalyzedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MetadataLabel> getMetadata() {
|
||||||
|
if (metadata != null) {
|
||||||
|
return List.copyOf(metadata);
|
||||||
|
} else {
|
||||||
|
return List.of(); // empty list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatusDescription() {
|
||||||
|
return statusDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getMalwareDescription() {
|
||||||
|
return malwareDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMalwareDescription(String malwareDescription) {
|
||||||
|
this.malwareDescription = malwareDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScore(String score) {
|
||||||
|
this.score = score;
|
||||||
|
switch(score) {
|
||||||
|
case "GOOD_HIGH":
|
||||||
|
this.ctScore = CTScore.NONE;
|
||||||
|
break;
|
||||||
|
case "GOOD_MEDIUM":
|
||||||
|
this.ctScore = CTScore.LIKELY_NONE;
|
||||||
|
break;
|
||||||
|
case "BAD_HIGH":
|
||||||
|
this.ctScore = CTScore.NOTABLE;
|
||||||
|
break;
|
||||||
|
case "BAD_MEDIUM":
|
||||||
|
this.ctScore = CTScore.LIKELY_NOTABLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.ctScore = CTScore.UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstAnalyzedDate(ZonedDateTime firstAnalyzedDate) {
|
||||||
|
this.firstAnalyzedDate = firstAnalyzedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastAnalyzedDate(ZonedDateTime lastAnalyzedDate) {
|
||||||
|
this.lastAnalyzedDate = lastAnalyzedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadata(List<MetadataLabel> metadata) {
|
||||||
|
this.metadata = List.copyOf(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusDescription(String statusDescription) {
|
||||||
|
this.statusDescription = statusDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CTCloudCostBean> getCost() {
|
||||||
|
return List.copyOf(cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCost(List<CTCloudCostBean> cost) {
|
||||||
|
this.cost = List.copyOf(cost);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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 com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata entry.
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class MetadataLabel {
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private final String value;
|
||||||
|
private final String extendedInfo;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public MetadataLabel(
|
||||||
|
@JsonProperty("key") String key,
|
||||||
|
@JsonProperty("value") String value,
|
||||||
|
@JsonProperty("info") String extendedInfo
|
||||||
|
) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
this.extendedInfo = extendedInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtendedInfo() {
|
||||||
|
return extendedInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util;
|
||||||
|
|
||||||
|
import com.license4j.HardwareID;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to generate license hostID and Target hostID for malware scan
|
||||||
|
*
|
||||||
|
* @author rishwanth
|
||||||
|
*/
|
||||||
|
public class CTHostIDGenerationUtil {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CTHostIDGenerationUtil.class.getName());
|
||||||
|
private static final String USER_NAME = System.getProperty("user.name");
|
||||||
|
private static String cachedId = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host ID Algorithm: Get MAC address from License4J. Get MD5 hash of it and
|
||||||
|
* grab the first 16 characters of the hash. Get user name that Cyber Triage
|
||||||
|
* is running as. MD5 hash of user name. Grab first 16 characters.
|
||||||
|
* Concatenate them and separate with underscore. Example:
|
||||||
|
* c84f70d1baf96420_7d7519bf21602c24
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String generateLicenseHostID() {
|
||||||
|
if (StringUtils.isBlank(cachedId)) {
|
||||||
|
try {
|
||||||
|
String hostName = StringUtils.defaultString(InetAddress.getLocalHost().getCanonicalHostName());
|
||||||
|
String macAddressMd5 = StringUtils.isNotBlank(HardwareID.getHardwareIDFromEthernetAddress())
|
||||||
|
? Md5HashUtil.getMD5MessageDigest(HardwareID.getHardwareIDFromEthernetAddress()).substring(0, 16)
|
||||||
|
: Md5HashUtil.getMD5MessageDigest(hostName).substring(0, 16);
|
||||||
|
|
||||||
|
String usernameMd5 = StringUtils.isNotBlank(USER_NAME)
|
||||||
|
? Md5HashUtil.getMD5MessageDigest(USER_NAME).substring(0, 16)
|
||||||
|
: Md5HashUtil.getMD5MessageDigest(hostName).substring(0, 16);
|
||||||
|
|
||||||
|
cachedId = macAddressMd5 + "_" + usernameMd5;
|
||||||
|
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "Unable to determine host name.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.BoostLicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the payload of boost license.
|
||||||
|
*/
|
||||||
|
public class LicenseDecryptorUtil {
|
||||||
|
|
||||||
|
private static final LicenseDecryptorUtil instance = new LicenseDecryptorUtil();
|
||||||
|
|
||||||
|
public static LicenseDecryptorUtil getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = ObjectMapperUtil.getInstance().getDefaultObjectMapper();
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
DecryptedLicenseResponse decrypted = parseLicenseJSON(licenseResponse.getBoostLicense());
|
||||||
|
return new LicenseInfo(licenseResponse, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a boost license response.
|
||||||
|
*
|
||||||
|
* @param licenseResponse The boost license response.
|
||||||
|
* @return The decrypted license response.
|
||||||
|
* @throws JsonProcessingException
|
||||||
|
* @throws
|
||||||
|
* com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException
|
||||||
|
*/
|
||||||
|
public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException {
|
||||||
|
|
||||||
|
String decryptedJsonResponse;
|
||||||
|
try {
|
||||||
|
decryptedJsonResponse = decryptLicenseString(
|
||||||
|
licenseResponse.getEncryptedJson(),
|
||||||
|
licenseResponse.getIv(),
|
||||||
|
licenseResponse.getEncryptedKey(),
|
||||||
|
licenseResponse.getVersion()
|
||||||
|
);
|
||||||
|
} catch (IOException | GeneralSecurityException ex) {
|
||||||
|
throw new InvalidLicenseException("An exception occurred while parsing the license string", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
DecryptedLicenseResponse decryptedLicense = objectMapper.readValue(decryptedJsonResponse, DecryptedLicenseResponse.class);
|
||||||
|
if (!"AUTOPSY".equalsIgnoreCase(decryptedLicense.getProduct())) {
|
||||||
|
// license file is expected to contain product of "CYBERTRIAGE"
|
||||||
|
throw new InvalidLicenseException("Not a valid Autopsy license");
|
||||||
|
}
|
||||||
|
|
||||||
|
return decryptedLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decryptLicenseString(String encryptedJson, String ivBase64, String encryptedKey, String version) throws IOException, GeneralSecurityException, InvalidLicenseException {
|
||||||
|
if (!"1.0".equals(version)) {
|
||||||
|
throw new InvalidLicenseException("Unexpected file version: " + version);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encryptedKeyBytes = Base64.getDecoder().decode(encryptedKey);
|
||||||
|
byte[] keyBytes = decryptKey(encryptedKeyBytes);
|
||||||
|
SecretKey key = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");
|
||||||
|
|
||||||
|
byte[] ivBytes = Base64.getDecoder().decode(ivBase64);
|
||||||
|
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||||
|
|
||||||
|
byte[] encryptedLicenseJsonBytes = Base64.getDecoder().decode(encryptedJson);
|
||||||
|
|
||||||
|
String algorithm = "AES/CBC/PKCS5Padding";
|
||||||
|
Cipher cipher = Cipher.getInstance(algorithm);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
||||||
|
byte[] licenseJsonBytes = cipher.doFinal(encryptedLicenseJsonBytes);
|
||||||
|
|
||||||
|
return new String(licenseJsonBytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey getPublicKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
String publicKeyString = """
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwIKulLyaLQ2WeO0gIW2G
|
||||||
|
3jQqny3Y/7VUevBKulAEywaUbvECvZ4zGsnaMyACjXxMNkA1xU2WeSMP/WqC03wz
|
||||||
|
4d71liUeAqOYKMdGHXFN2qswWz/ufK6An0pTEqYaoiUfcwSBVo2ZTUcMQexScKaS
|
||||||
|
ghmaWqBHBYx+lBkVMcLG2PtLDRZbqgJvJr2QCzMSVUpEGGQEWs7YolIq46KCgqsq
|
||||||
|
pTdfrdqd59x6oRhTLegswzxwLyouvrKbRqKR2ZRbVvlGtUnnnlLDuhEfd0flMxuv
|
||||||
|
W98Siw6dWe1K3x45nDu5py2G9Q9fZS8/2KHUC6QcLLstLIoPnZjCl9Lcur1U6s9N
|
||||||
|
f5aLI9mwMfmSJsoVOuwx2/MC98uHvPoPbG4ZjiT0aaGg4JccTGD6pssDA35zPhkk
|
||||||
|
1l6wktEYtyF2A7zjzuFxioQz8fHBzIbHPCxzu4S2gh3qOVFf7c9COmX9MsnB70o2
|
||||||
|
EZ1rxlFIJ7937IGJNwWOQuiMKTpEeT6BwTdQNZQPqCUGvZ5eEjhrm57yCF4zuyrt
|
||||||
|
AR8DG7ahK2YAarADHRyxTuxH1qY7E5/CTQKYk9tIYsV4O05CKj7B8rBMtjVNjb4b
|
||||||
|
d7JwPW43Z3J6jo/gLlVdGSPg8vQDNVLl6sdDM4Pm1eJEzgR2JlqXDCRDUGNNsXH2
|
||||||
|
qt9Ru8ykX7PAfF2Q3/qg1jkCAwEAAQ==
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
""";
|
||||||
|
|
||||||
|
publicKeyString = publicKeyString.replaceAll("-----BEGIN PUBLIC KEY-----", "").replaceAll("-----END PUBLIC KEY-----", "").replaceAll("\\s", "");
|
||||||
|
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
|
||||||
|
|
||||||
|
KeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||||
|
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] decryptKey(byte[] encryptedKeyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
||||||
|
|
||||||
|
PublicKey publicKey = getPublicKey();
|
||||||
|
|
||||||
|
Cipher decryptCipher = Cipher.getInstance("RSA");
|
||||||
|
decryptCipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||||
|
|
||||||
|
byte[] decryptedBytes = decryptCipher.doFinal(encryptedKeyBytes);
|
||||||
|
|
||||||
|
return decryptedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InvalidLicenseException extends Exception {
|
||||||
|
|
||||||
|
public InvalidLicenseException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidLicenseException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jayaram
|
||||||
|
*/
|
||||||
|
public class Md5HashUtil {
|
||||||
|
/**
|
||||||
|
* Returns MD5 hash value for the lower case value of the string provided.
|
||||||
|
* @param inp
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getMD5MessageDigest(String inp) {
|
||||||
|
if (StringUtils.isNotBlank(inp)) {
|
||||||
|
HashFunction hf = Hashing.md5(); // Using despite its deprecation as md5 is good enough for our uses.
|
||||||
|
HashCode hc = hf.newHasher()
|
||||||
|
.putString(inp.toLowerCase(), Charsets.UTF_8)
|
||||||
|
.hash();
|
||||||
|
return hc.toString();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JacksonException;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.DateTimeException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates default ObjectMapper
|
||||||
|
*/
|
||||||
|
public class ObjectMapperUtil {
|
||||||
|
|
||||||
|
private static final ObjectMapperUtil instance = new ObjectMapperUtil();
|
||||||
|
|
||||||
|
public static ObjectMapperUtil getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectMapperUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectMapper getDefaultObjectMapper() {
|
||||||
|
ObjectMapper defaultMapper = new ObjectMapper();
|
||||||
|
defaultMapper.registerModule(new JavaTimeModule());
|
||||||
|
return defaultMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UTCBaseZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
|
||||||
|
|
||||||
|
private final DateTimeFormatter formatter;
|
||||||
|
|
||||||
|
public UTCBaseZonedDateTimeDeserializer(DateTimeFormatter formatter) {
|
||||||
|
this.formatter = formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
|
||||||
|
String date = jp.getText();
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
LocalDateTime ldt = LocalDateTime.parse(date, formatter);
|
||||||
|
return ZonedDateTime.of(ldt, ZoneOffset.UTC);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ZonedDateTimeDeserializer extends UTCBaseZonedDateTimeDeserializer {
|
||||||
|
|
||||||
|
public ZonedDateTimeDeserializer() {
|
||||||
|
super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MDYDateDeserializer extends JsonDeserializer<ZonedDateTime> {
|
||||||
|
|
||||||
|
private final DateTimeFormatter formatter;
|
||||||
|
|
||||||
|
public MDYDateDeserializer() {
|
||||||
|
this.formatter = new DateTimeFormatterBuilder()
|
||||||
|
.parseCaseInsensitive()
|
||||||
|
.appendPattern("MMM d, [uuuu][uu]")
|
||||||
|
.toFormatter(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZonedDateTime deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
|
||||||
|
String date = jp.getText();
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
LocalDate ld = LocalDate.parse(date, formatter);
|
||||||
|
LocalDateTime ldt = ld.atStartOfDay();
|
||||||
|
return ZonedDateTime.of(ldt, ZoneOffset.UTC);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EpochTimeDeserializer<T> extends JsonDeserializer<T> {
|
||||||
|
|
||||||
|
private final Function<Long, T> timeDeserializer;
|
||||||
|
|
||||||
|
public EpochTimeDeserializer(Function<Long, T> timeDeserializer) {
|
||||||
|
this.timeDeserializer = timeDeserializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
|
||||||
|
JsonNode node = jp.getCodec().readTree(jp);
|
||||||
|
|
||||||
|
Long timeVal = null;
|
||||||
|
if (node.isNumber()) {
|
||||||
|
timeVal = node.asLong();
|
||||||
|
} else {
|
||||||
|
String nodeText = node.asText();
|
||||||
|
try {
|
||||||
|
timeVal = Long.parseLong(nodeText);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
// do nothing if can't parse as number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeVal != null) {
|
||||||
|
try {
|
||||||
|
return timeDeserializer.apply(timeVal);
|
||||||
|
} catch (DateTimeException ex) {
|
||||||
|
// do nothing if can't parse to epoch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InstantEpochMillisDeserializer extends EpochTimeDeserializer<Instant> {
|
||||||
|
|
||||||
|
public InstantEpochMillisDeserializer() {
|
||||||
|
super(InstantEpochMillisDeserializer::convert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Instant convert(Long longVal) {
|
||||||
|
try {
|
||||||
|
return Instant.ofEpochMilli(longVal);
|
||||||
|
} catch (DateTimeException ex) {
|
||||||
|
// do nothing if can't parse to epoch
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InstantEpochSecsDeserializer extends EpochTimeDeserializer<Instant> {
|
||||||
|
|
||||||
|
public InstantEpochSecsDeserializer() {
|
||||||
|
super(InstantEpochSecsDeserializer::convert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Instant convert(Long longVal) {
|
||||||
|
try {
|
||||||
|
return Instant.ofEpochSecond(longVal);
|
||||||
|
} catch (DateTimeException ex) {
|
||||||
|
// do nothing if can't parse to epoch
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
|
||||||
|
OptionsCategory_Name_CyberTriage=Cyber Triage
|
||||||
|
OptionsCategory_Keywords_CyberTriage=Cyber Triage,Cyber,Triage
|
||||||
|
LicenseDisclaimerPanel.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a non-free license to use.</html>
|
||||||
|
LicenseDisclaimerPanel.purchaseFromLabel.text=You can purchase a license from
|
||||||
|
LicenseDisclaimerPanel.link.text=<html><span style="color: blue; text-decoration: underline">https://cybertriage.com/autopsy-checkout</span></html>
|
||||||
|
LicenseDisclaimerPanel.border.title=Disclaimer
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
|
||||||
|
OptionsCategory_Name_CyberTriage=Cyber Triage
|
||||||
|
OptionsCategory_Keywords_CyberTriage=Cyber Triage,Cyber,Triage
|
||||||
|
LicenseDisclaimerPanel.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a non-free license to use.</html>
|
||||||
|
LicenseDisclaimerPanel.purchaseFromLabel.text=You can purchase a license from
|
||||||
|
LicenseDisclaimerPanel.link.text=<html><span style="color: blue; text-decoration: underline">https://cybertriage.com/autopsy-checkout</span></html>
|
||||||
|
LicenseDisclaimerPanel.border.title=Disclaimer
|
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,120,0,0,2,2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
|
<BorderConstraints direction="Center"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="contentPane">
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
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.ingest.IngestModuleGlobalSettingsPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options panel for Cyber Triage.
|
||||||
|
*/
|
||||||
|
public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel {
|
||||||
|
|
||||||
|
private static final int MAX_SUBPANEL_WIDTH = 650;
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CTOptionsPanel.class.getName());
|
||||||
|
|
||||||
|
private final List<CTOptionsSubPanel> subPanels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form CTOptions loading any CTOptionsSubPanel instances to be
|
||||||
|
* displayed.
|
||||||
|
*/
|
||||||
|
public CTOptionsPanel() {
|
||||||
|
initComponents();
|
||||||
|
Collection<? extends CTOptionsSubPanel> coll = Lookup.getDefault().lookupAll(CTOptionsSubPanel.class);
|
||||||
|
Stream<? extends CTOptionsSubPanel> panelStream = coll != null ? coll.stream() : Stream.empty();
|
||||||
|
this.subPanels = panelStream
|
||||||
|
.map(panel -> {
|
||||||
|
try {
|
||||||
|
// lookup is returning singleton instances which means this panel gets messed up when accessed
|
||||||
|
// from multiple places because the panel's children are being added to a different CTOptionsPanel
|
||||||
|
return (CTOptionsSubPanel) panel.getClass().getConstructor().newInstance();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(item -> item != null)
|
||||||
|
.sorted(Comparator.comparing(p -> p.getClass().getSimpleName().toUpperCase()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
addSubOptionsPanels(new LicenseDisclaimerPanel(), this.subPanels);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSubOptionsPanels(JPanel disclaimerPanel, List<CTOptionsSubPanel> subPanels) {
|
||||||
|
GridBagConstraints disclaimerConstraints = new GridBagConstraints();
|
||||||
|
disclaimerConstraints.gridx = 0;
|
||||||
|
disclaimerConstraints.gridy = 0;
|
||||||
|
disclaimerConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
disclaimerConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
disclaimerConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
disclaimerConstraints.weighty = 0;
|
||||||
|
disclaimerConstraints.weightx = 0;
|
||||||
|
|
||||||
|
contentPane.add(disclaimerPanel, disclaimerConstraints);
|
||||||
|
|
||||||
|
for (int i = 0; i < subPanels.size(); i++) {
|
||||||
|
CTOptionsSubPanel subPanel = subPanels.get(i);
|
||||||
|
|
||||||
|
subPanel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||||
|
CTOptionsPanel.this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = i + 1;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
gridBagConstraints.weighty = 0;
|
||||||
|
gridBagConstraints.weightx = 0;
|
||||||
|
|
||||||
|
contentPane.add(subPanel, gridBagConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
GridBagConstraints verticalConstraints = new GridBagConstraints();
|
||||||
|
verticalConstraints.gridx = 0;
|
||||||
|
verticalConstraints.gridy = subPanels.size() + 1;
|
||||||
|
verticalConstraints.weighty = 1;
|
||||||
|
verticalConstraints.weightx = 0;
|
||||||
|
|
||||||
|
JPanel verticalSpacer = new JPanel();
|
||||||
|
|
||||||
|
verticalSpacer.setMinimumSize(new Dimension(MAX_SUBPANEL_WIDTH, 0));
|
||||||
|
verticalSpacer.setPreferredSize(new Dimension(MAX_SUBPANEL_WIDTH, 0));
|
||||||
|
verticalSpacer.setMaximumSize(new Dimension(MAX_SUBPANEL_WIDTH, Short.MAX_VALUE));
|
||||||
|
contentPane.add(verticalSpacer, verticalConstraints);
|
||||||
|
|
||||||
|
GridBagConstraints horizontalConstraints = new GridBagConstraints();
|
||||||
|
horizontalConstraints.gridx = 1;
|
||||||
|
horizontalConstraints.gridy = 0;
|
||||||
|
horizontalConstraints.weighty = 0;
|
||||||
|
horizontalConstraints.weightx = 1;
|
||||||
|
|
||||||
|
JPanel horizontalSpacer = new JPanel();
|
||||||
|
contentPane.add(horizontalSpacer, horizontalConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane();
|
||||||
|
contentPane = new javax.swing.JPanel();
|
||||||
|
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
|
contentPane.setLayout(new java.awt.GridBagLayout());
|
||||||
|
scrollPane.setViewportView(contentPane);
|
||||||
|
|
||||||
|
add(scrollPane, java.awt.BorderLayout.CENTER);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveSettings() {
|
||||||
|
subPanels.forEach(panel -> panel.saveSettings());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadSavedSettings() {
|
||||||
|
subPanels.forEach(panel -> panel.loadSettings());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean valid() {
|
||||||
|
return subPanels.stream().allMatch(panel -> panel.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JPanel contentPane;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.beans.PropertyChangeSupport;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import org.netbeans.spi.options.OptionsPanelController;
|
||||||
|
import org.openide.util.HelpCtx;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options panel controller for CyberTriage.
|
||||||
|
*/
|
||||||
|
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_CyberTriage",
|
||||||
|
iconBase = "com/basistech/df/cybertriage/autopsy/images/logo.png",
|
||||||
|
position = 999999,
|
||||||
|
keywords = "#OptionsCategory_Keywords_CyberTriage",
|
||||||
|
keywordsCategory = "CyberTriage")
|
||||||
|
public final class CTOptionsPanelController extends OptionsPanelController {
|
||||||
|
|
||||||
|
private CTOptionsPanel panel;
|
||||||
|
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||||
|
private boolean changed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component should load its data here.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
getPanel().loadSavedSettings();
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when both the Ok and Apply buttons are pressed. It
|
||||||
|
* applies to any of the panels that have been opened in the process of
|
||||||
|
* using the options pane.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void applyChanges() {
|
||||||
|
if (changed) {
|
||||||
|
getPanel().saveSettings();
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the Cancel button is pressed. It applies to
|
||||||
|
* any of the panels that have been opened in the process of using the
|
||||||
|
* options pane.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return getPanel().valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to determine whether any changes have been made to this controller's
|
||||||
|
* panel.
|
||||||
|
*
|
||||||
|
* @return Whether or not a change has been made.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isChanged() {
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HelpCtx getHelpCtx() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getComponent(Lookup masterLookup) {
|
||||||
|
return getPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||||
|
pcs.addPropertyChangeListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||||
|
pcs.removePropertyChangeListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CTOptionsPanel getPanel() {
|
||||||
|
if (panel == null) {
|
||||||
|
panel = new CTOptionsPanel();
|
||||||
|
panel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||||
|
changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void changed() {
|
||||||
|
if (!changed) {
|
||||||
|
changed = true;
|
||||||
|
pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
|
||||||
|
}
|
||||||
|
pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||||
|
<TitledBorder title="Disclaimer">
|
||||||
|
<ResourceString PropertyName="titleX" bundle="com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties" key="LicenseDisclaimerPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</TitledBorder>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[2147483647, 90]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[562, 90]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[400, 90]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,90,0,0,2,50"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="disclaimer">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties" key="LicenseDisclaimerPanel.disclaimer.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="verticalAlignment" type="int" value="1"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="purchaseFromLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties" key="LicenseDisclaimerPanel.purchaseFromLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="-1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="3" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="link">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties" key="LicenseDisclaimerPanel.link.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||||
|
<Color id="Hand Cursor"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="linkMouseClicked"/>
|
||||||
|
</Events>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="-1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="spacer">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions;
|
||||||
|
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disclaimer for license and place to purchase CT license.
|
||||||
|
*/
|
||||||
|
public class LicenseDisclaimerPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(LicenseDisclaimerPanel.class.getName());
|
||||||
|
|
||||||
|
private static final String CHECKOUT_PAGE_URL = "https://cybertriage.com/autopsy-checkout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form LicenseDisclaimerPanel
|
||||||
|
*/
|
||||||
|
public LicenseDisclaimerPanel() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
|
||||||
|
javax.swing.JLabel disclaimer = new javax.swing.JLabel();
|
||||||
|
javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel();
|
||||||
|
javax.swing.JLabel link = new javax.swing.JLabel();
|
||||||
|
javax.swing.JPanel spacer = new javax.swing.JPanel();
|
||||||
|
|
||||||
|
setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.border.title"))); // NOI18N
|
||||||
|
setMaximumSize(new java.awt.Dimension(2147483647, 90));
|
||||||
|
setMinimumSize(new java.awt.Dimension(562, 90));
|
||||||
|
setPreferredSize(new java.awt.Dimension(400, 90));
|
||||||
|
setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(disclaimer, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.disclaimer.text")); // NOI18N
|
||||||
|
disclaimer.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridwidth = 2;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
add(disclaimer, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.purchaseFromLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 3);
|
||||||
|
add(purchaseFromLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(link, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.link.text")); // NOI18N
|
||||||
|
link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
|
||||||
|
link.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||||
|
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||||
|
linkMouseClicked(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||||
|
add(link, gridBagConstraints);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout spacerLayout = new javax.swing.GroupLayout(spacer);
|
||||||
|
spacer.setLayout(spacerLayout);
|
||||||
|
spacerLayout.setHorizontalGroup(
|
||||||
|
spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
spacerLayout.setVerticalGroup(
|
||||||
|
spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.weighty = 1.0;
|
||||||
|
add(spacer, gridBagConstraints);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void linkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_linkMouseClicked
|
||||||
|
if (Desktop.isDesktopSupported()) {
|
||||||
|
try {
|
||||||
|
Desktop.getDesktop().browse(new URI(CHECKOUT_PAGE_URL));
|
||||||
|
} catch (IOException | URISyntaxException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Error opening link to: " + CHECKOUT_PAGE_URL, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGGER.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened.");
|
||||||
|
}
|
||||||
|
}//GEN-LAST:event_linkMouseClicked
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
|
||||||
|
|
||||||
|
CTLicenseDialog.title=Add a License...
|
||||||
|
CTLicenseDialog.licenseNumberLabel.text=License Number:
|
||||||
|
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
CTLicenseDialog.cancelButton.text=Cancel
|
||||||
|
CTLicenseDialog.okButton.text=Ok
|
||||||
|
CTLicenseDialog.warningLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.countersResetLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title=License Info
|
||||||
|
CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scans
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=
|
||||||
|
EULADialog.cancelButton.text=Cancel
|
||||||
|
EULADialog.acceptButton.text=Accept
|
||||||
|
EULADialog.title=Cyber Triage End User License Agreement
|
@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
|
||||||
|
|
||||||
|
CTLicenseDialog.title=Add a License...
|
||||||
|
CTLicenseDialog.licenseNumberLabel.text=License Number:
|
||||||
|
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||||
|
CTLicenseDialog.cancelButton.text=Cancel
|
||||||
|
CTLicenseDialog.okButton.text=Ok
|
||||||
|
CTLicenseDialog.warningLabel.text=
|
||||||
|
CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>
|
||||||
|
CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.countersResetLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title=License Info
|
||||||
|
CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scans
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=
|
||||||
|
CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number:
|
||||||
|
CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License...
|
||||||
|
CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered
|
||||||
|
CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Already Entered
|
||||||
|
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
|
||||||
|
CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.
|
||||||
|
CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error
|
||||||
|
# {0} - expiresDate
|
||||||
|
CTMalwareScannerOptionsPanel_licenseInfo_expires=Expires: {0}
|
||||||
|
# {0} - idNumber
|
||||||
|
CTMalwareScannerOptionsPanel_licenseInfo_id=ID: {0}
|
||||||
|
# {0} - userName
|
||||||
|
# {1} - email
|
||||||
|
CTMalwareScannerOptionsPanel_licenseInfo_userInfo=<html>User: {0}<br/>Email: {1}</html>
|
||||||
|
# {0} - countersResetDate
|
||||||
|
CTMalwareScannerOptionsPanel_malwareScans_countersReset=Counters reset: {0}
|
||||||
|
# {0} - fileUploadsRemaining
|
||||||
|
CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining=File uploads remaining: {0}
|
||||||
|
# {0} - hashLookupsRemaining
|
||||||
|
CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining=Hash lookups remaining: {0}
|
||||||
|
# {0} - maxDailyFileLookups
|
||||||
|
CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day
|
||||||
|
# {0} - maxDailyLookups
|
||||||
|
CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day
|
||||||
|
CTMalwareScannerOptionsPanel_MalwareScansFetcher_apiErr_title=Server Error
|
||||||
|
CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_desc=A general error occurred while fetching malware scans information. Please try again later.
|
||||||
|
CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_title=General Error
|
||||||
|
CTOPtionsPanel_loadLicenseInfo_loading=Loading...
|
||||||
|
CTOPtionsPanel_loadMalwareScansInfo_loading=Loading...
|
||||||
|
EULADialog.cancelButton.text=Cancel
|
||||||
|
EULADialog.acceptButton.text=Accept
|
||||||
|
EULADialog.title=Cyber Triage End User License Agreement
|
@ -0,0 +1,138 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||||
|
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties" key="CTLicenseDialog.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="alwaysOnTop" type="boolean" value="true"/>
|
||||||
|
<Property name="resizable" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,122,0,0,1,-19"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="licenseNumberLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.licenseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="warningLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="java.awt.Color.RED" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.warningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[419, 36]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[419, 36]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[419, 36]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="buttonPadding">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JButton" name="okButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="cancelButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JTextField" name="licenseNumberTextField">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.licenseNumberTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions.ctcloud;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* License dialog
|
||||||
|
*/
|
||||||
|
public class CTLicenseDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
|
private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$");
|
||||||
|
private String licenseString = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form CTLicenseDialog
|
||||||
|
*/
|
||||||
|
public CTLicenseDialog(java.awt.Frame parent, boolean modal) {
|
||||||
|
super(parent, modal);
|
||||||
|
initComponents();
|
||||||
|
this.licenseNumberTextField.getDocument().putProperty("filterNewlines", Boolean.TRUE);
|
||||||
|
this.licenseNumberTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
verifyInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
verifyInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
verifyInput();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
String getValue() {
|
||||||
|
return licenseString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>"
|
||||||
|
})
|
||||||
|
private void verifyInput() {
|
||||||
|
String licenseInput = StringUtils.defaultString(this.licenseNumberTextField.getText());
|
||||||
|
if (LICENSE_PATTERN.matcher(licenseInput).matches()) {
|
||||||
|
this.warningLabel.setText("");
|
||||||
|
this.okButton.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
this.warningLabel.setText(Bundle.CTLicenseDialog_verifyInput_licenseNumberError());
|
||||||
|
this.okButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
|
||||||
|
javax.swing.JLabel licenseNumberLabel = new javax.swing.JLabel();
|
||||||
|
warningLabel = new javax.swing.JLabel();
|
||||||
|
javax.swing.JPanel buttonPadding = new javax.swing.JPanel();
|
||||||
|
okButton = new javax.swing.JButton();
|
||||||
|
cancelButton = new javax.swing.JButton();
|
||||||
|
licenseNumberTextField = new javax.swing.JTextField();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
setTitle(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.title")); // NOI18N
|
||||||
|
setAlwaysOnTop(true);
|
||||||
|
setResizable(false);
|
||||||
|
getContentPane().setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseNumberLabel, org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridwidth = 3;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
getContentPane().add(licenseNumberLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
warningLabel.setForeground(java.awt.Color.RED);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.warningLabel.text")); // NOI18N
|
||||||
|
warningLabel.setMaximumSize(new java.awt.Dimension(419, 36));
|
||||||
|
warningLabel.setMinimumSize(new java.awt.Dimension(419, 36));
|
||||||
|
warningLabel.setPreferredSize(new java.awt.Dimension(419, 36));
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.gridwidth = 3;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
getContentPane().add(warningLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout buttonPaddingLayout = new javax.swing.GroupLayout(buttonPadding);
|
||||||
|
buttonPadding.setLayout(buttonPaddingLayout);
|
||||||
|
buttonPaddingLayout.setHorizontalGroup(
|
||||||
|
buttonPaddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
buttonPaddingLayout.setVerticalGroup(
|
||||||
|
buttonPaddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 3;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
getContentPane().add(buttonPadding, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.okButton.text")); // NOI18N
|
||||||
|
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
okButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 2;
|
||||||
|
gridBagConstraints.gridy = 3;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
getContentPane().add(okButton, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.cancelButton.text")); // NOI18N
|
||||||
|
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cancelButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 1;
|
||||||
|
gridBagConstraints.gridy = 3;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
getContentPane().add(cancelButton, gridBagConstraints);
|
||||||
|
|
||||||
|
licenseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.gridwidth = 3;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
getContentPane().add(licenseNumberTextField, gridBagConstraints);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||||
|
this.licenseString = this.licenseNumberTextField.getText();
|
||||||
|
this.dispose();
|
||||||
|
}//GEN-LAST:event_okButtonActionPerformed
|
||||||
|
|
||||||
|
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||||
|
this.licenseString = null;
|
||||||
|
this.dispose();
|
||||||
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JButton cancelButton;
|
||||||
|
private javax.swing.JTextField licenseNumberTextField;
|
||||||
|
private javax.swing.JButton okButton;
|
||||||
|
private javax.swing.JLabel warningLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions.ctcloud;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles persisting CT Settings.
|
||||||
|
*/
|
||||||
|
public class CTLicensePersistence {
|
||||||
|
|
||||||
|
private static final String CT_SETTINGS_DIR = "CyberTriage";
|
||||||
|
private static final String CT_LICENSE_FILENAME = "CyberTriageLicense.json";
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CTLicensePersistence.class.getName());
|
||||||
|
|
||||||
|
private static final CTLicensePersistence instance = new CTLicensePersistence();
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = ObjectMapperUtil.getInstance().getDefaultObjectMapper();
|
||||||
|
|
||||||
|
public static CTLicensePersistence getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean saveLicenseResponse(LicenseResponse licenseResponse) {
|
||||||
|
if (licenseResponse != null) {
|
||||||
|
File licenseFile = getCTLicenseFile();
|
||||||
|
try {
|
||||||
|
licenseFile.getParentFile().mkdirs();
|
||||||
|
objectMapper.writeValue(licenseFile, licenseResponse);
|
||||||
|
return true;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "There was an error writing CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Optional<LicenseResponse> loadLicenseResponse() {
|
||||||
|
Optional<LicenseResponse> toRet = Optional.empty();
|
||||||
|
File licenseFile = getCTLicenseFile();
|
||||||
|
if (licenseFile.exists() && licenseFile.isFile()) {
|
||||||
|
try {
|
||||||
|
toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "There was an error reading CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Optional<LicenseInfo> loadLicenseInfo() {
|
||||||
|
return loadLicenseResponse().flatMap((license) -> {
|
||||||
|
try {
|
||||||
|
return Optional.ofNullable(LicenseDecryptorUtil.getInstance().createLicenseInfo(license));
|
||||||
|
} catch (JsonProcessingException | LicenseDecryptorUtil.InvalidLicenseException ex) {
|
||||||
|
logger.log(Level.WARNING, "There was an error decrypting license data from license file", ex);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getCTLicenseFile() {
|
||||||
|
return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_LICENSE_FILENAME).toFile();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-109,0,0,1,-29"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="licenseInfoPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||||
|
<TitledBorder title="License Info">
|
||||||
|
<ResourceString PropertyName="titleX" bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</TitledBorder>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="licenseInfoMessageLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="licenseInfoUserLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="licenseInfoExpiresLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="licenseInfoIdLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="licenseInfoAddButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoAddButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="licenseInfoAddButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="malwareScansPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||||
|
<TitledBorder title="Malware Scans">
|
||||||
|
<ResourceString PropertyName="titleX" bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.malwareScansPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</TitledBorder>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="malwareScansMessageLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="maxHashLookupsLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="maxFileUploadsLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="countersResetLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.countersResetLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="hashLookupsRemainingLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="fileUploadsRemainingLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,604 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions.ctcloud;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Optional;
|
||||||
|
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;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.netbeans.spi.options.OptionsPanelController;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options panel to be displayed in the CTOptionsPanel for settings regarding
|
||||||
|
* Cyber Triage Malware Scanner settings and license setup.
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = CTOptionsSubPanel.class)
|
||||||
|
public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CTMalwareScannerOptionsPanel.class.getName());
|
||||||
|
|
||||||
|
private static final DateTimeFormatter LICENSE_EXPIRES_FORMAT = DateTimeFormatter
|
||||||
|
.ofPattern("MMMM d, YYYY")
|
||||||
|
.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.getInferredUserTimeZone()));
|
||||||
|
|
||||||
|
private final CTApiDAO ctApiDAO = CTApiDAO.getInstance();
|
||||||
|
private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance();
|
||||||
|
|
||||||
|
private volatile LicenseInfo licenseInfo = null;
|
||||||
|
private volatile String licenseInfoMessage = null;
|
||||||
|
private volatile LicenseFetcher licenseFetcher = null;
|
||||||
|
|
||||||
|
private volatile AuthTokenResponse authTokenResponse = null;
|
||||||
|
private volatile String authTokenMessage = null;
|
||||||
|
private volatile AuthTokenFetcher authTokenFetcher = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*/
|
||||||
|
public CTMalwareScannerOptionsPanel() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
this.addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentHidden(ComponentEvent e) {
|
||||||
|
synchronized (CTMalwareScannerOptionsPanel.this) {
|
||||||
|
if (CTMalwareScannerOptionsPanel.this.isLicenseAddRunning()) {
|
||||||
|
CTMalwareScannerOptionsPanel.this.licenseFetcher.cancel(true);
|
||||||
|
CTMalwareScannerOptionsPanel.this.licenseFetcher = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTMalwareScannerOptionsPanel.this.isMalwareScansRunning()) {
|
||||||
|
CTMalwareScannerOptionsPanel.this.authTokenFetcher.cancel(true);
|
||||||
|
CTMalwareScannerOptionsPanel.this.authTokenFetcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentShown(ComponentEvent e) {
|
||||||
|
synchronized (CTMalwareScannerOptionsPanel.this) {
|
||||||
|
if (CTMalwareScannerOptionsPanel.this.licenseInfo != null) {
|
||||||
|
loadMalwareScansInfo(CTMalwareScannerOptionsPanel.this.licenseInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void saveSettings() {
|
||||||
|
ctPersistence.saveLicenseResponse(getLicenseInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean valid() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void loadSettings() {
|
||||||
|
Optional<LicenseInfo> licenseInfoOpt = ctPersistence.loadLicenseInfo();
|
||||||
|
LicenseInfo licenseInfo = licenseInfoOpt.orElse(null);
|
||||||
|
setLicenseDisplay(licenseInfo, null);
|
||||||
|
setMalwareScansDisplay(null, null);
|
||||||
|
if (licenseInfo != null) {
|
||||||
|
loadMalwareScansInfo(licenseInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized LicenseResponse getLicenseInfo() {
|
||||||
|
return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) {
|
||||||
|
this.licenseInfo = licenseInfo;
|
||||||
|
this.licenseInfoMessage = licenseMessage;
|
||||||
|
renderLicenseState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void setMalwareScansDisplay(AuthTokenResponse authTokenResponse, String authTokenMessage) {
|
||||||
|
this.authTokenResponse = authTokenResponse;
|
||||||
|
this.authTokenMessage = authTokenMessage;
|
||||||
|
renderLicenseState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if there is an operation to fetch the license.
|
||||||
|
*/
|
||||||
|
private synchronized boolean isLicenseAddRunning() {
|
||||||
|
return this.licenseFetcher != null && !this.licenseFetcher.isCancelled() && !this.licenseFetcher.isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if there is an operation to fetch malware scans information.
|
||||||
|
*/
|
||||||
|
private synchronized boolean isMalwareScansRunning() {
|
||||||
|
return this.authTokenFetcher != null && !this.authTokenFetcher.isCancelled() && !this.authTokenFetcher.isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"CTOPtionsPanel_loadLicenseInfo_loading=Loading..."
|
||||||
|
})
|
||||||
|
private synchronized void loadLicenseInfo(String licenseNumber) {
|
||||||
|
if (isLicenseAddRunning()) {
|
||||||
|
this.licenseFetcher.cancel(true);
|
||||||
|
}
|
||||||
|
setLicenseDisplay(null, Bundle.CTOPtionsPanel_loadLicenseInfo_loading());
|
||||||
|
setMalwareScansDisplay(null, null);
|
||||||
|
this.licenseFetcher = new LicenseFetcher(licenseNumber);
|
||||||
|
this.licenseFetcher.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"CTOPtionsPanel_loadMalwareScansInfo_loading=Loading..."
|
||||||
|
})
|
||||||
|
private synchronized void loadMalwareScansInfo(LicenseInfo licenseInfo) {
|
||||||
|
if (isMalwareScansRunning()) {
|
||||||
|
this.authTokenFetcher.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (licenseInfo == null || licenseInfo.getDecryptedLicense() == null) {
|
||||||
|
setMalwareScansDisplay(null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMalwareScansDisplay(null, Bundle.CTOPtionsPanel_loadMalwareScansInfo_loading());
|
||||||
|
|
||||||
|
this.authTokenFetcher = new AuthTokenFetcher(licenseInfo.getDecryptedLicense());
|
||||||
|
this.authTokenFetcher.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
|
||||||
|
javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel();
|
||||||
|
licenseInfoMessageLabel = new javax.swing.JLabel();
|
||||||
|
licenseInfoUserLabel = new javax.swing.JLabel();
|
||||||
|
licenseInfoExpiresLabel = new javax.swing.JLabel();
|
||||||
|
licenseInfoIdLabel = new javax.swing.JLabel();
|
||||||
|
licenseInfoAddButton = new javax.swing.JButton();
|
||||||
|
malwareScansPanel = new javax.swing.JPanel();
|
||||||
|
malwareScansMessageLabel = new javax.swing.JLabel();
|
||||||
|
maxHashLookupsLabel = new javax.swing.JLabel();
|
||||||
|
maxFileUploadsLabel = new javax.swing.JLabel();
|
||||||
|
countersResetLabel = new javax.swing.JLabel();
|
||||||
|
hashLookupsRemainingLabel = new javax.swing.JLabel();
|
||||||
|
fileUploadsRemainingLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
|
setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N
|
||||||
|
licenseInfoPanel.setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridwidth = 2;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
licenseInfoPanel.add(licenseInfoMessageLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoUserLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
licenseInfoPanel.add(licenseInfoUserLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoExpiresLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.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, 5, 5, 5);
|
||||||
|
licenseInfoPanel.add(licenseInfoExpiresLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoIdLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
licenseInfoPanel.add(licenseInfoIdLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoAddButton, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoAddButton.text")); // NOI18N
|
||||||
|
licenseInfoAddButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
licenseInfoAddButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 1;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
licenseInfoPanel.add(licenseInfoAddButton, gridBagConstraints);
|
||||||
|
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
add(licenseInfoPanel, gridBagConstraints);
|
||||||
|
|
||||||
|
malwareScansPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansPanel.border.title"))); // NOI18N
|
||||||
|
malwareScansPanel.setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(malwareScansMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridwidth = 2;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(malwareScansMessageLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(maxHashLookupsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(maxHashLookupsLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(maxFileUploadsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(maxFileUploadsLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(countersResetLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.countersResetLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 3;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(countersResetLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(hashLookupsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.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, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(hashLookupsRemainingLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(fileUploadsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text")); // NOI18N
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 1;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
malwareScansPanel.add(fileUploadsRemainingLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 2;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
add(malwareScansPanel, gridBagConstraints);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License...",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number:",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Already Entered",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_title=Invalid License Number",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_desc=Please verify that license number is of format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'"})
|
||||||
|
private void licenseInfoAddButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_licenseInfoAddButtonActionPerformed
|
||||||
|
CTLicenseDialog licenseDialog = new CTLicenseDialog(WindowManager.getDefault().getMainWindow(), true);
|
||||||
|
licenseDialog.setLocationRelativeTo(this);
|
||||||
|
licenseDialog.setVisible(true);
|
||||||
|
String licenseNumber = licenseDialog.getValue();
|
||||||
|
if (licenseNumber != null) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (this.licenseInfo == null || !licenseNumber.trim().equalsIgnoreCase(this.licenseInfo.getDecryptedLicense().getBoostLicenseId())) {
|
||||||
|
loadLicenseInfo(licenseNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
this,
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title(),
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}//GEN-LAST:event_licenseInfoAddButtonActionPerformed
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"# {0} - userName",
|
||||||
|
"# {1} - email",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseInfo_userInfo=<html>User: {0}<br/>Email: {1}</html>",
|
||||||
|
"# {0} - expiresDate",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseInfo_expires=Expires: {0}",
|
||||||
|
"# {0} - idNumber",
|
||||||
|
"CTMalwareScannerOptionsPanel_licenseInfo_id=ID: {0}",
|
||||||
|
"# {0} - maxDailyLookups",
|
||||||
|
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day",
|
||||||
|
"# {0} - maxDailyFileLookups",
|
||||||
|
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day",
|
||||||
|
"# {0} - countersResetDate",
|
||||||
|
"CTMalwareScannerOptionsPanel_malwareScans_countersReset=Counters reset: {0}",
|
||||||
|
"# {0} - hashLookupsRemaining",
|
||||||
|
"CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining=Hash lookups remaining: {0}",
|
||||||
|
"# {0} - fileUploadsRemaining",
|
||||||
|
"CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining=File uploads remaining: {0}"})
|
||||||
|
private synchronized void renderLicenseState() {
|
||||||
|
this.licenseInfoAddButton.setEnabled(!isLicenseAddRunning());
|
||||||
|
|
||||||
|
this.licenseInfoMessageLabel.setVisible(StringUtils.isNotBlank(this.licenseInfoMessage));
|
||||||
|
this.licenseInfoMessageLabel.setText(this.licenseInfoMessage);
|
||||||
|
|
||||||
|
if (licenseInfo == null) {
|
||||||
|
this.licenseInfoExpiresLabel.setVisible(false);
|
||||||
|
this.licenseInfoIdLabel.setVisible(false);
|
||||||
|
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.licenseInfoIdLabel.setVisible(true);
|
||||||
|
this.licenseInfoIdLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_id(StringUtils.defaultString(this.licenseInfo.getDecryptedLicense().getBoostLicenseId())));
|
||||||
|
this.licenseInfoUserLabel.setVisible(true);
|
||||||
|
this.licenseInfoUserLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_userInfo(
|
||||||
|
StringUtils.defaultString(this.licenseInfo.getDecryptedLicense().getCustomerName()),
|
||||||
|
StringUtils.defaultString(this.licenseInfo.getDecryptedLicense().getCustomerEmail())));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.malwareScansPanel.setVisible(StringUtils.isNotBlank(this.authTokenMessage) || authTokenResponse != null);
|
||||||
|
|
||||||
|
this.malwareScansMessageLabel.setVisible(StringUtils.isNotBlank(this.authTokenMessage));
|
||||||
|
this.malwareScansMessageLabel.setText(this.authTokenMessage);
|
||||||
|
|
||||||
|
if (authTokenResponse == null) {
|
||||||
|
this.maxHashLookupsLabel.setVisible(false);
|
||||||
|
this.maxFileUploadsLabel.setVisible(false);
|
||||||
|
this.countersResetLabel.setVisible(false);
|
||||||
|
this.hashLookupsRemainingLabel.setVisible(false);
|
||||||
|
this.fileUploadsRemainingLabel.setVisible(false);
|
||||||
|
} else {
|
||||||
|
this.maxHashLookupsLabel.setVisible(true);
|
||||||
|
this.maxHashLookupsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups(this.authTokenResponse.getHashLookupLimit()));
|
||||||
|
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.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);
|
||||||
|
this.fileUploadsRemainingLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining(remaining(this.authTokenResponse.getFileUploadLimit(), this.authTokenResponse.getFileUploadCount())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long remaining(Long total, Long used) {
|
||||||
|
total = total == null ? 0 : total;
|
||||||
|
used = used == null ? 0 : used;
|
||||||
|
return total - used;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acceptEula(LicenseResponse licenseResponse) {
|
||||||
|
try {
|
||||||
|
final EULADialog eulaDialog = new EULADialog(WindowManager.getDefault().getMainWindow(), true);
|
||||||
|
eulaDialog.setLocationRelativeTo(this);
|
||||||
|
eulaDialog.setSize(eulaDialog.getPreferredSize());
|
||||||
|
eulaDialog.setVisible(true);
|
||||||
|
|
||||||
|
if (eulaDialog.isAcceptPressed()) {
|
||||||
|
// only indicate a change to save if we have accepted EULA for a license
|
||||||
|
this.licenseInfo = LicenseDecryptorUtil.getInstance().createLicenseInfo(licenseResponse);
|
||||||
|
this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
|
}
|
||||||
|
} catch (IOException | InvalidLicenseException ex) {
|
||||||
|
logger.log(Level.WARNING, "An error occurred while fetching data", ex);
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
CTMalwareScannerOptionsPanel.this,
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
} finally {
|
||||||
|
setLicenseDisplay(this.licenseInfo, null);
|
||||||
|
loadMalwareScansInfo(this.licenseInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error",
|
||||||
|
"CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error",
|
||||||
|
"CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.",})
|
||||||
|
private class LicenseFetcher extends SwingWorker<LicenseResponse, Void> {
|
||||||
|
|
||||||
|
private final String licenseText;
|
||||||
|
|
||||||
|
public LicenseFetcher(String licenseText) {
|
||||||
|
this.licenseText = licenseText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LicenseResponse doInBackground() throws Exception {
|
||||||
|
if (this.isCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ctApiDAO.getLicenseInfo(licenseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
try {
|
||||||
|
LicenseResponse licenseResponse = get();
|
||||||
|
SwingUtilities.invokeLater(() -> acceptEula(licenseResponse));
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// ignore cancellation; just load current license
|
||||||
|
setLicenseDisplay(licenseInfo, null);
|
||||||
|
loadMalwareScansInfo(licenseInfo);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
if (ex.getCause() != null && ex.getCause() instanceof CTCloudException cloudEx) {
|
||||||
|
logger.log(Level.WARNING, "An API error occurred while fetching license information", cloudEx);
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
CTMalwareScannerOptionsPanel.this,
|
||||||
|
cloudEx.getErrorCode().getDescription(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, "An error occurred while fetching data", ex);
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
CTMalwareScannerOptionsPanel.this,
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
setLicenseDisplay(licenseInfo, null);
|
||||||
|
loadMalwareScansInfo(licenseInfo);
|
||||||
|
} finally {
|
||||||
|
synchronized (CTMalwareScannerOptionsPanel.this) {
|
||||||
|
CTMalwareScannerOptionsPanel.this.licenseFetcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"CTMalwareScannerOptionsPanel_MalwareScansFetcher_apiErr_title=Server Error",
|
||||||
|
"CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_title=General Error",
|
||||||
|
"CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_desc=A general error occurred while fetching malware scans information. Please try again later.",})
|
||||||
|
private class AuthTokenFetcher extends SwingWorker<AuthTokenResponse, Void> {
|
||||||
|
|
||||||
|
private final DecryptedLicenseResponse decryptedLicense;
|
||||||
|
|
||||||
|
public AuthTokenFetcher(DecryptedLicenseResponse decryptedLicense) {
|
||||||
|
this.decryptedLicense = decryptedLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthTokenResponse doInBackground() throws Exception {
|
||||||
|
if (this.isCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctApiDAO.getAuthToken(decryptedLicense);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
AuthTokenResponse authTokenResponse = null;
|
||||||
|
try {
|
||||||
|
authTokenResponse = get();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// ignore cancellation
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
if (ex.getCause() != null && ex.getCause() instanceof CTCloudException cloudEx) {
|
||||||
|
logger.log(Level.WARNING, "An API error occurred while fetching malware scans information for license", cloudEx);
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
CTMalwareScannerOptionsPanel.this,
|
||||||
|
cloudEx.getErrorDetails(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_MalwareScansFetcher_apiErr_title(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, "An error occurred while fetching data", ex);
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
CTMalwareScannerOptionsPanel.this,
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_desc(),
|
||||||
|
Bundle.CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_title(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized (CTMalwareScannerOptionsPanel.this) {
|
||||||
|
CTMalwareScannerOptionsPanel.this.authTokenFetcher = null;
|
||||||
|
if (!this.isCancelled()) {
|
||||||
|
setMalwareScansDisplay(authTokenResponse, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JLabel countersResetLabel;
|
||||||
|
private javax.swing.JLabel fileUploadsRemainingLabel;
|
||||||
|
private javax.swing.JLabel hashLookupsRemainingLabel;
|
||||||
|
private javax.swing.JButton licenseInfoAddButton;
|
||||||
|
private javax.swing.JLabel licenseInfoExpiresLabel;
|
||||||
|
private javax.swing.JLabel licenseInfoIdLabel;
|
||||||
|
private javax.swing.JLabel licenseInfoMessageLabel;
|
||||||
|
private javax.swing.JLabel licenseInfoUserLabel;
|
||||||
|
private javax.swing.JLabel malwareScansMessageLabel;
|
||||||
|
private javax.swing.JPanel malwareScansPanel;
|
||||||
|
private javax.swing.JLabel maxFileUploadsLabel;
|
||||||
|
private javax.swing.JLabel maxHashLookupsLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||||
|
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="EULADialog.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 32767]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[550, 550]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="size" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[550, 550]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,40,0,0,2,41"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="viewablePanel">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="paddingPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 0]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JButton" name="acceptButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="EULADialog.acceptButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="enabled" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="acceptButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="cancelButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="EULADialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions.ctcloud;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.concurrent.Worker.State;
|
||||||
|
import javafx.embed.swing.JFXPanel;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.web.WebView;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog for displaying the Cyber Triage EULA before the license is saved.
|
||||||
|
*/
|
||||||
|
public class EULADialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(EULADialog.class.getName());
|
||||||
|
private static final String EULA_RESOURCE = "EULA.htm";
|
||||||
|
|
||||||
|
private boolean acceptPressed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form EULADialog
|
||||||
|
*/
|
||||||
|
public EULADialog(java.awt.Frame parent, boolean modal) throws IOException {
|
||||||
|
super(parent, modal);
|
||||||
|
initComponents();
|
||||||
|
loadEULA();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAcceptPressed() {
|
||||||
|
return acceptPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadEULA() throws IOException {
|
||||||
|
InputStream eulaInputStream = EULADialog.class.getResourceAsStream(EULA_RESOURCE);
|
||||||
|
final String htmlString = IOUtils.toString(eulaInputStream, StandardCharsets.UTF_8);
|
||||||
|
final JFXPanel fxPanel = new JFXPanel();
|
||||||
|
this.viewablePanel.add(fxPanel, BorderLayout.CENTER);
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
WebView webView = new WebView();
|
||||||
|
webView.setMaxSize(Short.MAX_VALUE, Short.MAX_VALUE);
|
||||||
|
webView.setPrefSize(Short.MAX_VALUE, Short.MAX_VALUE);
|
||||||
|
webView.setMinSize(100, 100);
|
||||||
|
webView.getEngine().getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
|
||||||
|
if (newState == State.SUCCEEDED) {
|
||||||
|
SwingUtilities.invokeLater(() -> EULADialog.this.acceptButton.setEnabled(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
webView.getEngine().loadContent(htmlString, "text/html");
|
||||||
|
VBox root = new VBox(webView);
|
||||||
|
Scene scene = new Scene(root, Color.RED);
|
||||||
|
fxPanel.setScene(scene);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
|
||||||
|
viewablePanel = new javax.swing.JPanel();
|
||||||
|
javax.swing.JPanel paddingPanel = new javax.swing.JPanel();
|
||||||
|
acceptButton = new javax.swing.JButton();
|
||||||
|
javax.swing.JButton cancelButton = new javax.swing.JButton();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
setTitle(org.openide.util.NbBundle.getMessage(EULADialog.class, "EULADialog.title")); // NOI18N
|
||||||
|
setMaximumSize(new java.awt.Dimension(32767, 32767));
|
||||||
|
setPreferredSize(new java.awt.Dimension(550, 550));
|
||||||
|
setSize(new java.awt.Dimension(550, 550));
|
||||||
|
getContentPane().setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
|
viewablePanel.setLayout(new java.awt.BorderLayout());
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.gridwidth = 3;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.weighty = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||||
|
getContentPane().add(viewablePanel, gridBagConstraints);
|
||||||
|
|
||||||
|
paddingPanel.setMaximumSize(new java.awt.Dimension(32767, 0));
|
||||||
|
|
||||||
|
javax.swing.GroupLayout paddingPanelLayout = new javax.swing.GroupLayout(paddingPanel);
|
||||||
|
paddingPanel.setLayout(paddingPanelLayout);
|
||||||
|
paddingPanelLayout.setHorizontalGroup(
|
||||||
|
paddingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
paddingPanelLayout.setVerticalGroup(
|
||||||
|
paddingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
);
|
||||||
|
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
getContentPane().add(paddingPanel, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(acceptButton, org.openide.util.NbBundle.getMessage(EULADialog.class, "EULADialog.acceptButton.text")); // NOI18N
|
||||||
|
acceptButton.setEnabled(false);
|
||||||
|
acceptButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
acceptButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 2;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||||
|
getContentPane().add(acceptButton, gridBagConstraints);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(EULADialog.class, "EULADialog.cancelButton.text")); // NOI18N
|
||||||
|
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cancelButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 1;
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||||
|
getContentPane().add(cancelButton, gridBagConstraints);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void acceptButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_acceptButtonActionPerformed
|
||||||
|
acceptPressed = true;
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_acceptButtonActionPerformed
|
||||||
|
|
||||||
|
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JButton acceptButton;
|
||||||
|
private javax.swing.JPanel viewablePanel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.ctoptions.subpanel;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A panel to be put in the CyberTriage options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class CTOptionsSubPanel extends JPanel {
|
||||||
|
public abstract void loadSettings();
|
||||||
|
public abstract void saveSettings();
|
||||||
|
public abstract boolean valid();
|
||||||
|
}
|
BIN
Core/src/com/basistech/df/cybertriage/autopsy/images/logo.png
Normal file
BIN
Core/src/com/basistech/df/cybertriage/autopsy/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.malwarescan;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a batch when number of items reaches batchSize or flush. Processing
|
||||||
|
* blocks (and subsequently add and flush operations) until previous batch
|
||||||
|
* finishes.
|
||||||
|
*/
|
||||||
|
public class BatchProcessor<T> {
|
||||||
|
|
||||||
|
private ExecutorService processingExecutorService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private final BlockingQueue<T> batchingQueue;
|
||||||
|
private final int batchSize;
|
||||||
|
private final Consumer<List<T>> itemsConsumer;
|
||||||
|
private final long secondsTimeout;
|
||||||
|
|
||||||
|
public BatchProcessor(int batchSize, long secondsTimeout, Consumer<List<T>> itemsConsumer) {
|
||||||
|
this.batchingQueue = new LinkedBlockingQueue<>(batchSize);
|
||||||
|
this.batchSize = batchSize;
|
||||||
|
this.itemsConsumer = itemsConsumer;
|
||||||
|
this.secondsTimeout = secondsTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void add(T item) throws InterruptedException {
|
||||||
|
batchingQueue.add(item);
|
||||||
|
if (batchingQueue.size() >= batchSize) {
|
||||||
|
asyncProcessBatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void flushAndReset() throws InterruptedException {
|
||||||
|
// get any remaining
|
||||||
|
asyncProcessBatch();
|
||||||
|
|
||||||
|
// don't accept any new additions
|
||||||
|
processingExecutorService.shutdown();
|
||||||
|
|
||||||
|
// await termination
|
||||||
|
processingExecutorService.awaitTermination(secondsTimeout, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// get new (not shut down executor)
|
||||||
|
processingExecutorService = Executors.newSingleThreadExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void asyncProcessBatch() throws InterruptedException {
|
||||||
|
if (!batchingQueue.isEmpty()) {
|
||||||
|
final List<T> processingList = new ArrayList<>();
|
||||||
|
|
||||||
|
// transfer batching queue to processing queue
|
||||||
|
batchingQueue.drainTo(processingList);
|
||||||
|
|
||||||
|
// submit to be processed
|
||||||
|
processingExecutorService.submit(() -> itemsConsumer.accept(processingList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
MalwareScanIngestModule_malwareTypeDisplayName=Malware
|
||||||
|
# {0} - errorResponse
|
||||||
|
MalwareScanIngestModule_SharedProcessing_authTokenResponseError_desc=Received error: ''{0}'' when fetching the API authentication token for the license
|
||||||
|
MalwareScanIngestModule_SharedProcessing_authTokenResponseError_title=Authentication API error
|
||||||
|
MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO
|
||||||
|
MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES
|
||||||
|
MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted
|
||||||
|
MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title=Hash Lookups Exhausted
|
||||||
|
MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing
|
||||||
|
MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout
|
||||||
|
MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results
|
||||||
|
MalwareScanIngestModule_SharedProcessing_generalProcessingError_title=Hash Lookup Error
|
||||||
|
# {0} - errorResponse
|
||||||
|
MalwareScanIngestModule_SharedProcessing_repServicenResponseError_desc=Received error: ''{0}'' when fetching hash lookup results
|
||||||
|
MalwareScanIngestModule_SharedProcessing_repServicenResponseError_title=Lookup API error
|
||||||
|
MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out
|
||||||
|
MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout
|
||||||
|
# {0} - remainingLookups
|
||||||
|
MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc=This license only has {0} lookups remaining
|
||||||
|
MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low
|
||||||
|
MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled.
|
||||||
|
MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License
|
||||||
|
MalwareScanIngestModule_ShareProcessing_noRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled.
|
||||||
|
MalwareScanIngestModule_ShareProcessing_noRemaining_title=No remaining lookups
|
||||||
|
MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.
|
||||||
|
MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner
|
||||||
|
MalwareScanIngestModuleFactory_version=1.0.0
|
@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.malwarescan;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO;
|
||||||
|
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.LicenseInfo;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
import org.sleuthkit.autopsy.ingest.FileIngestModule;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModule;
|
||||||
|
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.AnalysisResult;
|
||||||
|
import org.sleuthkit.datamodel.Blackboard;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.HashUtility;
|
||||||
|
import org.sleuthkit.datamodel.HashUtility.HashResult;
|
||||||
|
import org.sleuthkit.datamodel.HashUtility.HashType;
|
||||||
|
import org.sleuthkit.datamodel.Score;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses CT cloud API to determine if file is malware
|
||||||
|
*/
|
||||||
|
public class MalwareScanIngestModule implements FileIngestModule {
|
||||||
|
|
||||||
|
private static final SharedProcessing sharedProcessing = new SharedProcessing();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||||
|
sharedProcessing.startUp(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(AbstractFile af) {
|
||||||
|
return sharedProcessing.process(af);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutDown() {
|
||||||
|
sharedProcessing.shutDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the bulk of processing for the ingest module and handles concurrent
|
||||||
|
* ingest modules adding files simultaneously.
|
||||||
|
*/
|
||||||
|
private static class SharedProcessing {
|
||||||
|
|
||||||
|
// batch size of 200 files max
|
||||||
|
private static final int BATCH_SIZE = 200;
|
||||||
|
// 1 day timeout for all API requests
|
||||||
|
private static final long FLUSH_SECS_TIMEOUT = 24 * 60 * 60;
|
||||||
|
|
||||||
|
//minimum lookups left before issuing warning
|
||||||
|
private static final long LOW_LOOKUPS_REMAINING = 250;
|
||||||
|
|
||||||
|
private static final Set<String> EXECUTABLE_MIME_TYPES = Stream.of(
|
||||||
|
"application/x-bat",//NON-NLS
|
||||||
|
"application/x-dosexec",//NON-NLS
|
||||||
|
"application/vnd.microsoft.portable-executable",//NON-NLS
|
||||||
|
"application/x-msdownload",//NON-NLS
|
||||||
|
"application/exe",//NON-NLS
|
||||||
|
"application/x-exe",//NON-NLS
|
||||||
|
"application/dos-exe",//NON-NLS
|
||||||
|
"vms/exe",//NON-NLS
|
||||||
|
"application/x-winexe",//NON-NLS
|
||||||
|
"application/msdos-windows",//NON-NLS
|
||||||
|
"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 Logger logger = Logger.getLogger(MalwareScanIngestModule.class.getName());
|
||||||
|
private final BatchProcessor<FileRecord> batchProcessor = new BatchProcessor<FileRecord>(BATCH_SIZE, FLUSH_SECS_TIMEOUT, this::handleBatch);
|
||||||
|
|
||||||
|
private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance();
|
||||||
|
private final CTApiDAO ctApiDAO = CTApiDAO.getInstance();
|
||||||
|
|
||||||
|
private RunState runState = null;
|
||||||
|
|
||||||
|
private SleuthkitCase tskCase = null;
|
||||||
|
private FileTypeDetector fileTypeDetector = null;
|
||||||
|
private LicenseInfo licenseInfo = null;
|
||||||
|
private BlackboardArtifact.Type malwareType = null;
|
||||||
|
private long dsId = 0;
|
||||||
|
private long ingestJobId = 0;
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low",
|
||||||
|
"# {0} - remainingLookups",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc=This license only has {0} lookups remaining",
|
||||||
|
"MalwareScanIngestModule_malwareTypeDisplayName=Malware",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled.",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_noRemaining_title=No remaining lookups",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_noRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled."
|
||||||
|
})
|
||||||
|
synchronized void startUp(IngestJobContext context) throws IngestModuleException {
|
||||||
|
// only run this code once per startup
|
||||||
|
if (runState == RunState.STARTED_UP || runState == RunState.DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// get saved license
|
||||||
|
Optional<LicenseInfo> licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo();
|
||||||
|
if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(),
|
||||||
|
null);
|
||||||
|
runState = RunState.DISABLED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfoOpt.get().getDecryptedLicense());
|
||||||
|
// syncronously fetch malware scans info
|
||||||
|
|
||||||
|
// determine lookups remaining
|
||||||
|
long lookupsRemaining = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount());
|
||||||
|
if (lookupsRemaining <= 0) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_noRemaining_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_noRemaining_desc(),
|
||||||
|
null);
|
||||||
|
runState = RunState.DISABLED;
|
||||||
|
return;
|
||||||
|
} else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc(lookupsRemaining),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup necessary variables for processing
|
||||||
|
tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||||
|
malwareType = tskCase.getBlackboard().getOrAddArtifactType(
|
||||||
|
MALWARE_TYPE_NAME,
|
||||||
|
Bundle.MalwareScanIngestModule_malwareTypeDisplayName(),
|
||||||
|
BlackboardArtifact.Category.ANALYSIS_RESULT);
|
||||||
|
fileTypeDetector = new FileTypeDetector();
|
||||||
|
dsId = context.getDataSource().getId();
|
||||||
|
ingestJobId = context.getJobId();
|
||||||
|
licenseInfo = licenseInfoOpt.get();
|
||||||
|
|
||||||
|
// set run state to initialized
|
||||||
|
runState = RunState.STARTED_UP;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
runState = RunState.DISABLED;
|
||||||
|
throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long remaining(Long limit, Long used) {
|
||||||
|
limit = limit == null ? 0 : limit;
|
||||||
|
used = used == null ? 0 : used;
|
||||||
|
return limit - used;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOrCalcHash(AbstractFile af) {
|
||||||
|
if (StringUtils.isNotBlank(af.getMd5Hash())) {
|
||||||
|
return af.getMd5Hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<HashResult> hashResults = HashUtility.calculateHashes(af, Collections.singletonList(HashType.MD5));
|
||||||
|
if (CollectionUtils.isNotEmpty(hashResults)) {
|
||||||
|
for (HashResult hashResult : hashResults) {
|
||||||
|
if (hashResult.getType() == HashType.MD5) {
|
||||||
|
return hashResult.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING,
|
||||||
|
MessageFormat.format("An error occurred while processing file name: {0} and obj id: {1}.",
|
||||||
|
af.getName(),
|
||||||
|
af.getId()),
|
||||||
|
ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout",
|
||||||
|
"MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out"
|
||||||
|
})
|
||||||
|
IngestModule.ProcessResult process(AbstractFile af) {
|
||||||
|
try {
|
||||||
|
if (runState == RunState.STARTED_UP
|
||||||
|
&& af.getKnown() != TskData.FileKnown.KNOWN
|
||||||
|
&& EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(fileTypeDetector.getMIMEType(af)).trim().toLowerCase())
|
||||||
|
&& CollectionUtils.isEmpty(af.getAnalysisResults(malwareType))) {
|
||||||
|
|
||||||
|
String md5 = getOrCalcHash(af);
|
||||||
|
if (StringUtils.isNotBlank(md5)) {
|
||||||
|
batchProcessor.add(new FileRecord(af.getId(), md5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ProcessResult.OK;
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
|
||||||
|
ex);
|
||||||
|
return IngestModule.ProcessResult.ERROR;
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_batchTimeout_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_ShareProcessing_batchTimeout_desc(),
|
||||||
|
ex);
|
||||||
|
return IngestModule.ProcessResult.ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_authTokenResponseError_title=Authentication API error",
|
||||||
|
"# {0} - errorResponse",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_authTokenResponseError_desc=Received error: ''{0}'' when fetching the API authentication token for the license",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_repServicenResponseError_title=Lookup API error",
|
||||||
|
"# {0} - errorResponse",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_repServicenResponseError_desc=Received error: ''{0}'' when fetching hash lookup results",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title=Hash Lookups Exhausted",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_generalProcessingError_title=Hash Lookup Error",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results",})
|
||||||
|
private void handleBatch(List<FileRecord> fileRecords) {
|
||||||
|
if (runState != RunState.STARTED_UP || fileRecords == null || fileRecords.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create mapping of md5 to corresponding object ids as well as just the list of md5's
|
||||||
|
Map<String, List<Long>> md5ToObjId = new HashMap<>();
|
||||||
|
|
||||||
|
for (FileRecord fr : fileRecords) {
|
||||||
|
if (fr == null || StringUtils.isBlank(fr.getMd5hash()) || fr.getObjId() <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sanitizedMd5 = sanitizedMd5(fr.getMd5hash());
|
||||||
|
md5ToObjId
|
||||||
|
.computeIfAbsent(sanitizedMd5, (k) -> new ArrayList<>())
|
||||||
|
.add(fr.getObjId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> md5Hashes = new ArrayList<>(md5ToObjId.keySet());
|
||||||
|
|
||||||
|
if (md5Hashes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// get an auth token with the license
|
||||||
|
AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense());
|
||||||
|
|
||||||
|
// make sure we are in bounds for the remaining scans
|
||||||
|
long remainingScans = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount());
|
||||||
|
if (remainingScans <= 0) {
|
||||||
|
runState = RunState.DISABLED;
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(),
|
||||||
|
null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// using auth token, get results
|
||||||
|
List<CTCloudBean> repResult = ctApiDAO.getReputationResults(
|
||||||
|
new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse),
|
||||||
|
md5Hashes
|
||||||
|
);
|
||||||
|
|
||||||
|
List<BlackboardArtifact> createdArtifacts = new ArrayList<>();
|
||||||
|
if (!CollectionUtils.isEmpty(repResult)) {
|
||||||
|
SleuthkitCase.CaseDbTransaction trans = null;
|
||||||
|
try {
|
||||||
|
trans = tskCase.beginTransaction();
|
||||||
|
for (CTCloudBean result : repResult) {
|
||||||
|
String sanitizedMd5 = sanitizedMd5(result.getMd5HashValue());
|
||||||
|
List<Long> objIds = md5ToObjId.remove(sanitizedMd5);
|
||||||
|
if (objIds == null || objIds.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Long objId : objIds) {
|
||||||
|
AnalysisResult res = createAnalysisResult(objId, result, trans);
|
||||||
|
if (res != null) {
|
||||||
|
createdArtifacts.add(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trans.commit();
|
||||||
|
trans = null;
|
||||||
|
} finally {
|
||||||
|
if (trans != null) {
|
||||||
|
trans.rollback();
|
||||||
|
createdArtifacts.clear();
|
||||||
|
trans = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(createdArtifacts)) {
|
||||||
|
tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
|
||||||
|
ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizedMd5(String orig) {
|
||||||
|
return StringUtils.defaultString(orig).trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO"
|
||||||
|
})
|
||||||
|
private AnalysisResult createAnalysisResult(Long objId, CTCloudBean cloudBean, SleuthkitCase.CaseDbTransaction trans) throws Blackboard.BlackboardException {
|
||||||
|
if (objId == null || cloudBean == null || cloudBean.getMalwareResult() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Score score = cloudBean.getMalwareResult().getCTScore() == null
|
||||||
|
? Score.SCORE_UNKNOWN
|
||||||
|
: cloudBean.getMalwareResult().getCTScore().getTskCore();
|
||||||
|
|
||||||
|
String conclusion = score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE
|
||||||
|
? Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes()
|
||||||
|
: Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No();
|
||||||
|
|
||||||
|
String justification = cloudBean.getMalwareResult().getStatusDescription();
|
||||||
|
|
||||||
|
return tskCase.getBlackboard().newAnalysisResult(
|
||||||
|
malwareType,
|
||||||
|
objId,
|
||||||
|
dsId,
|
||||||
|
score,
|
||||||
|
conclusion,
|
||||||
|
MALWARE_CONFIG,
|
||||||
|
justification,
|
||||||
|
Collections.emptyList(),
|
||||||
|
trans).getAnalysisResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout",
|
||||||
|
"MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing"
|
||||||
|
})
|
||||||
|
synchronized void shutDown() {
|
||||||
|
// if already shut down, return
|
||||||
|
if (runState == RunState.SHUT_DOWN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush any remaining items
|
||||||
|
try {
|
||||||
|
batchProcessor.flushAndReset();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
notifyWarning(
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_title(),
|
||||||
|
Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_desc(),
|
||||||
|
ex);
|
||||||
|
} finally {
|
||||||
|
// set state to shut down and clear any remaining
|
||||||
|
runState = RunState.SHUT_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyWarning(String title, String message, Exception ex) {
|
||||||
|
MessageNotifyUtil.Notify.warn(title, message);
|
||||||
|
logger.log(Level.WARNING, message, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum RunState {
|
||||||
|
STARTED_UP, DISABLED, SHUT_DOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileRecord {
|
||||||
|
|
||||||
|
private final long objId;
|
||||||
|
private final String md5hash;
|
||||||
|
|
||||||
|
FileRecord(long objId, String md5hash) {
|
||||||
|
this.objId = objId;
|
||||||
|
this.md5hash = md5hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getObjId() {
|
||||||
|
return objId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMd5hash() {
|
||||||
|
return md5hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.malwarescan;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctoptions.CTOptionsPanel;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.sleuthkit.autopsy.ingest.FileIngestModule;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for malware scan ingest modules.
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class)
|
||||||
|
@Messages({
|
||||||
|
"MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner",
|
||||||
|
"MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.",
|
||||||
|
"MalwareScanIngestModuleFactory_version=1.0.0"
|
||||||
|
})
|
||||||
|
public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The display name for the factory (static method).
|
||||||
|
*/
|
||||||
|
public static String getDisplayName() {
|
||||||
|
return Bundle.MalwareScanIngestModuleFactory_displayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModuleDisplayName() {
|
||||||
|
return MalwareScanIngestModuleFactory.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModuleDescription() {
|
||||||
|
return Bundle.MalwareScanIngestModuleFactory_description();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModuleVersionNumber() {
|
||||||
|
return Bundle.MalwareScanIngestModuleFactory_version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFileIngestModuleFactory() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) {
|
||||||
|
return new MalwareScanIngestModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasGlobalSettingsPanel() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() {
|
||||||
|
CTOptionsPanel optionsPanel = new CTOptionsPanel();
|
||||||
|
optionsPanel.loadSavedSettings();
|
||||||
|
return optionsPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@ -386,6 +387,30 @@ public final class UserPreferences {
|
|||||||
return viewPreferences.get(TIME_ZONE_FOR_DISPLAYS, TimeZone.GMT_ZONE.getID());
|
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) {
|
public static void setTimeZoneForDisplays(String timeZone) {
|
||||||
viewPreferences.put(TIME_ZONE_FOR_DISPLAYS, timeZone);
|
viewPreferences.put(TIME_ZONE_FOR_DISPLAYS, timeZone);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ ImageNode.createSheet.name.displayName=Name
|
|||||||
ImageNode.createSheet.name.desc=no description
|
ImageNode.createSheet.name.desc=no description
|
||||||
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\!
|
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\!
|
||||||
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\!
|
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\!
|
||||||
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n\nDetails: {0}
|
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n Is Autopsy or Cyber Triage already running?\n\nDetails: {0}
|
||||||
Installer.tskLibErr.err=Fatal Error\!
|
Installer.tskLibErr.err=Fatal Error\!
|
||||||
InterestingHits.interestingItems.text=INTERESTING ITEMS
|
InterestingHits.interestingItems.text=INTERESTING ITEMS
|
||||||
InterestingHits.displayName.text=Interesting Items
|
InterestingHits.displayName.text=Interesting Items
|
||||||
|
@ -315,7 +315,7 @@ ImageNode.createSheet.name.displayName=Name
|
|||||||
ImageNode.createSheet.name.desc=no description
|
ImageNode.createSheet.name.desc=no description
|
||||||
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\!
|
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\!
|
||||||
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\!
|
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\!
|
||||||
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n\nDetails: {0}
|
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n Is Autopsy or Cyber Triage already running?\n\nDetails: {0}
|
||||||
Installer.tskLibErr.err=Fatal Error\!
|
Installer.tskLibErr.err=Fatal Error\!
|
||||||
InterestingHits.interestingItems.text=INTERESTING ITEMS
|
InterestingHits.interestingItems.text=INTERESTING ITEMS
|
||||||
InterestingHits.displayName.text=Interesting Items
|
InterestingHits.displayName.text=Interesting Items
|
||||||
@ -418,6 +418,7 @@ ScoreContent_createSheet_filterType_displayName=Type
|
|||||||
ScoreContent_createSheet_name_desc=no description
|
ScoreContent_createSheet_name_desc=no description
|
||||||
ScoreContent_createSheet_name_displayName=Name
|
ScoreContent_createSheet_name_displayName=Name
|
||||||
ScoreContent_ScoreContentNode_name=Score
|
ScoreContent_ScoreContentNode_name=Score
|
||||||
|
ScoreContent_ScoreFileNode_type=File
|
||||||
ScoreContent_susFilter_text=Suspicious Items
|
ScoreContent_susFilter_text=Suspicious Items
|
||||||
SlackFileNode.getActions.viewInNewWin.text=View in New Window
|
SlackFileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
SlackFileNode.getActions.viewFileInDir.text=View File in Directory
|
SlackFileNode.getActions.viewFileInDir.text=View File in Directory
|
||||||
|
@ -70,8 +70,9 @@ public class Installer extends ModuleInstall {
|
|||||||
logger.log(Level.CONFIG, "Sleuth Kit Version: {0}", skVersion); //NON-NLS
|
logger.log(Level.CONFIG, "Sleuth Kit Version: {0}", skVersion); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception | UnsatisfiedLinkError e) {
|
||||||
logger.log(Level.SEVERE, "Error calling Sleuth Kit library (test call failed)", e); //NON-NLS
|
logger.log(Level.SEVERE, "Error calling Sleuth Kit library (test call failed)", e); //NON-NLS
|
||||||
|
logger.log(Level.SEVERE, "Is Autopsy or Cyber Triage already running?)", e); //NON-NLS
|
||||||
|
|
||||||
// Normal error box log handler won't be loaded yet, so show error here.
|
// Normal error box log handler won't be loaded yet, so show error here.
|
||||||
final Component parentComponent = null; // Use default window frame.
|
final Component parentComponent = null; // Use default window frame.
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.ingest;
|
package org.sleuthkit.autopsy.ingest;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.malwarescan.MalwareScanIngestModuleFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -33,7 +34,10 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.io.NbObjectInputStream;
|
import org.openide.util.io.NbObjectInputStream;
|
||||||
import org.openide.util.io.NbObjectOutputStream;
|
import org.openide.util.io.NbObjectOutputStream;
|
||||||
@ -54,6 +58,11 @@ public final class IngestJobSettings {
|
|||||||
private static final String LAST_FILE_INGEST_FILTER_PROPERTY = "Last_File_Ingest_Filter"; //NON-NLS
|
private static final String LAST_FILE_INGEST_FILTER_PROPERTY = "Last_File_Ingest_Filter"; //NON-NLS
|
||||||
private static final String MODULE_SETTINGS_FOLDER_NAME = "IngestSettings"; //NON-NLS
|
private static final String MODULE_SETTINGS_FOLDER_NAME = "IngestSettings"; //NON-NLS
|
||||||
|
|
||||||
|
private static final Set<String> DEFAULT_DISABLED_MODULES = Stream.of(
|
||||||
|
"Plaso",
|
||||||
|
MalwareScanIngestModuleFactory.getDisplayName()
|
||||||
|
).collect(Collectors.toSet());
|
||||||
|
|
||||||
private static final String MODULE_SETTINGS_FOLDER = Paths.get(
|
private static final String MODULE_SETTINGS_FOLDER = Paths.get(
|
||||||
Paths.get(PlatformUtil.getUserConfigDirectory()).relativize(Paths.get(PlatformUtil.getModuleConfigDirectory())).toString(),
|
Paths.get(PlatformUtil.getUserConfigDirectory()).relativize(Paths.get(PlatformUtil.getModuleConfigDirectory())).toString(),
|
||||||
MODULE_SETTINGS_FOLDER_NAME
|
MODULE_SETTINGS_FOLDER_NAME
|
||||||
@ -361,35 +370,34 @@ public final class IngestJobSettings {
|
|||||||
loadedModuleNames.add(moduleFactory.getModuleDisplayName());
|
loadedModuleNames.add(moduleFactory.getModuleDisplayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hard coding Plaso to be disabled by default. loadedModuleNames is
|
Set<String> defaultEnabledAndLoaded = new HashSet<>();
|
||||||
* passed below as the default list of enabled modules so briefly remove
|
Set<String> defaultDisabledAndLoaded = new HashSet<>();
|
||||||
* Plaso from loaded modules to get the list of enabled and disabled
|
for (String loadedModule: loadedModuleNames) {
|
||||||
* modules names. Then put Plaso back into loadedModulesNames to let the
|
if (DEFAULT_DISABLED_MODULES.contains(loadedModule)) {
|
||||||
* rest of the code continue as before.
|
defaultDisabledAndLoaded.add(loadedModule);
|
||||||
*/
|
} else {
|
||||||
final String plasoModuleName = "Plaso";
|
defaultEnabledAndLoaded.add(loadedModule);
|
||||||
boolean plasoLoaded = loadedModuleNames.contains(plasoModuleName);
|
}
|
||||||
if (plasoLoaded) {
|
|
||||||
loadedModuleNames.remove(plasoModuleName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the enabled/disabled ingest modules settings for this context. By
|
* Get the enabled/disabled ingest modules settings for this context. By
|
||||||
* default, all loaded modules except Plaso are enabled.
|
* default, all loaded modules except Plaso are enabled.
|
||||||
*/
|
*/
|
||||||
HashSet<String> enabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(loadedModuleNames));
|
HashSet<String> enabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.ENABLED_MODULES_PROPERTY, makeCsvList(defaultEnabledAndLoaded));
|
||||||
HashSet<String> disabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.DISABLED_MODULES_PROPERTY, plasoModuleName); //NON-NLS
|
HashSet<String> disabledModuleNames = getModulesNames(this.executionContext, IngestJobSettings.DISABLED_MODULES_PROPERTY, makeCsvList(defaultDisabledAndLoaded)); //NON-NLS
|
||||||
|
|
||||||
// If plaso was loaded, but appears in neither the enabled nor the
|
// double check to ensure all loaded modules are present in one of the lists in case more modules (in case settings didn't have a module)
|
||||||
// disabled list, add it to the disabled list.
|
for (String loadedModule : loadedModuleNames) {
|
||||||
if (!enabledModuleNames.contains(plasoModuleName) && !disabledModuleNames.contains(plasoModuleName)) {
|
// if neither enabled modules or disabled modules contains the loaded module, add it to the default location
|
||||||
disabledModuleNames.add(plasoModuleName);
|
if (!enabledModuleNames.contains(loadedModule) && !disabledModuleNames.contains(loadedModule)) {
|
||||||
|
if (DEFAULT_DISABLED_MODULES.contains(loadedModule)) {
|
||||||
|
disabledModuleNames.add(loadedModule);
|
||||||
|
} else {
|
||||||
|
enabledModuleNames.add(loadedModule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Put plaso back into loadedModuleNames
|
|
||||||
if (plasoLoaded) {
|
|
||||||
loadedModuleNames.add(plasoModuleName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.integrationtesting;
|
package org.sleuthkit.autopsy.integrationtesting;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.malwarescan.MalwareScanIngestModuleFactory;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
@ -46,7 +47,10 @@ public class ConfigurationModuleManager {
|
|||||||
private static final Logger logger = Logger.getLogger(ConfigurationModuleManager.class.getName());
|
private static final Logger logger = Logger.getLogger(ConfigurationModuleManager.class.getName());
|
||||||
|
|
||||||
private static final IngestJobSettings.IngestType DEFAULT_INGEST_FILTER_TYPE = IngestJobSettings.IngestType.ALL_MODULES;
|
private static final IngestJobSettings.IngestType DEFAULT_INGEST_FILTER_TYPE = IngestJobSettings.IngestType.ALL_MODULES;
|
||||||
private static final Set<String> DEFAULT_EXCLUDED_MODULES = Stream.of("Plaso").collect(Collectors.toSet());
|
private static final Set<String> DEFAULT_EXCLUDED_MODULES = Stream.of(
|
||||||
|
"Plaso",
|
||||||
|
MalwareScanIngestModuleFactory.getDisplayName()
|
||||||
|
).collect(Collectors.toSet());
|
||||||
private static final ConfigDeserializer configDeserializer = new ConfigDeserializer();
|
private static final ConfigDeserializer configDeserializer = new ConfigDeserializer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE ivy-module [
|
<!DOCTYPE ivy-module [
|
||||||
<!ENTITY javafx.version "17.0.7">
|
<!ENTITY javafx.version "17.0.7">
|
||||||
|
<!ENTITY jackson.version "2.15.2">
|
||||||
]>
|
]>
|
||||||
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
|
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
|
||||||
<info organisation="org.sleuthkit.autopsy" module="corelibs"/>
|
<info organisation="org.sleuthkit.autopsy" module="corelibs"/>
|
||||||
@ -87,7 +88,8 @@
|
|||||||
|
|
||||||
<dependency conf="autopsy_core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.4"/>
|
<dependency conf="autopsy_core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.4"/>
|
||||||
|
|
||||||
<dependency conf="autopsy_core->default" org="com.fasterxml.jackson.dataformat" name="jackson-dataformat-csv" rev="2.15.2"/>
|
<dependency conf="autopsy_core->default" org="com.fasterxml.jackson.dataformat" name="jackson-dataformat-csv" rev="&jackson.version;"/>
|
||||||
|
<dependency conf="autopsy_core->default" org="com.fasterxml.jackson.datatype" name="jackson-datatype-jsr310" rev="&jackson.version;"/>
|
||||||
|
|
||||||
<!-- better image resizing -->
|
<!-- better image resizing -->
|
||||||
<dependency conf="autopsy_core->default" org="org.imgscalr" name="imgscalr-lib" rev="4.2" />
|
<dependency conf="autopsy_core->default" org="org.imgscalr" name="imgscalr-lib" rev="4.2" />
|
||||||
@ -142,8 +144,8 @@
|
|||||||
|
|
||||||
<override org="com.google.code.gson" module="gson" rev="2.9.0"/>
|
<override org="com.google.code.gson" module="gson" rev="2.9.0"/>
|
||||||
<override org="com.google.guava" module="guava" rev="32.0.1-jre"/>
|
<override org="com.google.guava" module="guava" rev="32.0.1-jre"/>
|
||||||
<override org="com.fasterxml.jackson.core" module="jackson-databind" rev="2.15.2"/>
|
<override org="com.fasterxml.jackson.core" module="jackson-databind" rev="&jackson.version;"/>
|
||||||
<override org="com.fasterxml.jackson.core" module="jackson-core" rev="2.15.2"/>
|
<override org="com.fasterxml.jackson.core" module="jackson-core" rev="&jackson.version;"/>
|
||||||
|
|
||||||
<!-- changes to bouncy castle version may also be reflected in thirdparty/IcePDF 6.2.2 -->
|
<!-- changes to bouncy castle version may also be reflected in thirdparty/IcePDF 6.2.2 -->
|
||||||
<override org="org.bouncycastle" module="bcprov-jdk15on" rev="1.70"/>
|
<override org="org.bouncycastle" module="bcprov-jdk15on" rev="1.70"/>
|
||||||
|
@ -84,6 +84,7 @@ file.reference.jackson-annotations-2.15.2.jar=release/modules/ext/jackson-annota
|
|||||||
file.reference.jackson-core-2.15.2.jar=release/modules/ext/jackson-core-2.15.2.jar
|
file.reference.jackson-core-2.15.2.jar=release/modules/ext/jackson-core-2.15.2.jar
|
||||||
file.reference.jackson-databind-2.15.2.jar=release/modules/ext/jackson-databind-2.15.2.jar
|
file.reference.jackson-databind-2.15.2.jar=release/modules/ext/jackson-databind-2.15.2.jar
|
||||||
file.reference.jackson-dataformat-csv-2.15.2.jar=release/modules/ext/jackson-dataformat-csv-2.15.2.jar
|
file.reference.jackson-dataformat-csv-2.15.2.jar=release/modules/ext/jackson-dataformat-csv-2.15.2.jar
|
||||||
|
file.reference.jackson-datatype-jsr310-2.15.2.jar=release/modules/ext/jackson-datatype-jsr310-2.15.2.jar
|
||||||
file.reference.javafx-base-17.0.7-linux.jar=release/modules/ext/javafx-base-17.0.7-linux.jar
|
file.reference.javafx-base-17.0.7-linux.jar=release/modules/ext/javafx-base-17.0.7-linux.jar
|
||||||
file.reference.javafx-base-17.0.7-mac.jar=release/modules/ext/javafx-base-17.0.7-mac.jar
|
file.reference.javafx-base-17.0.7-mac.jar=release/modules/ext/javafx-base-17.0.7-mac.jar
|
||||||
file.reference.javafx-base-17.0.7-win.jar=release/modules/ext/javafx-base-17.0.7-win.jar
|
file.reference.javafx-base-17.0.7-win.jar=release/modules/ext/javafx-base-17.0.7-win.jar
|
||||||
|
@ -63,6 +63,12 @@
|
|||||||
<package>com.fasterxml.jackson.databind.type</package>
|
<package>com.fasterxml.jackson.databind.type</package>
|
||||||
<package>com.fasterxml.jackson.databind.util</package>
|
<package>com.fasterxml.jackson.databind.util</package>
|
||||||
<package>com.fasterxml.jackson.dataformat.csv</package>
|
<package>com.fasterxml.jackson.dataformat.csv</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310.deser</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310.deser.key</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310.ser</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310.ser.key</package>
|
||||||
|
<package>com.fasterxml.jackson.datatype.jsr310.util</package>
|
||||||
<package>com.github.lgooddatepicker.components</package>
|
<package>com.github.lgooddatepicker.components</package>
|
||||||
<package>com.github.lgooddatepicker.optionalusertools</package>
|
<package>com.github.lgooddatepicker.optionalusertools</package>
|
||||||
<package>com.github.lgooddatepicker.zinternaltools</package>
|
<package>com.github.lgooddatepicker.zinternaltools</package>
|
||||||
@ -197,8 +203,6 @@
|
|||||||
<package>com.google.rpc.context</package>
|
<package>com.google.rpc.context</package>
|
||||||
<package>com.google.thirdparty.publicsuffix</package>
|
<package>com.google.thirdparty.publicsuffix</package>
|
||||||
<package>com.google.type</package>
|
<package>com.google.type</package>
|
||||||
<package>com.microsoft.schemas.vml</package>
|
|
||||||
<package>com.microsoft.schemas.vml.impl</package>
|
|
||||||
<package>com.sun.javafx</package>
|
<package>com.sun.javafx</package>
|
||||||
<package>com.sun.javafx.animation</package>
|
<package>com.sun.javafx.animation</package>
|
||||||
<package>com.sun.javafx.application</package>
|
<package>com.sun.javafx.application</package>
|
||||||
@ -321,9 +325,6 @@
|
|||||||
<package>com.twelvemonkeys.util.regex</package>
|
<package>com.twelvemonkeys.util.regex</package>
|
||||||
<package>com.twelvemonkeys.util.service</package>
|
<package>com.twelvemonkeys.util.service</package>
|
||||||
<package>com.twelvemonkeys.xml</package>
|
<package>com.twelvemonkeys.xml</package>
|
||||||
<package>javax.annotation</package>
|
|
||||||
<package>javax.annotation.concurrent</package>
|
|
||||||
<package>javax.annotation.meta</package>
|
|
||||||
<package>javafx.animation</package>
|
<package>javafx.animation</package>
|
||||||
<package>javafx.application</package>
|
<package>javafx.application</package>
|
||||||
<package>javafx.beans</package>
|
<package>javafx.beans</package>
|
||||||
@ -340,7 +341,6 @@
|
|||||||
<package>javafx.event</package>
|
<package>javafx.event</package>
|
||||||
<package>javafx.fxml</package>
|
<package>javafx.fxml</package>
|
||||||
<package>javafx.geometry</package>
|
<package>javafx.geometry</package>
|
||||||
<package>javafx.graphics</package>
|
|
||||||
<package>javafx.print</package>
|
<package>javafx.print</package>
|
||||||
<package>javafx.scene</package>
|
<package>javafx.scene</package>
|
||||||
<package>javafx.scene.canvas</package>
|
<package>javafx.scene.canvas</package>
|
||||||
@ -362,19 +362,9 @@
|
|||||||
<package>javafx.stage</package>
|
<package>javafx.stage</package>
|
||||||
<package>javafx.util</package>
|
<package>javafx.util</package>
|
||||||
<package>javafx.util.converter</package>
|
<package>javafx.util.converter</package>
|
||||||
<package>javax.jms</package>
|
<package>javax.annotation</package>
|
||||||
<package>javax.mail</package>
|
<package>javax.annotation.concurrent</package>
|
||||||
<package>javax.mail.event</package>
|
<package>javax.annotation.meta</package>
|
||||||
<package>javax.mail.internet</package>
|
|
||||||
<package>javax.mail.search</package>
|
|
||||||
<package>javax.mail.util</package>
|
|
||||||
<package>javax.servlet</package>
|
|
||||||
<package>javax.servlet.http</package>
|
|
||||||
<package>javax.xml.parsers</package>
|
|
||||||
<package>javax.xml.transform</package>
|
|
||||||
<package>javax.xml.transform.dom</package>
|
|
||||||
<package>javax.xml.transform.sax</package>
|
|
||||||
<package>javax.xml.transform.stream</package>
|
|
||||||
<package>jfxtras.animation</package>
|
<package>jfxtras.animation</package>
|
||||||
<package>jfxtras.css</package>
|
<package>jfxtras.css</package>
|
||||||
<package>jfxtras.css.converters</package>
|
<package>jfxtras.css.converters</package>
|
||||||
@ -442,16 +432,6 @@
|
|||||||
<package>org.apache.commons.lang3.tuple</package>
|
<package>org.apache.commons.lang3.tuple</package>
|
||||||
<package>org.apache.commons.logging</package>
|
<package>org.apache.commons.logging</package>
|
||||||
<package>org.apache.commons.logging.impl</package>
|
<package>org.apache.commons.logging.impl</package>
|
||||||
<package>org.apache.log</package>
|
|
||||||
<package>org.apache.log.filter</package>
|
|
||||||
<package>org.apache.log.format</package>
|
|
||||||
<package>org.apache.log.output</package>
|
|
||||||
<package>org.apache.log.output.db</package>
|
|
||||||
<package>org.apache.log.output.io</package>
|
|
||||||
<package>org.apache.log.output.io.rotate</package>
|
|
||||||
<package>org.apache.log.output.jms</package>
|
|
||||||
<package>org.apache.log.output.net</package>
|
|
||||||
<package>org.apache.log.util</package>
|
|
||||||
<package>org.apache.commons.text</package>
|
<package>org.apache.commons.text</package>
|
||||||
<package>org.apache.commons.validator.routines</package>
|
<package>org.apache.commons.validator.routines</package>
|
||||||
<package>org.apache.commons.validator.routines.checkdigit</package>
|
<package>org.apache.commons.validator.routines.checkdigit</package>
|
||||||
@ -460,14 +440,7 @@
|
|||||||
<package>org.apache.log4j.config</package>
|
<package>org.apache.log4j.config</package>
|
||||||
<package>org.apache.log4j.helpers</package>
|
<package>org.apache.log4j.helpers</package>
|
||||||
<package>org.apache.log4j.jdbc</package>
|
<package>org.apache.log4j.jdbc</package>
|
||||||
<package>org.apache.log4j.jmx</package>
|
|
||||||
<package>org.apache.log4j.lf5</package>
|
|
||||||
<package>org.apache.log4j.lf5.util</package>
|
|
||||||
<package>org.apache.log4j.lf5.viewer</package>
|
|
||||||
<package>org.apache.log4j.lf5.viewer.categoryexplorer</package>
|
|
||||||
<package>org.apache.log4j.lf5.viewer.configure</package>
|
|
||||||
<package>org.apache.log4j.net</package>
|
<package>org.apache.log4j.net</package>
|
||||||
<package>org.apache.log4j.nt</package>
|
|
||||||
<package>org.apache.log4j.or</package>
|
<package>org.apache.log4j.or</package>
|
||||||
<package>org.apache.log4j.or.jms</package>
|
<package>org.apache.log4j.or.jms</package>
|
||||||
<package>org.apache.log4j.or.sax</package>
|
<package>org.apache.log4j.or.sax</package>
|
||||||
@ -931,6 +904,10 @@
|
|||||||
<runtime-relative-path>ext/jackson-dataformat-csv-2.15.2.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jackson-dataformat-csv-2.15.2.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jackson-dataformat-csv-2.15.2.jar</binary-origin>
|
<binary-origin>release/modules/ext/jackson-dataformat-csv-2.15.2.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jackson-datatype-jsr310-2.15.2.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jackson-datatype-jsr310-2.15.2.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/javafx-base-17.0.7-linux.jar</runtime-relative-path>
|
<runtime-relative-path>ext/javafx-base-17.0.7-linux.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/javafx-base-17.0.7-linux.jar</binary-origin>
|
<binary-origin>release/modules/ext/javafx-base-17.0.7-linux.jar</binary-origin>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#Updated by build script
|
||||||
#Wed, 28 Sep 2022 13:57:05 -0400
|
#Thu, 20 Jul 2023 19:55:04 -0400
|
||||||
LBL_splash_window_title=Starting Autopsy
|
LBL_splash_window_title=Starting Autopsy
|
||||||
SPLASH_HEIGHT=314
|
SPLASH_HEIGHT=314
|
||||||
SPLASH_WIDTH=538
|
SPLASH_WIDTH=538
|
||||||
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
|
|||||||
SplashRunningTextColor=0x0
|
SplashRunningTextColor=0x0
|
||||||
SplashRunningTextFontSize=19
|
SplashRunningTextFontSize=19
|
||||||
|
|
||||||
currentVersion=Autopsy 4.19.3
|
currentVersion=Autopsy 4.20.0
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#Updated by build script
|
#Updated by build script
|
||||||
#Wed, 28 Sep 2022 13:57:05 -0400
|
#Thu, 20 Jul 2023 19:55:04 -0400
|
||||||
CTL_MainWindow_Title=Autopsy 4.19.3
|
CTL_MainWindow_Title=Autopsy 4.20.0
|
||||||
CTL_MainWindow_Title_No_Project=Autopsy 4.19.3
|
CTL_MainWindow_Title_No_Project=Autopsy 4.20.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user