mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
merge from develop
This commit is contained in:
commit
0cd50f767d
@ -134,8 +134,8 @@
|
||||
<property environment="env"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/dist/sleuthkit-${TSK_VERSION}.jar"
|
||||
tofile="${ext.dir}/sleuthkit-${TSK_VERSION}.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.42.0.0.jar"
|
||||
tofile="${ext.dir}/sqlite-jdbc-3.42.0.0.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.42.0.1.jar"
|
||||
tofile="${ext.dir}/sqlite-jdbc-3.42.0.1.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/postgresql-42.3.5.jar"
|
||||
tofile="${ext.dir}/postgresql-42.3.5.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/c3p0-0.9.5.5.jar"
|
||||
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.core/10
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
|
||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
|
||||
OpenIDE-Module-Implementation-Version: 37
|
||||
OpenIDE-Module-Implementation-Version: 38
|
||||
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
||||
AutoUpdate-Show-In-Client: true
|
||||
AutoUpdate-Essential-Module: true
|
||||
|
@ -85,13 +85,13 @@ file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSH
|
||||
file.reference.serializer-2.7.2.jar=release/modules/ext/serializer-2.7.2.jar
|
||||
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
||||
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
||||
file.reference.sleuthkit-4.12.0.jar=release/modules/ext/sleuthkit-4.12.0.jar
|
||||
file.reference.sleuthkit-caseuco-4.12.0.jar=release/modules/ext/sleuthkit-caseuco-4.12.0.jar
|
||||
file.reference.sleuthkit-4.12.1.jar=release/modules/ext/sleuthkit-4.12.1.jar
|
||||
file.reference.sleuthkit-caseuco-4.12.1.jar=release/modules/ext/sleuthkit-caseuco-4.12.1.jar
|
||||
file.reference.slf4j-api-1.7.36.jar=release/modules/ext/slf4j-api-1.7.36.jar
|
||||
file.reference.snakeyaml-2.0.jar=release/modules/ext/snakeyaml-2.0.jar
|
||||
file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar
|
||||
file.reference.spotbugs-annotations-4.6.0.jar=release/modules/ext/spotbugs-annotations-4.6.0.jar
|
||||
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
|
||||
file.reference.sqlite-jdbc-3.42.0.1.jar=release/modules/ext/sqlite-jdbc-3.42.0.1.jar
|
||||
file.reference.txw2-2.3.3.jar=release/modules/ext/txw2-2.3.3.jar
|
||||
file.reference.xalan-2.7.2.jar=release/modules/ext/xalan-2.7.2.jar
|
||||
file.reference.xml-apis-1.4.01.jar=release/modules/ext/xml-apis-1.4.01.jar
|
||||
@ -107,4 +107,4 @@ license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/
|
||||
nbm.module.author=Brian Carrier
|
||||
nbm.needs.restart=true
|
||||
spec.version.base=10.24
|
||||
spec.version.base=10.25
|
||||
|
@ -718,12 +718,12 @@
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-4.12.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-4.12.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sleuthkit-4.12.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-4.12.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-caseuco-4.12.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-caseuco-4.12.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sleuthkit-caseuco-4.12.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-caseuco-4.12.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/slf4j-api-1.7.36.jar</runtime-relative-path>
|
||||
@ -742,8 +742,8 @@
|
||||
<binary-origin>release/modules/ext/spotbugs-annotations-4.6.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/txw2-2.3.3.jar</runtime-relative-path>
|
||||
|
@ -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
|
||||
|
||||
|
||||
CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required
|
||||
CTIntegrationMissingDialog.descriptionLabel.text=<html><body><p>The Cyber Triage Importer Module is required to open this case. </p><p>To open this case:</p><ul><li>Extract the module from the Integrations tab in the Cyber Triage options panel.</li><li>Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.</li><li>Click 'Add Plugins...' and select the path of the plugin.</li><li>Press 'Install' to finish the installation.</li></ul></body></html>
|
||||
CTIntegrationMissingDialog.docsLabel.text=<html>For more information, refer to the Cyber Triage Users Guide</html>
|
||||
CTIntegrationMissingDialog.okButton.text=OK
|
@ -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
|
||||
|
||||
|
||||
CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required
|
||||
CTIntegrationMissingDialog.descriptionLabel.text=<html><body><p>The Cyber Triage Importer Module is required to open this case. </p><p>To open this case:</p><ul><li>Extract the module from the Integrations tab in the Cyber Triage options panel.</li><li>Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.</li><li>Click 'Add Plugins...' and select the path of the plugin.</li><li>Press 'Install' to finish the installation.</li></ul></body></html>
|
||||
CTIntegrationMissingDialog.docsLabel.text=<html>For more information, refer to the Cyber Triage Users Guide</html>
|
||||
CTIntegrationMissingDialog.okButton.text=OK
|
@ -1,24 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<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 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/Bundle.properties" key="CTIntegrationMissingDialog.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"/>
|
||||
@ -29,17 +23,19 @@
|
||||
<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"/>
|
||||
<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,-65,0,0,1,-9"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="disclaimer">
|
||||
<Component class="javax.swing.JLabel" name="descriptionLabel">
|
||||
<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}")"/>
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/Bundle.properties" key="CTIntegrationMissingDialog.descriptionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[483, 116]"/>
|
||||
</Property>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
@ -51,10 +47,13 @@
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="purchaseFromLabel">
|
||||
<Component class="javax.swing.JLabel" name="docsLabel">
|
||||
<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}")"/>
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/Bundle.properties" key="CTIntegrationMissingDialog.docsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[312, 16]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
@ -63,14 +62,14 @@
|
||||
</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"/>
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="0" 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 name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><span style=\"color: blue; text-decoration: underline\">" + DOCS_PAGE_URL + "</span></html>"" type="code"/>
|
||||
</Property>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Hand Cursor"/>
|
||||
@ -79,24 +78,20 @@
|
||||
<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"/>
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="spacer">
|
||||
<Container class="javax.swing.JPanel" name="paddingPanel">
|
||||
<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"/>
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" 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>
|
||||
|
||||
@ -113,5 +108,24 @@
|
||||
</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/Bundle.properties" key="CTIntegrationMissingDialog.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>
|
||||
<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="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JComponent;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Provides directions with how to enable CT integration with Autopsy when
|
||||
* trying to open a CT exported case.
|
||||
*/
|
||||
public class CTIntegrationMissingDialog extends javax.swing.JDialog {
|
||||
|
||||
private static final String DOCS_PAGE_URL = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html";
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CTIntegrationMissingDialog.class.getName());
|
||||
|
||||
/**
|
||||
* Creates new form CTIntegrationMissingDialog
|
||||
*/
|
||||
public CTIntegrationMissingDialog(java.awt.Frame parent, boolean modal) {
|
||||
super(parent, modal);
|
||||
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 descriptionLabel = new javax.swing.JLabel();
|
||||
javax.swing.JLabel docsLabel = new javax.swing.JLabel();
|
||||
link = new javax.swing.JLabel();
|
||||
javax.swing.JPanel paddingPanel = new javax.swing.JPanel();
|
||||
javax.swing.JButton okButton = new javax.swing.JButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle(org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.title")); // NOI18N
|
||||
setAlwaysOnTop(true);
|
||||
setResizable(false);
|
||||
getContentPane().setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.descriptionLabel.text")); // NOI18N
|
||||
descriptionLabel.setMinimumSize(new java.awt.Dimension(483, 116));
|
||||
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);
|
||||
getContentPane().add(descriptionLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(docsLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.docsLabel.text")); // NOI18N
|
||||
docsLabel.setMinimumSize(new java.awt.Dimension(312, 16));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0);
|
||||
getContentPane().add(docsLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(link, "<html><span style=\"color: blue; text-decoration: underline\">" + DOCS_PAGE_URL + "</span></html>");
|
||||
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.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
getContentPane().add(link, gridBagConstraints);
|
||||
|
||||
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 = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
getContentPane().add(paddingPanel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.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 = 1;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 5);
|
||||
getContentPane().add(okButton, gridBagConstraints);
|
||||
|
||||
pack();
|
||||
}// </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(DOCS_PAGE_URL));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
LOGGER.log(Level.SEVERE, "Error opening link to: " + DOCS_PAGE_URL, e);
|
||||
}
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened.");
|
||||
}
|
||||
}//GEN-LAST:event_linkMouseClicked
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
dispose();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
public void showDialog(JComponent parentComp) {
|
||||
setLocationRelativeTo(parentComp == null ? getParent() : parentComp);
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel link;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -25,9 +25,12 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBeanResponse;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.util.CTHostIDGenerationUtil;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -45,6 +48,8 @@ public class CTApiDAO {
|
||||
private static final String LICENSE_REQUEST_PATH = "/_ah/api/license/v1/activate";
|
||||
private static final String AUTH_TOKEN_REQUEST_PATH = "/_ah/api/auth/v2/generate_token";
|
||||
private static final String CTCLOUD_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE";
|
||||
private static final String CTCLOUD_UPLOAD_FILE_METADATA_PATH = "/_ah/api/reputation/v1/upload/meta";
|
||||
|
||||
private static final String AUTOPSY_PRODUCT = "AUTOPSY";
|
||||
|
||||
private static final CTApiDAO instance = new CTApiDAO();
|
||||
@ -74,15 +79,28 @@ public class CTApiDAO {
|
||||
}
|
||||
|
||||
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException {
|
||||
return getAuthToken(decrypted, null);
|
||||
}
|
||||
|
||||
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, Long fileUploadSize) throws CTCloudException {
|
||||
AuthTokenRequest authTokenRequest = new AuthTokenRequest()
|
||||
.setAutopsyVersion(getAppVersion())
|
||||
.setRequestFileUpload(false)
|
||||
.setRequestFileUpload(fileUploadSize != null && fileUploadSize > 0)
|
||||
.setFileUploadSize(fileUploadSize != null && fileUploadSize > 0 ? fileUploadSize : null)
|
||||
.setBoostLicenseId(decrypted.getBoostLicenseId())
|
||||
.setHostId(decrypted.getLicenseHostId());
|
||||
|
||||
return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class);
|
||||
}
|
||||
|
||||
public void uploadFile(FileUploadRequest fileUploadRequest) throws CTCloudException {
|
||||
httpClient.doFileUploadPut(fileUploadRequest);
|
||||
}
|
||||
|
||||
public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException {
|
||||
httpClient.doPost(CTCLOUD_UPLOAD_FILE_METADATA_PATH, getAuthParams(authenticatedRequestData), metaRequest, null);
|
||||
}
|
||||
|
||||
private static Map<String, String> getAuthParams(AuthenticatedRequestData authenticatedRequestData) {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
|
@ -76,8 +76,7 @@ public class CTCloudException extends Exception{
|
||||
|
||||
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.",
|
||||
return String.format("An API error %s occurred. Please try again, and contact Basis support at %s for help if the problem persists.",
|
||||
StringUtils.isNotBlank(getCause().getLocalizedMessage()) ? "("+getCause().getLocalizedMessage()+")": "(Unknown)",
|
||||
Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM );
|
||||
}else {
|
||||
|
@ -18,148 +18,127 @@
|
||||
*/
|
||||
package com.basistech.df.cybertriage.autopsy.ctapi;
|
||||
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException.ErrorCode;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.io.InputStream;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
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.Collection;
|
||||
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 java.util.stream.Stream;
|
||||
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.lang.ArrayUtils;
|
||||
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.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.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.apache.http.impl.conn.SystemDefaultRoutePlanner;
|
||||
import org.apache.http.ssl.SSLInitializationException;
|
||||
import org.netbeans.core.ProxySettings;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
|
||||
/**
|
||||
* Makes the http requests to CT cloud.
|
||||
*
|
||||
* NOTE: regarding proxy settings, the host and port are handled by the
|
||||
* NbProxySelector. Any proxy authentication is handled by NbAuthenticator which
|
||||
* is installed at startup (i.e. NbAuthenticator.install). See
|
||||
* GeneralOptionsModel.testHttpConnection to see how the general options panel
|
||||
* tests the connection.
|
||||
*/
|
||||
public class CTCloudHttpClient {
|
||||
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 String NB_PROXY_SELECTOR_NAME = "org.netbeans.core.NbProxySelector";
|
||||
|
||||
private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec
|
||||
|
||||
private static final CTCloudHttpClient instance = new CTCloudHttpClient();
|
||||
|
||||
public static CTCloudHttpClient getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final ObjectMapper mapper = ObjectMapperUtil.getInstance().getDefaultObjectMapper();
|
||||
private final SSLContext sslContext;
|
||||
private String hostName = null;
|
||||
private final ProxySelector proxySelector;
|
||||
|
||||
private CTCloudHttpClient() {
|
||||
// leave as null for now unless we want to customize this at a later date
|
||||
this.sslContext = null;
|
||||
this.sslContext = createSSLContext();
|
||||
this.proxySelector = getProxySelector();
|
||||
}
|
||||
|
||||
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);
|
||||
private static URI getUri(String host, String path, Map<String, String> urlReqParams) throws URISyntaxException {
|
||||
String url = host + path;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
URI postURI = null;
|
||||
try {
|
||||
|
||||
postURI = getUri(HOST_URL, urlPath, urlReqParams);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) {
|
||||
|
||||
URI postURI = builder.build();
|
||||
HttpPost postRequest = new HttpPost(postURI);
|
||||
|
||||
|
||||
configureRequestTimeout(postRequest);
|
||||
postRequest.setHeader("Content-type", "application/json");
|
||||
|
||||
@ -177,30 +156,92 @@ public class CTCloudHttpClient {
|
||||
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;
|
||||
if (classType != null) {
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
String entityStr = EntityUtils.toString(entity);
|
||||
if (StringUtils.isNotBlank(entityStr)) {
|
||||
O respObj = mapper.readValue(entityStr, classType);
|
||||
return respObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine());
|
||||
handleNonOKResponse(response, "");
|
||||
}
|
||||
// transform all non-CTCloudException's into a CTCloudException
|
||||
} catch (CTCloudException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
LOGGER.log(Level.WARNING, "Error when parsing response from CyberTriage Cloud", ex);
|
||||
throw new CTCloudException(CTCloudException.parseUnknownException(ex), ex);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + url, ex);
|
||||
LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + postURI, ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex);
|
||||
} catch (SSLInitializationException ex) {
|
||||
LOGGER.log(Level.WARNING, "No such algorithm exception raised when creating SSL connection for CT Cloud using " + postURI, ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex);
|
||||
} catch (URISyntaxException ex) {
|
||||
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + url, ex);
|
||||
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + postURI, ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudException {
|
||||
if (fileUploadRequest == null) {
|
||||
throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null"));
|
||||
}
|
||||
|
||||
String fullUrlPath = fileUploadRequest.getFullUrlPath();
|
||||
String fileName = fileUploadRequest.getFileName();
|
||||
InputStream fileInputStream = fileUploadRequest.getFileInputStream();
|
||||
Long contentLength = fileUploadRequest.getContentLength();
|
||||
|
||||
if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) {
|
||||
throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0"));
|
||||
}
|
||||
|
||||
URI putUri;
|
||||
try {
|
||||
putUri = new URI(fullUrlPath);
|
||||
} catch (URISyntaxException ex) {
|
||||
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex);
|
||||
}
|
||||
|
||||
try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) {
|
||||
LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath);
|
||||
HttpPut put = new HttpPut(putUri);
|
||||
configureRequestTimeout(put);
|
||||
|
||||
put.addHeader("Connection", "keep-alive");
|
||||
put.setEntity(new InputStreamEntity(fileInputStream, contentLength, ContentType.APPLICATION_OCTET_STREAM));
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(put)) {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
|
||||
LOGGER.log(Level.INFO, "Response Received. - Status OK");
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, MessageFormat.format("Response Received. - Status Error {0}", response.getStatusLine()));
|
||||
handleNonOKResponse(response, fileName);
|
||||
}
|
||||
}
|
||||
} catch (SSLInitializationException ex) {
|
||||
LOGGER.log(Level.WARNING, "SSL exception raised when connecting to Reversing Labs for file content upload ", ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.WARNING, "IO Exception raised when connecting to Reversing Labs for file content upload ", ex);
|
||||
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A generic way to handle the HTTP response - when the response code is NOT
|
||||
* 200 OK.
|
||||
@ -263,147 +304,140 @@ public class CTCloudHttpClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Get ProxySelector present (favoring NbProxySelector if present).
|
||||
*
|
||||
* @return The found ProxySelector or null.
|
||||
*/
|
||||
private static CloseableHttpClient createConnection(ProxySettingArgs proxySettings, SSLContext sslContext) {
|
||||
HttpClientBuilder builder = getHttpClientBuilder(proxySettings);
|
||||
|
||||
if (sslContext != null) {
|
||||
builder.setSSLContext(sslContext);
|
||||
}
|
||||
return builder.build();
|
||||
private static ProxySelector getProxySelector() {
|
||||
Collection<? extends ProxySelector> selectors = Lookup.getDefault().lookupAll(ProxySelector.class);
|
||||
return (selectors != null ? selectors.stream() : Stream.empty())
|
||||
.filter(s -> s != null)
|
||||
.map(s -> (ProxySelector) s)
|
||||
.sorted((a, b) -> {
|
||||
String aName = a.getClass().getCanonicalName();
|
||||
String bName = b.getClass().getCanonicalName();
|
||||
boolean aIsNb = aName.equalsIgnoreCase(NB_PROXY_SELECTOR_NAME);
|
||||
boolean bIsNb = bName.equalsIgnoreCase(NB_PROXY_SELECTOR_NAME);
|
||||
if (aIsNb == bIsNb) {
|
||||
return StringUtils.compareIgnoreCase(aName, bName);
|
||||
} else {
|
||||
return aIsNb ? -1 : 1;
|
||||
}
|
||||
})
|
||||
.findFirst()
|
||||
// TODO take this out to remove proxy selector logging
|
||||
.map(s -> new LoggingProxySelector(s))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private static HttpClientBuilder getHttpClientBuilder(ProxySettingArgs proxySettings) {
|
||||
/**
|
||||
* Create an SSLContext object using our in-memory keystore.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static SSLContext createSSLContext() {
|
||||
LOGGER.log(Level.INFO, "Creating custom SSL context");
|
||||
try {
|
||||
|
||||
if (proxySettings.isSystemOrManualProxy()) {
|
||||
// I'm not sure how much of this is really necessary to set up, but it works
|
||||
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
|
||||
KeyManager[] keyManagers = getKeyManagers();
|
||||
TrustManager[] trustManagers = getTrustManagers();
|
||||
sslContext.init(keyManagers, trustManagers, new SecureRandom());
|
||||
return sslContext;
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error creating SSL context", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
LOGGER.info("Requesting Password Authentication...");
|
||||
return super.getPasswordAuthentication();
|
||||
}
|
||||
});
|
||||
// jvm default key manager
|
||||
// based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909
|
||||
private static KeyManager[] getKeyManagers() {
|
||||
LOGGER.log(Level.INFO, "Using default algorithm to create trust store: " + KeyManagerFactory.getDefaultAlgorithm());
|
||||
try {
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(null, null);
|
||||
return kmf.getKeyManagers();
|
||||
} catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting KeyManagers", ex);
|
||||
return new KeyManager[0];
|
||||
}
|
||||
|
||||
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());
|
||||
// jvm default trust store
|
||||
// based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909
|
||||
private static TrustManager[] getTrustManagers() {
|
||||
try {
|
||||
LOGGER.log(Level.INFO, "Using default algorithm to create trust store: " + TrustManagerFactory.getDefaultAlgorithm());
|
||||
TrustManagerFactory tmf
|
||||
= TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init((KeyStore) null);
|
||||
X509TrustManager tm = (X509TrustManager) tmf.getTrustManagers()[0];
|
||||
|
||||
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();
|
||||
return new TrustManager[]{tm};
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting TrustManager", ex);
|
||||
return new TrustManager[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CredentialsProvider for proxy, if one is configured.
|
||||
* Creates a connection to CT Cloud with the given arguments.
|
||||
*
|
||||
* @return CredentialsProvider, if a proxy is configured with credentials,
|
||||
* null otherwise
|
||||
* @param proxySelector The proxy selector.
|
||||
* @param sslContext The ssl context or null.
|
||||
* @return The connection to CT Cloud.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
private static CloseableHttpClient createConnection(ProxySelector proxySelector, SSLContext sslContext) throws SSLInitializationException {
|
||||
HttpClientBuilder builder;
|
||||
|
||||
if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION
|
||||
&& StringUtils.isBlank(ProxySettings.getAuthenticationUsername())
|
||||
&& ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword())
|
||||
&& WinHttpClients.isWinAuthAvailable()) {
|
||||
|
||||
builder = WinHttpClients.custom();
|
||||
builder.useSystemProperties();
|
||||
LOGGER.log(Level.WARNING, "Using Win HTTP Client");
|
||||
} else {
|
||||
builder = HttpClients.custom();
|
||||
// builder.setDefaultRequestConfig(config);
|
||||
LOGGER.log(Level.WARNING, "Using default http client");
|
||||
}
|
||||
|
||||
return proxyCredsProvider;
|
||||
if (sslContext != null) {
|
||||
builder.setSSLContext(sslContext);
|
||||
}
|
||||
|
||||
if (proxySelector != null) {
|
||||
builder.setRoutePlanner(new SystemDefaultRoutePlanner(proxySelector));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static class ProxySettingArgs {
|
||||
private static class LoggingProxySelector extends ProxySelector {
|
||||
|
||||
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;
|
||||
private final ProxySelector delegate;
|
||||
|
||||
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;
|
||||
public LoggingProxySelector(ProxySelector delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
boolean isSystemOrManualProxy() {
|
||||
return systemOrManualProxy;
|
||||
@Override
|
||||
public List<Proxy> select(URI uri) {
|
||||
List<Proxy> selectedProxies = delegate.select(uri);
|
||||
LOGGER.log(Level.INFO, MessageFormat.format("Proxy selected for {0} are {1}", uri, selectedProxies));
|
||||
return selectedProxies;
|
||||
}
|
||||
|
||||
String getHostName() {
|
||||
return hostName;
|
||||
@Override
|
||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||
LOGGER.log(Level.WARNING, MessageFormat.format("Connection failed connecting to {0} socket address {1}", uri, sa), ioe);
|
||||
delegate.connectFailed(uri, sa, ioe);
|
||||
}
|
||||
|
||||
String getProxyHostname() {
|
||||
return proxyHostname;
|
||||
}
|
||||
|
||||
int getProxyPort() {
|
||||
return proxyPort;
|
||||
}
|
||||
|
||||
String getProxyUserId() {
|
||||
return proxyUserId;
|
||||
}
|
||||
|
||||
char[] getProxyPassword() {
|
||||
return proxyPassword;
|
||||
}
|
||||
|
||||
public String getAuthScheme() {
|
||||
return authScheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import java.net.URI;
|
||||
/**
|
||||
* Constants regarding connections to cyber triage cloud.
|
||||
*/
|
||||
final public class Constants {
|
||||
final class Constants {
|
||||
|
||||
public static final String CYBER_TRIAGE = "CyberTriage";
|
||||
|
||||
|
@ -1,446 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
@ -34,6 +34,9 @@ public class AuthTokenRequest {
|
||||
@JsonProperty("requestFileUpload")
|
||||
private boolean requestFileUpload;
|
||||
|
||||
@JsonProperty("fileUploadSize")
|
||||
private Long fileUploadSize;
|
||||
|
||||
@JsonProperty("host_id")
|
||||
private String hostId;
|
||||
|
||||
@ -64,6 +67,16 @@ public class AuthTokenRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getFileUploadSize() {
|
||||
return fileUploadSize;
|
||||
}
|
||||
|
||||
public AuthTokenRequest setFileUploadSize(Long fileUploadSize) {
|
||||
this.fileUploadSize = fileUploadSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class DecryptedLicenseResponse {
|
||||
private final Long fileUploads;
|
||||
private final Instant activationTime;
|
||||
private final String product;
|
||||
private final String limitType;
|
||||
private final LicenseLimitType limitType;
|
||||
private final String timezone;
|
||||
private final String customerEmail;
|
||||
private final String customerName;
|
||||
@ -54,7 +54,7 @@ public class DecryptedLicenseResponse {
|
||||
@JsonDeserialize(using = InstantEpochMillisDeserializer.class)
|
||||
@JsonProperty("activationTime") Instant activationTime,
|
||||
@JsonProperty("product") String product,
|
||||
@JsonProperty("limitType") String limitType,
|
||||
@JsonProperty("limitType") LicenseLimitType limitType,
|
||||
@JsonProperty("timezone") String timezone,
|
||||
@JsonProperty("customerEmail") String customerEmail,
|
||||
@JsonProperty("customerName") String customerName
|
||||
@ -96,7 +96,7 @@ public class DecryptedLicenseResponse {
|
||||
return product;
|
||||
}
|
||||
|
||||
public String getLimitType() {
|
||||
public LicenseLimitType getLimitType() {
|
||||
return limitType;
|
||||
}
|
||||
|
||||
|
@ -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.json;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Data for a file upload request.
|
||||
*/
|
||||
public class FileUploadRequest {
|
||||
|
||||
private String fullUrlPath;
|
||||
private String fileName;
|
||||
private InputStream fileInputStream;
|
||||
private Long contentLength;
|
||||
|
||||
public String getFullUrlPath() {
|
||||
return fullUrlPath;
|
||||
}
|
||||
|
||||
public FileUploadRequest setFullUrlPath(String fullUrlPath) {
|
||||
this.fullUrlPath = fullUrlPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public FileUploadRequest setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputStream getFileInputStream() {
|
||||
return fileInputStream;
|
||||
}
|
||||
|
||||
public FileUploadRequest setFileInputStream(InputStream fileInputStream) {
|
||||
this.fileInputStream = fileInputStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public FileUploadRequest setContentLength(Long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The limit type (and reset) for the license.
|
||||
*/
|
||||
public enum LicenseLimitType {
|
||||
HOURLY,
|
||||
DAILY,
|
||||
WEEKLY,
|
||||
MONTHLY,
|
||||
NO_RESET;
|
||||
}
|
@ -32,18 +32,21 @@ public class LicenseResponse {
|
||||
private final Boolean hostChanged;
|
||||
private final Long hostChangesRemaining;
|
||||
private final BoostLicenseResponse boostLicense;
|
||||
private final String errorMsg;
|
||||
|
||||
@JsonCreator
|
||||
public LicenseResponse(
|
||||
@JsonProperty("success") Boolean success,
|
||||
@JsonProperty("hostChanged") Boolean hostChanged,
|
||||
@JsonProperty("hostChangesRemaining") Long hostChangesRemaining,
|
||||
@JsonProperty("boostLicense") BoostLicenseResponse boostLicense
|
||||
@JsonProperty("boostLicense") BoostLicenseResponse boostLicense,
|
||||
@JsonProperty("errorMsg") String errorMsg
|
||||
) {
|
||||
this.success = success;
|
||||
this.hostChanged = hostChanged;
|
||||
this.hostChangesRemaining = hostChangesRemaining;
|
||||
this.boostLicense = boostLicense;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public Boolean isSuccess() {
|
||||
@ -61,4 +64,8 @@ public class LicenseResponse {
|
||||
public BoostLicenseResponse getBoostLicense() {
|
||||
return boostLicense;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class MetadataUploadRequest {
|
||||
|
||||
@JsonProperty("file_upload_url")
|
||||
private String fileUploadUrl;
|
||||
|
||||
@JsonProperty("sha1")
|
||||
private String sha1;
|
||||
|
||||
@JsonProperty("sha256")
|
||||
private String sha256;
|
||||
|
||||
@JsonProperty("md5")
|
||||
private String md5;
|
||||
|
||||
@JsonProperty("filePath")
|
||||
private String filePath;
|
||||
|
||||
@JsonProperty("fileSize")
|
||||
private Long fileSizeBytes;
|
||||
|
||||
@JsonProperty("createdDate")
|
||||
private Long createdDate;
|
||||
|
||||
public String getFileUploadUrl() {
|
||||
return fileUploadUrl;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setFileUploadUrl(String fileUploadUrl) {
|
||||
this.fileUploadUrl = fileUploadUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setSha1(String sha1) {
|
||||
this.sha1 = sha1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSha256() {
|
||||
return sha256;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setSha256(String sha256) {
|
||||
this.sha256 = sha256;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setMd5(String md5) {
|
||||
this.md5 = md5;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getFileSizeBytes() {
|
||||
return fileSizeBytes;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setFileSizeBytes(Long fileSizeBytes) {
|
||||
this.fileSizeBytes = fileSizeBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
public MetadataUploadRequest setCreatedDate(Long createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,7 @@ import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Base64;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
@ -42,6 +43,7 @@ import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Decrypts the payload of boost license.
|
||||
@ -58,12 +60,12 @@ public class LicenseDecryptorUtil {
|
||||
|
||||
private LicenseDecryptorUtil() {
|
||||
}
|
||||
|
||||
|
||||
public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException {
|
||||
if (licenseResponse == null || licenseResponse.getBoostLicense() == null) {
|
||||
throw new InvalidLicenseException("License or boost license are null");
|
||||
if (licenseResponse == null) {
|
||||
throw new InvalidLicenseException("License is null");
|
||||
}
|
||||
|
||||
|
||||
DecryptedLicenseResponse decrypted = parseLicenseJSON(licenseResponse.getBoostLicense());
|
||||
return new LicenseInfo(licenseResponse, decrypted);
|
||||
}
|
||||
@ -78,6 +80,9 @@ public class LicenseDecryptorUtil {
|
||||
* com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException
|
||||
*/
|
||||
public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException {
|
||||
if (licenseResponse == null) {
|
||||
throw new InvalidLicenseException("Boost license is null");
|
||||
}
|
||||
|
||||
String decryptedJsonResponse;
|
||||
try {
|
||||
@ -101,6 +106,12 @@ public class LicenseDecryptorUtil {
|
||||
}
|
||||
|
||||
private String decryptLicenseString(String encryptedJson, String ivBase64, String encryptedKey, String version) throws IOException, GeneralSecurityException, InvalidLicenseException {
|
||||
if (ObjectUtils.anyNull(encryptedJson, ivBase64, encryptedKey, version)) {
|
||||
throw new InvalidLicenseException(MessageFormat.format(
|
||||
"encryptedJson: {0}, iv: {1}, encryptedKey: {2}, version: {3} must all be non-null",
|
||||
encryptedJson, ivBase64, encryptedKey, version));
|
||||
}
|
||||
|
||||
if (!"1.0".equals(version)) {
|
||||
throw new InvalidLicenseException("Unexpected file version: " + version);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
# 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.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use.</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
|
||||
LicenseDisclaimerPanel.trialLabel.text=You can try a free 7-day trial from
|
||||
|
@ -3,7 +3,7 @@
|
||||
# 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.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use.</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
|
||||
LicenseDisclaimerPanel.trialLabel.text=You can try a free 7-day trial from
|
||||
|
@ -26,12 +26,12 @@ import java.beans.PropertyChangeListener;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.swing.JPanel;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
|
||||
/**
|
||||
@ -64,12 +64,12 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel {
|
||||
}
|
||||
})
|
||||
.filter(item -> item != null)
|
||||
.sorted(Comparator.comparing(p -> p.getClass().getSimpleName().toUpperCase()))
|
||||
.sorted(Comparator.comparing(p -> p.getClass().getSimpleName().toUpperCase()).reversed())
|
||||
.collect(Collectors.toList());
|
||||
addSubOptionsPanels(new LicenseDisclaimerPanel(), this.subPanels);
|
||||
addSubOptionsPanels(this.subPanels);
|
||||
}
|
||||
|
||||
private void addSubOptionsPanels(JPanel disclaimerPanel, List<CTOptionsSubPanel> subPanels) {
|
||||
private void addSubOptionsPanels(List<CTOptionsSubPanel> subPanels) {
|
||||
GridBagConstraints disclaimerConstraints = new GridBagConstraints();
|
||||
disclaimerConstraints.gridx = 0;
|
||||
disclaimerConstraints.gridy = 0;
|
||||
@ -79,8 +79,6 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel {
|
||||
disclaimerConstraints.weighty = 0;
|
||||
disclaimerConstraints.weightx = 0;
|
||||
|
||||
contentPane.add(disclaimerPanel, disclaimerConstraints);
|
||||
|
||||
for (int i = 0; i < subPanels.size(); i++) {
|
||||
CTOptionsSubPanel subPanel = subPanels.get(i);
|
||||
|
||||
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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 org.sleuthkit.autopsy.coreutils.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
|
||||
}
|
@ -4,18 +4,16 @@
|
||||
|
||||
CTLicenseDialog.title=Add a License...
|
||||
CTLicenseDialog.licenseNumberLabel.text=License Number:
|
||||
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
CTLicenseDialog.licenseNumberTextField.text=
|
||||
CTLicenseDialog.cancelButton.text=Cancel
|
||||
CTLicenseDialog.okButton.text=Ok
|
||||
CTLicenseDialog.warningLabel.text=
|
||||
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.malwareScansPanel.border.title=Malware Scanner
|
||||
CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License
|
||||
CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
|
||||
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
|
||||
@ -24,3 +22,7 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=
|
||||
EULADialog.cancelButton.text=Cancel
|
||||
EULADialog.acceptButton.text=Accept
|
||||
EULADialog.title=Cyber Triage End User License Agreement
|
||||
CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text=
|
||||
CTMalwareScannerOptionsPanel.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use.</html>
|
||||
CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit
|
||||
CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
|
@ -4,24 +4,26 @@
|
||||
|
||||
CTLicenseDialog.title=Add a License...
|
||||
CTLicenseDialog.licenseNumberLabel.text=License Number:
|
||||
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
CTLicenseDialog.licenseNumberTextField.text=
|
||||
CTLicenseDialog.cancelButton.text=Cancel
|
||||
CTLicenseDialog.okButton.text=Ok
|
||||
CTLicenseDialog.warningLabel.text=
|
||||
CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>
|
||||
CTLicenseDialog_verifyInput_licenseNumberError=<html>Please enter a license number</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.malwareScansPanel.border.title=Malware Scanner
|
||||
CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License
|
||||
CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
|
||||
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
|
||||
CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text=
|
||||
CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=
|
||||
CTMalwareScannerOptionsPanel_getResetSuffix_daily=/day
|
||||
CTMalwareScannerOptionsPanel_getResetSuffix_hourly=/hour
|
||||
CTMalwareScannerOptionsPanel_getResetSuffix_monthly=/month
|
||||
CTMalwareScannerOptionsPanel_getResetSuffix_weekly=/week
|
||||
CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number:
|
||||
CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License...
|
||||
CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered
|
||||
@ -29,6 +31,8 @@ CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Alr
|
||||
CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_desc=Please verify that license number is of format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
||||
CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_title=Invalid License Number
|
||||
CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error
|
||||
# {0} - licenseCode
|
||||
CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}
|
||||
CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.
|
||||
CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error
|
||||
# {0} - expiresDate
|
||||
@ -45,9 +49,11 @@ CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining=File uploads rema
|
||||
# {0} - hashLookupsRemaining
|
||||
CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining=Hash lookups remaining: {0}
|
||||
# {0} - maxDailyFileLookups
|
||||
CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day
|
||||
# {1} - resetSuffix
|
||||
CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}{1}
|
||||
# {0} - maxDailyLookups
|
||||
CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day
|
||||
# {1} - resetSuffix
|
||||
CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}{1}
|
||||
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
|
||||
@ -56,3 +62,7 @@ CTOPtionsPanel_loadMalwareScansInfo_loading=Loading...
|
||||
EULADialog.cancelButton.text=Cancel
|
||||
EULADialog.acceptButton.text=Accept
|
||||
EULADialog.title=Cyber Triage End User License Agreement
|
||||
CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text=
|
||||
CTMalwareScannerOptionsPanel.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use.</html>
|
||||
CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit
|
||||
CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
|
@ -127,6 +127,9 @@
|
||||
<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>
|
||||
<Property name="toolTipText" 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.toolTipText" 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">
|
||||
|
@ -18,18 +18,20 @@
|
||||
*/
|
||||
package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.corecomponents.TextPrompt;
|
||||
|
||||
/**
|
||||
* License dialog
|
||||
*/
|
||||
public class CTLicenseDialog extends javax.swing.JDialog {
|
||||
class CTLicenseDialog extends javax.swing.JDialog {
|
||||
|
||||
private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$");
|
||||
private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9-_]+?\\s*$");
|
||||
private String licenseString = null;
|
||||
|
||||
/**
|
||||
@ -38,6 +40,7 @@ public class CTLicenseDialog extends javax.swing.JDialog {
|
||||
public CTLicenseDialog(java.awt.Frame parent, boolean modal) {
|
||||
super(parent, modal);
|
||||
initComponents();
|
||||
configureHintText();
|
||||
this.licenseNumberTextField.getDocument().putProperty("filterNewlines", Boolean.TRUE);
|
||||
this.licenseNumberTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
@ -56,13 +59,23 @@ public class CTLicenseDialog extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void configureHintText() {
|
||||
TextPrompt textPrompt = new TextPrompt(
|
||||
StringUtils.defaultString(this.licenseNumberTextField.getToolTipText()),
|
||||
this.licenseNumberTextField);
|
||||
|
||||
textPrompt.setForeground(Color.LIGHT_GRAY);
|
||||
float alpha = 0.9f; // Mostly opaque
|
||||
textPrompt.changeAlpha(alpha);
|
||||
}
|
||||
|
||||
String getValue() {
|
||||
return licenseString;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>"
|
||||
"CTLicenseDialog_verifyInput_licenseNumberError=<html>Please enter a license number</html>"
|
||||
})
|
||||
private void verifyInput() {
|
||||
String licenseInput = StringUtils.defaultString(this.licenseNumberTextField.getText());
|
||||
@ -165,6 +178,7 @@ public class CTLicenseDialog extends javax.swing.JDialog {
|
||||
getContentPane().add(cancelButton, gridBagConstraints);
|
||||
|
||||
licenseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.text")); // NOI18N
|
||||
licenseNumberTextField.setToolTipText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.toolTipText")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
@ -177,7 +191,8 @@ public class CTLicenseDialog extends javax.swing.JDialog {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
this.licenseString = this.licenseNumberTextField.getText();
|
||||
String inputText = this.licenseNumberTextField.getText();
|
||||
this.licenseString = inputText == null ? null : inputText.trim();
|
||||
this.dispose();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
|
@ -26,7 +26,6 @@ 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;
|
||||
@ -40,6 +39,7 @@ public class CTLicensePersistence {
|
||||
|
||||
private static final String CT_SETTINGS_DIR = "CyberTriage";
|
||||
private static final String CT_LICENSE_FILENAME = "CyberTriageLicense.json";
|
||||
private static final String MALWARE_INGEST_SETTINGS_FILENAME = "MalwareIngestSettings.json";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CTLicensePersistence.class.getName());
|
||||
|
||||
@ -94,4 +94,8 @@ public class CTLicensePersistence {
|
||||
private File getCTLicenseFile() {
|
||||
return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_LICENSE_FILENAME).toFile();
|
||||
}
|
||||
|
||||
private File getMalwareIngestFile() {
|
||||
return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, MALWARE_INGEST_SETTINGS_FILENAME).toFile();
|
||||
}
|
||||
}
|
||||
|
@ -11,103 +11,16 @@
|
||||
<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"/>
|
||||
<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,90,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">
|
||||
<TitledBorder title="Malware Scanner">
|
||||
<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>
|
||||
@ -121,78 +34,221 @@
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="malwareScansMessageLabel">
|
||||
<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/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.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"/>
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" 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>
|
||||
<Container class="javax.swing.JPanel" name="licenseInfoPanel">
|
||||
<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="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<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="1" 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="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="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="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="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="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="2" 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.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="2" 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>
|
||||
<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="4" 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="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="3" 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="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="3" 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="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="3" gridWidth="1" 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="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="5" 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="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="4" 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>
|
||||
<Container class="javax.swing.JPanel" name="purchasePanel">
|
||||
<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="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" 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>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<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/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.purchaseFromLabel.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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="purchaseLink">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="getHtmlLink(PURCHASE_URL)" type="code"/>
|
||||
</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="purchaseLinkMouseClicked"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -24,18 +24,22 @@ 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.LicenseLimitType;
|
||||
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.Desktop;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
@ -46,6 +50,7 @@ import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Options panel to be displayed in the CTOptionsPanel for settings regarding
|
||||
@ -71,6 +76,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
private volatile String licenseInfoMessage = null;
|
||||
private volatile LicenseFetcher licenseFetcher = null;
|
||||
|
||||
private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-malware-module";
|
||||
|
||||
private volatile AuthTokenResponse authTokenResponse = null;
|
||||
private volatile String authTokenMessage = null;
|
||||
private volatile AuthTokenFetcher authTokenFetcher = null;
|
||||
@ -127,12 +134,33 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
setMalwareScansDisplay(null, null);
|
||||
if (licenseInfo != null) {
|
||||
loadMalwareScansInfo(licenseInfo);
|
||||
this.purchaseFromLabel.setVisible(false);
|
||||
this.purchaseLink.setVisible(false);
|
||||
} else {
|
||||
this.purchaseFromLabel.setVisible(true);
|
||||
this.purchaseLink.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getHtmlLink(String url) {
|
||||
return "<html><span style=\"color: blue; text-decoration: underline\">" + url + "</span></html>";
|
||||
}
|
||||
|
||||
private void gotoLink(String url) {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URI(url));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.log(Level.SEVERE, "Error opening link to: " + url, e);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened.");
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized LicenseResponse getLicenseInfo() {
|
||||
return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) {
|
||||
this.licenseInfo = licenseInfo;
|
||||
@ -202,48 +230,55 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
malwareScansPanel = new javax.swing.JPanel();
|
||||
javax.swing.JLabel disclaimer = new javax.swing.JLabel();
|
||||
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();
|
||||
licenseInfoUserLabel = 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();
|
||||
maxHashLookupsLabel = new javax.swing.JLabel();
|
||||
hashLookupsRemainingLabel = new javax.swing.JLabel();
|
||||
malwareScansMessageLabel = new javax.swing.JLabel();
|
||||
countersResetLabel = new javax.swing.JLabel();
|
||||
fileUploadsRemainingLabel = new javax.swing.JLabel();
|
||||
javax.swing.JPanel purchasePanel = new javax.swing.JPanel();
|
||||
purchaseFromLabel = new javax.swing.JLabel();
|
||||
purchaseLink = 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
|
||||
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(disclaimer, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.disclaimer.text")); // NOI18N
|
||||
disclaimer.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
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(disclaimer, gridBagConstraints);
|
||||
|
||||
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.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
@ -252,12 +287,21 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(licenseInfoIdLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoIdLabel.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(licenseInfoIdLabel, 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 = 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);
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
licenseInfoPanel.add(licenseInfoUserLabel, 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() {
|
||||
@ -266,79 +310,108 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridx = 2;
|
||||
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.gridy = 4;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
malwareScansPanel.add(maxFileUploadsLabel, gridBagConstraints);
|
||||
licenseInfoPanel.add(maxFileUploadsLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(countersResetLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.countersResetLabel.text")); // NOI18N
|
||||
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 = 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);
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
licenseInfoPanel.add(maxHashLookupsLabel, 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.gridy = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
malwareScansPanel.add(hashLookupsRemainingLabel, gridBagConstraints);
|
||||
licenseInfoPanel.add(hashLookupsRemainingLabel, gridBagConstraints);
|
||||
|
||||
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 = 3;
|
||||
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(malwareScansMessageLabel, 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 = 5;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
licenseInfoPanel.add(countersResetLabel, 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.gridy = 4;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
malwareScansPanel.add(fileUploadsRemainingLabel, gridBagConstraints);
|
||||
licenseInfoPanel.add(fileUploadsRemainingLabel, 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;
|
||||
malwareScansPanel.add(licenseInfoPanel, gridBagConstraints);
|
||||
|
||||
purchasePanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.purchaseFromLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
purchasePanel.add(purchaseFromLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(purchaseLink, getHtmlLink(PURCHASE_URL));
|
||||
purchaseLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
|
||||
purchaseLink.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
purchaseLinkMouseClicked(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
|
||||
purchasePanel.add(purchaseLink, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
malwareScansPanel.add(purchasePanel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
@ -378,6 +451,10 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
}
|
||||
}//GEN-LAST:event_licenseInfoAddButtonActionPerformed
|
||||
|
||||
private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked
|
||||
gotoLink(PURCHASE_URL);
|
||||
}//GEN-LAST:event_purchaseLinkMouseClicked
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - userName",
|
||||
"# {1} - email",
|
||||
@ -387,9 +464,11 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
"# {0} - idNumber",
|
||||
"CTMalwareScannerOptionsPanel_licenseInfo_id=ID: {0}",
|
||||
"# {0} - maxDailyLookups",
|
||||
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day",
|
||||
"# {1} - resetSuffix",
|
||||
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}{1}",
|
||||
"# {0} - maxDailyFileLookups",
|
||||
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day",
|
||||
"# {1} - resetSuffix",
|
||||
"CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}{1}",
|
||||
"# {0} - countersResetDate",
|
||||
"CTMalwareScannerOptionsPanel_malwareScans_countersReset=Counters reset: {0}",
|
||||
"# {0} - hashLookupsRemaining",
|
||||
@ -406,7 +485,12 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
this.licenseInfoExpiresLabel.setVisible(false);
|
||||
this.licenseInfoIdLabel.setVisible(false);
|
||||
this.licenseInfoUserLabel.setVisible(false);
|
||||
this.purchaseFromLabel.setVisible(true);
|
||||
this.purchaseLink.setVisible(true);
|
||||
} else {
|
||||
this.purchaseFromLabel.setVisible(false);
|
||||
this.purchaseLink.setVisible(false);
|
||||
|
||||
this.licenseInfoExpiresLabel.setVisible(true);
|
||||
this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(
|
||||
this.licenseInfo.getDecryptedLicense().getExpirationDate() == null
|
||||
@ -420,12 +504,10 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
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) {
|
||||
if (authTokenResponse == null || this.licenseInfo == null) {
|
||||
this.maxHashLookupsLabel.setVisible(false);
|
||||
this.maxFileUploadsLabel.setVisible(false);
|
||||
this.countersResetLabel.setVisible(false);
|
||||
@ -433,15 +515,62 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
this.fileUploadsRemainingLabel.setVisible(false);
|
||||
} else {
|
||||
this.maxHashLookupsLabel.setVisible(true);
|
||||
this.maxHashLookupsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups(this.authTokenResponse.getHashLookupLimit()));
|
||||
this.maxHashLookupsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups(
|
||||
this.authTokenResponse.getHashLookupLimit(),
|
||||
getResetSuffix(this.licenseInfo.getDecryptedLicense().getLimitType())));
|
||||
|
||||
this.maxFileUploadsLabel.setVisible(true);
|
||||
this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(this.authTokenResponse.getFileUploadLimit()));
|
||||
this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(
|
||||
this.authTokenResponse.getFileUploadLimit(),
|
||||
getResetSuffix(this.licenseInfo.getDecryptedLicense().getLimitType())));
|
||||
|
||||
this.countersResetLabel.setVisible(true);
|
||||
this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(this.authTokenResponse.getResetDate() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getResetDate())));
|
||||
this.countersResetLabel.setText(getCountersResetText(this.licenseInfo.getDecryptedLicense().getLimitType(), this.authTokenResponse));
|
||||
|
||||
this.hashLookupsRemainingLabel.setVisible(true);
|
||||
this.hashLookupsRemainingLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining(remaining(this.authTokenResponse.getHashLookupLimit(), this.authTokenResponse.getHashLookupCount())));
|
||||
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())));
|
||||
this.fileUploadsRemainingLabel.setText(
|
||||
Bundle.CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining(
|
||||
remaining(this.authTokenResponse.getFileUploadLimit(), this.authTokenResponse.getFileUploadCount())));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCountersResetText(LicenseLimitType limitType, AuthTokenResponse authTokenResponse) {
|
||||
if (limitType == null || limitType == LicenseLimitType.NO_RESET) {
|
||||
return "";
|
||||
} else {
|
||||
return Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(
|
||||
MALWARE_SCANS_RESET_FORMAT.format(authTokenResponse.getResetDate()));
|
||||
}
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"CTMalwareScannerOptionsPanel_getResetSuffix_hourly=/hour",
|
||||
"CTMalwareScannerOptionsPanel_getResetSuffix_daily=/day",
|
||||
"CTMalwareScannerOptionsPanel_getResetSuffix_weekly=/week",
|
||||
"CTMalwareScannerOptionsPanel_getResetSuffix_monthly=/month"
|
||||
})
|
||||
private String getResetSuffix(LicenseLimitType limitType) {
|
||||
if (limitType == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (limitType) {
|
||||
case HOURLY:
|
||||
return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_hourly();
|
||||
case DAILY:
|
||||
return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_daily();
|
||||
case WEEKLY:
|
||||
return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_weekly();
|
||||
case MONTHLY:
|
||||
return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_monthly();
|
||||
case NO_RESET:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,6 +608,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
@NbBundle.Messages({
|
||||
"CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error",
|
||||
"CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error",
|
||||
"# {0} - licenseCode",
|
||||
"CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}",
|
||||
"CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.",})
|
||||
private class LicenseFetcher extends SwingWorker<LicenseResponse, Void> {
|
||||
|
||||
@ -500,8 +631,41 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
protected void done() {
|
||||
try {
|
||||
LicenseResponse licenseResponse = get();
|
||||
// if no result, show unauthorized
|
||||
if (licenseResponse == null) {
|
||||
logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch returned no result.");
|
||||
JOptionPane.showMessageDialog(
|
||||
CTMalwareScannerOptionsPanel.this,
|
||||
CTCloudException.ErrorCode.UN_AUTHORIZED.getDescription(),
|
||||
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
setLicenseDisplay(licenseInfo, null);
|
||||
loadMalwareScansInfo(licenseInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
// if not successful response
|
||||
if (!Boolean.TRUE.equals(licenseResponse.isSuccess())) {
|
||||
logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful");
|
||||
// use default message unless error message specified
|
||||
String message = Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc(licenseText);
|
||||
if (!StringUtils.isBlank(licenseResponse.getErrorMsg())) {
|
||||
message = licenseResponse.getErrorMsg();
|
||||
}
|
||||
JOptionPane.showMessageDialog(
|
||||
CTMalwareScannerOptionsPanel.this,
|
||||
message,
|
||||
Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
setLicenseDisplay(licenseInfo, null);
|
||||
loadMalwareScansInfo(licenseInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, load
|
||||
SwingUtilities.invokeLater(() -> acceptEula(licenseResponse));
|
||||
} catch (InterruptedException ex) {
|
||||
|
||||
} catch (InterruptedException | CancellationException ex) {
|
||||
// ignore cancellation; just load current license
|
||||
setLicenseDisplay(licenseInfo, null);
|
||||
loadMalwareScansInfo(licenseInfo);
|
||||
@ -548,8 +712,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
if (this.isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ctApiDAO.getAuthToken(decryptedLicense);
|
||||
|
||||
return ctApiDAO.getAuthToken(decryptedLicense);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -557,7 +721,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
AuthTokenResponse authTokenResponse = null;
|
||||
try {
|
||||
authTokenResponse = get();
|
||||
} catch (InterruptedException ex) {
|
||||
} catch (InterruptedException | CancellationException ex) {
|
||||
// ignore cancellation
|
||||
} catch (ExecutionException ex) {
|
||||
if (ex.getCause() != null && ex.getCause() instanceof CTCloudException cloudEx) {
|
||||
@ -600,5 +764,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
|
||||
private javax.swing.JPanel malwareScansPanel;
|
||||
private javax.swing.JLabel maxFileUploadsLabel;
|
||||
private javax.swing.JLabel maxHashLookupsLabel;
|
||||
private javax.swing.JLabel purchaseFromLabel;
|
||||
private javax.swing.JLabel purchaseLink;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ 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 {
|
||||
class EULADialog extends javax.swing.JDialog {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EULADialog.class.getName());
|
||||
private static final String EULA_RESOURCE = "EULA.htm";
|
||||
|
@ -0,0 +1,16 @@
|
||||
|
||||
# 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
|
||||
|
||||
CTIncidentImportOptionsPanel.border.title=Local Settings
|
||||
CTIncidentImportOptionsPanel.fileRepoPathLabel.text=Update the Cyber Triage Data Folder if you are not using the default location:
|
||||
CTIncidentImportOptionsPanel.fileRepoPathField.text=
|
||||
CTIncidentImportOptionsPanel.fileRepoBrowseButton.text=Browse
|
||||
CTIncidentImportOptionsPanel.caseOpenWarningLabel.text=Some settings cannot be modified while a case is open.
|
||||
CTIncidentImportOptionsPanel.fileRepoFileChooser.title=Cyber Triage Data Folder
|
||||
CTIncidentImportOptionsPanel.border.title_1=Incident Importer
|
||||
CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module.
|
||||
CTincidentImportOptionsPanel.instructionsTextLabel.text=
|
||||
CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to:
|
||||
CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module:
|
||||
CTIncidentImportOptionsPanel.importModuleDetected.text=
|
@ -0,0 +1,18 @@
|
||||
|
||||
# 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
|
||||
|
||||
CTIncidentImportOptionsPanel.border.title=Local Settings
|
||||
CTIncidentImportOptionsPanel.fileRepoPathLabel.text=Update the Cyber Triage Data Folder if you are not using the default location:
|
||||
CTIncidentImportOptionsPanel.fileRepoPathField.text=
|
||||
CTIncidentImportOptionsPanel.fileRepoBrowseButton.text=Browse
|
||||
CTIncidentImportOptionsPanel.caseOpenWarningLabel.text=Some settings cannot be modified while a case is open.
|
||||
CTIncidentImportOptionsPanel.fileRepoFileChooser.title=Cyber Triage Data Folder
|
||||
CTIncidentImportOptionsPanel.border.title_1=Incident Importer
|
||||
CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module.
|
||||
CTincidentImportOptionsPanel.instructionsTextLabel.text=
|
||||
CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to:
|
||||
CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module:
|
||||
CTIncidentImportOptionsPanel.importModuleDetected.text=
|
||||
CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected
|
||||
CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected
|
@ -0,0 +1,199 @@
|
||||
<?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="Incident Importer">
|
||||
<ResourceString PropertyName="titleX" bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.border.title_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</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,-50,0,0,1,-17"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="incidentTextPanel">
|
||||
<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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="incidentTextLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.incidentTextLabel.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="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="importModule">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.importModule.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="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="importModuleDetected">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.importModuleDetected.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="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="instructionsPanel">
|
||||
<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="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="instructionsTextLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.instructionsTextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="For instructions on obtaining the module refer to:"/>
|
||||
</AccessibilityProperties>
|
||||
<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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="instructionsLinkLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="getHtmlLink(CT_IMPORTER_DOC_LINK)" type="code"/>
|
||||
</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="instructionsLinkLabelMouseClicked"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="repoPanel">
|
||||
<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="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="fileRepoPathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.fileRepoPathLabel.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="2" gridHeight="1" fill="0" 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.JTextField" name="fileRepoPathField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.fileRepoPathField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fileRepoPathFieldActionPerformed"/>
|
||||
</Events>
|
||||
<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="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="fileRepoBrowseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.fileRepoBrowseButton.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="fileRepoBrowseButtonActionPerformed"/>
|
||||
</Events>
|
||||
<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="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="caseOpenWarningLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.caseOpenWarningLabel.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="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* 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.incidentoptions;
|
||||
|
||||
import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Stream;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.casemodule.AutopsyContentProvider;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
|
||||
|
||||
/**
|
||||
* Options panel for CyberTriage options for importing a CyberTriage incident
|
||||
*/
|
||||
@ServiceProvider(service = CTOptionsSubPanel.class)
|
||||
public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CTIncidentImportOptionsPanel.class.getName());
|
||||
|
||||
private static final String CT_IMPORTER_DOC_LINK = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html";
|
||||
|
||||
private static final String CT_STANDARD_CONTENT_PROVIDER_NAME = "CTStandardContentProvider";
|
||||
|
||||
private final JFileChooserFactory fileRepoChooserFactory = new JFileChooserFactory();
|
||||
private final CTSettingsPersistence ctPersistence = CTSettingsPersistence.getInstance();
|
||||
|
||||
private static String getHtmlLink(String url) {
|
||||
return "<html><span style=\"color: blue; text-decoration: underline\">" + url + "</span></html>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form CTIncidentImportOptionsPanel
|
||||
*/
|
||||
public CTIncidentImportOptionsPanel() {
|
||||
initComponents();
|
||||
this.fileRepoPathField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
fireSettingsChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
fireSettingsChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
fireSettingsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.CURRENT_CASE), (evt) -> {
|
||||
CTIncidentImportOptionsPanel.this.setEnabledItems(evt.getNewValue() != null);
|
||||
});
|
||||
}
|
||||
|
||||
private void setCTSettingsDisplay(CTSettings ctSettings) {
|
||||
this.fileRepoPathField.setText(ctSettings.getFileRepoPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void saveSettings() {
|
||||
ctPersistence.saveCTSettings(getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void loadSettings() {
|
||||
CTSettings ctSettings = ctPersistence.loadCTSettings();
|
||||
setCTSettingsDisplay(ctSettings);
|
||||
setModuleDetected();
|
||||
setEnabledItems(Case.isCaseOpen());
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected",
|
||||
"CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected"
|
||||
})
|
||||
private void setModuleDetected() {
|
||||
Collection<? extends AutopsyContentProvider> contentProviders = Lookup.getDefault().lookupAll(AutopsyContentProvider.class);
|
||||
boolean detected = ((Collection<? extends AutopsyContentProvider>) (contentProviders != null ? contentProviders : Collections.emptyList())).stream()
|
||||
.anyMatch(p -> p != null && StringUtils.defaultString(p.getName()).toUpperCase().startsWith(CT_STANDARD_CONTENT_PROVIDER_NAME.toUpperCase()));
|
||||
|
||||
this.importModuleDetected.setText(detected
|
||||
? Bundle.CTIncidentImportOptionsPanel_setModuleDetected_detected()
|
||||
: Bundle.CTIncidentImportOptionsPanel_setModuleDetected_notDetected());
|
||||
}
|
||||
|
||||
private void setEnabledItems(boolean caseOpen) {
|
||||
this.caseOpenWarningLabel.setVisible(caseOpen);
|
||||
this.fileRepoBrowseButton.setEnabled(!caseOpen);
|
||||
this.fileRepoPathField.setEnabled(!caseOpen);
|
||||
}
|
||||
|
||||
private void fireSettingsChanged() {
|
||||
this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
|
||||
private CTSettings getSettings() {
|
||||
return new CTSettings().setFileRepoPath(this.fileRepoPathField.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid() {
|
||||
return new File(this.fileRepoPathField.getText()).isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
incidentTextPanel = new javax.swing.JPanel();
|
||||
incidentTextLabel = new javax.swing.JLabel();
|
||||
javax.swing.JLabel importModule = new javax.swing.JLabel();
|
||||
importModuleDetected = new javax.swing.JLabel();
|
||||
instructionsPanel = new javax.swing.JPanel();
|
||||
instructionsTextLabel = new javax.swing.JLabel();
|
||||
instructionsLinkLabel = new javax.swing.JLabel();
|
||||
repoPanel = new javax.swing.JPanel();
|
||||
javax.swing.JLabel fileRepoPathLabel = new javax.swing.JLabel();
|
||||
fileRepoPathField = new javax.swing.JTextField();
|
||||
fileRepoBrowseButton = new javax.swing.JButton();
|
||||
caseOpenWarningLabel = new javax.swing.JLabel();
|
||||
|
||||
setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.border.title_1"))); // NOI18N
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
incidentTextPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(incidentTextLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.incidentTextLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
incidentTextPanel.add(incidentTextLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(importModule, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModule.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 3);
|
||||
incidentTextPanel.add(importModule, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(importModuleDetected, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModuleDetected.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
|
||||
incidentTextPanel.add(importModuleDetected, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
add(incidentTextPanel, gridBagConstraints);
|
||||
|
||||
instructionsPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(instructionsTextLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.instructionsTextLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
|
||||
instructionsPanel.add(instructionsTextLabel, gridBagConstraints);
|
||||
instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:");
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(instructionsLinkLabel, getHtmlLink(CT_IMPORTER_DOC_LINK));
|
||||
instructionsLinkLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
|
||||
instructionsLinkLabel.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
instructionsLinkLabelMouseClicked(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
instructionsPanel.add(instructionsLinkLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
add(instructionsPanel, gridBagConstraints);
|
||||
|
||||
repoPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(fileRepoPathLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoPathLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
repoPanel.add(fileRepoPathLabel, gridBagConstraints);
|
||||
|
||||
fileRepoPathField.setText(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoPathField.text")); // NOI18N
|
||||
fileRepoPathField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
fileRepoPathFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
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;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
repoPanel.add(fileRepoPathField, gridBagConstraints);
|
||||
fileRepoPathField.getAccessibleContext().setAccessibleName("");
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(fileRepoBrowseButton, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoBrowseButton.text")); // NOI18N
|
||||
fileRepoBrowseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
fileRepoBrowseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
repoPanel.add(fileRepoBrowseButton, gridBagConstraints);
|
||||
|
||||
caseOpenWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(caseOpenWarningLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.caseOpenWarningLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
repoPanel.add(caseOpenWarningLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
add(repoPanel, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
private void fileRepoBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileRepoBrowseButtonActionPerformed
|
||||
JFileChooser fileChooser = fileRepoChooserFactory.getChooser();
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
|
||||
File curSelectedDir = StringUtils.isBlank(this.fileRepoPathField.getText()) ? null : new File(this.fileRepoPathField.getText());
|
||||
if (curSelectedDir == null || !curSelectedDir.isDirectory()) {
|
||||
curSelectedDir = new File(CTSettings.getDefaultFileRepoPath());
|
||||
}
|
||||
|
||||
fileChooser.setCurrentDirectory(curSelectedDir);
|
||||
fileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoFileChooser.title"));
|
||||
int retVal = fileChooser.showOpenDialog(this);
|
||||
if (retVal == JFileChooser.APPROVE_OPTION) {
|
||||
this.fileRepoPathField.setText(fileChooser.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
}//GEN-LAST:event_fileRepoBrowseButtonActionPerformed
|
||||
|
||||
private void fileRepoPathFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileRepoPathFieldActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_fileRepoPathFieldActionPerformed
|
||||
|
||||
private void instructionsLinkLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_instructionsLinkLabelMouseClicked
|
||||
gotoLink(CT_IMPORTER_DOC_LINK);
|
||||
}//GEN-LAST:event_instructionsLinkLabelMouseClicked
|
||||
|
||||
private void gotoLink(String url) {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URI(url));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.log(Level.SEVERE, "Error opening link to: " + url, e);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened.");
|
||||
}
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel caseOpenWarningLabel;
|
||||
private javax.swing.JButton fileRepoBrowseButton;
|
||||
private javax.swing.JTextField fileRepoPathField;
|
||||
private javax.swing.JLabel importModuleDetected;
|
||||
private javax.swing.JLabel incidentTextLabel;
|
||||
private javax.swing.JPanel incidentTextPanel;
|
||||
private javax.swing.JLabel instructionsLinkLabel;
|
||||
private javax.swing.JPanel instructionsPanel;
|
||||
private javax.swing.JLabel instructionsTextLabel;
|
||||
private javax.swing.JPanel repoPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.incidentoptions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.modules.Places;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
|
||||
/**
|
||||
* CT settings that don't include license information. This code must be kept
|
||||
* in-sync with code in CT Autopsy Importer NBM.
|
||||
*/
|
||||
public class CTSettings {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CTSettings.class.getCanonicalName());
|
||||
private static final String DEFAULT_FILE_REPO_PATH = getAppDataLocalDirectory();
|
||||
|
||||
private static final String CYBERTRIAGE_FOLDER = "cybertriage";
|
||||
private static final String CYBERTRIAGE_DOT_FOLDER = "." + CYBERTRIAGE_FOLDER;
|
||||
|
||||
// based on com.basistech.df.cybertriage.utils.SystemProperties
|
||||
private static String getAppDataLocalDirectory() {
|
||||
if (Objects.nonNull(Places.getUserDirectory()) && Places.getUserDirectory().getAbsolutePath().endsWith("testuserdir")) { // APP is in testing .. this should return the test path
|
||||
LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath());
|
||||
return Places.getUserDirectory().getAbsolutePath();
|
||||
}
|
||||
|
||||
// try to use LOCALAPPDATA on windows
|
||||
String localDataStr = System.getenv("LOCALAPPDATA");
|
||||
if (StringUtils.isNotBlank(localDataStr)) {
|
||||
Path localAppPath = Paths.get(localDataStr, CYBERTRIAGE_FOLDER);
|
||||
try {
|
||||
Files.createDirectories(localAppPath);
|
||||
LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString());
|
||||
return localAppPath.toString();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
// try to use ~/.cybertriage anywhere else
|
||||
if (!PlatformUtil.isWindowsOS()) {
|
||||
String homePathStr = System.getenv("HOME");
|
||||
if (StringUtils.isNotBlank(homePathStr)) {
|
||||
Path localAppPath = Paths.get(homePathStr, CYBERTRIAGE_DOT_FOLDER);
|
||||
try {
|
||||
Files.createDirectories(localAppPath);
|
||||
LOGGER.log(Level.INFO, "Non-windows Application Data Path: " + localAppPath.toString());
|
||||
return localAppPath.toString();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// defer to user directory otherwise
|
||||
return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error
|
||||
}
|
||||
|
||||
public static String getDefaultFileRepoPath() {
|
||||
return DEFAULT_FILE_REPO_PATH;
|
||||
}
|
||||
|
||||
static CTSettings getDefaultSettings() {
|
||||
return new CTSettings()
|
||||
.setFileRepoPath(DEFAULT_FILE_REPO_PATH);
|
||||
}
|
||||
|
||||
private String fileRepoPath = DEFAULT_FILE_REPO_PATH;
|
||||
|
||||
public String getFileRepoPath() {
|
||||
return fileRepoPath;
|
||||
}
|
||||
|
||||
public CTSettings setFileRepoPath(String fileRepoPath) {
|
||||
this.fileRepoPath = fileRepoPath;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.incidentoptions;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
|
||||
/**
|
||||
* Handles persisting CT Settings. This code must be kept in-sync with code in
|
||||
* CT Autopsy Importer NBM.
|
||||
*/
|
||||
public class CTSettingsPersistence {
|
||||
|
||||
private static final String CT_SETTINGS_DIR = "CyberTriage";
|
||||
private static final String CT_SETTINGS_FILENAME = "CyberTriageSettings.json";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CTSettingsPersistence.class.getName());
|
||||
|
||||
private static final CTSettingsPersistence instance = new CTSettingsPersistence();
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
public static CTSettingsPersistence getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public synchronized boolean saveCTSettings(CTSettings ctSettings) {
|
||||
if (ctSettings != null) {
|
||||
|
||||
File settingsFile = getCTSettingsFile();
|
||||
settingsFile.getParentFile().mkdirs();
|
||||
try {
|
||||
objectMapper.writeValue(settingsFile, ctSettings);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "There was an error writing CyberTriage settings to file: " + settingsFile.getAbsolutePath(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized CTSettings loadCTSettings() {
|
||||
|
||||
CTSettings settings = null;
|
||||
File settingsFile = getCTSettingsFile();
|
||||
if (settingsFile.isFile()) {
|
||||
try {
|
||||
settings = objectMapper.readValue(settingsFile, CTSettings.class);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "There was an error reading CyberTriage settings to file: " + settingsFile.getAbsolutePath(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return settings == null
|
||||
? CTSettings.getDefaultSettings()
|
||||
: settings;
|
||||
|
||||
}
|
||||
|
||||
private File getCTSettingsFile() {
|
||||
return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_SETTINGS_FILENAME).toFile();
|
||||
}
|
||||
}
|
@ -21,14 +21,10 @@ 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;
|
||||
|
||||
/**
|
||||
@ -36,7 +32,7 @@ import java.util.function.Consumer;
|
||||
* blocks (and subsequently add and flush operations) until previous batch
|
||||
* finishes.
|
||||
*/
|
||||
public class BatchProcessor<T> {
|
||||
class BatchProcessor<T> {
|
||||
|
||||
private ExecutorService processingExecutorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
|
||||
DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash
|
||||
MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
|
||||
MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
|
||||
MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
|
@ -1,3 +1,7 @@
|
||||
MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Waiting for all uploaded files to complete scanning.
|
||||
MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results
|
||||
MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later.
|
||||
MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout
|
||||
MalwareScanIngestModule_malwareTypeDisplayName=Malware
|
||||
# {0} - errorResponse
|
||||
MalwareScanIngestModule_SharedProcessing_authTokenResponseError_desc=Received error: ''{0}'' when fetching the API authentication token for the license
|
||||
@ -6,6 +10,8 @@ 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_exhaustedResultsHashLookups_desc=Not all files were processed because hash lookup limits were exceeded. Please try again when your limits reset.
|
||||
MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Lookup Limits Exceeded
|
||||
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
|
||||
@ -16,12 +22,29 @@ MalwareScanIngestModule_SharedProcessing_repServicenResponseError_title=Lookup A
|
||||
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_lowLookupsLimitWarning_desc=This license only has {0} lookups remaining.
|
||||
MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title=Hash Lookups Low
|
||||
# {0} - remainingUploads
|
||||
MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.
|
||||
MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit 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.
|
||||
MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Malware scanning will be disabled.
|
||||
MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups
|
||||
MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled.
|
||||
MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads
|
||||
MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc=There are no more file uploads on this license at this time. File uploads will be disabled for remaining uploads.
|
||||
MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining File Uploads
|
||||
# {0} - objectId
|
||||
MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}).
|
||||
MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload
|
||||
MalwareScanIngestModuleFactory_description=Identifies executable files with malware.
|
||||
MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner
|
||||
MalwareScanIngestModuleFactory_version=1.0.0
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
|
||||
MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
|
||||
DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash
|
||||
MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
|
||||
MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
|
||||
MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,8 @@ import org.sleuthkit.autopsy.ingest.FileIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings;
|
||||
|
||||
/**
|
||||
* Factory for malware scan ingest modules.
|
||||
@ -32,7 +34,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
@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_description=Identifies executable files with malware.",
|
||||
"MalwareScanIngestModuleFactory_version=1.0.0"
|
||||
})
|
||||
public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
@ -66,7 +68,7 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
|
||||
@Override
|
||||
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) {
|
||||
return new MalwareScanIngestModule();
|
||||
return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -81,4 +83,23 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
return optionsPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIngestJobSettingsPanel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
|
||||
if (settings instanceof MalwareScanIngestSettings) {
|
||||
return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings);
|
||||
}
|
||||
/*
|
||||
* Compatibility check for older versions.
|
||||
*/
|
||||
if (settings instanceof NoIngestModuleIngestJobSettings) {
|
||||
return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
|
||||
/**
|
||||
* Ingest job settings for the Malware scanner module.
|
||||
*/
|
||||
final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final boolean DEFAULT_QUERY_FILES = true;
|
||||
private static final boolean DEFAULT_UPLOAD_FILES = true;
|
||||
|
||||
public boolean queryFiles;
|
||||
public boolean uploadFiles;
|
||||
|
||||
/**
|
||||
* Instantiate the ingest job settings with default values.
|
||||
*/
|
||||
MalwareScanIngestSettings() {
|
||||
this.queryFiles = DEFAULT_QUERY_FILES;
|
||||
this.uploadFiles = DEFAULT_UPLOAD_FILES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the ingest job settings.
|
||||
*
|
||||
* @param computeHashes Compute hashes if none are present
|
||||
* @param verifyHashes Verify hashes if any are present
|
||||
*/
|
||||
MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) {
|
||||
this.queryFiles = queryFiles;
|
||||
this.uploadFiles = uploadFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersionNumber() {
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should files be queried?
|
||||
*
|
||||
* @return true if files should be queried, false otherwise
|
||||
*/
|
||||
public boolean shouldQueryFiles() {
|
||||
return queryFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether files should be queried.
|
||||
*
|
||||
* @param queryFiles true if files should be queried
|
||||
*/
|
||||
void setqueryFiles(boolean queryFiles) {
|
||||
this.queryFiles = queryFiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should files be uploaded?
|
||||
*
|
||||
* @return true if files should be uploaded, false otherwise
|
||||
*/
|
||||
public boolean shouldUploadFiles() {
|
||||
return uploadFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether files should be uploaded.
|
||||
*
|
||||
* @param uploadFiles true if files should be uploaded
|
||||
*/
|
||||
void setUploadFiles(boolean uploadFiles) {
|
||||
this.uploadFiles = uploadFiles;
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 155]"/>
|
||||
</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"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="6" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="6" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
<Component id="paidLicenseTextArea" min="-2" pref="243" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="185" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="paidLicenseTextArea" min="-2" pref="32" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="queryFilesCheckbox">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.queryFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="uploadFilesCheckbox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="label" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="ingestSettingsLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="ingestSettingsLabel" property="font" relativeSize="true" size="0"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.ingestSettingsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextArea" name="paidLicenseTextArea">
|
||||
<Properties>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Segoe UI" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="rows" type="int" value="5"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.paidLicenseTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Autopsy 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.json.LicenseInfo;
|
||||
import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence;
|
||||
import java.util.Optional;
|
||||
import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
|
||||
|
||||
/**
|
||||
* Ingest job settings panel for the Malware scanner ingest.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
||||
|
||||
private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance();
|
||||
|
||||
MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) {
|
||||
initComponents();
|
||||
customizeComponents(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update components with values from the ingest job settings.
|
||||
*
|
||||
* @param settings The ingest job settings.
|
||||
*/
|
||||
private void customizeComponents(MalwareScanIngestSettings settings) {
|
||||
Optional<LicenseInfo> licenseInfoOpt = ctPersistence.loadLicenseInfo();
|
||||
LicenseInfo licenseInfo = licenseInfoOpt.orElse(null);
|
||||
if (licenseInfo != null) {
|
||||
this.paidLicenseTextArea.setVisible(false);
|
||||
this.queryFilesCheckbox.setVisible(true);
|
||||
this.queryFilesCheckbox.setEnabled(false);
|
||||
this.uploadFilesCheckbox.setVisible(true);
|
||||
this.queryFilesCheckbox.setSelected(true);
|
||||
this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles());
|
||||
} else {
|
||||
this.paidLicenseTextArea.setVisible(true);
|
||||
this.queryFilesCheckbox.setVisible(false);
|
||||
this.uploadFilesCheckbox.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestModuleIngestJobSettings getSettings() {
|
||||
return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
queryFilesCheckbox = new javax.swing.JCheckBox();
|
||||
uploadFilesCheckbox = new javax.swing.JCheckBox();
|
||||
ingestSettingsLabel = new javax.swing.JLabel();
|
||||
paidLicenseTextArea = new javax.swing.JTextArea();
|
||||
|
||||
setPreferredSize(new java.awt.Dimension(300, 155));
|
||||
|
||||
queryFilesCheckbox.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N
|
||||
queryFilesCheckbox.setEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N
|
||||
uploadFilesCheckbox.setFocusable(false);
|
||||
uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N
|
||||
|
||||
ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N
|
||||
|
||||
paidLicenseTextArea.setColumns(20);
|
||||
paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N
|
||||
paidLicenseTextArea.setRows(5);
|
||||
paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N
|
||||
paidLicenseTextArea.setWrapStyleWord(true);
|
||||
paidLicenseTextArea.setBorder(null);
|
||||
paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
paidLicenseTextArea.setFocusable(false);
|
||||
paidLicenseTextArea.setOpaque(false);
|
||||
paidLicenseTextArea.setRequestFocusEnabled(false);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(ingestSettingsLabel))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(uploadFilesCheckbox))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(queryFilesCheckbox))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(5, 5, 5)
|
||||
.addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(185, 185, 185))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(ingestSettingsLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(queryFilesCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(uploadFilesCheckbox)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
);
|
||||
|
||||
uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel ingestSettingsLabel;
|
||||
private javax.swing.JTextArea paidLicenseTextArea;
|
||||
private javax.swing.JCheckBox queryFilesCheckbox;
|
||||
private javax.swing.JCheckBox uploadFilesCheckbox;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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.google.common.net.InetAddresses;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Utility class to anonymize paths.
|
||||
*/
|
||||
class PathNormalizer {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(PathNormalizer.class.getName());
|
||||
|
||||
private static final String ANONYMIZED_USERNAME = "<user>";
|
||||
private static final String ANONYMIZED_IP = "<private_ip>";
|
||||
private static final String ANONYMIZED_HOSTNAME = "<hostname>";
|
||||
private static final String FORWARD_SLASH = "/";
|
||||
private static final String BACK_SLASH = "\\";
|
||||
|
||||
private static final Pattern USER_PATH_FORWARD_SLASH_REGEX = Pattern.compile("(?<!all )([/]{0,1}\\Qusers\\E/)(?!(public|Default|defaultAccount|All Users))([^/]+)(/){0,1}", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern USER_PATH_BACK_SLASH_REGEX = Pattern.compile("(?<!all )([\\\\]{0,1}\\Qusers\\E\\\\)(?!(public|Default|defaultAccount|All Users))([^\\\\]+)([\\\\]){0,1}", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final Pattern USER_PATH_FORWARD_SLASH_REGEX_XP = Pattern.compile("([/]{0,1}\\Qdocuments and settings\\E/)(?!(Default User|All Users))([^/]+)(/){0,1}", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern USER_PATH_BACK_SLASH_REGEX_XP = Pattern.compile("([\\\\]{0,1}\\Qdocuments and settings\\E\\\\)(?!(Default User|All Users))([^\\\\]+)(\\\\){0,1}", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final Pattern UNC_PATH_FORWARD_SLASH_PATTERN = Pattern.compile("(//)([^/]+)(/){0,1}");
|
||||
private static final Pattern UNC_PATH_BACK_SLASH_PATTERN = Pattern.compile("(\\\\\\\\)([^\\\\]+)(\\\\){0,1}");
|
||||
|
||||
private static final String USERNAME_REGEX_REPLACEMENT = "$1" + ANONYMIZED_USERNAME + "$4";
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
|
||||
PathNormalizer(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
}
|
||||
|
||||
protected List<String> getUsernames() {
|
||||
try {
|
||||
return this.skCase.getOsAccountManager().getOsAccounts().stream()
|
||||
.filter(acct -> acct != null)
|
||||
.map(acct -> acct.getLoginName().orElse(null))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "There was an error getting current os accounts", ex);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public String normalizePath(String inputString) {
|
||||
if (StringUtils.isBlank(inputString)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String anonymousString = anonymizeUserFromPathsWithForwardSlashes(inputString);
|
||||
anonymousString = anonymizeUserFromPathsWithBackSlashes(anonymousString);
|
||||
anonymousString = anonymizeServerFromUNCPath(anonymousString);
|
||||
|
||||
return anonymousString;
|
||||
}
|
||||
|
||||
private String anonymizeUserFromPathsWithForwardSlashes(String stringWithUsername) {
|
||||
String anonymousString = stringWithUsername;
|
||||
anonymousString = regexReplace(anonymousString, USER_PATH_FORWARD_SLASH_REGEX_XP, USERNAME_REGEX_REPLACEMENT);
|
||||
anonymousString = regexReplace(anonymousString, USER_PATH_FORWARD_SLASH_REGEX, USERNAME_REGEX_REPLACEMENT);
|
||||
anonymousString = replaceFolder(anonymousString, getUsernames(), ANONYMIZED_USERNAME, FORWARD_SLASH);
|
||||
return anonymousString;
|
||||
}
|
||||
|
||||
// Most paths in CyberTriage are normalized with forward slashes
|
||||
// but there can still be strings containing paths that are not normalized such paths contained in arguments or event log payloads
|
||||
private String anonymizeUserFromPathsWithBackSlashes(String stringWithUsername) {
|
||||
String anonymousString = stringWithUsername;
|
||||
anonymousString = regexReplace(anonymousString, USER_PATH_BACK_SLASH_REGEX_XP, USERNAME_REGEX_REPLACEMENT);
|
||||
anonymousString = regexReplace(anonymousString, USER_PATH_BACK_SLASH_REGEX, USERNAME_REGEX_REPLACEMENT);
|
||||
anonymousString = replaceFolder(anonymousString, getUsernames(), ANONYMIZED_USERNAME, BACK_SLASH);
|
||||
|
||||
return anonymousString;
|
||||
}
|
||||
|
||||
private String anonymizeServerFromUNCPath(String inputString) {
|
||||
|
||||
Set<String> serverNames = new HashSet<>();
|
||||
String anonymousString = inputString.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
Matcher forwardSlashMatcher = UNC_PATH_FORWARD_SLASH_PATTERN.matcher(anonymousString);
|
||||
while (forwardSlashMatcher.find()) {
|
||||
String serverName = forwardSlashMatcher.group(2);
|
||||
serverNames.add(serverName);
|
||||
}
|
||||
|
||||
Matcher backSlashMatcher = UNC_PATH_BACK_SLASH_PATTERN.matcher(anonymousString);
|
||||
while (backSlashMatcher.find()) {
|
||||
String serverName = backSlashMatcher.group(2);
|
||||
serverNames.add(serverName);
|
||||
}
|
||||
|
||||
for (String serverName : serverNames) {
|
||||
|
||||
if (StringUtils.isBlank(serverName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (InetAddresses.isInetAddress(serverName) && isLocalIP(serverName)) {
|
||||
anonymousString = replaceFolder(anonymousString, Collections.singletonList(serverName), ANONYMIZED_IP);
|
||||
} else {
|
||||
anonymousString = replaceFolder(anonymousString, Collections.singletonList(serverName), ANONYMIZED_HOSTNAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return anonymousString;
|
||||
}
|
||||
|
||||
private static String regexReplace(String orig, Pattern pattern, String regexReplacement) {
|
||||
Matcher matcher = pattern.matcher(orig);
|
||||
return matcher.replaceAll(regexReplacement);
|
||||
}
|
||||
|
||||
private static String replaceFolder(String orig, List<String> valuesToReplace, String replacementValue) {
|
||||
String anonymized = orig;
|
||||
anonymized = replaceFolder(anonymized, valuesToReplace, replacementValue, FORWARD_SLASH);
|
||||
anonymized = replaceFolder(anonymized, valuesToReplace, replacementValue, BACK_SLASH);
|
||||
return anonymized;
|
||||
}
|
||||
|
||||
private static String replaceFolder(String orig, List<String> valuesToReplace, String replacementValue, String folderDelimiter) {
|
||||
if (orig == null || valuesToReplace == null) {
|
||||
return orig;
|
||||
}
|
||||
|
||||
String anonymousString = orig;
|
||||
|
||||
// ensure non-null
|
||||
folderDelimiter = StringUtils.defaultString(folderDelimiter);
|
||||
replacementValue = StringUtils.defaultString(replacementValue);
|
||||
|
||||
// replace
|
||||
for (String valueToReplace : valuesToReplace) {
|
||||
if (StringUtils.isNotEmpty(valueToReplace)) {
|
||||
anonymousString = StringUtils.replace(anonymousString,
|
||||
folderDelimiter + valueToReplace + folderDelimiter,
|
||||
folderDelimiter + replacementValue + folderDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
return anonymousString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if IP Address is Any Local / Site Local / Link Local / Loop
|
||||
* back local. Sample list "0.0.0.0", wildcard addres
|
||||
* "10.1.1.1","10.10.10.10", site local address "127.0.0.0","127.2.2.2",
|
||||
* loopback address "169.254.0.0","169.254.10.10", Link local address
|
||||
* "172.16.0.0","172.31.245.245", site local address
|
||||
*
|
||||
* @param ipAddress
|
||||
* @return
|
||||
*/
|
||||
public static boolean isLocalIP(String ipAddress) {
|
||||
try {
|
||||
InetAddress a = InetAddresses.forString(ipAddress);
|
||||
return a.isAnyLocalAddress() || a.isSiteLocalAddress()
|
||||
|| a.isLoopbackAddress() || a.isLinkLocalAddress();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
LOGGER.log(Level.WARNING, "Invalid IP string", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -66,8 +66,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the
|
||||
Case.open.msgDlg.updated.title=Case Database Schema Update
|
||||
Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\
|
||||
this case are missing. Would you like to search for them now?\n\
|
||||
Previously, the image was located at:\n\
|
||||
{0}\n\
|
||||
Previously, the image with host, {0}, was located at:\n\
|
||||
{1}\n\
|
||||
Please note that you will still be able to browse directories and generate reports\n\
|
||||
if you choose No, but you will not be able to view file content or run the ingest process.
|
||||
Case.checkImgExist.confDlg.doesntExist.title=Missing Image
|
||||
|
@ -16,6 +16,7 @@ Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it mus
|
||||
Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host.
|
||||
Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window
|
||||
Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case.
|
||||
Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded.
|
||||
# {0} - exception message
|
||||
Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}.
|
||||
# {0} - exception message
|
||||
@ -252,8 +253,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the
|
||||
Case.open.msgDlg.updated.title=Case Database Schema Update
|
||||
Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\
|
||||
this case are missing. Would you like to search for them now?\n\
|
||||
Previously, the image was located at:\n\
|
||||
{0}\n\
|
||||
Previously, the image with host, {0}, was located at:\n\
|
||||
{1}\n\
|
||||
Please note that you will still be able to browse directories and generate reports\n\
|
||||
if you choose No, but you will not be able to view file content or run the ingest process.
|
||||
Case.checkImgExist.confDlg.doesntExist.title=Missing Image
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import com.basistech.df.cybertriage.autopsy.CTIntegrationMissingDialog;
|
||||
import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils;
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
@ -177,6 +178,7 @@ public class Case {
|
||||
private static final String CASE_ACTION_THREAD_NAME = "%s-case-action";
|
||||
private static final String CASE_RESOURCES_THREAD_NAME = "%s-manage-case-resources";
|
||||
private static final String NO_NODE_ERROR_MSG_FRAGMENT = "KeeperErrorCode = NoNode";
|
||||
private static final String CT_PROVIDER_PREFIX = "CTStandardContentProvider_";
|
||||
private static final Logger logger = Logger.getLogger(Case.class.getName());
|
||||
private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
|
||||
private static final Object caseActionSerializationLock = new Object();
|
||||
@ -192,6 +194,8 @@ public class Case {
|
||||
private final SleuthkitEventListener sleuthkitEventListener;
|
||||
private CollaborationMonitor collaborationMonitor;
|
||||
private Services caseServices;
|
||||
// matches something like '\\.\PHYSICALDRIVE0'
|
||||
private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\PHYSICALDRIVE\\d*\\s*$";
|
||||
|
||||
private volatile boolean hasDataSource = false;
|
||||
private volatile boolean hasData = false;
|
||||
@ -1301,9 +1305,18 @@ public class Case {
|
||||
for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
|
||||
long obj_id = entry.getKey();
|
||||
String path = entry.getValue();
|
||||
boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path));
|
||||
boolean fileExists = (new File(path).exists()|| DriveUtils.driveExists(path));
|
||||
if (!fileExists) {
|
||||
// CT-7336: ignore relocating datasources if file provider is present and placeholder path is used.
|
||||
if (newCurrentCase.getMetadata() != null
|
||||
&& !StringUtils.isBlank(newCurrentCase.getMetadata().getContentProviderName())
|
||||
&& (path == null || path.matches(PLACEHOLDER_DS_PATH_REGEX))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
DataSource ds = newCurrentCase.getSleuthkitCase().getDataSource(obj_id);
|
||||
String hostName = StringUtils.defaultString(ds.getHost() == null ? "" : ds.getHost().getName());
|
||||
// Using invokeAndWait means that the dialog will
|
||||
// open on the EDT but this thread will wait for an
|
||||
// answer. Using invokeLater would cause this loop to
|
||||
@ -1313,7 +1326,7 @@ public class Case {
|
||||
public void run() {
|
||||
int response = JOptionPane.showConfirmDialog(
|
||||
mainFrame,
|
||||
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path),
|
||||
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", hostName, path),
|
||||
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"),
|
||||
JOptionPane.YES_NO_OPTION);
|
||||
if (response == JOptionPane.YES_OPTION) {
|
||||
@ -1325,7 +1338,7 @@ public class Case {
|
||||
}
|
||||
|
||||
});
|
||||
} catch (InterruptedException | InvocationTargetException ex) {
|
||||
} catch (InterruptedException | InvocationTargetException | TskCoreException | TskDataException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
@ -2729,6 +2742,7 @@ public class Case {
|
||||
"Case.progressMessage.openingCaseDatabase=Opening case database...",
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
|
||||
"# {0} - exception message", "Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
|
||||
"Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded.",
|
||||
"Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User."
|
||||
})
|
||||
private void openCaseDataBase(ProgressIndicator progressIndicator) throws CaseActionException {
|
||||
@ -2737,14 +2751,15 @@ public class Case {
|
||||
String databaseName = metadata.getCaseDatabaseName();
|
||||
|
||||
ContentStreamProvider contentProvider = loadContentProvider(metadata.getContentProviderName());
|
||||
if (StringUtils.isNotBlank(metadata.getContentProviderName()) && contentProvider == null) {
|
||||
if (metadata.getContentProviderName().trim().toUpperCase().startsWith(CT_PROVIDER_PREFIX.toUpperCase())) {
|
||||
new CTIntegrationMissingDialog(WindowManager.getDefault().getMainWindow(), true).showDialog(null);
|
||||
}
|
||||
throw new CaseActionException(Bundle.Case_exceptionMessage_contentProviderCouldNotBeFound());
|
||||
}
|
||||
|
||||
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
|
||||
// only prefix with metadata directory if databaseName is a relative path
|
||||
String fullDatabasePath = (new File(databaseName).isAbsolute())
|
||||
? databaseName
|
||||
: Paths.get(metadata.getCaseDirectory(), databaseName).toString();
|
||||
|
||||
caseDb = SleuthkitCase.openCase(fullDatabasePath, contentProvider);
|
||||
caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath(), contentProvider);
|
||||
} else if (UserPreferences.getIsMultiUserModeEnabled()) {
|
||||
caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory(), contentProvider);
|
||||
} else {
|
||||
|
@ -29,16 +29,8 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
@ -51,13 +43,10 @@ import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.autopsy.coreutils.XMLUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@ -121,7 +110,6 @@ public final class CaseMetadata {
|
||||
private static final String SCHEMA_VERSION_SIX = "6.0";
|
||||
private final static String CONTENT_PROVIDER_ELEMENT_NAME = "ContentProvider";
|
||||
private final static String CONTENT_PROVIDER_NAME_ELEMENT_NAME = "Name";
|
||||
private final static String CONTENT_PROVIDER_ARG_DEFAULT_KEY = "DEFAULT";
|
||||
|
||||
/*
|
||||
* Unread fields, regenerated on save.
|
||||
@ -136,7 +124,7 @@ public final class CaseMetadata {
|
||||
private String caseName;
|
||||
private CaseDetails caseDetails;
|
||||
private String caseDatabaseName;
|
||||
private String caseDatabasePath; // Legacy
|
||||
private String caseDatabasePath;
|
||||
private String textIndexName; // Legacy
|
||||
private String createdDate;
|
||||
private String createdByVersion;
|
||||
@ -258,7 +246,9 @@ public final class CaseMetadata {
|
||||
* @return The case directory.
|
||||
*/
|
||||
public String getCaseDirectory() {
|
||||
return metadataFilePath.getParent().toString();
|
||||
return StringUtils.isBlank(this.caseDatabasePath)
|
||||
? metadataFilePath.getParent().toString()
|
||||
: Paths.get(this.caseDatabasePath).getParent().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -637,6 +627,7 @@ public final class CaseMetadata {
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
|
||||
break;
|
||||
default:
|
||||
this.caseDatabasePath = getElementTextContent(caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, false);
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
|
||||
break;
|
||||
@ -650,11 +641,9 @@ public final class CaseMetadata {
|
||||
*/
|
||||
Path possibleAbsoluteCaseDbPath = Paths.get(this.caseDatabaseName);
|
||||
Path caseDirectoryPath = Paths.get(getCaseDirectory());
|
||||
if (possibleAbsoluteCaseDbPath.getNameCount() > 1) {
|
||||
if (possibleAbsoluteCaseDbPath.toFile().isAbsolute()) {
|
||||
this.caseDatabasePath = this.caseDatabaseName;
|
||||
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString();
|
||||
} else {
|
||||
this.caseDatabasePath = caseDirectoryPath.resolve(caseDatabaseName).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
} catch (ParserConfigurationException | SAXException | IOException ex) {
|
||||
@ -719,12 +708,12 @@ public final class CaseMetadata {
|
||||
* @return The full path to the case database file for a single-user case.
|
||||
*
|
||||
* @throws UnsupportedOperationException If called for a multi-user case.
|
||||
* @deprecated Do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
public String getCaseDatabasePath() throws UnsupportedOperationException {
|
||||
if (Case.CaseType.SINGLE_USER_CASE == caseType) {
|
||||
return Paths.get(getCaseDirectory(), caseDatabaseName).toString();
|
||||
return StringUtils.isBlank(this.caseDatabasePath)
|
||||
? this.metadataFilePath.getParent().resolve(this.caseDatabaseName).toString()
|
||||
: this.caseDatabasePath;
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2021 Basis Technology Corp.
|
||||
* Copyright 2011-2023 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -64,6 +64,7 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_IT
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_TL_EVENT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ASSOCIATED_OBJECT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_KEYWORD_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE;
|
||||
|
||||
/**
|
||||
* Classes for creating nodes for BlackboardArtifacts.
|
||||
@ -72,7 +73,7 @@ public class Artifacts {
|
||||
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST
|
||||
= EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
|
||||
|
||||
|
||||
/**
|
||||
* Base class for a parent node of artifacts.
|
||||
*/
|
||||
@ -242,6 +243,7 @@ public class Artifacts {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) {
|
||||
|
||||
int typeId = type.getTypeID();
|
||||
if (TSK_EMAIL_MSG.getTypeID() == typeId) {
|
||||
EmailExtracted.RootNode emailNode = new EmailExtracted(skCase, dsObjId).new RootNode();
|
||||
@ -267,7 +269,9 @@ public class Artifacts {
|
||||
} else if (TSK_HASHSET_HIT.getTypeID() == typeId) {
|
||||
HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT);
|
||||
|
||||
} else if (TSK_MALWARE.getTypeID() == typeId) {
|
||||
MalwareHits.RootNode malwareHits = new MalwareHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(malwareHits, TSK_MALWARE);
|
||||
} else {
|
||||
return new TypeNodeKey(type, dsObjId);
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ public interface AutopsyItemVisitor<T> {
|
||||
T visit(KeywordHits kh);
|
||||
|
||||
T visit(HashsetHits hh);
|
||||
|
||||
T visit(MalwareHits mh);
|
||||
|
||||
T visit(EmailExtracted ee);
|
||||
|
||||
@ -169,6 +171,11 @@ public interface AutopsyItemVisitor<T> {
|
||||
return defaultVisit(hh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(MalwareHits mh) {
|
||||
return defaultVisit(mh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHits ih) {
|
||||
return defaultVisit(ih);
|
||||
|
@ -111,6 +111,8 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
T visit(HashsetHits.RootNode hhrn);
|
||||
|
||||
T visit(HashsetHits.HashsetNameNode hhsn);
|
||||
|
||||
T visit(MalwareHits.RootNode mhrn);
|
||||
|
||||
T visit(EmailExtracted.RootNode eern);
|
||||
|
||||
@ -431,6 +433,11 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
return defaultVisit(hhsn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(MalwareHits.RootNode mhrn) {
|
||||
return defaultVisit(mhrn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHits.RootNode ihrn) {
|
||||
return defaultVisit(ihrn);
|
||||
|
343
Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java
Executable file
343
Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java
Executable file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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 org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode;
|
||||
import org.sleuthkit.datamodel.AnalysisResult;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE;
|
||||
import org.sleuthkit.datamodel.Score;
|
||||
|
||||
/**
|
||||
* Malware hits node support. Inner classes have all of the nodes in the tree.
|
||||
*/
|
||||
public class MalwareHits implements AutopsyVisitableItem {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MalwareHits.class.getName());
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
|
||||
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
|
||||
private SleuthkitCase skCase;
|
||||
private final MalwareResults malwareResults;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param skCase Case DB
|
||||
*
|
||||
*/
|
||||
public MalwareHits(SleuthkitCase skCase) {
|
||||
this(skCase, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param skCase Case DB
|
||||
* @param objId Object id of the data source
|
||||
*
|
||||
*/
|
||||
public MalwareHits(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.filteringDSObjId = objId;
|
||||
malwareResults = new MalwareResults();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores all of the malware results in a single class that is observable
|
||||
* for the child nodes
|
||||
*/
|
||||
private class MalwareResults extends Observable implements Observer {
|
||||
|
||||
// list of artifacts
|
||||
// NOTE: the list can be accessed by multiple worker threads and needs to be synchronized
|
||||
private final Set<Long> malwareHits = new HashSet<>();
|
||||
|
||||
MalwareResults() {
|
||||
addNotify();
|
||||
update();
|
||||
}
|
||||
|
||||
Set<Long> getArtifactIds() {
|
||||
synchronized (malwareHits) {
|
||||
return Collections.unmodifiableSet(malwareHits);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
final void update() {
|
||||
synchronized (malwareHits) {
|
||||
malwareHits.clear();
|
||||
}
|
||||
|
||||
if (skCase == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS
|
||||
+ "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS
|
||||
+ "blackboard_artifacts.artifact_type_id=" + TSK_MALWARE.getTypeID() //NON-NLS
|
||||
+ " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS
|
||||
+ " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS
|
||||
+ " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; //NON-NLS
|
||||
}
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||
ResultSet resultSet = dbQuery.getResultSet();
|
||||
synchronized (malwareHits) {
|
||||
while (resultSet.next()) {
|
||||
long artifactObjId = resultSet.getLong("artifact_obj_id"); //NON-NLS
|
||||
malwareHits.add(artifactObjId);
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
|
||||
}
|
||||
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* Due to some unresolved issues with how cases are
|
||||
* closed, it is possible for the event to have a null
|
||||
* oldValue if the event is a remote event.
|
||||
*/
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_MALWARE.getTypeID()) {
|
||||
malwareResults.update();
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
malwareResults.update();
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
protected void addNotify() {
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
protected void removeNotify() {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
removeNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level node for all malware hits
|
||||
*/
|
||||
public class RootNode extends UpdatableCountTypeNode {
|
||||
|
||||
public RootNode() {
|
||||
super(Children.create(new HitFactory(TSK_MALWARE.getDisplayName()), true),
|
||||
Lookups.singleton(TSK_MALWARE.getDisplayName()),
|
||||
TSK_MALWARE.getDisplayName(),
|
||||
filteringDSObjId,
|
||||
TSK_MALWARE);
|
||||
|
||||
super.setName(TSK_MALWARE.getTypeName());
|
||||
// TODO make an icon
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"),
|
||||
getName()));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* When this method is called, the count to be displayed will be
|
||||
* updated.
|
||||
*/
|
||||
@Override
|
||||
void updateDisplayName() {
|
||||
super.setDisplayName(TSK_MALWARE.getDisplayName() + " (" + malwareResults.getArtifactIds().size() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the nodes for the malware hits.
|
||||
*/
|
||||
private class HitFactory extends BaseChildFactory<AnalysisResult> implements Observer {
|
||||
|
||||
private final Map<Long, AnalysisResult> artifactHits = new HashMap<>();
|
||||
|
||||
private HitFactory(String nodeName) {
|
||||
super(nodeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAdd() {
|
||||
malwareResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
malwareResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(AnalysisResult key) {
|
||||
return new BlackboardArtifactNode(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AnalysisResult> makeKeys() {
|
||||
if (skCase != null) {
|
||||
|
||||
malwareResults.getArtifactIds().forEach((id) -> {
|
||||
try {
|
||||
if (!artifactHits.containsKey(id)) {
|
||||
AnalysisResult art = skCase.getBlackboard().getAnalysisResultById(id);
|
||||
//Cache attributes while we are off the EDT.
|
||||
//See JIRA-5969
|
||||
art.getAttributes();
|
||||
artifactHits.put(id, art);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
});
|
||||
return new ArrayList<>(artifactHits.values());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3
|
||||
OpenIDE-Module-Implementation-Version: 7
|
||||
OpenIDE-Module-Implementation-Version: 8
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties
|
||||
OpenIDE-Module-Specification-Version: 1.4
|
||||
AutoUpdate-Show-In-Client: true
|
||||
|
@ -144,7 +144,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.24</specification-version>
|
||||
<specification-version>10.25</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -162,7 +162,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>6</release-version>
|
||||
<specification-version>6.6</specification-version>
|
||||
<specification-version>6.7</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
|
@ -1,4 +1,4 @@
|
||||
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
|
||||
file.reference.sqlite-jdbc-3.42.0.1.jar=release/modules/ext/sqlite-jdbc-3.42.0.1.jar
|
||||
javac.source=17
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=LICENSE-2.0.txt
|
||||
|
@ -127,7 +127,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.24</specification-version>
|
||||
<specification-version>10.25</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -142,8 +142,8 @@
|
||||
</module-dependencies>
|
||||
<public-packages/>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
|
@ -1,7 +1,7 @@
|
||||
Manifest-Version: 1.0
|
||||
AutoUpdate-Show-In-Client: true
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6
|
||||
OpenIDE-Module-Implementation-Version: 23
|
||||
OpenIDE-Module-Implementation-Version: 24
|
||||
OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class
|
||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties
|
||||
|
@ -48,4 +48,4 @@ javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
||||
nbm.needs.restart=true
|
||||
spec.version.base=6.6
|
||||
spec.version.base=6.7
|
||||
|
@ -128,7 +128,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.24</specification-version>
|
||||
<specification-version>10.25</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
29
NEWS.txt
29
NEWS.txt
@ -1,3 +1,32 @@
|
||||
---------------- VERSION 4.21.0 ---------------
|
||||
Library Updates
|
||||
- Update Java to version 17
|
||||
- Update aLeapp/iLeapp executables.
|
||||
- Update JNA Version
|
||||
- Update SQLite library version
|
||||
- Updated 3rd party libraries that have known CVE's
|
||||
|
||||
Ingest Module Updates:
|
||||
- Recent Activity checks for malicious Chrome extensions from list provided by https://github.com/randomaccess3/detections
|
||||
- Keyword Search module now can search without needing to index text into Solr.
|
||||
- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license). https://www.cybertriage.com/autopsy-malware-module/
|
||||
|
||||
Add Data Source Updates:
|
||||
- Timestamps for logical files can be added. Issue https://github.com/sleuthkit/autopsy/issues/5852, https://github.com/sleuthkit/autopsy/issues/1788
|
||||
- List of logical files/folders can be edited before they are added. Issue https://github.com/sleuthkit/autopsy/issues/7347
|
||||
|
||||
GUI Updates:
|
||||
- Add "has attachments" flag for emails. Issue https://github.com/sleuthkit/autopsy/issues/7358
|
||||
- Add Score to tree view
|
||||
|
||||
Bugs:
|
||||
- Fix path for lnk files
|
||||
- Fix exporting of CSV files. Issue https://github.com/sleuthkit/autopsy/issues/6717
|
||||
|
||||
Misc:
|
||||
- Added File Repository concept for data source files that are in a central location. Required for Cyber Triage import feature.
|
||||
- Added Spanish language support, contributor https://github.com/AburtoArielPM
|
||||
|
||||
---------------- VERSION 4.20.0 --------------
|
||||
Recent Activity Updates:
|
||||
- Added Favicons, Profiles and Extensions to Chromium Browsers
|
||||
|
@ -1,6 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6
|
||||
OpenIDE-Module-Implementation-Version: 19
|
||||
OpenIDE-Module-Implementation-Version: 20
|
||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
|
||||
OpenIDE-Module-Requires:
|
||||
|
@ -1,6 +1,6 @@
|
||||
javac.source=17
|
||||
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
|
||||
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
|
||||
file.reference.sqlite-jdbc-3.42.0.1.jar=release/modules/ext/sqlite-jdbc-3.42.0.1.jar
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
||||
|
@ -88,8 +88,8 @@
|
||||
<binary-origin>release/modules/ext/Rejistry-1.1-SNAPSHOT.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
|
@ -1,3 +1,3 @@
|
||||
<project name="TSK_VERSION">
|
||||
<property name="TSK_VERSION" value="4.12.0"/>
|
||||
<property name="TSK_VERSION" value="4.12.1"/>
|
||||
</project>
|
||||
|
@ -47,7 +47,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.24</specification-version>
|
||||
<specification-version>10.25</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -73,7 +73,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>6</release-version>
|
||||
<specification-version>6.6</specification-version>
|
||||
<specification-version>6.7</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
|
63
docs/doxygen-user/ct_malware_scanner.dox
Normal file
63
docs/doxygen-user/ct_malware_scanner.dox
Normal file
@ -0,0 +1,63 @@
|
||||
/*! \page ct_malware_scanner_page Cyber Triage Malware Scanner Module
|
||||
|
||||
[TOC]
|
||||
|
||||
What Does It Do
|
||||
========
|
||||
|
||||
The Cyber Triage Malware Scanner module will use the malware scanning infrastructure from Cyber Triage to identify if any Windows executables are malware. It will query an online service using the file's hash value to see if the file was already analyzed and allows you to upload files for analysis if they are new.
|
||||
|
||||
This module requires a commercial license from Cyber Triage.
|
||||
|
||||
For more information on what the module does or obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed.
|
||||
|
||||
|
||||
Configuration
|
||||
==============
|
||||
|
||||
You will need to first get a paid or eval license from the above URL. The code will come in via email. Example license formats include:
|
||||
|
||||
- AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070
|
||||
- b826a555-951f-42ca-86ce-439a81106688
|
||||
|
||||
Once you have a license, you must add it on the Autopsy Options panel.
|
||||
Choose the 'Cyber Triage' tab and choose 'Add License'.
|
||||
|
||||
\image html malware-scanner-global-options-panel-no-license.png
|
||||
|
||||
After you enter the license number from your email, you will then need to review and agree to the license terms.
|
||||
|
||||
|
||||
The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset.
|
||||
|
||||
\image html malware-scanner-global-options-panel.png
|
||||
|
||||
|
||||
|
||||
Using the Module
|
||||
======
|
||||
|
||||
Ingest Settings
|
||||
------
|
||||
|
||||
For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. Refer to the main [website](https://cybertriage.com/autopsy-malware-module) for details on what happens when files are uploaded.
|
||||
|
||||
\image html malware-scanner-ingest-panel.png
|
||||
|
||||
|
||||
|
||||
Out of Scans
|
||||
-------
|
||||
|
||||
If you go beyond your limits, you will get a dialog that not all files were analyzed. You can wait until your limits reset and then start ingest again with only the malware scanning module enabled. It will ignore the files that are already analyzed.
|
||||
|
||||
|
||||
Seeing Results
|
||||
------
|
||||
|
||||
Once ingest has completed, the files with malware will be listed in the Malware node in the tree.
|
||||
|
||||
|
||||
\image html malware-artifact-tree.png
|
||||
|
||||
*/
|
@ -1,5 +1,5 @@
|
||||
<hr/>
|
||||
<p><i>Copyright © 2012-2022 Basis Technology. Generated on $date<br/>
|
||||
<p><i>Copyright © 2012-2023 BasisTech. Generated on $date<br/>
|
||||
This work is licensed under a
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/">Creative Commons Attribution-Share Alike 3.0 United States License</a>.
|
||||
</i></p>
|
||||
|
BIN
docs/doxygen-user/images/malware-artifact-tree.png
Normal file
BIN
docs/doxygen-user/images/malware-artifact-tree.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
docs/doxygen-user/images/malware-scanner-ingest-panel.png
Normal file
BIN
docs/doxygen-user/images/malware-scanner-ingest-panel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
@ -58,6 +58,7 @@ The following topics are available here:
|
||||
- \subpage ileapp_page
|
||||
- \subpage aleapp_page
|
||||
- \subpage yara_page
|
||||
- \subpage ct_malware_scanner_page
|
||||
|
||||
- Reviewing the Results
|
||||
- \subpage uilayout_page
|
||||
|
@ -4,7 +4,7 @@ app.title=Autopsy
|
||||
### lowercase version of above
|
||||
app.name=${branding.token}
|
||||
### if left unset, version will default to today's date
|
||||
app.version=4.20.0
|
||||
app.version=4.21.0
|
||||
### build.type must be one of: DEVELOPMENT, RELEASE
|
||||
#build.type=RELEASE
|
||||
build.type=DEVELOPMENT
|
||||
|
@ -33,7 +33,7 @@ sub main {
|
||||
update_core_project_xml();
|
||||
update_unix_setup();
|
||||
|
||||
print "Files updated. You need to commit and push them\n";
|
||||
print "Files updated and added to git. You need to commit (no -a) and push.\n";
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.24</specification-version>
|
||||
<specification-version>10.25</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
# NOTE: update_sleuthkit_version.pl updates this value and relies
|
||||
# on it keeping the same name and whitespace. Don't change it.
|
||||
TSK_VERSION=4.12.0
|
||||
TSK_VERSION=4.12.1
|
||||
|
||||
|
||||
usage() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user