· 8 years ago · Jan 10, 2018, 08:38 PM
1package dslab.client;
2
3import java.io.*;
4import java.net.Socket;
5import java.security.InvalidKeyException;
6import java.security.NoSuchAlgorithmException;
7import java.util.ArrayList;
8import java.util.Base64;
9import java.util.Scanner;
10import java.util.concurrent.ExecutorService;
11import java.util.concurrent.Executors;
12import java.util.regex.Matcher;
13import java.util.regex.Pattern;
14
15import dslab.ComponentFactory;
16import dslab.mailbox.Message;
17import dslab.util.Config;
18import dslab.util.Keys;
19
20import javax.crypto.Mac;
21import javax.crypto.SecretKey;
22
23public class MessageClient implements IMessageClient, Runnable {
24
25 private String componentId;
26 private Config config;
27 private InputStream in;
28 private PrintStream out;
29
30 private Socket socket;
31
32 private SecretKey sharedSecretKey;
33
34 private ExecutorService pool = Executors.newFixedThreadPool(1);
35
36
37 /**
38 * Creates a new client instance.
39 *
40 * @param componentId the id of the component that corresponds to the Config resource
41 * @param config the component config
42 * @param in the input stream to read console input from
43 * @param out the output stream to write console output to
44 */
45 public MessageClient(String componentId, Config config, InputStream in, PrintStream out) {
46 this.componentId = componentId;
47 this.config = config;
48 this.in = in;
49 this.out = out;
50
51 try {
52 this.sharedSecretKey = Keys.readSecretKey(new File("keys/hmac.key"));
53 } catch (IOException e) {
54 e.printStackTrace();
55 }
56 }
57
58 @Override
59 public void run() {
60 Scanner sc = new Scanner(in);
61
62 /*
63 The connection to the DMAP server should be established as soon as the client starts,
64 using the server and login details stored in the client’s properties file
65 */
66
67 try {
68 socket = new Socket(config.getString("mailbox.host"), config.getInt("mailbox.port"));
69 PrintStream out = new PrintStream(socket.getOutputStream());
70
71 // TODO WICHTIG!!!!!!!!!!!!!!!!! einkommentieren: if (!in.readLine().equals("ok DMAP")) return;
72 out.println("startsecure");
73 out.println("login " + config.getString("mailbox.user") + " " + config.getString("mailbox.password"));
74
75 System.out.println("ok run");
76
77 while(sc.hasNext()) {
78
79 String cmd = sc.next();
80 String[] splitted = cmd.split(" ");
81 //TODO Validierung
82 switch(splitted[0]) {
83 case "inbox" :
84 inbox();
85 break;
86 case "delete" :
87 delete(splitted[1]);
88 break;
89 case "verify" :
90 verify(splitted[1]);
91 break;
92 case "msg" :
93 Pattern p = Pattern.compile("\"([^\"]*)\"");
94 Matcher m = p.matcher(cmd);
95 msg(splitted[1], m.group(1), m.group(1));
96 break;
97 case "shutdown" :
98 shutdown();
99 break;
100 default:
101 shutdown();
102 break;
103 }
104 }
105 out.close();
106 } catch (IOException e) {
107 e.printStackTrace();
108 }
109
110 sc.close();
111 shutdown();
112 }
113
114 @Override
115 public void inbox() {
116 try {
117 PrintStream out = new PrintStream(socket.getOutputStream());
118 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
119
120 out.println("list");
121 ArrayList<Integer> messageIds = new ArrayList<Integer>();
122 for (String line = in.readLine(); line != null; line = in.readLine()) {
123 if(line.equals("ok"))
124 break;
125 messageIds.add(Integer.parseInt(line.split(" ")[0]));
126 }
127
128 for(Integer messageId : messageIds) {
129 out.println("show " + messageId);
130 System.out.println(messageId);
131 for (String line = in.readLine(); line != null; line = in.readLine()) {
132 if(!line.split(" ")[0].equals("hash") && !line.equals("ok")){
133 System.out.println(line);
134 }
135 }
136 }
137 out.close();
138 in.close();
139 } catch (IOException e) {
140 e.printStackTrace();
141 }
142 }
143
144 @Override
145 public void delete(String id) {
146 out.println("delete " + id);
147 System.out.println("ok");
148 }
149
150 @Override
151 public void verify(String id) {
152
153 int messageId = Integer.parseInt(id);
154 Message message = loadMessage(messageId);
155 String hash = signMessage(message);
156
157 if(hash.equals(message.getHash()))
158 out.println("ok");
159 else
160 out.println("error");
161 }
162
163 public String signMessage(Message message) {
164 byte[] hash = new byte[0];
165 try {
166 Mac macInstance = Mac.getInstance("HmacSHA256");
167 macInstance.init(sharedSecretKey);
168
169 String msg = String.join("\n", message.getFrom(), message.getToClients(), message.getSubject(), message.getData());
170 hash = macInstance.doFinal(msg.getBytes());
171 } catch (NoSuchAlgorithmException e) {
172 //TODO macInstace Algo not found
173 } catch (InvalidKeyException e) {
174 e.printStackTrace();
175 }
176 return Base64.getEncoder().encodeToString(hash);
177 }
178
179 @Override
180 public void msg(String to, String subject, String data) {
181 /*
182 The connection to the DMEP server should be established every time the msg command is invoked.
183 */
184
185 try {
186 Socket transferSocket = new Socket(config.getString("transfer.host"), config.getInt("transfer.port"));
187 PrintStream out = new PrintStream(transferSocket.getOutputStream());
188 BufferedReader in = new BufferedReader(new InputStreamReader(transferSocket.getInputStream()));
189
190 out.println("begin");
191 in.readLine();
192 out.println(to);
193 in.readLine();
194 out.println(subject);
195 in.readLine();
196 out.println(data);
197 in.readLine();
198 out.println(config.getString("transfer.email"));
199 in.readLine();
200 out.println("send");
201 in.readLine();
202 out.println("quit");
203 in.readLine();
204
205 System.out.println("ok");
206 out.close();
207 in.close();
208 } catch (IOException e) {
209 e.printStackTrace();
210 }
211
212 }
213
214 public Message loadMessage(int messageId){
215 Message m = new Message(null, null, null, null, null);
216
217 try {
218 PrintStream out = new PrintStream(socket.getOutputStream());
219 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
220
221 out.println("show " + messageId);
222 m.setFrom(in.readLine().split(" ")[1]);
223 m.setTo(in.readLine().split(" ")[1]);
224
225 String[] newLine = in.readLine().split(" ");
226 String tmp = "";
227 for(int x = 1; x < newLine.length; x++) {
228 tmp += newLine[x] + " ";
229 }
230 tmp = tmp.substring(0, tmp.length() - 1);
231 m.setSubject(tmp);
232
233 newLine = in.readLine().split(" ");
234 tmp = "";
235 for(int x = 1; x < newLine.length; x++) {
236 tmp += newLine[x] + " ";
237 }
238 tmp = tmp.substring(0, tmp.length() - 1);
239 m.setData(tmp);
240
241 m.setHash(in.readLine().split(" ")[1]);
242
243 if(in.readLine().equals("ok"))
244 return m;
245
246 } catch (IOException e) {
247 e.printStackTrace();
248 }
249 return null;
250 }
251
252 @Override
253 public void shutdown() {
254 //TODO Logout
255 }
256
257 public static void main(String[] args) throws Exception {
258 IMessageClient client = ComponentFactory.createMessageClient(args[0], System.in, System.out);
259 client.run();
260 }
261}