/* Athena/Aegis Encrypted Chat Platform
* ServerThread.java: Controls the threads for each user connected to Aegis
*
* Copyright (C) 2010 OlympuSoft
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.misc.BASE64Encoder;
/**
* A ServerThread is created for each connected user, to route messages around
* @author OlympuSoft
*/
public class ServerThread extends Thread {
//Change to 1 or 2 for debug output
private static int debug = 1;
//Create the DataStreams on the current sockets
private DataInputStream serverDin = null;
private DataInputStream clientDin = null;
private DataOutputStream serverDout = null;
//Define Global Variable Username / Password
private String username;
private String password;
//Our current sockets
private Socket c2ssocket;
private Socket c2csocket;
//Governs thread life. If connection is not alive, thread terminates
private int isAlive = 1;
/**
* Instantiate this thread for the current sockets
* @param server The server that spawned this thread
* @param c2ssocket The "server" thread
* @param c2csocket The "client" thread
*/
public ServerThread(Socket c2ssocket, Socket c2csocket) {
// Remember which socket we are on
this.c2ssocket = c2ssocket;
this.c2csocket = c2csocket;
//Start up the thread
start();
}
/**
* Runs when the thread starts. Let's user log in, then routes messages
*/
@Override
public void run() {
try {
//Create a datainputstream on the current socket to accept data from the client
serverDin = new DataInputStream(c2ssocket.getInputStream());
clientDin = new DataInputStream(c2csocket.getInputStream());
//Getting the Username over the stream for authentication
String usernameCipher = serverDin.readUTF();
if (debug == 2) {
Server.writeLog("Encrypted Username: " + usernameCipher);
}
//Decrypt the username
username = RSACrypto.rsaDecryptPrivate(new BigInteger(usernameCipher).toByteArray(),
Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent());
if (debug >= 1) {
Server.writeLog("Decrypted Username: " + username);
}
//Interupt means they want to create a new user
if (username.equals("Interupt")) {
//Do nothing
} else {
//Get the password hash
password = decryptServerPrivate(serverDin.readUTF());
//Debug statements
if (debug >= 1) {
Server.writeLog("Username: " + username);
Server.writeLog("Password: " + password);
}
//Authenticate the user.
String loginOutcome = login(username, password);
if (debug >= 1) {
Server.writeLog(loginOutcome);
}
//Maps username to socket after user logs in
Server.mapUserServerSocket(username, c2ssocket);
Server.mapUserClientSocket(username, c2csocket);
System.gc();
}
if (username.equals("Interupt")) {
routeMessage(serverDin, clientDin);
} else {
//Route around messages coming in from the client while they are connected
while (isAlive == 1) {
//Take in messages from this thread's client and route them to another client
routeMessage(serverDin, clientDin);
System.gc();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//Socket is closed, remove it from the list
try {
if (debug >= 1) {
Server.writeLog("REMOVING USERNAME: " + username);
}
if (username == null) {
Server.removeConnection(c2ssocket, c2csocket);
} else {
Server.removeConnection(c2ssocket, c2csocket, username);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Routes messages for the thread's user
* @param serverDin The "server" inputstream
* @param clientDin The "client" inputstream
* @throws NumberFormatException Generally, difficulty encrypting or decrypting message headers
* @throws InterruptedException
*/
public void routeMessage(DataInputStream serverDin, DataInputStream clientDin) throws NumberFormatException, InterruptedException {
try {
//Read in the toUser
String toUser = decryptServerPrivate(serverDin.readUTF());
//Read in the From User
String fromUser = decryptServerPrivate(serverDin.readUTF());
//Read in the Encrypted message
String messageEncrypted = serverDin.readUTF();
if (debug >= 1) {
Server.writeLog("Decrypted:" + toUser);
}
//Is the message an eventcode meant for the server?
if (toUser.equals("Aegis")) {
if (debug >= 1) {
Server.writeLog("Server eventcode detected! ");
}
if (debug >= 1) {
Server.writeLog(decryptServerPrivate(messageEncrypted));
}
try {
systemMessageListener(Integer.parseInt(decryptServerPrivate(messageEncrypted)));
} catch (NumberFormatException e) {
Server.writeLog("Message is NOT an eventcode. Ignoring...");
}
return;
}//Is the message someone trying to create an account?
if (toUser.equals("Interupt")) {
try {
systemMessageListener(Integer.parseInt(decryptServerPrivate(messageEncrypted)));
} catch (NumberFormatException e) {
Server.writeLog("Message is NOT an eventcode. Continuing...");
}
return;
} //Is this a normal message to another client
else {
if (debug >= 1) {
Server.writeLog("Routing normal message to: " + toUser + "\nmessage from: " + fromUser);
}
if (debug == 2) {
Server.writeLog("\nEncrypted message: " + messageEncrypted);
}
sendMessage(toUser, fromUser, messageEncrypted);
}
//Collect some garbage
System.gc();
} catch (IOException e) {
//Something broke. Disconnect the user.
if (debug == 2) {
e.printStackTrace();
}
isAlive = 0;
}
}
/**
* Handles all messages addressed to "Aegis"
* @param eventCode The eventcode requested by the client
* @throws InterruptedException
* @throws IOException
*/
public void systemMessageListener(int eventCode) throws InterruptedException, IOException {
switch (eventCode) {
case 000:
if (debug == 1) {
Server.writeLog("Event code received. createUsername() run.");
}
createUsername();
break;
case 001:
if (debug == 1) {
Server.writeLog("Event code received. negotiateClientStatus() run.");
}
negotiateClientStatus();
break;
case 002:
if (debug == 1) {
Server.writeLog("Event code received. senToAll() run.");
}
Server.sendToAll("ServerLogOn", username,getBlocklist());
break;
case 003:
if (debug == 1) {
Server.writeLog("Event code received. negotiateClientStatus(\"Checkuserstatus\") run.");
}
negotiateClientStatus("CheckUserStatus");
break;
case 004:
if (debug == 1) {
Server.writeLog("Event code received. publicKeyRequest() run.");
}
publicKeyRequest();
break;
case 005:
if (debug == 1) {
Server.writeLog("Event code received. returnBuddyListHash() run.");
}
returnBuddyListHash();
break;
case 006:
if (debug == 1) {
Server.writeLog("Event code received. receiveBuddyListfromClient() run.");
}
recieveBuddyListFromClient();
break;
case 007:
if (debug == 1) {
Server.writeLog("Event code received. sendPrivateKeyToClients() run.");
}
sendPrivateKeyToClient();
break;
case 8:
if (debug == 1) {
Server.writeLog("Event code received. sendBuddyListToClient() run.");
}
sendBuddyListToClient();
break;
case 9:
if (debug == 1) {
Server.writeLog("Event code received. receiveBugReport() run.");
}
receiveBugReport();
break;
case 10:
if (debug == 1) {
Server.writeLog("Event code received. receiveBugReport(flag) run.");
}
receiveBugReport(true);
break;
case 11:
if (debug == 1) {
Server.writeLog("Event code received. resetPassword() run.");
}
resetPassword();
break;
case 12:
if (debug == 1) {
Server.writeLog("Event code received. createChat() run.");
}
createChat();
break;
case 13:
if (debug == 1) {
Server.writeLog("Event code received. requestSocketInfo() run.");
}
requestSocketInfo();
break;
case 14:
if (debug == 1) {
Server.writeLog("Event code received. joinChat() run.");
}
joinChat();
break;
case 15:
if (debug == 1) {
Server.writeLog("Event code received. leaveChat() run.");
}
leaveChat();
break;
case 16:
if (debug == 1) {
Server.writeLog("Event code received. chatInvite() run.");
}
chatInvite();
break;
case 17:
if (debug == 1) {
Server.writeLog("Event code received. chatTalk() run.");
}
chatTalk();
break;
case 18:
if (debug == 1) {
Server.writeLog("Event code received. userList() run.");
}
userList();
break;
case 19:
if (debug >= 1) {
Server.writeLog("Event code received. DPInvite() run.");
}
dPInvite();
break;
case 20:
if (debug >= 1) {
Server.writeLog("Event code received. dPResult() run.");
}
dPResult();
break;
case 21:
if (debug >= 1) {
Server.writeLog("Event code received. fileInvite() run.");
}
fileInvite();
break;
case 22:
if (debug >=1) {
Server.writeLog("Event code received. fileResult() run.");
}
fileResult();
break;
case 23:
if (debug >= 1) {
Server.writeLog("Event code received. addBlocklist() run.");
}
addBlocklist();
break;
case 24:
if (debug >= 1) {
Server.writeLog("Event code received. removeBlocklist() run.");
}
removeBlocklist();
break;
case 25:
if (debug >= 1) {
Server.writeLog("Event code received. sendEmail() run.");
}
sendEmail();
break;
case 26:
if (debug >= 1) {
Server.writeLog("Event code received. returnBlockList() run.");
}
returnBlockList();
default:
return;
}
}
private void returnBlockList() throws IOException{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String[] myBlockList = getBlocklist();
String csvList="";
for(int i=0;i<myBlockList.length;i++){
csvList+=myBlockList[i]+",";
}
serverDout.writeUTF(encryptServerPrivate(csvList));
}
private void sendEmail() throws IOException{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String toEmail = decryptServerPrivate(serverDin.readUTF());
String subject = decryptServerPrivate(serverDin.readUTF());
String body = decryptServerPrivate(serverDin.readUTF());
String uuid = UUID.randomUUID().toString();
uuid = uuid.replace("-","");
uuid = uuid.substring(0,5);
System.out.println("FROM: "+uuid+"@athenachat.org");
System.out.println("TO: "+toEmail);
System.out.println("RE: "+subject);
System.out.println("Body: "+body);
SendMail sendMail = new SendMail(uuid+"@athenachat.org", toEmail, subject, body+"\n\nSent using AthenaChat anonymous email system.");
sendMail.send();
}
private String[] getBlocklist() {
try{
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt = con.createStatement();
int listSize=0;
ResultSet rs = null;
//Add user to chat in Database so they will get messages
rs = stmt.executeQuery("SELECT COUNT(*) FROM blocklist WHERE username = '"+ username + "';");
while (rs.next()) {
listSize = rs.getInt(1);
}
String[] blockList = new String[listSize];
rs = stmt.executeQuery("SELECT blocked_user FROM blocklist WHERE username = '"+ username + "';");
int i=0;
while (rs.next()) {
blockList[i] = rs.getString(1);
i++;
}
//Close the connections
rs.close();
stmt.close();
con.close();
return blockList;
} catch(Exception e){e.printStackTrace();}return null;
}
private String[] getBlockedlist() {
try{
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt = con.createStatement();
int listSize=0;
ResultSet rs = null;
//Add user to chat in Database so they will get messages
Server.writeLog("THE FUCKING QUERY IS FUCKIN: SELECT COUNT(*) FROM blocklist WHERE blocked_user = '"+ username + "');");
rs = stmt.executeQuery("SELECT COUNT(*) FROM blocklist WHERE blocked_user = '"+ username + "';");
while (rs.next()) {
listSize = rs.getInt(1);
}
String[] blockList = new String[listSize];
rs = stmt.executeQuery("SELECT username FROM blocklist WHERE blocked_user = '"+ username + "';");
int i=0;
while (rs.next()) {
blockList[i] = rs.getString(1);
i++;
}
//Close the connections
rs.close();
stmt.close();
con.close();
return blockList;
} catch(Exception e){e.printStackTrace();}return null;
}
private void addBlocklist() {
try{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String userToBlock = decryptServerPrivate(serverDin.readUTF());
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt = con.createStatement();
//Add user to chat in Database so they will get messages
stmt.executeUpdate("INSERT into blocklist (username,blocked_user) values('" + username + "','" + userToBlock + "');");
if (debug >= 1) {
Server.writeLog("User blocked: "+username+"/"+userToBlock);
}
//Close the connections
stmt.close();
con.close();
sendMessage(userToBlock,"ServerLogOff", encryptServerPrivate(username));
} catch(Exception e) { e.printStackTrace();}
}
private void removeBlocklist() {
try{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String userToBlock = decryptServerPrivate(serverDin.readUTF());
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt = con.createStatement();
//Add user to chat in Database so they will get messages
int deleted = stmt.executeUpdate("DELETE FROM blocklist WHERE username='" + username + "' AND blocked_user='" + userToBlock + "';");
if (deleted == 1 && debug >= 1) {
Server.writeLog(username + " unblocked "+userToBlock);
}
//Close the connections
stmt.close();
con.close();
sendMessage(userToBlock,"ServerLogOn", encryptServerPrivate(username));
} catch(Exception e) { e.printStackTrace();}
}
private void fileResult() {
try{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String usernameResult = decryptServerPrivate(serverDin.readUTF());
String resultString = serverDin.readUTF();
sendMessage(usernameResult, "FileResult", resultString);
} catch (Exception e) {
e.printStackTrace();
}
}
private void fileInvite() {
try {
if (debug == 1) {
Server.writeLog("In fileInvite()");
}
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String invitingUser = decryptServerPrivate(serverDin.readUTF());
String inviteString = serverDin.readUTF();
//For each user to invite, take their name, and take the session key encrypted with their public key
if (debug == 1) {
Server.writeLog("Trying to send file to: " + invitingUser);
}
sendMessage(invitingUser, "FileInvite", inviteString);
//sendMessage(invitingUser, "DPSessionKey", sessionKey);
if (debug >= 1) {
Server.writeLog("Sent invitation");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void dPResult() {
try{
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String usernameResult = decryptServerPrivate(serverDin.readUTF());
String success = decryptServerPrivate(serverDin.readUTF());
String inviteString = username + "," + success;
sendMessage(usernameResult, "DPResult", encryptServerPrivate(inviteString));
} catch (Exception e) {
e.printStackTrace();
}
}
private void dPInvite() {
try {
if (debug == 1) {
Server.writeLog("In dPInvite()");
}
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String invitingUser = decryptServerPrivate(serverDin.readUTF());
String sessionKey = serverDin.readUTF();
//For each user to invite, take their name, and take the session key encrypted with their public key
if (debug == 1) {
Server.writeLog("Inviting user: " + invitingUser);
}
sendMessage(invitingUser, "DPInvite", encryptServerPrivate(username));
sendMessage(invitingUser, "DPSessionKey", sessionKey);
if (debug >= 1) {
Server.writeLog("Sent invitation");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Sends the client the userlist for the selected group chat
*/
private void userList() {
try {
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Get the chatUID
int chatNum = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
//Grab a DB connection
Connection con = Server.dbConnect();
Statement stmt;
ResultSet rs = null;
//Get a list of existing chats
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT username FROM chat WHERE chatid = '" + chatNum + "';");
if (debug >= 1) {
Server.writeLog("Got list of users");
}
String message = "";
//Send the message to the users in the chat
while (rs.next()) {
message += rs.getString(1) + ",";
}
//Close everything
rs.close();
stmt.close();
con.close();
//Return the userlist
serverDout.writeUTF(encryptServerPrivate(message));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Sends a message from the client to the selected group chat
*/
private void chatTalk() {
try {
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Take in the chatUID and the message
int chatNum = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
String message = serverDin.readUTF();
//We have the message. Now we have to find out who to send it to.
if (debug == 1) {
Server.writeLog("Sending received message to chat number " + chatNum);
}
//Grab a DB connection
Connection con = Server.dbConnect();
Statement stmt;
ResultSet rs = null;
//Get a list of existing chats
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT username FROM chat WHERE chatid = '" + chatNum + "' AND username != '" + username + "';");
Server.writeLog("Got list of users");
//Send the message to the users in the chat
while (rs.next()) {
sendMessage(rs.getString(1), String.valueOf(chatNum), message);
}
//Close all DB connections
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Send a chat invitation to a specific chat to a list of selected users
*/
private void chatInvite() {
try {
if (debug == 1) {
Server.writeLog("In chatInvite()");
}
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Get the chatUID, chat name, and number of users to invite
int chatNum = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
String chatName = decryptServerPrivate(serverDin.readUTF());
String inviteString = chatName + "," + username + "," + chatNum;
int inviteList = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
//Debug statements
if (debug >= 1) {
Server.writeLog("Received chat number: " + chatNum);
Server.writeLog("Received chat name: " + chatName);
Server.writeLog("Constructed inviteString: " + inviteString);
Server.writeLog("Inviting " + inviteList + " people");
}
String sessionKey = "";
String invitingUser = "";
int x = 0;
//For each user to invite, take their name, and take the session key encrypted with their public key
for (x = 0; x < inviteList; x++) {
invitingUser = decryptServerPrivate(serverDin.readUTF());
sessionKey = serverDin.readUTF();
if (debug == 1) {
Server.writeLog("Inviting user: " + invitingUser);
}
sendMessage(invitingUser, "ChatInvite", encryptServerPrivate(inviteString));
sendMessage(invitingUser, "SessionKey", sessionKey);
}
if (debug >= 1) {
Server.writeLog("Invited " + (x + 1) + " people");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Remove the user from a specified chat, and delete the chat if it is empty
*/
private void leaveChat() {
try {
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Get the chatUID
int chatNum = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
if (debug >= 1) {
Server.writeLog("User " + username + " is leaving chat number " + chatNum + "!!!!");
}
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt;
ResultSet rs = null;
//Delete the user from the chat table, since he can't get messages for it anymore. Left for some reason
stmt = con.createStatement();
int deleted = stmt.executeUpdate("DELETE FROM chat WHERE username='" + username + "' AND chatid='" + chatNum + "';");
if (deleted == 1 && debug >= 1) {
Server.writeLog(username + " was successfully removed from the chat with UID " + chatNum);
}
//Get the users left in the chat
rs = stmt.executeQuery("SELECT username FROM chat WHERE chatid = '" + chatNum + "';");
//Delete the whole chat if it is empty
if (rs.next()) {
if (debug >= 1) {
Server.writeLog("Still people in the chat. Not closing.");
}
} else {
if (debug >= 1) {
Server.writeLog("No one is left in chat " + chatNum + " closing chat");
}
stmt.executeUpdate("DELETE FROM allchats WHERE chatid='" + chatNum + "';");
}
//Close the connections
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Join the user to a specific chat if they accept the invitation
*/
private void joinChat() {
try {
//Get chat UID to join
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
int chatNum = Integer.parseInt(decryptServerPrivate(serverDin.readUTF()));
if (debug >= 1) {
Server.writeLog("Joining user " + username + " to chat number " + chatNum + "!!!!!");
}
//Grab a connection to the database
Connection con = Server.dbConnect();
Statement stmt = con.createStatement();
//Add user to chat in Database so they will get messages
stmt.executeUpdate("INSERT into chat (username,chatid) values('" + username + "','" + chatNum + "')");
if (debug >= 1) {
Server.writeLog("Inserted the chatid into the allchat table.");
}
//Close the connections
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Pass off the socket information for a username. Useful for direct-protect and file transfer
*/
private void requestSocketInfo() {
try {
//String userForSocket = decryptServerPrivate(serverDin.readUTF());
//Socket foundSocket = (Socket) Server.userToClientSocket.get(userForSocket);
//return foundSocket.getInetAddress().toString();
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
serverDout.writeUTF(encryptServerPrivate(c2ssocket.getInetAddress().toString()));
} catch (Exception e) {
e.printStackTrace();
//return null;
}
}
/**
* Create a chat. Generates a UID, adds it to the DB, and informs the creator
*/
private void createChat() {
try {
if (debug >= 1) {
Server.writeLog("In the method.");
}
//Grab output stream for the user.
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
if (debug >= 1) {
Server.writeLog("Created the output stream which we shouldn't have to do.");
}
//Grab a connection to the database
Connection con = Server.dbConnect();
if (debug >= 1) {
Server.writeLog("Connected to the database.");
}
//Get the chat name from the user
String chatName = decryptServerPrivate(serverDin.readUTF());
if (debug >= 1) {
Server.writeLog("Took in the desired chat name.");
}
//Is the chatID a dupe?
int dupe = 0;
Statement stmt;
ResultSet rs = null;
int randInt = 0;
//Generate a unique, random number for the chat
do {
//Generate a random number for the chat
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte seed[] = random.generateSeed(20);
random.setSeed(seed);
randInt = random.nextInt(9999);
if (debug >= 1) {
Server.writeLog("Generated random chat ID: " + randInt);
}
//Get a list of existing chats
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT chatid FROM allchats");
if (debug >= 1) {
Server.writeLog("Got list of existing chats.");
}
//Read chatIDs into array
while (rs.next()) {
if (rs.getInt("chatid") == randInt) {
dupe = 1;
} else {
dupe = 0;
}
}
} while (dupe == 1);
//Close the statement and result set
rs.close();
//The chatID is not a duplicate. We can create the chat and add it to the DB
if (debug >= 1) {
Server.writeLog("Generated number is not a duplicate.");
}
stmt.executeUpdate("INSERT into allchats (chatid,chatname) values('" + randInt + "','" + chatName.replace('\'', '\\') + "')");
if (debug >= 1) {
Server.writeLog("Inserted the chatid into the allchat table.");
}
//Now insert the username and the chat id into the chat table
stmt.executeUpdate("INSERT into chat (username, chatid) values('" + username + "','" + randInt + "')");
if (debug >= 1) {
Server.writeLog("Inserted the username and chatid into the chat table.");
}
//Close the DB connections
stmt.close();
con.close();
//Send back the chatUID
serverDout.writeUTF(encryptServerPrivate(String.valueOf(randInt)));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Allow the user to reset the password, provided they answer their secret question correctly
*/
private void resetPassword() {
try {
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Use dbConnect() to connect to the database
Connection con = Server.dbConnect();
//Take in the username to find the secret question and answer for
String userToReset = decryptServerPrivate(serverDin.readUTF());
String secretQuestion = null;
String secretAnswer = null;
//Create a statement and resultset for the query
Statement stmt;
Statement insertSTMT;
ResultSet rs = null;
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT * FROM Users WHERE username = '" + userToReset + "'");
//Get their secret question and answer hash
if (rs.next()) {
secretQuestion = rs.getString("secretq");
secretAnswer = rs.getString("secreta");
} else {
secretQuestion = "Invalid Username, try again.";
return;
}
//Close the resultset
rs.close();
//Send the secret question to the client for answering
serverDout.writeUTF(encryptServerPrivate(secretQuestion));
if (debug >= 1) {
Server.writeLog("SENT Question: " + secretQuestion);
}
//Read in the user's answer hash
String secretAnswerHash = decryptServerPrivate(serverDin.readUTF());
if (debug >= 1) {
Server.writeLog("READ Answer: " + secretAnswerHash);
}
//Read in the user's desired passwordchange
String newPassword = decryptServerPrivate(serverDin.readUTF());
if (secretAnswerHash.equals(secretAnswer)) {
Server.writeLog("HASHES MATCH");
String insertString = "UPDATE Users SET password='" + newPassword + "' WHERE username = '" + userToReset + "'";
insertSTMT = con.createStatement();
insertSTMT.executeUpdate(insertString);
if (debug >= 1) {
Server.writeLog("PASSWORDCHANGED");
}
//Close Connections
insertSTMT.close();
//Success message
serverDout.writeUTF(encryptServerPrivate("1"));
} else {
if (debug >= 1) {
Server.writeLog("HASH MISMATCH. ABORT");
}
//Failure message
serverDout.writeUTF(encryptServerPrivate("0"));
}
//Close Connections
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Receive an automated bug report from the user
*/
private void receiveBugReport() {
if (debug == 1) {
Server.writeLog("Receiving bug report stacktrace");
Server.writeLog("Receiving bug report comments");
}
String trace = "";
String comments = "";
try {
trace = decryptServerPrivate(serverDin.readUTF());
comments = decryptServerPrivate(serverDin.readUTF());
} catch (Exception e) {
e.printStackTrace();
}
if (debug >= 1) {
Server.writeLog("Bug report received from " + username + ": " + comments);
Server.writeLog("Stacktrace follows:" + trace);
}
}
/**
* Receive a manual bug report/feature request from the user
* @param flag Overload differentiation
*/
private void receiveBugReport(boolean flag) {
if (debug == 1) {
Server.writeLog("Receiving bug report/feature request");
}
String title = "";
String recreate = "";
String expected = "";
String actual = "";
try {
title = decryptServerPrivate(serverDin.readUTF());
recreate = decryptServerPrivate(serverDin.readUTF());
expected = decryptServerPrivate(serverDin.readUTF());
actual = decryptServerPrivate(serverDin.readUTF());
} catch (Exception e) {
e.printStackTrace();
}
if (debug >= 1) {
Server.writeLog("BEGIN BUG REPORT");
Server.writeLog("Bug report received from " + username + ": ");
Server.writeLog("Brief Description: " + title);
Server.writeLog("Steps to recreate: " + recreate);
Server.writeLog("Expected Outcome: " + expected);
Server.writeLog("Actual Outcome: " + actual);
Server.writeLog("END OF REPORT");
}
}
/**
* If the user needs a copy of their buddylist, send it to them
* @return success
* @throws IOException
*/
private boolean sendBuddyListToClient() throws IOException {
String[] buddyListArray = returnBuddyListArray(true);
if (debug >= 1) {
Server.writeLog("Inside sendBuddyListToClient");
}
int numLines = buddyListArray.length;
if (debug >= 1) {
Server.writeLog("numLines: " + numLines);
}
//Send Athena the number of lines we're sending
serverDout.writeUTF(encryptServerPrivate(String.valueOf(numLines)));
//Send the lines of the file!
for (int x = 0; x < buddyListArray.length; x++) {
serverDout.writeUTF(encryptServerPrivate(buddyListArray[x]));
}
return true;
}
/**
* This method returns a nice string array full of the usernames (for now) that are in the buddylist file
* @param flag Overload differentiator
* @return String array of the buddylist pieces
* @throws IOException
*/
public String[] returnBuddyListArray(boolean flag) throws IOException {
int count;
int readChars;
InputStream is;
//Let's get the number of lines in the file
File newFile = new File("buddylists/" + username + "/buddylist.csv");
if (!(newFile.exists())) {
boolean success = new File("buddylists/" + username).mkdirs();
if (success) {
newFile.createNewFile();
is = new BufferedInputStream(new FileInputStream("buddylists/" + username + "/buddylist.csv"));
} else {
newFile.createNewFile();
}
}
is = new BufferedInputStream(new FileInputStream("buddylists/" + username + "/buddylist.csv"));
byte[] c = new byte[1024];
count = 0;
readChars = 0;
while ((readChars = is.read(c)) != -1) {
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
//Make the string array the size of the number of lines in the file
String[] usernames = new String[count];
//If there are no lines in the file we know that the user has no buddies! :(
if (count == 0) {
return usernames;
} else {
File newFile2 = new File("buddylists/" + username + "/buddylist.csv");
if (!(newFile2.exists())) {
newFile2.createNewFile();
}
BufferedReader in = new BufferedReader(new FileReader("buddylists/" + username + "/buddylist.csv"));
int x = 0;
String raw;
//Split each line on every ',' then take the string before that and add it to the usernames array | God I love split.
while ((raw = in.readLine()) != null) {
String foo[] = raw.split(",");
usernames[x] = foo[0];
x++;
}
return usernames;
}
}
/**
* Sends the user a copy of his private key
* @throws IOException
*/
private void sendPrivateKeyToClient() throws IOException {
RSAPrivateKeySpec privateKey = RSACrypto.readPrivKeyFromFile("keys/" + username + ".priv");
//Send over ack message
sendSystemMessage(username, "Incoming private key components");
//Send over components
String privateKeyMod = privateKey.getModulus().toString();
if (debug == 2) {
Server.writeLog("PRIVATE KEY MOD: " + privateKeyMod);
}
String privateKeyExp = privateKey.getPrivateExponent().toString();
if (debug == 2) {
Server.writeLog("PRIVATE KEY MOD: " + privateKeyExp);
}
//Send half a time plz!
if (debug == 2) {
Server.writeLog("Length of the private key: " + privateKeyMod.length());
}
//Send how many chunks will be coming
if (privateKeyMod.length() > 245) {
double messageNumbers = (double) privateKeyMod.length() / 245;
int messageNumbersInt = (int) Math.ceil(messageNumbers);
serverDout.writeUTF(String.valueOf(messageNumbersInt));
if (debug >= 1) {
Server.writeLog("MessageLength: " + privateKeyMod.length() + "\nMessageLength/245: " + messageNumbers + "\nCeiling of that: " + messageNumbersInt);
}
//TODO THIS IS A MESSSSS
String[] messageChunks = new String[(int) messageNumbersInt];
for (int i = 0; i < messageChunks.length; i++) {
int begin = i * 245;
int end = begin + 245;
if (end > privateKeyMod.length()) {
end = privateKeyMod.length();
}
messageChunks[i] = privateKeyMod.substring(begin, end);
serverDout.writeUTF(encryptServerPrivate(messageChunks[i]));
}
}
if (privateKeyExp.length() > 245) {
double messageNumbers = (double) privateKeyExp.length() / 245;
int messageNumbersInt = (int) Math.ceil(messageNumbers);
serverDout.writeUTF(String.valueOf(messageNumbersInt));
if (debug >= 1) {
Server.writeLog("MessageLength: " + privateKeyMod.length() + "\nMessageLength/245: " + messageNumbers + "\nCeiling of that: " + messageNumbersInt);
}
String[] messageChunks = new String[(int) messageNumbersInt];
for (int i = 0; i < messageChunks.length; i++) {
int begin = i * 245;
int end = begin + 245;
if (end > privateKeyExp.length()) {
end = privateKeyExp.length();
}
messageChunks[i] = privateKeyExp.substring(begin, end);
serverDout.writeUTF(encryptServerPrivate(messageChunks[i]));
}
}
}
/**
* Takes in user's buddylist and writes it to a file as backup
* @param buddyList
* @param buddyListName
*/
public void writeBuddyListToFile(String[] buddyList, String buddyListName) {
BufferedWriter out;
File newFile = new File("buddylists/" + buddyListName + "/buddylist.csv");
try {
if (!(newFile.exists())) {
boolean success = new File("users/" + buddyListName).mkdirs();
if (success) {
newFile.createNewFile();
} else {
newFile.createNewFile();
}
} else {
newFile.delete();
newFile.createNewFile();
}
out = new BufferedWriter(new FileWriter("buddylists/" + buddyListName + "/buddylist.csv"));
for (int i = 0; i < buddyList.length; i++) {
out.write(buddyList[i] + "\n");
}
out.close();
} catch (Exception e) {
if (debug == 1) {
Server.writeLog("ERROR WRITING BUDDYLIST");
}
}
}
/**
* Takes in buddylist from the user
* @throws IOException
*/
private void recieveBuddyListFromClient() throws IOException {
String[] buddyListLines;
Server.writeLog("Should be begin: " + decryptServerPrivate(serverDin.readUTF()));
buddyListLines = new String[(Integer.parseInt(decryptServerPrivate(serverDin.readUTF())))];
Server.writeLog("Buddylist lines: " + buddyListLines.length);
for (int y = 0; y < buddyListLines.length; y++) {
buddyListLines[y] = decryptServerPrivate(serverDin.readUTF());
Server.writeLog("Encrypted buddylist lines " + buddyListLines[y]);
}
writeBuddyListToFile(buddyListLines, username);
Server.writeLog("Successfully wrote buddy list to file");
}
/**
* Decrypt a message using the server's private key
* @param ciphertext The encrypted message
* @return The decrypted message
*/
public static String decryptServerPrivate(String ciphertext) {
//Turn the String into a BigInteger. Get the bytes of the BigInteger for a byte[]
byte[] cipherBytes = (new BigInteger(ciphertext)).toByteArray();
//Decrypt the byte[], returns a String
return RSACrypto.rsaDecryptPrivate(cipherBytes, Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent());
}
/**
* Encrypt a message using the server's private key
* @param plaintext The plaintext message
* @return The encrypted message
*/
public static String encryptServerPrivate(String plaintext) {
//Encrypt the string and return it
if (debug == 1) {
Server.writeLog("Plaintext in encryptServerPrivate: " + plaintext);
}
BigInteger plaintextBigInt = new BigInteger(RSACrypto.rsaEncryptPrivate(plaintext, Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
return plaintextBigInt.toString();
}
/**
* Figure out if a user is online or not
*/
public void negotiateClientStatus() {
try {
String[] blockedList = getBlockedlist();
//Listen for the username
String findUserCipher = serverDin.readUTF();
int blocked=0;
if (debug >= 1) {
Server.writeLog("FINDUSERCIPHER!@$!#@" + findUserCipher);
}
byte[] findUserBytes = (new BigInteger(findUserCipher)).toByteArray();
String findUserDecrypted = RSACrypto.rsaDecryptPrivate(findUserBytes, Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent());
if(blockedList.length!=0){
for(int i=0;i<blockedList.length;i++){
if(blockedList[i].equals(findUserDecrypted)) blocked=1;
}}
//Print out the received username
if (debug >= 1) {
Server.writeLog("Username received: " + findUserDecrypted);
}
if(blocked==0){
//Check to see if the username is in the current Hashtable, return result
if ((Server.userToServerSocket.containsKey(findUserDecrypted))) {
serverDout.writeUTF(encryptServerPrivate("1"));
Server.writeLog("(Online)\n");
} else {
serverDout.writeUTF(encryptServerPrivate("0"));
Server.writeLog("(Offline)\n");
}}
else {
serverDout.writeUTF(encryptServerPrivate("0"));
Server.writeLog("(Offline)\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Check a user's online status
* @param checkUserFlag Overload differentiator
*/
public void negotiateClientStatus(String checkUserFlag) {
try {
String[] blockedList = getBlockedlist();
if (debug >= 1) {
Server.writeLog(username);
}
int blocked=0;
//Listen for the username
String findUser = decryptServerPrivate(serverDin.readUTF());
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Print out the received username
if (debug >= 1) {
Server.writeLog("Username received: " + findUser);
}
if (debug >= 1) {
Server.writeLog("Socket serverDout: " + serverDout.toString());
}
if(blockedList.length!=0){
for(int i=0;i<blockedList.length;i++){
if(blockedList[i].equals(findUser)) blocked=1;
}}
//Check to see if the username is in the current Hashtable, return result
if(blocked==0){
//Check to see if the username is in the current Hashtable, return result
if ((Server.userToServerSocket.containsKey(findUser))) {
serverDout.writeUTF(encryptServerPrivate("1"));
Server.writeLog("(Online)\n");
} else {
serverDout.writeUTF(encryptServerPrivate("0"));
Server.writeLog("(Offline)\n");
}}
else {
serverDout.writeUTF(encryptServerPrivate("0"));
Server.writeLog("(Offline)\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Check the hash of the backed-up buddylist for comparison
*/
public void returnBuddyListHash() {
try {
String buddyListToFind = serverDin.readUTF();
byte[] buddyListBytes = (new BigInteger(buddyListToFind)).toByteArray();
String buddyListDecrypted = RSACrypto.rsaDecryptPrivate(buddyListBytes, Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent());
//Grab the hash of the buddy list
File buddylist = new File("buddylists/" + buddyListDecrypted + "/buddylist.csv");
if (!(buddylist.exists())) {
boolean success = new File("buddylists/" + buddyListDecrypted + "/").mkdirs();
if (success) {
buddylist.createNewFile();
} else {
buddylist.createNewFile();
}
}
String path = "buddylists/".concat(buddyListDecrypted).concat("/buddylist.csv");
if (debug >= 1) {
Server.writeLog("PATH: " + path);
}
String hashOfBuddyList = FileHash.getMD5Checksum(path);
String lastModDateOfBuddyList = String.valueOf(buddylist.lastModified());
//Send information
serverDout.writeUTF(encryptServerPrivate(hashOfBuddyList));
serverDout.writeUTF(encryptServerPrivate(lastModDateOfBuddyList));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create a new user
* @return success
* @throws IOException
*/
public boolean createUsername() throws IOException {
try {
//Use dbConnect() to connect to the database
Connection con = Server.dbConnect();
//Get the DataOutputStream
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
//Create a statement and resultset for the query
Statement stmt;
Statement insertSTMT;
ResultSet rs = null;
//Read the new user's public key components
String publicModString = serverDin.readUTF();
String publicExpString = serverDin.readUTF();
//Read in the private key components
String privateKeyModString = serverDin.readUTF();
String privateKeyExpString = serverDin.readUTF();
//Read all encrypted data in
String firstName = decryptServerPrivate(serverDin.readUTF());
String lastName = decryptServerPrivate(serverDin.readUTF());
String emailAddress = decryptServerPrivate(serverDin.readUTF());
String newUser = decryptServerPrivate(serverDin.readUTF());
String newPassword = decryptServerPrivate(serverDin.readUTF());
String secretQuestion = decryptServerPrivate(serverDin.readUTF());
String secretAnswer = decryptServerPrivate(serverDin.readUTF());
//Turn the public key components into BigIntegers for use
BigInteger publicMod = new BigInteger(publicModString);
BigInteger publicExp = new BigInteger(publicExpString);
//Turn the private key components into BigIntegers for use
BigInteger privateMod = new BigInteger(privateKeyModString);
BigInteger privateExp = new BigInteger(privateKeyExpString);
//Write encrpyted private key to file
RSACrypto.saveToFile("keys/" + newUser + ".priv", privateMod, privateExp);
if (debug >= 1) {
Server.writeLog("New User Decrypted Information:");
Server.writeLog("First Name: " + firstName);
Server.writeLog("Last Name: " + lastName);
Server.writeLog("Email Address: " + emailAddress);
Server.writeLog("User Name: " + newUser);
Server.writeLog("Password Hash: " + newPassword);
Server.writeLog("Secret Question: " + secretQuestion);
Server.writeLog("Secret Answer Hash: " + secretAnswer);
}
stmt = con.createStatement();
if (debug == 1) {
Server.writeLog("Statement created\nCreating username: " + newUser + "\nPassword: " + newPassword);
}
//See if the username already exists.
rs = stmt.executeQuery("SELECT * FROM Users WHERE username = '" + newUser + "'");
if (debug == 1) {
Server.writeLog("newUser: " + newUser);
}
//Test to see if there are any results
if (rs.next()) {
//Send status message that the username has already been taken.
BigInteger failedRegistrationResultBigInt = new BigInteger(RSACrypto.rsaEncryptPrivate("Username has already been taken, please try again.",
Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(failedRegistrationResultBigInt.toString());
rs.close();
return false;
} else {
//Store the new user's public key on to the filesystem
File newFile = new File("keys/" + newUser + ".pub");
if (!(newFile.exists())) {
newFile.createNewFile();
} else {
return false;
}
RSACrypto.saveToFile("keys/" + newUser + ".pub", publicMod, publicExp);
//Grab the users new password
String insertString = "insert into Users (FirstName, LastName, EmailAddress, username, password, secretq, secreta) values('" + firstName + "', '"
+ lastName + "', '" + emailAddress + "', '" + newUser + "', '" + newPassword + "', '" + secretQuestion.replace('\'', '\\') + "', '"
+ secretAnswer + "')";
insertSTMT = con.createStatement();
insertSTMT.executeUpdate(insertString);
//Inform of our success
BigInteger successfulRegistrationResultBigInt = new BigInteger(RSACrypto.rsaEncryptPrivate("Account has been successfully created.",
Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(successfulRegistrationResultBigInt.toString());
//Close Connections
stmt.close();
insertSTMT.close();
con.close();
rs.close();
SendMail sendMail = new SendMail("admins@athenachat.org", emailAddress, "Welcome To AthenaChat", firstName+",\n\nYour AthenaChat account has been successfully created. You can now securely share information with anyone. Enjoy!\n\nThanks,\nAthenaChat Admins");
sendMail.send();
return true;
}
} catch (Exception e) {
//Inform of our failure
BigInteger exceptionRegistrationResultBigInt = new BigInteger(RSACrypto.rsaEncryptPrivate("Something went wrong, please inform the Athena Administrators.",
Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(exceptionRegistrationResultBigInt.toString());
return false;
}
}
/**
* Sends a message from the user to another user
* @param toUser
* @param fromUser
* @param message
*/
void sendMessage(String toUser, String fromUser, String message) {
Socket foundSocket = null;
DataOutputStream clientDout = null;
String[] blockedList = getBlockedlist();
int blocked=0;
if(blockedList.length!=0){
for(int i=0;i<blockedList.length;i++){
if(blockedList[i].equals(toUser)&&fromUser.equals(username)) blocked=1;
}}
//Debug statement: who is this going to?
if (debug == 1) {
Server.writeLog(toUser);
}
//Look up the socket associated with the with whom we want to talk
//We will use this to find which outputstream to send out
//If we cannot find the user or socket, send back an error
if ((Server.userToClientSocket.containsKey(toUser))&&blocked==0) {
if (debug == 1) {
Server.writeLog("Found user.. Continuing...");
}
foundSocket = (Socket) Server.userToClientSocket.get(toUser);
try {
clientDout = new DataOutputStream(foundSocket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
if (debug == 1) {
Server.writeLog("Found Socket: " + foundSocket);
}
} else {
sendMessage(fromUser, "UnavailableUser", encryptServerPrivate(toUser));
return;
}
//Send the message, and the user it is from
try {
//Encrypt the fromUser with the public key of userB (we want everything to be anonymous,
//so we can't encrypt the fromUser with the private key of the server, anyone can decrypt that)
//TODO WTF were we thinking here?
// We are doing exactly what we said we shouldn't. FFS.
BigInteger fromUserCipherBigInt = new BigInteger(RSACrypto.rsaEncryptPrivate(fromUser,
Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
clientDout.writeUTF(fromUserCipherBigInt.toString());
clientDout.writeUTF(message);
} catch (IOException ie) {
Server.writeLog("Message could not be sent");
}
if (debug >= 1) {
Server.writeLog("message sent, i think");
}
}
/**
* Sends a system message to the selected user
* @param toUser
* @param message
*/
void sendSystemMessage(String toUser, String message) {
Socket foundSocket = null;
DataOutputStream serverDout = null;
//Debug statement: who is this going to?
if (debug == 1) {
Server.writeLog("Who is this message going to? " + toUser);
}
//Look up the socket associated with the with whom we want to talk
//We will use this to find which outputstream to send out
//If we cannot find the user or socket, send back an error
if ((Server.userToServerSocket.containsKey(toUser))) {
if (debug == 1) {
Server.writeLog("Found user.. Continuing...");
}
foundSocket = (Socket) Server.userToServerSocket.get(toUser);
try {
serverDout = new DataOutputStream(foundSocket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
if (debug == 1) {
Server.writeLog("Found Socket: " + foundSocket);
}
}
//Send the message, and the user it is from
try {
Server.writeLog("TOUSER: " + toUser + "\nMESSAGE: " + message);
BigInteger messageCipher = new BigInteger(RSACrypto.rsaEncryptPrivate(message, Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(messageCipher.toString());
if (debug >= 1) {
Server.writeLog("Message sent:\n " + message);
}
} catch (IOException ie) {
Server.writeLog("Message could not be sent");
}
}
/**
* Authenticates the user so they can being to send and receive messages
* @param clientName username
* @param clientPassword password hash
* @return success
* @throws IOException
*/
public String login(String clientName, String clientPassword) throws IOException {
serverDout = new DataOutputStream(c2ssocket.getOutputStream());
String localHashed = "";
try {
//Get the password from the database
//Grab a DB connection
Connection con = Server.dbConnect();
Statement stmt;
ResultSet rs = null;
//Get a list of existing chats
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT password FROM Users WHERE username = '" + clientName + "';");
//Send the message to the users in the chat
if (rs.next()) {
localHashed = rs.getString(1);
}
//Close all DB connections
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
//Login fail handler
if (debug >= 1) {
Server.writeLog("User has failed to login");
}
BigInteger returnCipher = new BigInteger(RSACrypto.rsaEncryptPrivate("Failed", Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(returnCipher.toString());
Server.removeConnection(c2ssocket, c2csocket, clientName);
return returnCipher.toString();
}
//Debug messages.
if (debug == 1) {
Server.writeLog("User logging in...");
}
if (debug == 1) {
Server.writeLog("Hashed Password:" + localHashed);
}
if (debug == 1) {
Server.writeLog("Username :" + clientName);
}
//Verify the password hash provided from the user matches the one in the server's hashtable
if (clientPassword.equals(localHashed)) {
BigInteger returnCipher = new BigInteger(RSACrypto.rsaEncryptPrivate("Success", Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(returnCipher.toString());
return returnCipher.toString();
} else {
//Login fail handler
BigInteger returnCipher = new BigInteger(RSACrypto.rsaEncryptPrivate("Failed", Server.serverPriv.getModulus(), Server.serverPriv.getPrivateExponent()));
serverDout.writeUTF(returnCipher.toString());
Server.removeConnection(c2ssocket, c2csocket, clientName);
return returnCipher.toString();
}
}
/**
* Computer the SHA-1 hash of a string
* @param toHash The data to hash
* @return The hash
* @throws Exception
*/
public String computeHash(String toHash) throws Exception {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1"); //step 2
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
}
try {
md.update(toHash.getBytes("UTF-8")); //step 3
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
byte raw[] = md.digest(); //step 4
String hash = (new BASE64Encoder()).encode(raw); //step 5
return hash; //step 6
}
/**
* Sends the public key of a requested user to the user
* @throws IOException
*/
public void publicKeyRequest() throws IOException {
if (debug >= 1) {
Server.writeLog(username);
}
try {
//Listen for the username
String findUser = decryptServerPrivate(serverDin.readUTF());
//Print out the received username
if (debug >= 1) {
Server.writeLog("Username received PUBLIC KEY REQUEST: " + findUser);
}
File newFile = new File("keys/" + findUser + ".pub");
if ((newFile.exists())) {
RSAPublicKeySpec keyToReturn = RSACrypto.readPubKeyFromFile("keys/" + findUser + ".pub");
if (debug >= 1) {
Server.writeLog("MOD: " + keyToReturn.getModulus().toString());
Server.writeLog("EXP: " + keyToReturn.getPublicExponent().toString());
}
//Check to see if the user has a key file on the server
serverDout.writeUTF(keyToReturn.getModulus().toString());
serverDout.writeUTF(keyToReturn.getPublicExponent().toString());
if (debug >= 1) {
Server.writeLog("Modulus Returned\n");
Server.writeLog("Exponent Returned\n");
}
} else {
serverDout.writeUTF("-1");
if (debug >= 1) {
Server.writeLog("User does not have a keyfile with us");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}