commit fb6a79296585e92b0bd7e4d3e0b174cdf02755dd
Author: Romain <>
Date: Sun Feb 21 20:01:13 2021 +0100
Snapshot 23797f5059
diff --git a/Licence note b/Licence note
new file mode 100644
index 0000000..01464de
--- /dev/null
+++ b/Licence note
@@ -0,0 +1 @@
+If you find software that doesn’t have a license, that means you have no permission from the creators of the software to use, modify, or share the software. Although a code host such as GitHub may allow you to view and fork the code, this does not imply that you are permitted to use, modify, or share the software for any purpose.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..da43e24
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+# CommandPC
+
+CommandPC is a program for executing commands on a remote machine regardless of the operating system.
+
+## Description
+
+The too long didn't read version is that: it's like SSH, but less secure and just a fun experimentation with threads, internationalization, encryption and GUI in JAVA.
+
+Composed of two part, a client and a server, this application allow you to send encrypted command from one machine to another. Both the client and the server can operate with or without a gui.
+English and French language are disponible within the application.
+
+## Instruction
+
+### Server
+
+Without the `nogui` argument, the server display its status with a system tray icon. By right-clicking the icon you can interact with it.
+
+| Server started | Server stopped |
+|:--------------:|:--------------:|
+|![server-systemTray-icon](img/CommandPC_systemTrayIcon.png)|![server-systemTray-icon](img/CommandPC_systemTrayIcon2.png)|||
+
+Example:
+
+- Windows sytem tray: ![server-systemTray-icon](img/CommandPC_systemTrayWindows.png)
+- Linux XFCE system tray: ![server-systemTray-icon](img/CommandPC_systemTrayLinux.png)
+
+Right-clicking on the icon allow you to start and stop the server. The command line argument `port=X` chand the listening port.
+
+### Client
+
+The client use a graphical interface to guide the user and is available in both French and English (using the "Français"/"English" button at the bottom)
+The interface is composed of two pane: "connection" and "command".
+
+The "connection" pane allows the connection to a remote server.
+
+![connection-result](img/CommandPC_connectionResult.png)
+
+After the connection established, the "command" pane allow to send commands to the server.
+
+| 'ls /' on a Linux machine | 'ipconfig' on a Windows machine and gui in French for a change |
+|:-------------------------:|:-------------------------------:|
+|![ls](img/CommandPC_commandLs.png)|![ipconfig](img/CommandPC_commandIpconfig.png)|
+
+## Security concerns
+
+**TLDR: Use at your own risk over a secure network.**
+
+### Command
+
+No effort is made to check if the command that you send is compatible with the user privilige, exist or is even safe to use.
+
+### Identity
+
+No identification of the user or the machine is made. In other words, if a server is running any number of client can connect and run command on it.
+
+### Encryption
+
+This software use AES 128 bits encryption, but like too many software (including payed one) it has flaws that make it unsuitable to use over unsecured networks.
+
+The main issue is the fact that during the first communication between the client and the server, the communication is encrypted via a master key.
+This master key, is the same for all firsts exchanges. After that, a new communication key is generated between individual client and the server.
+If somebody were to use a packet sniffer on the network, knowing the master key it's possible to get the communication key thus defeating the encryption entirely.
+
+Side note, AES 128 allow this program to run on any implementation of the Java platform. See the [Cipher documentation](https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html) for the complete list of "safe to use" cipher standard.
diff --git a/client/.classpath b/client/.classpath
new file mode 100644
index 0000000..fd51525
--- /dev/null
+++ b/client/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 0000000..ed9b2c9
--- /dev/null
+++ b/client/.gitignore
@@ -0,0 +1,91 @@
+########################
+#JAVA
+########################
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+########################
+# ECLIPSE
+########################
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+
diff --git a/client/.project b/client/.project
new file mode 100644
index 0000000..1b0fe6e
--- /dev/null
+++ b/client/.project
@@ -0,0 +1,17 @@
+
+
+ client
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/client/resource/iconCommandPC.png b/client/resource/iconCommandPC.png
new file mode 100644
index 0000000..7fa2e8e
Binary files /dev/null and b/client/resource/iconCommandPC.png differ
diff --git a/client/resource/iconCommunication.png b/client/resource/iconCommunication.png
new file mode 100644
index 0000000..5fed72c
Binary files /dev/null and b/client/resource/iconCommunication.png differ
diff --git a/client/resource/iconConnection.png b/client/resource/iconConnection.png
new file mode 100644
index 0000000..472d8a8
Binary files /dev/null and b/client/resource/iconConnection.png differ
diff --git a/client/src/bundle/Bundle.properties b/client/src/bundle/Bundle.properties
new file mode 100644
index 0000000..ffa92f3
--- /dev/null
+++ b/client/src/bundle/Bundle.properties
@@ -0,0 +1,38 @@
+
+address = Address
+
+clear = Clear
+
+command = Command
+
+commandToExecute = Command to execute:
+
+connected = Connected
+
+connectedTo = Connected to
+
+connection = Connection
+
+connectionEnded = Connection ended
+
+errorSpecifyAddressAndPort = Specify both address and port.
+
+execute = Execute
+
+help_argument = Arguments:
+
+help_cmd = Send a command X to the remote server. Don't launch the graphical user interface.
+
+help_help = Show this help message.
+
+help_intro = CommandPC is a program for executing commands on a remote machine regardless of the operating system.
+
+help_ip = Set the server address to X.
+
+help_port = Set the server port to X.
+
+languageAlt = Fran\u00E7ais
+
+languageName = English
+
+port = Port
diff --git a/client/src/bundle/Bundle_fr.properties b/client/src/bundle/Bundle_fr.properties
new file mode 100644
index 0000000..b120855
--- /dev/null
+++ b/client/src/bundle/Bundle_fr.properties
@@ -0,0 +1,38 @@
+
+address = Adresse
+
+clear = Vider
+
+command = Commande
+
+commandToExecute = Commande \u00E0 ex\u00E9cuter:
+
+connected = Connect\u00E9
+
+connectedTo = Connect\u00E9 \u00E0
+
+connection = Connexion
+
+connectionEnded = Connexion termin\u00E9e
+
+errorSpecifyAddressAndPort = Pr\u00E9cisez l'adresse et le port.
+
+execute = Ex\u00E9cuter
+
+help_argument = Arguments:
+
+help_cmd = Envoie une commande X au serveur distant. Ne d\u00E9marre pas l'interface graphique.
+
+help_help = Affiche ce message d'aide.
+
+help_intro = CommandPC est un programme destin\u00E9 \u00E0 ex\u00E9cuter des commandes sur un serveur distant, quelque soit son syst\u00E8me d'exploitation.
+
+help_ip = D\u00E9fini l'adresse du serveur distant.
+
+help_port = D\u00E9fini le port du serveur distant.
+
+languageAlt = English
+
+languageName = Fran\u00E7ais
+
+port = Port
diff --git a/client/src/generic/Status.java b/client/src/generic/Status.java
new file mode 100644
index 0000000..abfdaf0
--- /dev/null
+++ b/client/src/generic/Status.java
@@ -0,0 +1,53 @@
+package generic;
+
+/**
+ * Generic response class.
+ */
+public class Status {
+ /** Indicate if the operation was a success. By default, false. */
+ public boolean success;
+ /** Response message.*/
+ public String message;
+ /** Response payload.*/
+ public T payload;
+ /** Response error */
+ public E error;
+
+ public Status() {
+ super();
+ this.success=false;
+ }
+ public Status(boolean success) {
+ super();
+ this.success = success;
+ }
+ public Status(boolean success, String message) {
+ super();
+ this.success = success;
+ this.message = message;
+ }
+ public Status(boolean success, String message, T payload) {
+ super();
+ this.success = success;
+ this.message = message;
+ this.payload = payload;
+ }
+ public Status(boolean success, String message, T payload, E error) {
+ super();
+ this.success = success;
+ this.message = message;
+ this.payload = payload;
+ this.error = error;
+ }
+ @Override
+ public String toString() {
+ String result="Status [success="+success+", message="+message;
+ if(payload!=null) {
+ result+=", payload="+payload.toString();
+ }
+ if(error!=null) {
+ result+=", error="+error.toString();
+ }
+ return result+"]";
+ }
+}
\ No newline at end of file
diff --git a/client/src/gui/GUI.java b/client/src/gui/GUI.java
new file mode 100644
index 0000000..c44ae5b
--- /dev/null
+++ b/client/src/gui/GUI.java
@@ -0,0 +1,173 @@
+package gui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingConstants;
+import javax.swing.WindowConstants;
+
+import generic.Status;
+import gui.panel.CommunicationPanel;
+import gui.panel.ConnectionPanel;
+import network.CommunicationManager;
+
+public class GUI extends JFrame {
+ private static final long serialVersionUID = 1L;
+ private ConnectionPanel connectionPanel;
+ private CommunicationPanel communicationPanel;
+ private JPanel languagePanel;
+ private JButton languageButton;
+ private JTabbedPane tabbedPane;
+
+ private CommunicationManager communicationManager;
+
+ public GUI(CommunicationManager communicationManager) {
+ super();
+ this.communicationManager=communicationManager;
+ connectionPanel=new ConnectionPanel(this);
+ connectionPanel.setAddress(communicationManager.getAddress());
+ connectionPanel.setPort(String.valueOf(communicationManager.getPort()));
+ communicationPanel=new CommunicationPanel(this);
+ initialize();
+ }
+
+ /**
+ * Initialize the default state of the different GUI elements.
+ */
+ private void initialize() {
+ this.setTitle("CommandPC - MARTIN Romain");
+ this.setIconImage(getToolkit().getImage(getClass().getResource("/iconCommandPC.png")));
+ this.setSize(600,300);
+ this.setResizable(true);
+
+ this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ this.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ communicationManager.disconnect();
+ dispose();
+ };
+ });
+
+ GridBagLayout gbl_contentPane=new GridBagLayout();
+ getContentPane().setLayout(gbl_contentPane);
+
+ tabbedPane=new JTabbedPane(SwingConstants.TOP);
+ tabbedPane.add("panelConnection",connectionPanel);
+ tabbedPane.add("panelCommunication",communicationPanel);
+ tabbedPane.setIconAt(0,new ImageIcon(getClass().getResource("/iconConnection.png")));
+ tabbedPane.setIconAt(1,new ImageIcon(getClass().getResource("/iconCommunication.png")));
+ tabbedPane.setEnabledAt(1,false);
+ GridBagConstraints gbc_tabbedPane=new GridBagConstraints();
+ gbc_tabbedPane.gridx=0;
+ gbc_tabbedPane.gridy=0;
+ gbc_tabbedPane.weightx=1.0d;
+ gbc_tabbedPane.weighty=1.0d;
+ gbc_tabbedPane.fill=GridBagConstraints.BOTH;
+ getContentPane().add(tabbedPane,gbc_tabbedPane);
+
+ GridBagLayout gbl_languagePanel=new GridBagLayout();
+ languagePanel=new JPanel(gbl_languagePanel);
+ GridBagConstraints gbc_languagePanel=new GridBagConstraints();
+ gbc_languagePanel.gridx=0;
+ gbc_languagePanel.gridy=1;
+ gbc_languagePanel.fill=GridBagConstraints.HORIZONTAL;
+
+ languageButton=new JButton("languageButton");
+ languageButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent e) {
+ if(Locale.getDefault().getLanguage().equals(Locale.FRENCH.toString())) {
+ Locale.setDefault(Locale.ENGLISH);
+ }else {
+ Locale.setDefault(Locale.FRENCH);
+ }
+ //ResourceBundle.clearCache();
+ setText();
+ }
+ });
+ languagePanel.add(languageButton);
+
+ getContentPane().add(languagePanel,gbc_languagePanel);
+
+ setText();
+ }
+
+ /**
+ * Set the correct text for all graphical elements according to the default {@link Locale}.
+ * @see java.util.Locale#getDefault()
+ */
+ private void setText(){
+ ResourceBundle resourceBundle=ResourceBundle.getBundle("bundle/Bundle",Locale.getDefault());
+ languageButton.setText(resourceBundle.getString("languageAlt"));
+ tabbedPane.setTitleAt(0,resourceBundle.getString("connection"));
+ tabbedPane.setTitleAt(1,resourceBundle.getString("command"));
+
+ communicationPanel.setText();
+ connectionPanel.setText();
+ }
+
+ /**
+ * Request connection status change.
+ * @param isConnection true if this is a connection request, false to disconnect.
+ * @param address address of the remote server.
+ * @param port port of the remote server.
+ * @return true if operation successful.
+ */
+ public boolean changeConnectionStatus(boolean isConnection,String address,String port) {
+ //Disconnection
+ if(isConnection==false) {
+ communicationManager.disconnect();
+ tabbedPane.setEnabledAt(1,false);
+ tabbedPane.setSelectedIndex(0);
+ return true;
+ }
+
+ ResourceBundle resourceBundle=ResourceBundle.getBundle("bundle/Bundle",Locale.getDefault());
+
+ if(address.isBlank() || port.isBlank()) {
+ connectionPanel.addLog(resourceBundle.getString("errorSpecifyAddressAndPort"),true);
+ return false;
+ }
+
+ Status