Allow 'startsecure' to be issued at any time
This commit is contained in:
parent
a9eab7cfb9
commit
93a2a87f07
@ -12,6 +12,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import at.ac.tuwien.dsg.orvell.Shell;
|
||||||
|
import at.ac.tuwien.dsg.orvell.annotation.Command;
|
||||||
import dslab.ComponentFactory;
|
import dslab.ComponentFactory;
|
||||||
import dslab.exception.FailedVerificationException;
|
import dslab.exception.FailedVerificationException;
|
||||||
import dslab.util.Config;
|
import dslab.util.Config;
|
||||||
@ -22,6 +24,8 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
|
|
||||||
public class MessageClient implements IMessageClient, Runnable {
|
public class MessageClient implements IMessageClient, Runnable {
|
||||||
private static final Logger logger = Logger.getLogger(MessageClient.class.getName());
|
private static final Logger logger = Logger.getLogger(MessageClient.class.getName());
|
||||||
|
private final String componentId;
|
||||||
|
private final InputStream consoleIn;
|
||||||
|
|
||||||
private final String transferHost;
|
private final String transferHost;
|
||||||
private final int transferPort;
|
private final int transferPort;
|
||||||
@ -38,9 +42,11 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
|
|
||||||
private PrintWriter dmtpOut;
|
private PrintWriter dmtpOut;
|
||||||
private BufferedReader dmtpIn;
|
private BufferedReader dmtpIn;
|
||||||
private PrintWriter dmapOut;
|
private PrintStream dmapOut;
|
||||||
private BufferedReader dmapIn;
|
private BufferedReader dmapIn;
|
||||||
|
|
||||||
|
private final Shell shell;
|
||||||
|
|
||||||
private Cipher aesEncryptCipher;
|
private Cipher aesEncryptCipher;
|
||||||
private Cipher aesDecryptCipher;
|
private Cipher aesDecryptCipher;
|
||||||
private byte[] challenge;
|
private byte[] challenge;
|
||||||
@ -62,6 +68,13 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
this.mailboxUser = config.getString("mailbox.user");
|
this.mailboxUser = config.getString("mailbox.user");
|
||||||
this.mailboxPassword = config.getString("mailbox.password");
|
this.mailboxPassword = config.getString("mailbox.password");
|
||||||
|
|
||||||
|
this.componentId = componentId;
|
||||||
|
this.consoleIn = in;
|
||||||
|
|
||||||
|
this.shell = new Shell(in, out);
|
||||||
|
this.shell.register(this);
|
||||||
|
this.shell.setPrompt(this.componentId + "> ");
|
||||||
|
|
||||||
logger.info(String.format("TransferHost: %s\nTransferPort: %d\nMailboxHost: %s\nMailboxPort: %d\nTransferEmail: %s\nMailboxUser: %s\nMailboxPassword: %s",
|
logger.info(String.format("TransferHost: %s\nTransferPort: %d\nMailboxHost: %s\nMailboxPort: %d\nTransferEmail: %s\nMailboxUser: %s\nMailboxPassword: %s",
|
||||||
transferHost, transferPort, mailboxHost, mailboxPort, transferEmail, mailboxUser, mailboxPassword));
|
transferHost, transferPort, mailboxHost, mailboxPort, transferEmail, mailboxUser, mailboxPassword));
|
||||||
}
|
}
|
||||||
@ -72,7 +85,7 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
logger.info("Starting connection to MailboxHost on " + this.mailboxHost + " on port " + this.mailboxPort);
|
logger.info("Starting connection to MailboxHost on " + this.mailboxHost + " on port " + this.mailboxPort);
|
||||||
this.dmapSocket = new Socket(this.mailboxHost, this.mailboxPort);
|
this.dmapSocket = new Socket(this.mailboxHost, this.mailboxPort);
|
||||||
this.dmapIn = new BufferedReader(new InputStreamReader(this.dmapSocket.getInputStream()));
|
this.dmapIn = new BufferedReader(new InputStreamReader(this.dmapSocket.getInputStream()));
|
||||||
this.dmapOut = new PrintWriter(this.dmapSocket.getOutputStream(), true);
|
this.dmapOut = new PrintStream(this.dmapSocket.getOutputStream(), true);
|
||||||
|
|
||||||
String input = null;
|
String input = null;
|
||||||
String message = null;
|
String message = null;
|
||||||
@ -84,10 +97,8 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
|
|
||||||
startSecure();
|
startSecure();
|
||||||
loginUser();
|
loginUser();
|
||||||
|
shell.run();
|
||||||
|
|
||||||
while (!Thread.currentThread().isInterrupted() && ((input = this.dmapIn.readLine()) != null)) {
|
|
||||||
// TODO implement commands
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("Could not connect to MailboxHost " + this.mailboxHost + " on port " + this.mailboxPort);
|
logger.severe("Could not connect to MailboxHost " + this.mailboxHost + " on port " + this.mailboxPort);
|
||||||
shutdown();
|
shutdown();
|
||||||
@ -103,7 +114,7 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
message = "login " + this.mailboxUser + " " + this.mailboxPassword;
|
message = "login " + this.mailboxUser + " " + this.mailboxPassword;
|
||||||
this.dmapOut.println(getAesCiphertext(message));
|
this.dmapOut.println(getAesCiphertext(message));
|
||||||
String response = getAesPlaintext(this.dmapIn.readLine());
|
String response = getAesPlaintext(this.dmapIn.readLine());
|
||||||
if (!response.startsWith("ok DMAP2.0"))
|
if (!response.startsWith("ok"))
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +139,6 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||||
// Make generator generate public key from X509 spec
|
// Make generator generate public key from X509 spec
|
||||||
serverPublicKey = kf.generatePublic(spec);
|
serverPublicKey = kf.generatePublic(spec);
|
||||||
logger.info("Server's Public Key: " + serverPublicKey);
|
|
||||||
String clientChallenge = generateChallengeMessage(serverPublicKey);
|
String clientChallenge = generateChallengeMessage(serverPublicKey);
|
||||||
// Send clientChallenge to server
|
// Send clientChallenge to server
|
||||||
logger.info("Send clientchallenge to Server: " + clientChallenge);
|
logger.info("Send clientchallenge to Server: " + clientChallenge);
|
||||||
@ -274,21 +284,25 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
return (Base64.getEncoder().encodeToString(cipherTextChallenge));
|
return (Base64.getEncoder().encodeToString(cipherTextChallenge));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command
|
||||||
@Override
|
@Override
|
||||||
public void inbox() {
|
public void inbox() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command
|
||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command
|
||||||
@Override
|
@Override
|
||||||
public void verify(String id) {
|
public void verify(String id) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command
|
||||||
@Override
|
@Override
|
||||||
public void msg(String to, String subject, String data) {
|
public void msg(String to, String subject, String data) {
|
||||||
try {
|
try {
|
||||||
@ -302,6 +316,7 @@ public class MessageClient implements IMessageClient, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (dmtpSocket != null) {
|
if (dmtpSocket != null) {
|
||||||
|
|||||||
@ -13,14 +13,12 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -41,6 +39,8 @@ public class DMAPConnection implements Runnable {
|
|||||||
private Cipher aesEncryptCipher;
|
private Cipher aesEncryptCipher;
|
||||||
private Cipher aesDecryptCipher;
|
private Cipher aesDecryptCipher;
|
||||||
|
|
||||||
|
private boolean secure = false;
|
||||||
|
|
||||||
public DMAPConnection(Socket connection, ConcurrentHashMap<Email, LinkedList<Message>> storage, ConcurrentHashMap<String, String> userStorage, String componentId) {
|
public DMAPConnection(Socket connection, ConcurrentHashMap<Email, LinkedList<Message>> storage, ConcurrentHashMap<String, String> userStorage, String componentId) {
|
||||||
this.componentId = componentId;
|
this.componentId = componentId;
|
||||||
this.socket = connection;
|
this.socket = connection;
|
||||||
@ -56,20 +56,21 @@ public class DMAPConnection implements Runnable {
|
|||||||
this.out = new PrintWriter(socket.getOutputStream(), true);
|
this.out = new PrintWriter(socket.getOutputStream(), true);
|
||||||
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
out.println("ok DMAP2.0");
|
out.println("ok DMAP2.0");
|
||||||
startSecure();
|
|
||||||
login();
|
loginLoop();
|
||||||
|
|
||||||
String userInput;
|
String userInput;
|
||||||
while (!Thread.currentThread().isInterrupted() && (userInput = in.readLine()) != null) {
|
while (!Thread.currentThread().isInterrupted() && (userInput = in.readLine()) != null) {
|
||||||
if ("quit".equals(userInput)) {
|
if ("quit".equals(userInput)) {
|
||||||
out.println("ok bye");
|
out.println("ok bye");
|
||||||
shutdown();
|
loginLoop();
|
||||||
} else if ("logout".equals(userInput)) {
|
} else if ("logout".equals(userInput)) {
|
||||||
out.println("ok");
|
out.println("ok");
|
||||||
shutdown();
|
currentUser = null;
|
||||||
|
loginLoop();
|
||||||
} else if ("list".equals(userInput)) {
|
} else if ("list".equals(userInput)) {
|
||||||
listMessages();
|
listMessages();
|
||||||
} else if ("delete".equals(userInput.split("\\s+")[0])) {
|
} else if (userInput.startsWith("delete")) {
|
||||||
if (userInput.split("\\s+").length == 2) {
|
if (userInput.split("\\s+").length == 2) {
|
||||||
try {
|
try {
|
||||||
deleteMessage(userInput.split("\\s+")[1]);
|
deleteMessage(userInput.split("\\s+")[1]);
|
||||||
@ -79,7 +80,7 @@ public class DMAPConnection implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
out.println("Please supply a message id to delete!");
|
out.println("Please supply a message id to delete!");
|
||||||
}
|
}
|
||||||
} else if ("show".equals(userInput.split("\\s+")[0])) {
|
} else if (userInput.startsWith("show")) {
|
||||||
if (userInput.split("\\s+").length == 2) {
|
if (userInput.split("\\s+").length == 2) {
|
||||||
try {
|
try {
|
||||||
showMessage(userInput.split("\\s+")[1]);
|
showMessage(userInput.split("\\s+")[1]);
|
||||||
@ -89,6 +90,8 @@ public class DMAPConnection implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
out.println("Please supply a message id to show!");
|
out.println("Please supply a message id to show!");
|
||||||
}
|
}
|
||||||
|
} else if (userInput.startsWith("startsecure")) {
|
||||||
|
startSecure();
|
||||||
} else {
|
} else {
|
||||||
out.println("error protocol error");
|
out.println("error protocol error");
|
||||||
shutdown();
|
shutdown();
|
||||||
@ -104,6 +107,57 @@ public class DMAPConnection implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loginLoop() {
|
||||||
|
String userInput;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
userInput = in.readLine();
|
||||||
|
if (userInput.startsWith("quit")) {
|
||||||
|
out.println("ok bye");
|
||||||
|
shutdown();
|
||||||
|
} else if (userInput.startsWith("login")) {
|
||||||
|
String[] args = userInput.split("\\s+");
|
||||||
|
if (args.length != 3)
|
||||||
|
out.println("Please specify a username and password to login!");
|
||||||
|
if (this.userStorage.containsKey(args[1])) {
|
||||||
|
// Check if username exists
|
||||||
|
if (args[2].equals(this.userStorage.get(args[1]))) {
|
||||||
|
// Check if password matches
|
||||||
|
for (Email email : this.storage.keySet()) {
|
||||||
|
if (args[1].equals(email.getUsername())) {
|
||||||
|
// Set current user if login successful
|
||||||
|
currentUser = email;
|
||||||
|
logger.info("User successfully logged in: " + currentUser.toString());
|
||||||
|
out.println("ok");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error wrong password");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error unknown user");
|
||||||
|
}
|
||||||
|
} else if (userInput.startsWith("startsecure")) {
|
||||||
|
startSecure();
|
||||||
|
} else {
|
||||||
|
out.println("error not logged in");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedIOException ioe) {
|
||||||
|
logger.info("Received interrupt from parent. Shutting down...");
|
||||||
|
shutdown();
|
||||||
|
} catch (SocketException e) {
|
||||||
|
logger.finer("Received interrupt. Exiting " + this.toString());
|
||||||
|
shutdown();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Failed to get IO-Stream");
|
||||||
|
e.printStackTrace();
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the startsecure command issued by the MessageClient.
|
* Handles the startsecure command issued by the MessageClient.
|
||||||
*/
|
*/
|
||||||
@ -111,7 +165,6 @@ public class DMAPConnection implements Runnable {
|
|||||||
String userInput;
|
String userInput;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
userInput = in.readLine(); // Should always be "startsecure"
|
|
||||||
// Send componentId
|
// Send componentId
|
||||||
out.println("ok " + componentId);
|
out.println("ok " + componentId);
|
||||||
// Receive client challenge, secret key and iv
|
// Receive client challenge, secret key and iv
|
||||||
@ -129,6 +182,7 @@ public class DMAPConnection implements Runnable {
|
|||||||
logger.severe("Received " + userInput + "from MessageClient. Did not match 'ok'");
|
logger.severe("Received " + userInput + "from MessageClient. Did not match 'ok'");
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
|
this.secure = true; // Encrypted communication from now on
|
||||||
} catch (InterruptedIOException ioe) {
|
} catch (InterruptedIOException ioe) {
|
||||||
logger.info("Received interrupt from parent. Shutting down...");
|
logger.info("Received interrupt from parent. Shutting down...");
|
||||||
shutdown();
|
shutdown();
|
||||||
@ -230,11 +284,11 @@ public class DMAPConnection implements Runnable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
userInput = getAesPlaintext(in.readLine());
|
userInput = in.readLine();
|
||||||
if ("quit".equals(userInput.split("\\s+")[0])) {
|
if (userInput.startsWith("quit")) {
|
||||||
out.println(getAesCiphertext("ok bye"));
|
out.println("ok bye");
|
||||||
shutdown();
|
shutdown();
|
||||||
} else if ("login".equals(userInput.split("\\s+")[0])) {
|
} else if (userInput.startsWith("login")) {
|
||||||
String[] args = userInput.split("\\s+");
|
String[] args = userInput.split("\\s+");
|
||||||
if (args.length != 3)
|
if (args.length != 3)
|
||||||
out.println("Please specify a username and password to login!");
|
out.println("Please specify a username and password to login!");
|
||||||
@ -297,12 +351,14 @@ public class DMAPConnection implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void listMessages() {
|
private void listMessages() {
|
||||||
|
logger.info("'list' command received");
|
||||||
if (storage.get(currentUser).isEmpty()) {
|
if (storage.get(currentUser).isEmpty()) {
|
||||||
out.println("You do not have any messages at the moment!");
|
out.println("You do not have any messages at the moment!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Message m : storage.get(currentUser)) {
|
for (Message m : storage.get(currentUser)) {
|
||||||
|
logger.info("Printing message from user: " + m.listMessage());
|
||||||
out.println(m.listMessage());
|
out.println(m.listMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user