From dc99b20fad2b975ac29531766cb84e31d54ba6cd Mon Sep 17 00:00:00 2001 From: Timothy Clark Date: Wed, 7 Feb 2024 11:03:59 -0600 Subject: [PATCH 1/5] Added UI changes to support per-tool signing and configuration persistence option. --- .../netspi/awssigner/view/BurpTabPanel.form | 267 ++++++++++++++++-- .../netspi/awssigner/view/BurpTabPanel.java | 175 ++++++++++-- 2 files changed, 392 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/netspi/awssigner/view/BurpTabPanel.form b/src/main/java/com/netspi/awssigner/view/BurpTabPanel.form index d23a355..0e1878f 100644 --- a/src/main/java/com/netspi/awssigner/view/BurpTabPanel.form +++ b/src/main/java/com/netspi/awssigner/view/BurpTabPanel.form @@ -95,49 +95,59 @@ - + + - - + + + - + + - + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + @@ -165,7 +175,8 @@ - + @@ -180,7 +191,7 @@ - + @@ -255,6 +266,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1116,9 +1333,9 @@ - + - + @@ -1214,7 +1431,7 @@ - + @@ -1230,7 +1447,7 @@ - + @@ -1259,7 +1476,7 @@ - + diff --git a/src/main/java/com/netspi/awssigner/view/BurpTabPanel.java b/src/main/java/com/netspi/awssigner/view/BurpTabPanel.java index 97d7425..5c54138 100644 --- a/src/main/java/com/netspi/awssigner/view/BurpTabPanel.java +++ b/src/main/java/com/netspi/awssigner/view/BurpTabPanel.java @@ -1,8 +1,7 @@ package com.netspi.awssigner.view; import com.netspi.awssigner.log.LogWriter; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; + import java.util.regex.Pattern; import javax.swing.border.EtchedBorder; @@ -38,6 +37,17 @@ private void initComponents() { logLevelLabel = new javax.swing.JLabel(); logLevelComboBox = new javax.swing.JComboBox<>(); globalSettingsSeparator = new javax.swing.JSeparator(); + signForPanel = new javax.swing.JPanel(); + signForLabel = new javax.swing.JLabel(); + signForAllCheckbox = new javax.swing.JCheckBox(); + signForRepeaterCheckbox = new javax.swing.JCheckBox(); + signForProxyCheckbox = new javax.swing.JCheckBox(); + signForIntruderCheckbox = new javax.swing.JCheckBox(); + signForExtensionsCheckbox = new javax.swing.JCheckBox(); + signForScannerCheckbox = new javax.swing.JCheckBox(); + signForTargetCheckbox = new javax.swing.JCheckBox(); + signForSequencerCheckbox = new javax.swing.JCheckBox(); + persistConfigurationCheckbox = new javax.swing.JCheckBox(); profileManagementLabel = new javax.swing.JLabel(); profileManagementDescriptionLabel = new javax.swing.JLabel(); addProfileButton = new javax.swing.JButton(); @@ -124,7 +134,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { signingEnabledCheckbox.setFont(signingEnabledCheckbox.getFont()); signingEnabledCheckbox.setSelected(true); signingEnabledCheckbox.setText("Signing Enabled"); - signingEnabledCheckbox.setToolTipText("Enable/Disable request signing globally"); + signingEnabledCheckbox.setToolTipText("Enable/Disable request signing globally."); signingEnabledCheckbox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); alwaysSignWithProfileLabel.setFont(alwaysSignWithProfileLabel.getFont()); @@ -144,46 +154,150 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { logLevelComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Error", "Info", "Debug" })); logLevelComboBox.setToolTipText("Set the extension's logging verbosity"); + signForLabel.setText("Sign For:"); + + signForAllCheckbox.setFont(signForAllCheckbox.getFont()); + signForAllCheckbox.setSelected(true); + signForAllCheckbox.setText("All"); + signForAllCheckbox.setToolTipText("Enable/Disable signing for all requests."); + signForAllCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForRepeaterCheckbox.setFont(signForRepeaterCheckbox.getFont()); + signForRepeaterCheckbox.setText("Repeater"); + signForRepeaterCheckbox.setToolTipText("Enable/Disable signing for Repeater requests."); + signForRepeaterCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForProxyCheckbox.setFont(signForProxyCheckbox.getFont()); + signForProxyCheckbox.setText("Proxy"); + signForProxyCheckbox.setToolTipText("Enable/Disable signing for Proxy requests."); + signForProxyCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForIntruderCheckbox.setFont(signForIntruderCheckbox.getFont()); + signForIntruderCheckbox.setText("Intruder "); + signForIntruderCheckbox.setToolTipText("Enable/Disable signing for Intruder requests."); + signForIntruderCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForExtensionsCheckbox.setFont(signForExtensionsCheckbox.getFont()); + signForExtensionsCheckbox.setText("Extensions"); + signForExtensionsCheckbox.setToolTipText("Enable/Disable signing for Extension requests."); + signForExtensionsCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForScannerCheckbox.setFont(signForScannerCheckbox.getFont()); + signForScannerCheckbox.setText("Scanner"); + signForScannerCheckbox.setToolTipText("Enable/Disable signing for Scanner requests."); + signForScannerCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForTargetCheckbox.setFont(signForTargetCheckbox.getFont()); + signForTargetCheckbox.setText("Target"); + signForTargetCheckbox.setToolTipText("Enable/Disable signing for Target requests."); + signForTargetCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + signForSequencerCheckbox.setFont(signForSequencerCheckbox.getFont()); + signForSequencerCheckbox.setText("Sequencer"); + signForSequencerCheckbox.setToolTipText("Enable/Disable signing for Sequencer requests."); + signForSequencerCheckbox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + + javax.swing.GroupLayout signForPanelLayout = new javax.swing.GroupLayout(signForPanel); + signForPanel.setLayout(signForPanelLayout); + signForPanelLayout.setHorizontalGroup( + signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(signForPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(signForLabel) + .addGroup(signForPanelLayout.createSequentialGroup() + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(signForAllCheckbox) + .addComponent(signForProxyCheckbox)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(signForPanelLayout.createSequentialGroup() + .addComponent(signForRepeaterCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(signForExtensionsCheckbox)) + .addGroup(signForPanelLayout.createSequentialGroup() + .addComponent(signForIntruderCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(signForTargetCheckbox))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(signForSequencerCheckbox) + .addComponent(signForScannerCheckbox)))) + .addContainerGap(28, Short.MAX_VALUE)) + ); + signForPanelLayout.setVerticalGroup( + signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(signForPanelLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(signForLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(signForAllCheckbox) + .addComponent(signForRepeaterCheckbox) + .addComponent(signForExtensionsCheckbox) + .addComponent(signForScannerCheckbox)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(signForPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(signForProxyCheckbox) + .addComponent(signForIntruderCheckbox) + .addComponent(signForTargetCheckbox) + .addComponent(signForSequencerCheckbox))) + ); + + persistConfigurationCheckbox.setFont(persistConfigurationCheckbox.getFont()); + persistConfigurationCheckbox.setSelected(true); + persistConfigurationCheckbox.setText("Persist Configuration"); + persistConfigurationCheckbox.setToolTipText("Enable/Disable configuration persistence."); + persistConfigurationCheckbox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel); globalSettingsPanel.setLayout(globalSettingsPanelLayout); globalSettingsPanelLayout.setHorizontalGroup( globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(globalSettingsSeparator) .addGroup(globalSettingsPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(globalSettingsLabel) .addGroup(globalSettingsPanelLayout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(globalSettingsDescriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addComponent(persistConfigurationCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(signingEnabledCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(alwaysSignWithProfileLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(alwaysSignWithProfileComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(logLevelLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(logLevelComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))) - .addGap(248, 391, Short.MAX_VALUE)) - .addComponent(globalSettingsSeparator) + .addComponent(logLevelComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(globalSettingsLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(signForPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(155, Short.MAX_VALUE)) ); globalSettingsPanelLayout.setVerticalGroup( globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(globalSettingsLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(globalSettingsDescriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(signingEnabledCheckbox) - .addComponent(alwaysSignWithProfileLabel) - .addComponent(alwaysSignWithProfileComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(logLevelLabel) - .addComponent(logLevelComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(globalSettingsLabel) + .addGap(12, 12, 12) + .addComponent(globalSettingsDescriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(signingEnabledCheckbox) + .addComponent(alwaysSignWithProfileLabel) + .addComponent(alwaysSignWithProfileComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(logLevelLabel) + .addComponent(logLevelComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(persistConfigurationCheckbox))) + .addComponent(signForPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(103, 103, 103) .addComponent(globalSettingsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(8, 8, 8)) ); @@ -435,9 +549,9 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { .addContainerGap() .addComponent(assumeRoleSessionPolicyConfigurationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(assumeRoleSessionPolicyDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE) + .addComponent(assumeRoleSessionPolicyDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 56, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(assumeRoleSessionPolicyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE) + .addComponent(assumeRoleSessionPolicyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(assumeRoleSessionPolicyPrettifyButton)) ); @@ -573,7 +687,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commandExtractedSectionLabel) .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(commandConfigurationDescriptionLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 684, Short.MAX_VALUE) + .addComponent(commandConfigurationDescriptionLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 692, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, commandPanelLayout.createSequentialGroup() .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commandDurationLabel) @@ -585,7 +699,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { .addGroup(commandPanelLayout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(commandExtractedSectionDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE) + .addComponent(commandExtractedSectionDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 683, Short.MAX_VALUE) .addGroup(commandPanelLayout.createSequentialGroup() .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commandExtractedSessionTokenLabel) @@ -604,7 +718,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { .addContainerGap() .addComponent(commandConfigurationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(commandConfigurationDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 71, Short.MAX_VALUE) + .addComponent(commandConfigurationDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(commandPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(commandCommandLabel) @@ -827,6 +941,7 @@ private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ public javax.swing.JButton importProfilesButton; public javax.swing.JComboBox logLevelComboBox; private javax.swing.JLabel logLevelLabel; + public javax.swing.JCheckBox persistConfigurationCheckbox; private javax.swing.JLabel profileConfigurationLabel; public javax.swing.JPanel profileConfigurationPanel; public javax.swing.JScrollPane profileConfigurationScrollPane; @@ -846,6 +961,16 @@ private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ private javax.swing.JLabel profileStatusLabel; public javax.swing.JLabel profileStatusTextLabel; public javax.swing.JPanel rightSideParentPanel; + public javax.swing.JCheckBox signForAllCheckbox; + public javax.swing.JCheckBox signForExtensionsCheckbox; + public javax.swing.JCheckBox signForIntruderCheckbox; + private javax.swing.JLabel signForLabel; + private javax.swing.JPanel signForPanel; + public javax.swing.JCheckBox signForProxyCheckbox; + public javax.swing.JCheckBox signForRepeaterCheckbox; + public javax.swing.JCheckBox signForScannerCheckbox; + public javax.swing.JCheckBox signForSequencerCheckbox; + public javax.swing.JCheckBox signForTargetCheckbox; public javax.swing.JCheckBox signingEnabledCheckbox; private javax.swing.JLabel staticAccessKeyLabel; public javax.swing.JTextField staticAccessKeyTextField; From 8d9d8c75ec2577e477c68ec65ebe3b9c5d2daf73 Mon Sep 17 00:00:00 2001 From: Timothy Clark Date: Wed, 7 Feb 2024 11:26:23 -0600 Subject: [PATCH 2/5] Implement logic for per-tool signing support. --- src/main/java/burp/BurpExtender.java | 25 ++++++++ .../controller/AWSSignerController.java | 57 +++++++++++++++++++ .../model/AWSSignerConfiguration.java | 3 + 3 files changed, 85 insertions(+) diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 740ab85..c2d2c69 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -11,7 +11,10 @@ import com.netspi.awssigner.view.BurpUIComponentCustomizer; import com.netspi.awssigner.view.BurpTabPanel; import java.awt.Component; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import javax.swing.JMenuItem; import javax.swing.SwingUtilities; @@ -19,8 +22,24 @@ //This is the Burp primary class. It needs to live in this package and have this name public class BurpExtender implements IBurpExtender, ITab, IHttpListener, IContextMenuFactory { + static { + final Map tempMap = new HashMap(); + + tempMap.put(IBurpExtenderCallbacks.TOOL_SUITE, "All"); + tempMap.put(IBurpExtenderCallbacks.TOOL_EXTENDER, "Extensions"); + tempMap.put(IBurpExtenderCallbacks.TOOL_INTRUDER, "Intruder"); + tempMap.put(IBurpExtenderCallbacks.TOOL_PROXY, "Proxy"); + tempMap.put(IBurpExtenderCallbacks.TOOL_REPEATER, "Repeater"); + tempMap.put(IBurpExtenderCallbacks.TOOL_SCANNER, "Scanner"); + tempMap.put(IBurpExtenderCallbacks.TOOL_SEQUENCER, "Sequencer"); + tempMap.put(IBurpExtenderCallbacks.TOOL_TARGET, "Target"); + + TOOL_FLAG_TRANSLATION_MAP = Collections.unmodifiableMap(tempMap); + } public static final String EXTENSION_NAME = "AWS Signer"; + private static final Map TOOL_FLAG_TRANSLATION_MAP; + private BurpTabPanel view; private AWSSignerConfiguration model; private AWSSignerController controller; @@ -99,6 +118,12 @@ public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequ return; } + // Is the request from a tool we want to sign? + if ((model.signForTools & toolFlag) == 0 && (model.signForTools & IBurpExtenderCallbacks.TOOL_SUITE) == 0) { + LogWriter.logDebug("Signing for requests from " + TOOL_FLAG_TRANSLATION_MAP.get(toolFlag) + " is not enabled. Ignoring Message."); + return; + } + //Could be a request we want to sign. Let's analyze it IRequestInfo request = helpers.analyzeRequest(messageInfo); diff --git a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java index 2dc51f4..d295ede 100644 --- a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java +++ b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java @@ -1,6 +1,7 @@ package com.netspi.awssigner.controller; import burp.BurpExtender; +import burp.IBurpExtenderCallbacks; import burp.IContextMenuInvocation; import com.netspi.awssigner.credentials.SigningCredentials; import com.google.gson.GsonBuilder; @@ -96,6 +97,62 @@ private void initListeners() { } })); + //Sign for all check box + view.signForAllCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_SUITE; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for repeater check box + view.signForRepeaterCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_REPEATER; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for proxy check box + view.signForProxyCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_PROXY; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for intruder check box + view.signForIntruderCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_INTRUDER; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign target check box + view.signForTargetCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_TARGET; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for extensions check box + view.signForExtensionsCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_EXTENDER; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for sequencer check box + view.signForSequencerCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_SEQUENCER; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + + //Sign for scanner check box + view.signForScannerCheckbox.addItemListener((ItemEvent e) -> { + logDebug("signForTools before: " + Integer.toBinaryString(model.signForTools)); + model.signForTools = model.signForTools ^ IBurpExtenderCallbacks.TOOL_SCANNER; + logDebug("signForTools after: " + Integer.toBinaryString(model.signForTools)); + }); + //Add button view.addProfileButton.addActionListener(((ActionEvent e) -> { logDebug("Add Profile Button Clicked."); diff --git a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java index 1bc036d..c59b893 100644 --- a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java +++ b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java @@ -5,10 +5,13 @@ import java.util.Optional; import java.util.stream.Collectors; +import burp.IBurpExtenderCallbacks; + public class AWSSignerConfiguration { public volatile boolean isEnabled = true; public volatile List profiles = new ArrayList<>(); public volatile Profile alwaysSignWithProfile; + public volatile int signForTools = IBurpExtenderCallbacks.TOOL_SUITE; public List getProfileNames() { return profiles.stream().map(Profile::getName).collect(Collectors.toList()); From f48cd96e0d3c8b2045e64ac9cd50fe2865489843 Mon Sep 17 00:00:00 2001 From: Timothy Clark Date: Wed, 7 Feb 2024 11:37:04 -0600 Subject: [PATCH 3/5] Bugfix for Test Profile Credentials button not always using the current credentials in the UI. --- .../controller/AWSSignerController.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java index d295ede..642d4f2 100644 --- a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java +++ b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java @@ -34,7 +34,6 @@ import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; @@ -325,6 +324,31 @@ private void initListeners() { } Profile profile = currentProfileOptional.get(); + + // Bug fix to use the updated config if the input text field still has focus + if (profile instanceof StaticCredentialsProfile) { + if (view.staticAccessKeyTextField.hasFocus()) { + ((StaticCredentialsProfile) profile).setAccessKey(view.staticAccessKeyTextField.getText()); + } + if (view.staticSecretKeyTextField.hasFocus()) { + ((StaticCredentialsProfile) profile).setSecretKey(view.staticSecretKeyTextField.getText()); + } + if (view.staticSessionTokenTextField.hasFocus()) { + ((StaticCredentialsProfile) profile).setSessionToken(view.staticSessionTokenTextField.getText()); + } + } else if (profile instanceof CommandProfile) { + if (view.commandCommandTextField.hasFocus()) { + ((CommandProfile) profile).setCommand(view.commandCommandTextField.getText()); + } + if (view.commandDurationTextField.hasFocus()) { + ((CommandProfile) profile).setDurationSecondsFromText(view.commandDurationTextField.getText()); + } + } else if ( profile instanceof AssumeRoleProfile) { + if (view.assumeRoleRoleArnTextField.hasFocus()) { + ((AssumeRoleProfile) profile).setRoleArn(view.assumeRoleRoleArnTextField.getText()); + } + } + //Check if we even have enough information to test this profile if (!profile.requiredFieldsAreSet()) { logDebug("Profile " + profile.getName() + " does not have all required fields"); From deea601ed794a1cc4aa6f84541eb5a1c12e72b81 Mon Sep 17 00:00:00 2001 From: Timothy Clark Date: Wed, 7 Feb 2024 12:12:51 -0600 Subject: [PATCH 4/5] Added support for configuration persistence on a per-project basis. --- src/main/java/burp/BurpExtender.java | 9 +- .../controller/AWSSignerController.java | 45 +++++- .../model/AWSSignerConfiguration.java | 27 +++- .../com/netspi/awssigner/model/Profile.java | 4 +- .../awssigner/utils/AWSSignerUtils.java | 153 ++++++++++++++++++ 5 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index c2d2c69..ff828b2 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -8,6 +8,7 @@ import com.netspi.awssigner.signing.DelegatingAwsRequestSigner; import com.netspi.awssigner.signing.ParsedAuthHeader; import com.netspi.awssigner.signing.SigningException; +import com.netspi.awssigner.utils.AWSSignerUtils; import com.netspi.awssigner.view.BurpUIComponentCustomizer; import com.netspi.awssigner.view.BurpTabPanel; import java.awt.Component; @@ -52,8 +53,14 @@ public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { //Save callbacks and helpers for later reference this.callbacks = callbacks; + AWSSignerUtils.setBurpExtenderCallbacks(callbacks); helpers = callbacks.getHelpers(); + // Extension unload/shutdown callback + this.callbacks.registerExtensionStateListener(()-> { + this.model.persist(); + }); + //Setup styling BurpUIComponentCustomizer.setBurpStyler((Component component) -> { callbacks.customizeUiComponent(component); @@ -66,7 +73,7 @@ public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { //Create the view view = new BurpTabPanel(); //Create the model - model = new AWSSignerConfiguration(); + model = AWSSignerConfiguration.getOrCreateProjectConfiguration(); //Create controller to keep them in sync controller = new AWSSignerController(view, model); diff --git a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java index 642d4f2..35bd1af 100644 --- a/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java +++ b/src/main/java/com/netspi/awssigner/controller/AWSSignerController.java @@ -66,8 +66,42 @@ public AWSSignerController(BurpTabPanel view, AWSSignerConfiguration model) { initListeners(); - //Add the initial profile - addProfile(new StaticCredentialsProfile(INIT_PROFILE_NAME)); + //Add the initial profile if no profiles exist already + + if (this.model.profiles.isEmpty()) { + addProfile(new StaticCredentialsProfile(INIT_PROFILE_NAME)); + } else { + this.view.profileList.setSelectedIndex(0); + } + + syncViewWithModel(); + } + + private void syncViewWithModel(){ + + //Setup profile list + DefaultListModel listModel = resetProfileList(); + view.profileList.setSelectedIndex(0); + + //Reset "Always Sign With" combo box + resetAlwaysSignWithProfileComboBox(); + + initializeProfileConfigurationTab(model.profiles.get(0)); + + // Hack to preserve the state of the flag bits, since the handlers for setSelected flip the bits currently. + + int tmp = model.signForTools; + this.view.persistConfigurationCheckbox.setSelected(model.shouldPersist); + this.view.signingEnabledCheckbox.setSelected(model.isEnabled); + this.view.signForAllCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_SUITE) != 0); + this.view.signForProxyCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_PROXY) != 0); + this.view.signForIntruderCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_INTRUDER) != 0); + this.view.signForExtensionsCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_EXTENDER) != 0); + this.view.signForRepeaterCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_REPEATER) != 0); + this.view.signForTargetCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_TARGET) != 0); + this.view.signForScannerCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_SCANNER) != 0); + this.view.signForSequencerCheckbox.setSelected((model.signForTools & IBurpExtenderCallbacks.TOOL_SEQUENCER) != 0); + model.signForTools = tmp; } private void initListeners() { @@ -78,6 +112,13 @@ private void initListeners() { logInfo("Signing Enabled: " + model.isEnabled); }); + //Configuration persistence checkbox + view.persistConfigurationCheckbox.addItemListener((ItemEvent e) -> { + logDebug("Persist Configuration Checkbox State Change."); + model.shouldPersist = (e.getStateChange() == ItemEvent.SELECTED); + logInfo("Persist Configuration Enabled: " + model.shouldPersist); + }); + //"Always Sign With" profile selection combox box alwaysSignWithComboBoxProfileSelectionListener = new ComboBoxProfileSelectionListener(model, "Always Sign With", (Profile profile) -> { logDebug("Setting \"Always Sign With\" Profile to: " + profile); diff --git a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java index c59b893..e56776b 100644 --- a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java +++ b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java @@ -1,17 +1,42 @@ package com.netspi.awssigner.model; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import com.netspi.awssigner.utils.AWSSignerUtils; + import burp.IBurpExtenderCallbacks; -public class AWSSignerConfiguration { +public class AWSSignerConfiguration implements Serializable { public volatile boolean isEnabled = true; public volatile List profiles = new ArrayList<>(); public volatile Profile alwaysSignWithProfile; public volatile int signForTools = IBurpExtenderCallbacks.TOOL_SUITE; + public volatile boolean shouldPersist = true; + + public static final String PREFERENCE_KEY_SUFFIX = "aws-signer-configuration"; + + public synchronized void persist() { + if (shouldPersist) { + AWSSignerUtils.storeObjectForCurrentProject(PREFERENCE_KEY_SUFFIX, this); + } + } + + public static AWSSignerConfiguration getOrCreateProjectConfiguration() { + + AWSSignerConfiguration config = new AWSSignerConfiguration(); + + Object o = AWSSignerUtils.getStoredObjectForCurrentProject(PREFERENCE_KEY_SUFFIX); + + if ( o != null && o instanceof AWSSignerConfiguration) { + config = (AWSSignerConfiguration) o; + } + + return config; + } public List getProfileNames() { return profiles.stream().map(Profile::getName).collect(Collectors.toList()); diff --git a/src/main/java/com/netspi/awssigner/model/Profile.java b/src/main/java/com/netspi/awssigner/model/Profile.java index 2e4a0a7..8232018 100644 --- a/src/main/java/com/netspi/awssigner/model/Profile.java +++ b/src/main/java/com/netspi/awssigner/model/Profile.java @@ -2,10 +2,12 @@ import com.netspi.awssigner.credentials.SignerCredentialException; import com.netspi.awssigner.credentials.SigningCredentials; + +import java.io.Serializable; import java.util.Objects; import java.util.Optional; -public abstract class Profile { +public abstract class Profile implements Serializable { protected String name; protected boolean isEnabled = true; diff --git a/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java b/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java new file mode 100644 index 0000000..6902afb --- /dev/null +++ b/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java @@ -0,0 +1,153 @@ +package com.netspi.awssigner.utils; + +import com.netspi.awssigner.log.LogWriter; + +import burp.IBurpExtenderCallbacks; +import burp.IHttpRequestResponse; +import burp.IHttpService; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.URL; +import java.util.Base64; +import java.util.UUID; + +public final class AWSSignerUtils { + private static String PREFERENCES_URL_STRING = "aws-signer-project-preferences"; + + private static IBurpExtenderCallbacks callbacks; + private static IHttpService httpService; + + public static void setBurpExtenderCallbacks(IBurpExtenderCallbacks callbacks) { + AWSSignerUtils.callbacks = callbacks; + httpService = callbacks.getHelpers().buildHttpService(PREFERENCES_URL_STRING, 65535, true); + } + + public static Object getStoredObjectForCurrentProject(String key) { + String projectUUIDString = getOrGenerateProjectUUID(); + LogWriter.logDebug("Project UUID string is: " + projectUUIDString); + + String base64 = callbacks.loadExtensionSetting(projectUUIDString+ "-" + key); + + Object result = null; + + if ( base64 != null ){ + try { + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(base64))); + + result = ois.readObject(); + } catch ( Exception e ) { + e.printStackTrace(); + } + } + + return result; + } + + public static void storeObjectForCurrentProject(String key, Object value) { + String projectUUIDString = getOrGenerateProjectUUID(); + LogWriter.logDebug("Project UUID string is: " + projectUUIDString); + + try { + + ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(outputBuffer); + oos.writeObject(value); + + byte[] serializedObject = outputBuffer.toByteArray(); + + String base64 = Base64.getEncoder().encodeToString(serializedObject); + + callbacks.saveExtensionSetting(projectUUIDString + "-" + key, base64); + } catch ( Exception e ) { + e.printStackTrace(); + } + } + + private static String getOrGenerateProjectUUID() { + IHttpRequestResponse[] sitemap = callbacks.getSiteMap(httpService.getProtocol() +"://" + httpService.getHost() + ":" + httpService.getPort() + "/" + PREFERENCES_URL_STRING); + + String uuidString = null; + + if (sitemap.length == 0) { + uuidString = UUID.randomUUID().toString(); + HttpResponseWrapper uuid = new HttpResponseWrapper(); + + try { + byte[] buffer = callbacks.getHelpers().buildHttpRequest(new URL(httpService.getProtocol(), httpService.getHost(), httpService.getPort(), "/" + PREFERENCES_URL_STRING)); + + + uuid.setRequest(buffer); + uuid.setResponse(uuidString.getBytes()); + uuid.setHttpService(httpService); + + uuid.setRequest(buffer); + callbacks.addToSiteMap(uuid); + } catch ( Exception e ){ + + e.printStackTrace(); + } + } else { + uuidString = new String(sitemap[0].getResponse()); + } + + LogWriter.logDebug("Using project UUID: " + uuidString); + + return uuidString; + } + + static class HttpResponseWrapper implements IHttpRequestResponse { + + private byte[] requestData; + private byte[] responseData; + private IHttpService service; + + @Override + public byte[] getRequest() { + return requestData; + } + + @Override + public void setRequest(byte[] message) { + this.requestData = message; + } + + @Override + public byte[] getResponse() { + return responseData; + } + + @Override + public void setResponse(byte[] message) { + this.responseData = message; + } + + @Override + public String getComment() { + return null; + } + + @Override + public void setComment(String comment) {} + + @Override + public String getHighlight() { + return null; + } + + @Override + public void setHighlight(String color) {} + + @Override + public IHttpService getHttpService() { + return service; + } + + @Override + public void setHttpService(IHttpService httpService) { + this.service = httpService; + } + } +} \ No newline at end of file From 09724798d0369eb8fbf6aad0f95b9d7697f177ad Mon Sep 17 00:00:00 2001 From: Timothy Clark Date: Wed, 7 Feb 2024 12:55:31 -0600 Subject: [PATCH 5/5] Variable renaming and a few comments. --- .../awssigner/model/AWSSignerConfiguration.java | 6 +++--- .../netspi/awssigner/utils/AWSSignerUtils.java | 15 ++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java index e56776b..8c0df93 100644 --- a/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java +++ b/src/main/java/com/netspi/awssigner/model/AWSSignerConfiguration.java @@ -17,11 +17,11 @@ public class AWSSignerConfiguration implements Serializable { public volatile int signForTools = IBurpExtenderCallbacks.TOOL_SUITE; public volatile boolean shouldPersist = true; - public static final String PREFERENCE_KEY_SUFFIX = "aws-signer-configuration"; + public static final String STORED_CONFIG_OBJECT_KEY = "aws-signer-configuration"; public synchronized void persist() { if (shouldPersist) { - AWSSignerUtils.storeObjectForCurrentProject(PREFERENCE_KEY_SUFFIX, this); + AWSSignerUtils.storeObjectForCurrentProject(STORED_CONFIG_OBJECT_KEY, this); } } @@ -29,7 +29,7 @@ public static AWSSignerConfiguration getOrCreateProjectConfiguration() { AWSSignerConfiguration config = new AWSSignerConfiguration(); - Object o = AWSSignerUtils.getStoredObjectForCurrentProject(PREFERENCE_KEY_SUFFIX); + Object o = AWSSignerUtils.getStoredObjectForCurrentProject(STORED_CONFIG_OBJECT_KEY); if ( o != null && o instanceof AWSSignerConfiguration) { config = (AWSSignerConfiguration) o; diff --git a/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java b/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java index 6902afb..031ce90 100644 --- a/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java +++ b/src/main/java/com/netspi/awssigner/utils/AWSSignerUtils.java @@ -15,16 +15,17 @@ import java.util.UUID; public final class AWSSignerUtils { - private static String PREFERENCES_URL_STRING = "aws-signer-project-preferences"; + private static String CONFIG_URL_STRING = "aws-signer-project-config"; private static IBurpExtenderCallbacks callbacks; private static IHttpService httpService; public static void setBurpExtenderCallbacks(IBurpExtenderCallbacks callbacks) { AWSSignerUtils.callbacks = callbacks; - httpService = callbacks.getHelpers().buildHttpService(PREFERENCES_URL_STRING, 65535, true); + httpService = callbacks.getHelpers().buildHttpService(CONFIG_URL_STRING, 65535, true); } + // Fetches a base64 encoded, serialized object as a burp setting on a per-project basis public static Object getStoredObjectForCurrentProject(String key) { String projectUUIDString = getOrGenerateProjectUUID(); LogWriter.logDebug("Project UUID string is: " + projectUUIDString); @@ -46,6 +47,7 @@ public static Object getStoredObjectForCurrentProject(String key) { return result; } + // Stores a base64 encoded, serialized object as a burp setting on a per-project basis public static void storeObjectForCurrentProject(String key, Object value) { String projectUUIDString = getOrGenerateProjectUUID(); LogWriter.logDebug("Project UUID string is: " + projectUUIDString); @@ -67,18 +69,21 @@ public static void storeObjectForCurrentProject(String key, Object value) { } private static String getOrGenerateProjectUUID() { - IHttpRequestResponse[] sitemap = callbacks.getSiteMap(httpService.getProtocol() +"://" + httpService.getHost() + ":" + httpService.getPort() + "/" + PREFERENCES_URL_STRING); + IHttpRequestResponse[] sitemap = callbacks.getSiteMap(httpService.getProtocol() +"://" + httpService.getHost() + ":" + httpService.getPort() + "/" + CONFIG_URL_STRING); String uuidString = null; + // UUID for this project hasnt been generated yet if (sitemap.length == 0) { uuidString = UUID.randomUUID().toString(); HttpResponseWrapper uuid = new HttpResponseWrapper(); try { - byte[] buffer = callbacks.getHelpers().buildHttpRequest(new URL(httpService.getProtocol(), httpService.getHost(), httpService.getPort(), "/" + PREFERENCES_URL_STRING)); + // Generate a fabricated request in the sitemap to store the UUID in the project for future retreival + // This is needed as the legacy API does not support distinguishing what project we are in natively + byte[] buffer = callbacks.getHelpers().buildHttpRequest(new URL(httpService.getProtocol(), httpService.getHost(), httpService.getPort(), "/" + CONFIG_URL_STRING)); uuid.setRequest(buffer); uuid.setResponse(uuidString.getBytes()); uuid.setHttpService(httpService); @@ -86,7 +91,6 @@ private static String getOrGenerateProjectUUID() { uuid.setRequest(buffer); callbacks.addToSiteMap(uuid); } catch ( Exception e ){ - e.printStackTrace(); } } else { @@ -98,6 +102,7 @@ private static String getOrGenerateProjectUUID() { return uuidString; } + // Used as a wrapper "HttpRequestResponse" object we can store in the sitemap, but we use it to just store arbitrary data in the response buffer. static class HttpResponseWrapper implements IHttpRequestResponse { private byte[] requestData;