· 8 years ago · Jan 04, 2018, 05:26 PM
1package Server;
2
3import java.net.Socket;
4import java.io.OutputStream;
5import java.io.InputStreamReader;
6import java.nio.charset.StandardCharsets;
7import com.google.gson.*;
8import com.google.gson.stream.*;
9import java.io.FileInputStream;
10import java.io.FileNotFoundException;
11import java.io.IOException;
12import java.io.UnsupportedEncodingException;
13import java.security.InvalidKeyException;
14import java.security.NoSuchAlgorithmException;
15import java.util.Base64;
16import java.util.HashMap;
17import java.util.logging.Level;
18import java.util.logging.Logger;
19import javax.crypto.Mac;
20import javax.crypto.SecretKey;
21import javax.crypto.spec.SecretKeySpec;
22
23class ServerActions implements Runnable {
24
25 boolean registered = false;
26
27 Socket client;
28 JsonReader in;
29 OutputStream out;
30 ServerControl registry;
31 private String sessionKeys;
32 HashMap<String, byte[]> cartoes = new HashMap<String, byte[]>();
33
34 ServerActions(Socket c, ServerControl r)
35 {
36 client = c;
37 registry = r;
38
39 try
40 {
41 in = new JsonReader(new InputStreamReader(c.getInputStream(), "UTF-8"));
42 out = c.getOutputStream();
43 }
44 catch (Exception e)
45 {
46 System.err.print("Cannot use client socket: " + e);
47 Thread.currentThread().interrupt();
48 }
49 }
50
51 JsonObject readCommand() {
52 try {
53 JsonElement data = new JsonParser().parse(in);
54 if (data.isJsonObject()) {
55 return data.getAsJsonObject();
56 }
57 System.err.print("Error while reading command from socket (not a JSON object), connection will be shutdown\n");
58 return null;
59 } catch (JsonIOException | JsonSyntaxException e) {
60 System.err.print("Error while reading JSON command from socket, connection will be shutdown\n");
61 return null;
62 }
63
64 }
65
66 void executeCommand(JsonObject data) {
67 JsonElement cmd = data.get("type");
68 JsonElement mac = data.get("mac");
69 UserDescription me;
70
71 if (cmd.isJsonNull())
72 {
73 System.err.println("Invalid command in request: " + data);
74 return;
75 }
76 if(mac.isJsonNull()){
77 System.err.print("No \"mac\" field in \"mac\" request: " + data);
78 sendResult(null, "\"wrong request format\"");
79 return;
80 }
81 if(!calcMAC(data.remove("mac").toString(), mac.toString()))
82 {
83 System.err.print("MAC Algorthm Failed: " + data);
84 sendResult(null, "\"bad mac calc\"");
85 return;
86 }
87
88 //SESSION
89 if (cmd.getAsString().equals("session"))
90 {
91 JsonElement sessionKey = data.get("sessionKey");
92
93 if (sessionKey == null)
94 {
95 System.err.print("No \"sessionKey\" field in \"session\" request: " + data);
96 sendResult(null, "\"wrong request format\"");
97 return;
98 }
99
100 // adiciona a sessionKey e incrementa um novo sessionID
101 int count = sessionKeys.containsValue(sessionKey) ? sessionKeys.get(sessionKey) : 0;
102 int sessionID = count + 1;
103 sessionKeys.put(sessionKey.getAsString(), sessionID);
104
105 sendResult("\"result\":\"" + sessionID + "\"", null);
106 return;
107 }
108 // CREATE
109
110 if (cmd.getAsString().equals("create")) {
111 JsonElement uuid = data.get("uuid");
112 JsonElement cc = data.get("cartao");
113 int id = registry.getId(uuid.getAsString());
114 String descricao = null;
115
116 FileInputStream is;
117 try {
118 is = new FileInputStream("mboxes\\" + id + "\\description");
119 byte[] pub = new byte[is.available()];
120 is.read(pub);
121
122 String pb = new String(pub);
123 descricao = pb;
124 } catch (FileNotFoundException ex) {
125 Logger.getLogger(ServerActions.class.getName()).log(Level.SEVERE, null, ex);
126 } catch (IOException ex) {
127 Logger.getLogger(ServerActions.class.getName()).log(Level.SEVERE, null, ex);
128 }
129
130 byte[] cartao = Base64.getDecoder().decode(cc.getAsString());
131
132 if (cc == null) {
133 System.err.print("No \"cc\" field in \"cc\" request: " + data);
134 sendResult(null, "\"wrong request format\"");
135 return;
136 }
137
138 if (uuid == null) {
139 System.err.print("No \"uuid\" field in \"create\" request: " + data);
140 sendResult(null, "\"wrong request format\"");
141 return;
142 }
143
144 if (registry.userExists(uuid.getAsString())) {
145 System.err.println("User already exists: " + data);
146 sendResult(null, "\"uuid already exists\"");
147 return;
148 }
149
150 if (descricao.contains(cc.getAsString()) == true) {
151 //int id = registry.getId(uuid.getAsString());
152 sendResult("\"result\":\"" + id + "\"", null);
153
154 } else {
155
156 cartoes.put(uuid.getAsString(), cartao);
157 data.remove("type");
158 data.remove("cartao");
159 data.remove("mac");
160 me = registry.addUser(data);
161 sendResult("\"result\":\"" + me.id + "\",\"type\":\"create\",\"uuid\":\"" + uuid.getAsString() + "\"", null);
162
163 }
164 return;
165 }
166//
167// // LIST
168// if (cmd.getAsString().equals("list"))
169// {
170// String list;
171// int user = 0; // 0 means all users
172// JsonElement id = data.get("id");
173//
174// if (id != null)
175// {
176// user = id.getAsInt();
177// }
178//
179// System.out.println("List " + (user == 0 ? "all users" : "user ") + user);
180//
181// list = registry.listUsers(user);
182//
183// //sendResult("\"data\":" + (list == null ? "[]" : list), null);
184// sendResult("\"type\":\"list\",\"data\":" + (list == null ? "[]" : list), null);
185//
186// return;
187// }
188//
189// // NEW
190// if (cmd.getAsString().equals("new"))
191// {
192// JsonElement id = data.get("id");
193// int user = id == null ? -1 : id.getAsInt();
194//
195// if (id == null || user <= 0)
196// {
197// System.err.print("No valid \"id\" field in \"new\" request: " + data);
198// sendResult(null, "\"wrong request format\"");
199// return;
200// }
201//
202// sendResult("\"type\":\"new\",\"result\":" + registry.userNewMessages(user), null);
203// return;
204// }
205//
206// // ALL
207// if (cmd.getAsString().equals("all"))
208// {
209// JsonElement id = data.get("id");
210// int user = id == null ? -1 : id.getAsInt();
211//
212// if (id == null || user <= 0)
213// {
214// System.err.print("No valid \"id\" field in \"new\" request: " + data);
215// sendResult(null, "\"wrong request format\"");
216// return;
217// }
218//
219// sendResult("\"type\":\"all\",\"result\":[" + registry.userAllMessages(user) + ","
220// + registry.userSentMessages(user) + "]", null);
221// return;
222// }
223//
224// // SEND
225// if (cmd.getAsString().equals("send"))
226// {
227// JsonElement src = data.get("src");
228// JsonElement dst = data.get("dst");
229// JsonElement msg = data.get("msg");
230// JsonElement copy = data.get("copy");
231//
232// if (src == null || dst == null || msg == null || copy == null)
233// {
234// System.err.print("Badly formated \"send\" request: " + data);
235// sendResult(null, "\"wrong request format\"");
236// return;
237// }
238//
239// int srcId = src.getAsInt();
240// int dstId = dst.getAsInt();
241//
242// if (registry.userExists(srcId) == false)
243// {
244// System.err.print("Unknown source id for \"send\" request: " + data);
245// sendResult(null, "\"wrong parameters\"");
246// return;
247// }
248//
249// if (registry.userExists(dstId) == false)
250// {
251// System.err.print("Unknown destination id for \"send\" request: " + data);
252// sendResult(null, "\"wrong parameters\"");
253// return;
254// }
255//
256// // Save message and copy
257// String response = registry.sendMessage(srcId, dstId,
258// msg.getAsString(),
259// copy.getAsString());
260//
261// sendResult("\"type\":\"send\",\"result\":" + response, null);
262// return;
263// }
264//
265// // RECV
266// if (cmd.getAsString().equals("recv"))
267// {
268// JsonElement id = data.get("id");
269// JsonElement msg = data.get("msg");
270//
271// if (id == null || msg == null)
272// {
273// System.err.print("Badly formated \"recv\" request: " + data);
274// sendResult(null, "\"wrong request format\"");
275// return;
276// }
277//
278// int fromId = id.getAsInt();
279//
280// if (registry.userExists(fromId) == false)
281// {
282// System.err.print("Unknown source id for \"recv\" request: " + data);
283// sendResult(null, "\"wrong parameters\"");
284// return;
285// }
286//
287// if (registry.messageExists(fromId, msg.getAsString()) == false
288// && registry.messageExists(fromId, "_" + msg.getAsString()) == false)
289// {
290// System.err.println("Unknown message for \"recv\" request: " + data);
291// sendResult(null, "\"wrong parameters\"");
292// return;
293// }
294//
295// // Read message
296// String response = registry.recvMessage(fromId, msg.getAsString());
297//
298// sendResult("\"type\":\"recv\",\"result\":" + response, null);
299// return;
300// }
301//
302// // RECEIPT
303// if (cmd.getAsString().equals("receipt"))
304// {
305// JsonElement id = data.get("id");
306// JsonElement msg = data.get("msg");
307// JsonElement receipt = data.get("receipt");
308//
309// if (id == null || msg == null || receipt == null)
310// {
311// System.err.print("Badly formated \"receipt\" request: " + data);
312// sendResult(null, "\"wrong request format\"");
313// return;
314// }
315//
316// int fromId = id.getAsInt();
317//
318// if (registry.messageWasRed(fromId, msg.getAsString()) == false)
319// {
320// System.err.print("Unknown, or not yet red, message for \"receipt\" request: " + data);
321// sendResult(null, "\"wrong parameters\"");
322// return;
323// }
324//
325// // Store receipt
326// registry.storeReceipt(fromId, msg.getAsString(), receipt.getAsString());
327// return;
328// }
329//
330// // STATUS
331// if (cmd.getAsString().equals("status"))
332// {
333// JsonElement id = data.get("id");
334// JsonElement msg = data.get("msg");
335//
336// if (id == null || msg == null)
337// {
338// System.err.print("Badly formated \"status\" request: " + data);
339// sendResult(null, "\"wrong request format\"");
340// return;
341// }
342//
343// int fromId = id.getAsInt();
344//
345// if (registry.copyExists(fromId, msg.getAsString()) == false)
346// {
347// System.err.print("Unknown message for \"status\" request: " + data);
348// sendResult(null, "\"wrong parameters\"");
349// return;
350// }
351//
352// // Get receipts
353// String response = registry.getReceipts(fromId, msg.getAsString());
354//
355// sendResult("\"type\":\"status\",\"result\":" + response, null);
356// return;
357// }
358
359 sendResult(null, "\"Unknown request\"");
360 }
361
362 void sendResult(String result, String error) {
363 String msg = "{";
364
365 // Usefull result
366 if (result != null) {
367 msg += result;
368 }
369
370 // error message
371 if (error != null) {
372 msg += "\"error\":" + error;
373 }
374 // error message
375 /*if (sessionID < 1)
376 {
377 msg += "\"error\":" + error;
378 try
379 {
380 System.out.print("Send result: " + msg + "}\n");
381 out.write(msg.getBytes(StandardCharsets.UTF_8));
382 }
383 catch (Exception e) {}
384 }
385
386 String json = msg + "}";
387
388 try
389 {
390 msg += ",\"mac\":\"" + new String(Base64.getEncoder().encode(genMAC(json, sessionID))) + "\"}\n";
391 System.out.print("Send result: " + msg);
392 out.write(msg.getBytes(StandardCharsets.UTF_8));
393 }
394 catch (Exception e) {}*/
395 }
396
397 boolean calcMAC(String json, String mac) {
398 return false;
399 }
400
401 /*
402 * MAC Algorithm Generator
403 */
404 public byte[] genMAC(String json, int sessionID) {
405 // decode the base64 encoded string
406 byte[] decodedKey = Base64.getDecoder().decode(getSessionKey(sessionID));
407 // rebuild key using SecretKeySpec
408 SecretKey sessionKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "HmacMD5");
409
410 Mac mac;
411 try {
412 mac = Mac.getInstance(sessionKey.getAlgorithm());
413 mac.init(sessionKey);
414
415 byte[] b = json.getBytes("UTF-8");
416 return mac.doFinal(b);
417 } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException ex) {
418 Logger.getLogger(ServerActions.class.getName()).log(Level.SEVERE, null, ex);
419 return null;
420 }
421 }
422
423 private String getSessionKey(int value) {
424 for (String key : sessionKeys.keySet()) {
425 if (sessionKeys.get(key).equals(value)) {
426 return key; //return the first found
427 }
428 }
429 return null;
430 }
431
432 @Override
433 public void run() {
434 while (true) {
435 JsonObject cmd = readCommand();
436 if (cmd == null) {
437 try {
438 client.close();
439 } catch (IOException e) {
440 }
441 return;
442 }
443 executeCommand(cmd);
444 }
445
446 }
447}