// Uses FILIUS' own firewall window of a computer (GUIApplicationFirewallWindow // on a GUIDesktopPanel) on firewall-pc's server as a person does: the three // boxes, the port field with its two lists and "Hinzufügen" (also with what // is no number, and numbers no port is), a row chosen and "Löschen". After // each step it writes what the window shows (the boxes and whether they can // be changed, the port field, the table, the log and whether it can be typed // into) and, where traffic is asked, what reaches the server from a computer // of its network and one behind the router: a ping, a TCP connection to its // echo server (a socket of the client's own), its DNS server asked for a name. The reference for the room's // firewall window (packages/core/test/firewallWindow.test.ts). // // Usage: java -cp filius.jar:lib/*:classes FirewallWindowRun import filius.gui.anwendungssicht.GUIApplicationFirewallWindow; import filius.gui.anwendungssicht.GUIDesktopPanel; import filius.software.clientserver.ServerBaustein; import filius.software.system.Betriebssystem; import filius.software.system.InternetKnotenBetriebssystem; import filius.software.transportschicht.TCPSocket; import filius.software.vermittlungsschicht.IcmpPaket; import java.awt.Component; import java.awt.Container; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.table.TableModel; public class FirewallWindowRun { static final String LOCAL = "00000000-0000-0000-0000-000000000201"; static final String REMOTE = "00000000-0000-0000-0000-000000000203"; static final String SERVER = "00000000-0000-0000-0000-000000000204"; static final String SERVER_ADDRESS = "10.0.0.10"; static final String SERVER_CLASS = "filius.software.clientserver.ServerBaustein"; static final List steps = new ArrayList<>(); static GUIApplicationFirewallWindow window; static ScenarioNetwork network; static int sequence = 1; static Object field(Object object, String name) throws Exception { Field field = GUIApplicationFirewallWindow.class.getDeclaredField(name); field.setAccessible(true); return field.get(object); } static void onEdt(Runnable action) throws Exception { SwingUtilities.invokeLater(action); Thread.sleep(500); } static Map box(String name) throws Exception { JCheckBox box = (JCheckBox) field(window, name); Map shown = new LinkedHashMap<>(); shown.put("selected", box.isSelected()); shown.put("enabled", box.isEnabled()); return shown; } static List> rows(JTable table) { List> rows = new ArrayList<>(); TableModel model = table.getModel(); for (int row = 0; row < model.getRowCount(); row++) { List cells = new ArrayList<>(); for (int column = 0; column < model.getColumnCount(); column++) cells.add(String.valueOf(model.getValueAt(row, column))); rows.add(cells); } return rows; } static InternetKnotenBetriebssystem system(String id) { return (InternetKnotenBetriebssystem) network.nodes.get(id).getSystemSoftware(); } static String ping(String from) { IcmpPaket answer = system(from).holeICMP().sendProbe(SERVER_ADDRESS, 64, 1, sequence++); return answer == null ? "null" : "ICMP " + answer.getIcmpType() + "/" + answer.getIcmpCode() + " from " + answer.getSender(); } /** A TCP connection to the server's echo server, as its client opens one (a socket of its own, closed again): "connected" or Java's exception. */ static String connect(String from) throws Exception { AtomicReference result = new AtomicReference<>("(no answer)"); Thread thread = new Thread(() -> { try { TCPSocket socket = new TCPSocket(system(from), SERVER_ADDRESS, 55555); socket.verbinden(); result.set("connected"); // Held a moment, as a person's client would: Java's echo server takes no connection closed at once (the next ones then time out). Thread.sleep(500); socket.schliessen(); } catch (Exception error) { result.set(error.getClass().getSimpleName() + ": " + error.getMessage()); } }); thread.start(); thread.join(60000); Thread.sleep(1000); return result.get(); } static String resolve(String from) throws Exception { AtomicReference result = new AtomicReference<>("(no answer)"); Thread thread = new Thread(() -> { try { result.set(String.valueOf(system(from).holeDNSClient().holeIPAdresse("www.filius.de"))); } catch (Exception error) { result.set(error.getClass().getSimpleName()); } }); thread.start(); thread.join(30000); return result.get(); } static void step(String name, boolean traffic) throws Exception { Map result = new LinkedHashMap<>(); result.put("step", name); if (traffic) { Map reached = new LinkedHashMap<>(); for (String[] each : new String[][] { { "local", LOCAL }, { "remote", REMOTE } }) { Map from = new LinkedHashMap<>(); from.put("ping", ping(each[1])); from.put("tcp", connect(each[1])); from.put("dns", resolve(each[1])); reached.put(each[0], from); } result.put("traffic", reached); } result.put("active", box("cbEinAus")); result.put("icmp", box("cbIcmp")); result.put("udp", box("cbUdp")); result.put("port", ((JTextField) field(window, "tfPort")).getText()); result.put("protocol", String.valueOf(((JComboBox) field(window, "cbProtocol")).getSelectedItem())); result.put("sender", String.valueOf(((JComboBox) field(window, "cbAlleAbsender")).getSelectedItem())); result.put("rows", rows((JTable) field(window, "tTabellePort"))); JTextArea log = (JTextArea) field(window, "log"); result.put("log", log.getText()); result.put("logEditable", log.isEditable()); steps.add(result); } static void press(String text) throws Exception { List found = new ArrayList<>(); collect(window, text, found); JButton button = found.get(0); onEdt(button::doClick); } static void collect(Container container, String text, List found) { for (Component component : container.getComponents()) { if (component instanceof JButton && text.equals(((JButton) component).getText())) found.add((JButton) component); if (component instanceof Container) collect((Container) component, text, found); } } static void click(String box) throws Exception { JCheckBox each = (JCheckBox) field(window, box); onEdt(each::doClick); } /** The port typed, the protocol (0 TCP, 1 UDP, 2 *) and the sender (0 all, 1 the same network) chosen, "Hinzufügen". */ static void add(String port, int protocol, int sender) throws Exception { JTextField field = (JTextField) field(window, "tfPort"); JComboBox protocols = (JComboBox) field(window, "cbProtocol"); JComboBox senders = (JComboBox) field(window, "cbAlleAbsender"); onEdt(() -> { field.setText(port); protocols.setSelectedIndex(protocol); senders.setSelectedIndex(sender); }); press("Hinzufügen"); } static void choose(int row) throws Exception { JTable table = (JTable) field(window, "tTabellePort"); onEdt(() -> table.setRowSelectionInterval(row, row)); } public static void main(String[] args) throws Exception { try { run(args); } catch (Throwable error) { error.printStackTrace(); System.exit(1); } System.exit(0); } static void run(String[] args) throws Exception { network = ScenarioNetwork.read(args[0]); Betriebssystem server = (Betriebssystem) network.nodes.get(SERVER).getSystemSoftware(); server.installApp("filius.software.firewall.Firewall", false); server.installApp(SERVER_CLASS, false); ServerBaustein echo = (ServerBaustein) server.holeSoftware(SERVER_CLASS); echo.setPort(55555); echo.setAktiv(true); network.start(); Thread.sleep(500); JFrame frame = new JFrame(); GUIDesktopPanel desktop = new GUIDesktopPanel(server); frame.getContentPane().add(desktop); window = (GUIApplicationFirewallWindow) desktop.starteAnwendung("filius.software.firewall.Firewall"); SwingUtilities.invokeAndWait(() -> { frame.pack(); frame.setVisible(true); }); Thread.sleep(500); step("open", true); // What Java's field does not take: nothing happens. add("abc", 0, 0); step("add port abc", false); add("", 0, 0); step("add an empty port", false); add("55555", 0, 0); step("add 55555 TCP for all senders", true); add("53", 1, 1); step("add 53 UDP for the same network", true); click("cbIcmp"); step("ICMP no longer allowed", true); click("cbUdp"); step("UDP filter off", true); // Numbers that are no port. add("-1", 2, 0); step("add -1 for all protocols", false); add("0", 0, 0); step("add 0 TCP", false); add("70000", 0, 1); step("add 70000 TCP for the same network", false); add(" 80", 0, 0); step("add a port after a space", false); // "Löschen" with no row chosen, then the first row. press("Löschen"); step("delete with no row chosen", false); choose(0); press("Löschen"); step("delete row 0", true); // Off: the boxes cannot be changed; on again. click("cbEinAus"); step("firewall off", true); click("cbEinAus"); step("firewall on again", false); Map output = new LinkedHashMap<>(); output.put("steps", steps); try (FileOutputStream out = new FileOutputStream(args[1])) { out.write((FlsOracle.Json.write(output, "") + "\n").getBytes(StandardCharsets.UTF_8)); } network.stop(); System.out.println("firewall window steps: " + steps.size()); } }