diff --git a/Core/src/org/sleuthkit/autopsy/images/yara_32.png b/Core/src/org/sleuthkit/autopsy/images/yara_32.png new file mode 100755 index 0000000000000000000000000000000000000000..9fdb23052ae46848f37fd292391c7b9244e35455 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/yara_32.png differ diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSet.java b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSet.java new file mode 100755 index 0000000000000000000000000000000000000000..12b383894428703f15938fcde11e518aa20a2619 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSet.java @@ -0,0 +1,81 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.rules; + +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +/** + * Represents a yara rule set which is a collection of yara rule files. + */ +public class RuleSet implements Comparable<RuleSet> { + + private final String name; + private final Path path; + + /** + * Construct a new RuleSet. + * + * @param name Name of the rule set. + * @param path Directory path to the rule set. + */ + RuleSet(String name, Path path) { + this.name = name; + this.path = path; + } + + /** + * Returns the name of the rule set. + * + * @return Name of rule set. + */ + public String getName() { + return name; + } + + /** + * Returns location if the rule set files. + * + * @return The path for this rule set. + */ + public Path getPath() { + return path; + } + + /** + * Returns a list of the rule files in this rule set. + * + * @return List of Files in current directory. + */ + public List<File> getRuleFiles() { + return Arrays.asList(path.toFile().listFiles()); + } + + @Override + public String toString() { + return getName(); + } + + @Override + public int compareTo(RuleSet ruleSet) { + return getName().compareTo(ruleSet.getName()); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetException.java b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetException.java new file mode 100755 index 0000000000000000000000000000000000000000..7ae0e12c45570dd77d2022fe394b97c3c80aa418 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetException.java @@ -0,0 +1,47 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.rules; + +/** + * + * An exception class for yara rule sets. + */ +public class RuleSetException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Construct a RuleSetException with the given message. + * + * @param msg Exception message. + */ + RuleSetException(String msg) { + super(msg); + } + + /** + * Construct a RuleSetException with the given message and exception. + * + * @param msg Exception message. + * @param ex Exception. + */ + RuleSetException(String msg, Exception ex) { + super(msg, ex); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java new file mode 100755 index 0000000000000000000000000000000000000000..eab2f8081928e90f1b371e03c9cdae08e6365086 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java @@ -0,0 +1,109 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2020 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.modules.yara.rules; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; + +/** + * + * Yara Rule Set Manager. Manages the creation, deletion of yara rule sets. + */ +public class RuleSetManager { + + private final static String BASE_FOLDER = "yara"; + private final static String RULE_SET_FOLDER = "ruleSets"; + + /** + * Create a new Yara rule set with the given set name. + * + * @param name Name of new rule set + * + * @return Newly created RuleSet + * + * @throws RuleSetException RuleSet with given name already exists. + */ + public RuleSet createRuleSet(String name) throws RuleSetException { + + if (isRuleSetExists(name)) { + throw new RuleSetException(String.format("Yara rule set with name %s already exits.", name)); + } + + Path basePath = getRuleSetPath(); + Path setPath = Paths.get(basePath.toString(), name); + + setPath.toFile().mkdir(); + + return new RuleSet(name, setPath); + } + + /** + * Returns a list of all of the existing yara rule sets. + * + * @return + */ + public List<RuleSet> getRuleSetList() { + List<RuleSet> ruleSets = new ArrayList<>(); + Path basePath = getRuleSetPath(); + + String[] ruleSetNames = basePath.toFile().list(); + + for (String setName : ruleSetNames) { + ruleSets.add(new RuleSet(setName, Paths.get(basePath.toString(), setName))); + } + + return ruleSets; + } + + /** + * Check if a yara rule set of the given name exists. + * + * @param name Yara rule set name + * + * @return True if the rule set exist. + */ + public boolean isRuleSetExists(String name) { + Path basePath = getRuleSetPath(); + Path setPath = Paths.get(basePath.toString(), name); + + return setPath.toFile().exists(); + } + + /** + * Returns the Path to get RuleSet directory. If it does not exist it is + * created. + * + * @return Yara rule set directory path. + */ + private Path getRuleSetPath() { + Path basePath = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), BASE_FOLDER, RULE_SET_FOLDER); + File baseFile = basePath.toFile(); + + if (!baseFile.exists()) { + baseFile.mkdirs(); + } + + return basePath; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties new file mode 100755 index 0000000000000000000000000000000000000000..5012f855b42dba159465977d5afb4cb7a3e9efaf --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties @@ -0,0 +1,10 @@ +OptionCategory_Name_YaraRuleSetOption=Yara Rule Sets +OptionCategory_Keywords_YaraRuleSetOption=YaraRuleSets +RuleSetPanel.newButton.text=New Set +RuleSetPanel.deleteButton.text=Delete Set +RuleSetPanel.ruleSetListLabel.text=Rule Sets: +RuleSetDetailsPanel.ruleSetListLabel.text=The folder currently contains the following rule files: +RuleSetDetailsPanel.setDetailsLabel.text=Set Details +RuleSetDetailsPanel.openFolderButton.text=Open Folder +RuleSetPanel.descriptionField.text=This module allows you to find files the match Yara rules. Each set has a list of Yara rule files. A file need only match one rule in the set to be found. +RuleSetDetailsPanel.openLabel.text=Place rule files in the set's folder. They will be compiled before use. diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED new file mode 100755 index 0000000000000000000000000000000000000000..a6b64a97c0cdb6b37cdd35efe706d5a6b53f855f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED @@ -0,0 +1,17 @@ +OptionCategory_Name_YaraRuleSetOption=Yara Rule Sets +OptionCategory_Keywords_YaraRuleSetOption=YaraRuleSets +RuleSetDetailsPanel_failed_to_open_folder_msg=Failed to open new window for rule set file. +RuleSetDetailsPanel_failed_to_open_folder_title=Open Error +RuleSetPanel.newButton.text=New Set +RuleSetPanel.deleteButton.text=Delete Set +RuleSetPanel.ruleSetListLabel.text=Rule Sets: +RuleSetDetailsPanel.ruleSetListLabel.text=The folder currently contains the following rule files: +RuleSetDetailsPanel.setDetailsLabel.text=Set Details +RuleSetDetailsPanel.openFolderButton.text=Open Folder +RuleSetPanel.descriptionField.text=This module allows you to find files the match Yara rules. Each set has a list of Yara rule files. A file need only match one rule in the set to be found. +RuleSetDetailsPanel.openLabel.text=Place rule files in the set's folder. They will be compiled before use. +# {0} - rule set name +YaraRuleSetOptionPanel_badName_msg=Rule set name {0} already exists.\nRule set names must be unique. +YaraRuleSetOptionPanel_badName_title=Create Rule Set +YaraRuleSetOptionPanel_new_rule_set_name_msg=Supply a new unique rule set name: +YaraRuleSetOptionPanel_new_rule_set_name_title=Rule Set Name diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.form new file mode 100755 index 0000000000000000000000000000000000000000..2f1c87a69fbe23684c927a52a58558ffc77c68f8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.form @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,2,-85"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> + <SubComponents> + <Component class="javax.swing.JLabel" name="ruleSetListLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetDetailsPanel.ruleSetListLabel.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="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="0" insetsBottom="3" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JLabel" name="setDetailsLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetDetailsPanel.setDetailsLabel.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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="10" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="openFolderButton"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/org/sleuthkit/autopsy/images/folder-icon-16.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetDetailsPanel.openFolderButton.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="openFolderButtonActionPerformed"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="1" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JLabel" name="openLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetDetailsPanel.openLabel.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="10" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Container class="javax.swing.JScrollPane" name="scrollPane"> + <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="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/> + </Constraint> + </Constraints> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + </Container> + </SubComponents> +</Form> diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.java new file mode 100755 index 0000000000000000000000000000000000000000..8c284a190e10a40eb25955b4924ef6197f24a742 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetDetailsPanel.java @@ -0,0 +1,197 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.ui; + +import java.awt.Component; +import java.awt.Desktop; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.modules.yara.rules.RuleSet; + +/** + * A panel for displaying the details of an individual yara rule set. + */ +public class RuleSetDetailsPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private static final Logger logger = Logger.getLogger(RuleSetDetailsPanel.class.getName()); + + private RuleSet currentRuleSet; + private final DefaultListModel<File> fileListModel; + private final JList<File> fileList; + + /** + * Creates new form RuleSetDetailsPanel + */ + public RuleSetDetailsPanel() { + initComponents(); + + fileListModel = new DefaultListModel<>(); + fileList = new JList<>(); + fileList.setModel(fileListModel); + fileList.setCellRenderer(new FileRenderer()); + openFolderButton.setEnabled(false); + + } + + /** + * Update the panel to show the details of the given RuleSet. + * + * @param ruleSet New RuleSet to display + */ + void setRuleSet(RuleSet ruleSet) { + currentRuleSet = ruleSet; + + fileListModel.clear(); + + if (ruleSet != null) { + List<File> files = currentRuleSet.getRuleFiles(); + + for (File file : files) { + fileListModel.addElement(file); + } + } + + openFolderButton.setEnabled(ruleSet != null); + } + + /** + * Simple ListCellRenderer for the file list. + */ + private final class FileRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof File) { + File file = (File) value; + setText(file.getName()); + setToolTipText(file.getAbsolutePath()); + } + + return this; + } + } + + /** + * 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 ruleSetListLabel = new javax.swing.JLabel(); + javax.swing.JLabel setDetailsLabel = new javax.swing.JLabel(); + openFolderButton = new javax.swing.JButton(); + openLabel = new javax.swing.JLabel(); + scrollPane = new javax.swing.JScrollPane(); + + setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(ruleSetListLabel, org.openide.util.NbBundle.getMessage(RuleSetDetailsPanel.class, "RuleSetDetailsPanel.ruleSetListLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(16, 0, 3, 0); + add(ruleSetListLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(setDetailsLabel, org.openide.util.NbBundle.getMessage(RuleSetDetailsPanel.class, "RuleSetDetailsPanel.setDetailsLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 10, 0); + add(setDetailsLabel, gridBagConstraints); + + openFolderButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/folder-icon-16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(openFolderButton, org.openide.util.NbBundle.getMessage(RuleSetDetailsPanel.class, "RuleSetDetailsPanel.openFolderButton.text")); // NOI18N + openFolderButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + openFolderButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(10, 0, 0, 0); + add(openFolderButton, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(openLabel, org.openide.util.NbBundle.getMessage(RuleSetDetailsPanel.class, "RuleSetDetailsPanel.openLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(10, 0, 0, 0); + add(openLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0); + add(scrollPane, gridBagConstraints); + }// </editor-fold>//GEN-END:initComponents + + @Messages({ + "RuleSetDetailsPanel_failed_to_open_folder_msg=Failed to open new window for rule set file.", + "RuleSetDetailsPanel_failed_to_open_folder_title=Open Error" + }) + private void openFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openFolderButtonActionPerformed + if (currentRuleSet != null) { + File file = currentRuleSet.getPath().toFile(); + if (file.exists()) { + try { + Desktop.getDesktop().open(file); + } catch (IOException ex) { + JOptionPane.showMessageDialog(this, + Bundle.RuleSetDetailsPanel_failed_to_open_folder_msg(), + Bundle.RuleSetDetailsPanel_failed_to_open_folder_title(), + JOptionPane.ERROR_MESSAGE); + logger.log(Level.WARNING, String.format("Failed to open external file explorer for: %s", currentRuleSet.getPath().toString()), ex); + } + } + } + }//GEN-LAST:event_openFolderButtonActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton openFolderButton; + private javax.swing.JLabel openLabel; + private javax.swing.JScrollPane scrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.form b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.form new file mode 100755 index 0000000000000000000000000000000000000000..bd3e12390f4641d2ef0e2fea53c7b58a38eade9a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.form @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-114,0,0,1,-112"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> + <SubComponents> + <Component class="javax.swing.JTextPane" name="descriptionField"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo"> + <LineBorder/> + </Border> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetPanel.descriptionField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="opaque" type="boolean" value="false"/> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/> + <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/> + </AuxValues> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JLabel" name="ruleSetListLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetPanel.ruleSetListLabel.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="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Container class="javax.swing.JScrollPane" name="scrollPane"> + <AuxValues> + <AuxValue name="autoScrollPane" 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="0" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="0" insetsBottom="10" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/> + </Constraint> + </Constraints> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + </Container> + <Container class="javax.swing.JPanel" name="buttonPanel"> + <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="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout"> + <Property name="columns" type="int" value="0"/> + <Property name="horizontalGap" type="int" value="5"/> + <Property name="rows" type="int" value="1"/> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="newButton"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/org/sleuthkit/autopsy/images/add16.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetPanel.newButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="deleteButton"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/org/sleuthkit/autopsy/images/delete16.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="RuleSetPanel.deleteButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.java b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.java new file mode 100755 index 0000000000000000000000000000000000000000..63474a8adb2a6edd56a47164e50f12c1af0c59ac --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/RuleSetPanel.java @@ -0,0 +1,231 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.ui; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import org.sleuthkit.autopsy.modules.yara.rules.RuleSet; + +/** + * Panel for managing yara rule sets. + */ +public final class RuleSetPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private final DefaultListModel<RuleSet> listModel; + private final JList<RuleSet> ruleSetList; + + public RuleSetPanel() { + initComponents(); + + // Creating and initializing JList here to better take + // advantace of JList use of generics. + ruleSetList = new JList<>(); + listModel = new DefaultListModel<>(); + scrollPane.setViewportView(ruleSetList); + ruleSetList.setModel(listModel); + ruleSetList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ruleSetList.setCellRenderer(new RuleSetRenderer()); + ruleSetList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + deleteButton.setEnabled(getSelectedRule() != null); + } + }); + + deleteButton.setEnabled(false); + } + + /** + * Add the list of rule sets to the list model. + * + * @param ruleSetList Rule sets to add. + */ + void addSetList(List<RuleSet> newSetList) { + // Put the list into alphectical order. + List<RuleSet> list = new ArrayList<>(); + list.addAll(newSetList); + Collections.sort(list); + + listModel.clear(); + + for (RuleSet set : list) { + listModel.addElement(set); + } + } + + /** + * Adds a new rule to the list. + * + * @param set + */ + void addRuleSet(RuleSet set) { + // This will assure that the new item + // appears in the correct location. + List<RuleSet> list = Collections.list(listModel.elements()); + list.add(set); + + addSetList(list); + + ruleSetList.setSelectedValue(set, true); + } + + /** + * Removes a rule set from the list. + * + * @param set + */ + void removeRuleSet(RuleSet set) { + listModel.removeElement(set); + } + + /** + * Add a listener for the new rule set action. + * + * @param listener + */ + void addNewRuleListener(ActionListener listener) { + newButton.addActionListener(listener); + } + + /** + * Add a listener for the delete rule set action. + * + * @param listener + */ + void addDeleteRuleListener(ActionListener listener) { + deleteButton.addActionListener(listener); + } + + /** + * Add a listener for list selection change. + * + * @param listener + */ + void addListSelectionListener(ListSelectionListener listener) { + ruleSetList.addListSelectionListener(listener); + } + + /** + * Returns the current selected rule set. + * + * @return Currently selected rule set or null if one is not selected. + */ + RuleSet getSelectedRule() { + return ruleSetList.getSelectedValue(); + } + + /** + * Simple ListCellRenderer for a RuleSet. + */ + private final class RuleSetRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof RuleSet) { + RuleSet set = (RuleSet) value; + setText(set.getName()); + setToolTipText(set.getName()); + } + + return this; + } + } + + /** + * 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.JTextPane descriptionField = new javax.swing.JTextPane(); + javax.swing.JLabel ruleSetListLabel = new javax.swing.JLabel(); + scrollPane = new javax.swing.JScrollPane(); + javax.swing.JPanel buttonPanel = new javax.swing.JPanel(); + newButton = new javax.swing.JButton(); + deleteButton = new javax.swing.JButton(); + + setLayout(new java.awt.GridBagLayout()); + + descriptionField.setEditable(false); + descriptionField.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + descriptionField.setText(org.openide.util.NbBundle.getMessage(RuleSetPanel.class, "RuleSetPanel.descriptionField.text")); // NOI18N + descriptionField.setOpaque(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + add(descriptionField, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(ruleSetListLabel, org.openide.util.NbBundle.getMessage(RuleSetPanel.class, "RuleSetPanel.ruleSetListLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0); + add(ruleSetListLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 0, 10, 0); + add(scrollPane, gridBagConstraints); + + buttonPanel.setLayout(new java.awt.GridLayout(1, 0, 5, 0)); + + newButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newButton, org.openide.util.NbBundle.getMessage(RuleSetPanel.class, "RuleSetPanel.newButton.text")); // NOI18N + buttonPanel.add(newButton); + + deleteButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deleteButton, org.openide.util.NbBundle.getMessage(RuleSetPanel.class, "RuleSetPanel.deleteButton.text")); // NOI18N + buttonPanel.add(deleteButton); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(buttonPanel, gridBagConstraints); + }// </editor-fold>//GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton deleteButton; + private javax.swing.JButton newButton; + private javax.swing.JScrollPane scrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.form b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.form new file mode 100755 index 0000000000000000000000000000000000000000..680d63ebfcbcbf7d719ddb920b1e2ea23726bb1a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.form @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" 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.LineBorderInfo"> + <LineBorder/> + </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,1,44,0,0,2,45"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="scrollPane"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="null"/> + </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.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription"> + <BorderConstraints direction="Center"/> + </Constraint> + </Constraints> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Container class="javax.swing.JPanel" name="viewportPanel"> + <AuxValues> + <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/> + <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> + <SubComponents> + <Component class="javax.swing.JSeparator" name="separator"> + <Properties> + <Property name="orientation" 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="1" gridY="-1" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="org.sleuthkit.autopsy.modules.yara.ui.RuleSetDetailsPanel" name="ruleSetDetailsPanel"> + <Properties> + <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[500, 97]"/> + </Property> + <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[500, 204]"/> + </Property> + </Properties> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="2" gridY="-1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="10" insetsBottom="10" insetsRight="10" anchor="17" weightX="1.0" weightY="1.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="org.sleuthkit.autopsy.modules.yara.ui.RuleSetPanel" name="ruleSetPanel"> + <Properties> + <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[400, 2147483647]"/> + </Property> + <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[400, 107]"/> + </Property> + <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[400, 214]"/> + </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="3" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="10" insetsBottom="10" insetsRight="10" anchor="17" weightX="0.0" weightY="1.0"/> + </Constraint> + </Constraints> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java new file mode 100755 index 0000000000000000000000000000000000000000..18f32aaf69ec08f9be52050a97ba39784d127dbc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java @@ -0,0 +1,186 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JOptionPane; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.modules.yara.rules.RuleSetException; +import org.sleuthkit.autopsy.modules.yara.rules.RuleSetManager; + +/** + * + * Yara Rule Set Option Panel. + */ +public class YaraRuleSetOptionPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private static final Logger logger = Logger.getLogger(YaraRuleSetOptionPanel.class.getName()); + + private final RuleSetManager manager; + + /** + * Creates new form YaraRuleSetOptionPanel + */ + public YaraRuleSetOptionPanel() { + initComponents(); + + manager = new RuleSetManager(); + + ruleSetPanel.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + handleSelectionChange(); + } + }); + + ruleSetPanel.addDeleteRuleListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + handleDeleteRuleSet(); + } + }); + + ruleSetPanel.addNewRuleListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + handleNewRuleSet(); + } + }); + } + + /** + * Update the panel with the current rule set. + */ + void updatePanel() { + ruleSetPanel.addSetList(manager.getRuleSetList()); + } + + /** + * Handle the change in rule set selection. Update the detail panel with the + * selected rule. + */ + private void handleSelectionChange() { + ruleSetDetailsPanel.setRuleSet(ruleSetPanel.getSelectedRule()); + } + + @NbBundle.Messages({ + "YaraRuleSetOptionPanel_new_rule_set_name_msg=Supply a new unique rule set name:", + "YaraRuleSetOptionPanel_new_rule_set_name_title=Rule Set Name", + "# {0} - rule set name", + "YaraRuleSetOptionPanel_badName_msg=Rule set name {0} already exists.\nRule set names must be unique.", + "YaraRuleSetOptionPanel_badName_title=Create Rule Set" + }) + /** + * Handle the new rule set action. Prompt the user for a rule set name, + * create the new set and update the rule set list. + */ + private void handleNewRuleSet() { + String value = JOptionPane.showInputDialog(this, + Bundle.YaraRuleSetOptionPanel_new_rule_set_name_msg(), + Bundle.YaraRuleSetOptionPanel_new_rule_set_name_title()); + try { + ruleSetPanel.addRuleSet(manager.createRuleSet(value)); + } catch (RuleSetException ex) { + JOptionPane.showMessageDialog(this, + Bundle.YaraRuleSetOptionPanel_badName_msg(value), + Bundle.YaraRuleSetOptionPanel_badName_title(), + JOptionPane.ERROR_MESSAGE); + logger.log(Level.WARNING, "Failed to create new rule set, user provide existing name.", ex); + } + } + + /** + * Handle the delete rule action. Delete the rule set and update the the + * rule set list. + */ + private void handleDeleteRuleSet() { + ruleSetPanel.removeRuleSet(ruleSetPanel.getSelectedRule()); + } + + /** + * 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.JScrollPane scrollPane = new javax.swing.JScrollPane(); + javax.swing.JPanel viewportPanel = new javax.swing.JPanel(); + javax.swing.JSeparator separator = new javax.swing.JSeparator(); + ruleSetDetailsPanel = new org.sleuthkit.autopsy.modules.yara.ui.RuleSetDetailsPanel(); + ruleSetPanel = new org.sleuthkit.autopsy.modules.yara.ui.RuleSetPanel(); + + setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + setLayout(new java.awt.BorderLayout()); + + scrollPane.setBorder(null); + + viewportPanel.setLayout(new java.awt.GridBagLayout()); + + separator.setOrientation(javax.swing.SwingConstants.VERTICAL); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.weighty = 1.0; + viewportPanel.add(separator, gridBagConstraints); + + ruleSetDetailsPanel.setMinimumSize(new java.awt.Dimension(500, 97)); + ruleSetDetailsPanel.setPreferredSize(new java.awt.Dimension(500, 204)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); + viewportPanel.add(ruleSetDetailsPanel, gridBagConstraints); + + ruleSetPanel.setMaximumSize(new java.awt.Dimension(400, 2147483647)); + ruleSetPanel.setMinimumSize(new java.awt.Dimension(400, 107)); + ruleSetPanel.setPreferredSize(new java.awt.Dimension(400, 214)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); + viewportPanel.add(ruleSetPanel, gridBagConstraints); + + scrollPane.setViewportView(viewportPanel); + + add(scrollPane, java.awt.BorderLayout.CENTER); + }// </editor-fold>//GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private org.sleuthkit.autopsy.modules.yara.ui.RuleSetDetailsPanel ruleSetDetailsPanel; + private org.sleuthkit.autopsy.modules.yara.ui.RuleSetPanel ruleSetPanel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetsOptionPanelController.java b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetsOptionPanelController.java new file mode 100755 index 0000000000000000000000000000000000000000..7619e23b4ccec95907b388ed93a13e452e7b2100 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetsOptionPanelController.java @@ -0,0 +1,90 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 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.modules.yara.ui; + +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +/** + * Yara rule set option panel controller. + * + */ +@OptionsPanelController.TopLevelRegistration( + categoryName = "#OptionCategory_Name_YaraRuleSetOption", + iconBase = "org/sleuthkit/autopsy/images/yara_32.png", + keywords = "#OptionCategory_Keywords_YaraRuleSetOption", + keywordsCategory = "YaraRuleSets", + position = 20 +) +public class YaraRuleSetsOptionPanelController extends OptionsPanelController { + + private YaraRuleSetOptionPanel panel = null; + + @Override + public void update() { + if (panel != null) { + panel.updatePanel(); + } + } + + @Override + public void applyChanges() { + + } + + @Override + public void cancel() { + + } + + @Override + public JComponent getComponent(Lookup masterLookup) { + panel = new YaraRuleSetOptionPanel(); + return panel; + } + + @Override + public HelpCtx getHelpCtx() { + return null; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener pl) { + + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener pl) { + + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public boolean isChanged() { + return false; + } + +}