Skip to content

Commit

Permalink
Introduce IntruderConfigModel to simplify IntruderConfigView and enab…
Browse files Browse the repository at this point in the history
…le testing.
  • Loading branch information
DolphFlynn committed Feb 25, 2024
1 parent 2e076cf commit 816e665
Show file tree
Hide file tree
Showing 4 changed files with 699 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public ConfigView(BurpConfig burpConfig, UserInterface userInterface, boolean is

private void createUIComponents() {
proxyConfigView = new ProxyConfigView(userInterface, burpConfig.proxyConfig());
intruderConfigView = new IntruderConfigView(userInterface, keysModel, burpConfig.intruderConfig());
intruderConfigView = new IntruderConfigView(userInterface, new IntruderConfigModel(keysModel, burpConfig.intruderConfig()));
scannerConfigView = new ScannerConfigView(userInterface, burpConfig.scannerConfig(), isProVersion);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.blackberry.jwteditor.view.config;

import burp.intruder.FuzzLocation;
import burp.intruder.IntruderConfig;
import com.blackberry.jwteditor.model.keys.Key;
import com.blackberry.jwteditor.model.keys.KeysModel;
import com.blackberry.jwteditor.model.keys.KeysModelListener.SimpleKeysModelListener;
import com.nimbusds.jose.JWSAlgorithm;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import static java.util.Arrays.stream;

class IntruderConfigModel {
static final String SIGNING_KEYS_UPDATED = "signingKeysUpdated";
static final String SELECTED_KEY_UPDATED = "selectedKeyUpdated";
static final String SIGNING_ALGORITHMS_UPDATED = "signingAlgorithmsUpdated";
static final String SELECTED_ALGORITHM_UPDATED = "selectedAlgorithmUpdated";
static final String RESIGN_UPDATED = "resignUpdated";

private static final JWSAlgorithm[] NO_ALGORITHMS = new JWSAlgorithm[0];

private final PropertyChangeSupport propertyChangeSupport;
private final KeysModel keysModel;
private final IntruderConfig intruderConfig;
private final List<PropertyChangeListener> listeners;

private String[] signingKeyIds;
private JWSAlgorithm[] selectedKeySigningAlgorithms;

IntruderConfigModel(KeysModel keysModel, IntruderConfig intruderConfig) {
this.keysModel = keysModel;
this.intruderConfig = intruderConfig;
this.signingKeyIds = signingKeyIds();
this.selectedKeySigningAlgorithms = signingAlgorithms();
this.listeners = new ArrayList<>();
this.propertyChangeSupport = new PropertyChangeSupport(this);

keysModel.addKeyModelListener(new SimpleKeysModelListener(this::updateSigningKeyList));
}

String fuzzParameter() {
return intruderConfig.fuzzParameter();
}

void setFuzzParameter(String fuzzParameter) {
intruderConfig.setFuzzParameter(fuzzParameter);
}

FuzzLocation fuzzLocation() {
return intruderConfig.fuzzLocation();
}

void setFuzzLocation(FuzzLocation fuzzLocation) {
intruderConfig.setFuzzLocation(fuzzLocation);
}

FuzzLocation[] fuzzLocations() {
return FuzzLocation.values();
}

boolean hasSigningKeys() {
return !keysModel.getSigningKeys().isEmpty();
}

String[] signingKeyIds() {
return keysModel.getSigningKeys().stream().map(Key::getID).toArray(String[]::new);
}

String signingKeyId() {
return intruderConfig.signingKeyId();
}

public void setSigningKeyId(String signingKeyId) {
String oldSigningKeyId = intruderConfig.signingKeyId();
JWSAlgorithm[] oldAlgorithms = selectedKeySigningAlgorithms;
intruderConfig.setSigningKeyId(signingKeyId);

boolean selectedKeyUnchanged = (oldSigningKeyId == null && signingKeyId==null) || (oldSigningKeyId != null && oldSigningKeyId.equals(signingKeyId));

if (!selectedKeyUnchanged) {
selectedKeySigningAlgorithms = signingAlgorithms();
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldAlgorithms, selectedKeySigningAlgorithms);
}
}

JWSAlgorithm[] signingAlgorithms() {
if (intruderConfig.signingKeyId() == null) {
return NO_ALGORITHMS;
}

return keysModel.getSigningKeys().stream()
.filter(k -> k.getID().equals(intruderConfig.signingKeyId()))
.findFirst()
.orElseThrow()
.getSigningAlgorithms();
}

JWSAlgorithm signingAlgorithm() {
return intruderConfig.signingAlgorithm();
}

void setSigningAlgorithm(JWSAlgorithm signingAlgorithm) {
intruderConfig.setSigningAlgorithm(signingAlgorithm);
}

boolean resign() {
return intruderConfig.resign() && hasSigningKeys();
}

void setResign(boolean resign) {
intruderConfig.setResign(resign);
}

void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
propertyChangeSupport.addPropertyChangeListener(listener);
}

void clearListeners() {
listeners.forEach(propertyChangeSupport::removePropertyChangeListener);
}

private void updateSigningKeyList() {
String[] oldSigningKeyIds = signingKeyIds;
JWSAlgorithm[] oldSigningAlgorithms = selectedKeySigningAlgorithms;
JWSAlgorithm oldSigningAlgorithm = intruderConfig.signingAlgorithm();
signingKeyIds = signingKeyIds();
propertyChangeSupport.firePropertyChange(SIGNING_KEYS_UPDATED, oldSigningKeyIds, signingKeyIds);

String selectedKeyId = intruderConfig.signingKeyId();
boolean modelIsEmpty = signingKeyIds.length == 0;
boolean modelWasEmpty = oldSigningKeyIds.length == 0 && signingKeyIds.length > 0;
boolean selectedKeyDeleted = selectedKeyId != null && (signingKeyIds.length == 0 || stream(signingKeyIds).noneMatch(selectedKeyId::equals));
boolean wasResigning = intruderConfig.resign();

if (modelIsEmpty) {
selectedKeySigningAlgorithms = NO_ALGORITHMS;
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldSigningAlgorithms, NO_ALGORITHMS);

String oldSigningKeyId = intruderConfig.signingKeyId();
intruderConfig.setSigningKeyId(null);
propertyChangeSupport.firePropertyChange(SELECTED_KEY_UPDATED, oldSigningKeyId, null);

intruderConfig.setSigningAlgorithm(null);
propertyChangeSupport.firePropertyChange(SELECTED_ALGORITHM_UPDATED, oldSigningAlgorithm, null);

intruderConfig.setResign(false);
propertyChangeSupport.firePropertyChange(RESIGN_UPDATED, wasResigning, false);
}
else if (modelWasEmpty || selectedKeyDeleted) {
String firstKeyId = signingKeyIds[0];
intruderConfig.setSigningKeyId(firstKeyId);
selectedKeySigningAlgorithms = signingAlgorithms();
JWSAlgorithm firstSigningAlgorithm = selectedKeySigningAlgorithms[0];
intruderConfig.setSigningAlgorithm(firstSigningAlgorithm);
intruderConfig.setResign(false);

propertyChangeSupport.firePropertyChange(SELECTED_KEY_UPDATED, null, firstKeyId);
propertyChangeSupport.firePropertyChange(SIGNING_ALGORITHMS_UPDATED, oldSigningAlgorithms, selectedKeySigningAlgorithms);
propertyChangeSupport.firePropertyChange(SELECTED_ALGORITHM_UPDATED, oldSigningAlgorithm, firstSigningAlgorithm);
propertyChangeSupport.firePropertyChange(RESIGN_UPDATED, wasResigning, false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,16 @@

import burp.api.montoya.ui.UserInterface;
import burp.intruder.FuzzLocation;
import burp.intruder.IntruderConfig;
import com.blackberry.jwteditor.model.keys.Key;
import com.blackberry.jwteditor.model.keys.KeysModel;
import com.blackberry.jwteditor.model.keys.KeysModelListener.SimpleKeysModelListener;
import com.blackberry.jwteditor.view.utils.DocumentAdapter;
import com.nimbusds.jose.JWSAlgorithm;

import javax.swing.*;
import java.util.List;
import java.util.Optional;

import static com.blackberry.jwteditor.view.config.IntruderConfigModel.*;
import static java.awt.Font.BOLD;


class IntruderConfigView {
private final IntruderConfig intruderConfig;
private final KeysModel keysModel;

private JPanel mainPanel;
private JTextField intruderParameterName;
private JComboBox comboBoxPayloadPosition;
Expand All @@ -47,93 +39,66 @@ class IntruderConfigView {
private JCheckBox resignIntruderJWS;
private JComboBox comboBoxIntruderSigningAlg;

IntruderConfigView(UserInterface userInterface, KeysModel keysModel, IntruderConfig intruderConfig) {
this.keysModel = keysModel;
this.intruderConfig = intruderConfig;

intruderParameterName.setText(intruderConfig.fuzzParameter());
IntruderConfigView(UserInterface userInterface, IntruderConfigModel model) {
intruderParameterName.setText(model.fuzzParameter());
intruderParameterName.getDocument().addDocumentListener(
new DocumentAdapter(e -> intruderConfig.setFuzzParameter(intruderParameterName.getText()))
new DocumentAdapter(e -> model.setFuzzParameter(intruderParameterName.getText()))
);

comboBoxPayloadPosition.setModel(new DefaultComboBoxModel<>(FuzzLocation.values()));
comboBoxPayloadPosition.setSelectedItem(intruderConfig.fuzzLocation());
comboBoxPayloadPosition.addActionListener(e -> intruderConfig.setFuzzLocation((FuzzLocation) comboBoxPayloadPosition.getSelectedItem()));
comboBoxPayloadPosition.setModel(new DefaultComboBoxModel<>(model.fuzzLocations()));
comboBoxPayloadPosition.setSelectedItem(model.fuzzLocation());
comboBoxPayloadPosition.addActionListener(e -> model.setFuzzLocation((FuzzLocation) comboBoxPayloadPosition.getSelectedItem()));

updateSigningKeyList();
comboBoxIntruderSigningKeyId.addActionListener(e -> {
String newSigningKeyId = (String) comboBoxIntruderSigningKeyId.getSelectedItem();
comboBoxIntruderSigningKeyId.setModel(new DefaultComboBoxModel<>(model.signingKeyIds()));
comboBoxIntruderSigningKeyId.setSelectedItem(model.signingKeyId());
comboBoxIntruderSigningKeyId.setEnabled(model.hasSigningKeys());
comboBoxIntruderSigningKeyId.addActionListener(e -> model.setSigningKeyId((String) comboBoxIntruderSigningKeyId.getSelectedItem()));

if (!intruderConfig.signingKeyId().equals(newSigningKeyId)) {
intruderConfig.setSigningKeyId(newSigningKeyId);
updateSigningAlgorithmList();
}
});
comboBoxIntruderSigningAlg.addActionListener(e -> intruderConfig.setSigningAlgorithm((JWSAlgorithm) comboBoxIntruderSigningAlg.getSelectedItem()));
resignIntruderJWS.addActionListener(e -> intruderConfig.setResign(resignIntruderJWS.isSelected()));
keysModel.addKeyModelListener(new SimpleKeysModelListener(this::updateSigningKeyList));
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel<>(model.signingAlgorithms()));
comboBoxIntruderSigningAlg.setSelectedItem(model.signingAlgorithm());
comboBoxIntruderSigningAlg.setEnabled(model.hasSigningKeys());
comboBoxIntruderSigningAlg.addActionListener(e -> model.setSigningAlgorithm((JWSAlgorithm) comboBoxIntruderSigningAlg.getSelectedItem()));

resignIntruderJWS.setEnabled(model.hasSigningKeys());
resignIntruderJWS.setSelected(model.resign());
resignIntruderJWS.addActionListener(e -> model.setResign(resignIntruderJWS.isSelected()));

intruderLabel.setFont(intruderLabel.getFont().deriveFont(BOLD));
userInterface.applyThemeToComponent(mainPanel);
}

private void updateSigningKeyList() {
List<Key> signingKeys = keysModel.getSigningKeys();
String[] signingKeyIds = signingKeys.stream().map(Key::getID).toArray(String[]::new);
String modelSelectedSigningId = intruderConfig.signingKeyId();

String viewSelectedKeyId = (String) comboBoxIntruderSigningKeyId.getSelectedItem();
comboBoxIntruderSigningKeyId.setModel(new DefaultComboBoxModel<>(signingKeyIds));

if (signingKeys.isEmpty()) {
resignIntruderJWS.setSelected(false);
resignIntruderJWS.setEnabled(false);
comboBoxIntruderSigningKeyId.setEnabled(false);
comboBoxIntruderSigningAlg.setEnabled(false);
intruderConfig.setResign(false);
intruderConfig.setSigningKeyId(null);
} else {
resignIntruderJWS.setEnabled(true);
comboBoxIntruderSigningKeyId.setEnabled(true);
comboBoxIntruderSigningAlg.setEnabled(true);

Optional<Key> selectedKey = signingKeys.stream()
.filter(k -> k.getID().equals(modelSelectedSigningId))
.findFirst();

if (selectedKey.isPresent()) {
Key key = selectedKey.get();

resignIntruderJWS.setSelected(intruderConfig.resign());
comboBoxIntruderSigningKeyId.setSelectedItem(key.getID());

if (!modelSelectedSigningId.equals(viewSelectedKeyId)) {
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(key.getSigningAlgorithms()));
comboBoxIntruderSigningAlg.setSelectedIndex(0);
}
} else {
resignIntruderJWS.setSelected(false);
comboBoxIntruderSigningKeyId.setSelectedIndex(0);

Key key = signingKeys.get(0);
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(key.getSigningAlgorithms()));
}
}
}
updateControls(model.hasSigningKeys());

model.addPropertyChangeListener(evt -> {
switch (evt.getPropertyName()) {
case SIGNING_KEYS_UPDATED:
comboBoxIntruderSigningKeyId.setModel(new DefaultComboBoxModel<>((String[]) evt.getNewValue()));
comboBoxIntruderSigningKeyId.setSelectedItem(model.signingKeyId());
updateControls(model.hasSigningKeys());
resignIntruderJWS.setSelected(model.resign());
break;

case SIGNING_ALGORITHMS_UPDATED:
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel((JWSAlgorithm[]) evt.getNewValue()));
break;

case SELECTED_KEY_UPDATED:
comboBoxIntruderSigningKeyId.setSelectedItem(evt.getNewValue());
break;

private void updateSigningAlgorithmList() {
Key key = keysModel.getSigningKeys().stream()
.filter(k -> k.getID().equals(intruderConfig.signingKeyId()))
.findFirst()
.orElseThrow();
case SELECTED_ALGORITHM_UPDATED:
comboBoxIntruderSigningAlg.setSelectedItem(evt.getNewValue());
break;

JWSAlgorithm[] signingAlgorithms = key.getSigningAlgorithms();
comboBoxIntruderSigningAlg.setModel(new DefaultComboBoxModel(signingAlgorithms));
case RESIGN_UPDATED:
resignIntruderJWS.setSelected((Boolean) evt.getNewValue());
break;
}
});
}

if (signingAlgorithms.length > 0) {
JWSAlgorithm algorithm = signingAlgorithms[0];
comboBoxIntruderSigningAlg.setSelectedItem(algorithm);
intruderConfig.setSigningAlgorithm(algorithm);
}
private void updateControls(boolean hasSigningKeys) {
resignIntruderJWS.setEnabled(hasSigningKeys);
comboBoxIntruderSigningKeyId.setEnabled(hasSigningKeys);
comboBoxIntruderSigningAlg.setEnabled(hasSigningKeys);
}
}
Loading

0 comments on commit 816e665

Please sign in to comment.