package org.expeditee.auth.account; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.CertificateException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.sql.SQLException; import java.text.ParseException; import java.util.ArrayList; import java.util.Base64; import java.util.Collection; import java.util.List; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import org.expeditee.auth.Actions; import org.expeditee.auth.AuthenticatorBrowser; import org.expeditee.auth.mail.gui.MailBay; import org.expeditee.auth.tags.AuthenticationTag; import org.expeditee.encryption.CryptographyConstants; import org.expeditee.gui.Browser; import org.expeditee.gui.DisplayController; import org.expeditee.gui.Frame; import org.expeditee.gui.FrameIO; import org.expeditee.gui.MessageBay; import org.expeditee.items.Item; import org.expeditee.items.Text; import org.expeditee.settings.Settings; import org.expeditee.settings.UserSettings; import org.expeditee.settings.identity.secrets.KeyList; public class Authenticate implements CryptographyConstants { /** * Given a username and password, potentially login. * @param userdata * @return AuthenticationResult.SuccessLogin if login works, AuthenticationResult.ErrorLoginNobody or AuthenticationResult.ErrorLoginUsernamePasswordCombo otherwise. */ public static AuthenticationResult login(Map userdata) { String username = userdata.get(AuthenticationTag.Username); String password = userdata.get(AuthenticationTag.Password); if (username.equals(AuthenticatorBrowser.USER_NOBODY)) { return AuthenticationResult.ErrorLoginNobody; } SecretKey personalKey = null; try { personalKey = AuthenticatorBrowser.getInstance().getSecretKey(username, password); } catch (Exception e) { return AuthenticationResult.ErrorLoginUsernamePasswordCombo; } if (personalKey == null) { return AuthenticationResult.ErrorLoginUsernamePasswordCombo; } UserSettings.UserName.set(username); if (!username.equals(AuthenticatorBrowser.ADMINACCOUNT)) { // Set the personal key to bootstrap the encrypted frame loading. Text personalKeyText = KeyList.PersonalKey.generateText(); personalKeyText.setData(Base64.getEncoder().encodeToString(personalKey.getEncoded())); KeyList.PersonalKey.setSetting(personalKeyText); // Load in and cache the profile frame using the personal key fetched from keystore. FrameIO.ClearCache(); Frame oneFrame = FrameIO.LoadProfile(username); for (int i = 1; i <= FrameIO.getLastNumber(oneFrame.getFramesetName()); i++) { Frame f = FrameIO.LoadFrame(oneFrame.getFramesetName() + i); if (f != null) { List data = f.getData(); if(data != null && data.contains("MultiuserCredentials")) { AuthenticatorBrowser.CREDENTIALS_FRAME = f.getNumber(); } else if (data != null && data.contains("PasswordColleagues")) { AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME = f.getNumber(); } else if (data != null && data.contains("SecretsFrame")) { AuthenticatorBrowser.SECRETS_FRAME = f.getNumber(); } } } // Update were we get our frames. UserSettings.setupDefaultFolders(); MessageBay.clear(); MessageBay.updateFramesetLocation(); MailBay.disconnect(); // Parse the users profile to refresh settings. Text settingsLink = new Text("settings"); settingsLink.setLink(oneFrame.getFramesetName() + "2"); Settings.parseSettings(settingsLink); // At this point we at least login, but maybe with problems. AuthenticationResult res = AuthenticationResult.SuccessLogin; // Check mail and update last read files. MailBay.clear(); try { Text keyItem = KeyList.PrivateKey.get(); if (keyItem.getData() != null) { // Check mail. String keyEncoded = keyItem.getData().get(0); byte[] keyBytes = Base64.getDecoder().decode(keyEncoded); PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); org.expeditee.auth.mail.Mail.checkMail(key); } else { res.additionalInfo.add("No private key present: your communication with other Expeditee users will be limited until this is resolved."); } } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException | SQLException | ParseException | IOException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { res.additionalInfo.add("An error occured while attempting to load in mail sent to you by other Expeditee users. See the exception for more information."); e.printStackTrace(); } catch (InvalidKeySpecException e) { res.additionalInfo.add("Stored data cannot be used to create a private key. See exception for more information."); e.printStackTrace(); } Collection usernameFields = Actions.getByData(FrameIO.LoadFrame("multiuser1"), "txtUsername"); usernameFields.forEach(usernameField -> usernameField.setText(username)); Frame requestedFrame = FrameIO.LoadFrame(Browser.getStartFrame()); Frame homeFrame = FrameIO.LoadFrame("home1"); Frame choice = requestedFrame != null ? requestedFrame : homeFrame != null ? homeFrame : oneFrame; DisplayController.setCurrentFrame(choice, true); } return AuthenticationResult.SuccessLogin; } /** * Logs out the current authenticated user. * @return AuthenticationResult.SuccessLogout to signal the logout has occured. */ public static AuthenticationResult logout() { // Set user to nobody. UserSettings.UserName.set(AuthenticatorBrowser.USER_NOBODY); // Update were we get our frames. UserSettings.setupDefaultFolders(); MessageBay.updateFramesetLocation(); MailBay.disconnect(); // Reset all of the settings. Settings.resetAllSettings(); // Display login frame Frame auth1 = FrameIO.LoadFrame("authentication1"); DisplayController.setCurrentFrame(auth1, true); return AuthenticationResult.SuccessLogout; } public enum AuthenticationResult { SuccessLogin, SuccessLogout, ErrorLoginNobody, ErrorLoginUsernamePasswordCombo; private List additionalInfo = new ArrayList(); public String toString() { switch (this) { case SuccessLogin: StringBuilder sb = new StringBuilder(); sb.append("Logged in as: " + UserSettings.UserName.get()); if (additionalInfo.isEmpty()) { return sb.toString(); } else { String nl = System.getProperty("line.separator"); sb.append("However: " + nl); for (String info: additionalInfo) { sb.append(info + nl); } return sb.toString(); } case SuccessLogout: return "You are now logged out of Expeditee."; case ErrorLoginNobody: return "You cannot log into Expeditee as the user \'nobody\'"; case ErrorLoginUsernamePasswordCombo: return "The username + password combination was incorrect."; } String message = "Was the list of possible enum results updated without nessasary changes to thh toString() function?"; throw new IllegalArgumentException(message); } } }