source: trunk/src/org/expeditee/auth/Actions.java@ 1299

Last change on this file since 1299 was 1299, checked in by bln4, 5 years ago

When account is created, the new users home frame is now set to their profile 1 frame. Now actions (such as gotohome) act logically.

File size: 33.8 KB
Line 
1package org.expeditee.auth;
2
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.nio.file.Files;
8import java.nio.file.Path;
9import java.nio.file.Paths;
10import java.nio.file.StandardCopyOption;
11import java.security.InvalidKeyException;
12import java.security.KeyFactory;
13import java.security.KeyPair;
14import java.security.KeyPairGenerator;
15import java.security.KeyStoreException;
16import java.security.NoSuchAlgorithmException;
17import java.security.PrivateKey;
18import java.security.PublicKey;
19import java.security.SecureRandom;
20import java.security.cert.CertificateException;
21import java.security.spec.InvalidKeySpecException;
22import java.security.spec.PKCS8EncodedKeySpec;
23import java.sql.SQLException;
24import java.text.ParseException;
25import java.util.Base64;
26import java.util.Collection;
27import java.util.HashMap;
28import java.util.List;
29import java.util.Map;
30import java.util.Optional;
31import java.util.Random;
32import java.util.function.Consumer;
33import java.util.stream.Collectors;
34
35import javax.crypto.BadPaddingException;
36import javax.crypto.IllegalBlockSizeException;
37import javax.crypto.NoSuchPaddingException;
38import javax.crypto.SecretKey;
39import javax.crypto.spec.SecretKeySpec;
40
41import org.apollo.io.AudioPathManager;
42import org.expeditee.agents.ExistingFramesetException;
43import org.expeditee.agents.InvalidFramesetNameException;
44import org.expeditee.auth.Mail.MailEntry;
45import org.expeditee.auth.gui.MailBay;
46import org.expeditee.auth.tags.AuthenticationTag;
47import org.expeditee.auth.tags.Constants;
48import org.expeditee.core.Colour;
49import org.expeditee.gui.Browser;
50import org.expeditee.gui.DisplayController;
51import org.expeditee.gui.Frame;
52import org.expeditee.gui.FrameIO;
53import org.expeditee.gui.MessageBay;
54import org.expeditee.io.ExpReader;
55import org.expeditee.items.Item;
56import org.expeditee.items.PermissionPair;
57import org.expeditee.items.Text;
58import org.expeditee.items.UserAppliedPermission;
59import org.expeditee.setting.GenericSetting;
60import org.expeditee.setting.Setting;
61import org.expeditee.setting.TextSetting;
62import org.expeditee.settings.Settings;
63import org.expeditee.settings.UserSettings;
64import org.expeditee.settings.folders.FolderSettings;
65import org.expeditee.settings.identity.secrets.KeyList;
66import org.ngikm.cryptography.CryptographyConstants;
67
68public class Actions implements CryptographyConstants {
69
70 //Debug Functions
71 public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
72 String time = org.expeditee.stats.Formatter.getDateTime();
73 String sender = UserSettings.UserName.get();
74 String topic = "Test Message";
75 String message = "This is a test message.";
76 Map<String, String> options = new HashMap<String, String>();
77 options.put("Neat", "Beep");
78 MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
79 Mail.sendMail(mail, colleagueName);
80 }
81 private static String userbackup = "authadmin";
82 public static void ToggleAuth() {
83 String backup = UserSettings.UserName.get();
84 UserSettings.UserName.set(userbackup);
85 userbackup = backup;
86 }
87
88 /**
89 * Display Expeditee Mail
90 * @throws IOException
91 * @throws SQLException
92 * @throws ClassNotFoundException
93 * @throws CertificateException
94 * @throws NoSuchAlgorithmException
95 * @throws FileNotFoundException
96 * @throws KeyStoreException
97 * @throws ParseException
98 */
99 public static void ToggleBay() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException, IOException, ParseException {
100 if (!DisplayController.isMailMode()) {
101 MailBay.ensureLink();
102 Mail.clear();
103 AuthenticatorBrowser.getInstance().loadMailDatabase();
104 }
105 DisplayController.ToggleMailMode();
106 }
107
108 /**
109 * Action used to navigate the authorised user back to their desktop.
110 */
111 public static void AuthGoToDesktop() {
112 DisplayController.setCurrentFrame(FrameIO.LoadFrame(UserSettings.HomeFrame.get()), true);
113 }
114
115 /**
116 * Action used to created a new user account.
117 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
118 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
119 * @throws SQLException
120 * @throws IOException
121 * @throws ExistingFramesetException
122 * @throws InvalidFramesetNameException
123 * @throws ClassNotFoundException
124 * @throws FileNotFoundException
125 * @throws CertificateException
126 * @throws NoSuchAlgorithmException
127 * @throws KeyStoreException
128 * @throws BadPaddingException
129 * @throws IllegalBlockSizeException
130 * @throws NoSuchPaddingException
131 * @throws InvalidKeySpecException
132 * @throws InvalidKeyException
133 * @throws ParseException
134 * @throws Exception
135 */
136 public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, ParseException {
137 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
138 Optional<Map<AuthenticationTag, String>> userdata =
139 AuthenticationTag.fetchUserData(textItems, false,
140 AuthenticationTag.Username,
141 AuthenticationTag.Password,
142 AuthenticationTag.PasswordAgain,
143 AuthenticationTag.Email,
144 AuthenticationTag.EmailAgain);
145
146 if (userdata.isPresent()) {
147 Map<AuthenticationTag, String> userData = userdata.get();
148
149 // A profile already existing with 'username' means an account cannot be created with that username.
150 if (FrameIO.LoadProfile(userData.get(AuthenticationTag.Username)) != null) {
151 MessageBay.errorMessage(Constants.ERROR_PROFILE_NAME_PREEXISTS);
152 return;
153 }
154
155 // The chosen username must be a valid frameset name.
156 if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) {
157 MessageBay.errorMessage(Constants.ERROR_INVALID_USERNAME);
158 return;
159 }
160
161 // The passwords provided must match
162 if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) {
163 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
164 return;
165 }
166
167 // The emails provided must match
168 if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) {
169 MessageBay.errorMessage(Constants.ERROR_MISMATCH_EMAILS);
170 return;
171 }
172
173 createAccount(userData);
174 login(userData);
175 AuthenticatorBrowser.Authenticated = true;
176 } else {
177 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
178 }
179 }
180
181 /**
182 * Action used to start authentication as a specified user.
183 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
184 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
185 * @throws Exception
186 */
187 public static void AuthLogin() throws Exception {
188 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
189 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password);
190 if (userdata.isPresent()) {
191 login(userdata.get());
192 AuthenticatorBrowser.Authenticated = true;
193 } else {
194 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
195 }
196 }
197
198 /**
199 * Action used to change the currently authenticated users password.
200 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
201 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
202 * Will fail if no user is currently logged in.
203 * @throws IOException
204 * @throws CertificateException
205 * @throws FileNotFoundException
206 * @throws KeyStoreException
207 * @throws NoSuchAlgorithmException
208 * @throws SQLException
209 * @throws ClassNotFoundException
210 */
211 public static void AuthChangePassword() throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
212 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
213
214 if (!AuthenticatorBrowser.Authenticated) {
215 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
216 } else {
217 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain);
218 if (userdata.isPresent()) {
219 final Map<AuthenticationTag, String> userData = userdata.get();
220 if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) {
221 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
222 } else {
223 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
224 changePassword(userData);
225 }
226 } else {
227 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
228 }
229 }
230 }
231
232 public static void AuthGotoAccountManagement() {
233 if (AuthenticatorBrowser.Authenticated) {
234 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), false);
235 } else {
236 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_AUTHENTICATION1), false);
237 }
238 }
239
240 public static void AuthShareFrameset() throws IOException {
241 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
242
243 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset);
244 if (userdata.isPresent()) {
245 Map<AuthenticationTag, String> userData = userdata.get();
246 FrameIO.SuspendCache();
247 Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1);
248 FrameIO.ResumeCache();
249
250 if (toShare == null) {
251 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION);
252 return;
253 }
254
255 shareFrameset(toShare);
256 }
257 }
258
259 /**
260 * Navigation action for progressing the process of recruiting colleagues to assist in password recovery.
261 * Hides certain content that AuthSubmitPWCollegues goes onto show if it does not fail.
262 */
263 public static void AuthGotoColleagueSubmissionFrame() {
264 Frame destination = FrameIO.LoadFrame(Constants.FRAME_COLLEAGUE_SUBMISSION_FRAME);
265 DisplayController.setCurrentFrame(destination, true);
266 Collection<Item> toHide = getByData(destination, Constants.DATA_SHOW_ON_PROGRESS);
267 for (Item i: toHide) {
268 i.setVisible(false);
269 }
270 }
271
272 /**
273 * Action used to start the process of formalising the password recovery process.
274 * @throws SQLException
275 * @throws IOException
276 * @throws ClassNotFoundException
277 * @throws CertificateException
278 * @throws NoSuchAlgorithmException
279 * @throws FileNotFoundException
280 * @throws KeyStoreException
281 * @throws InvalidKeySpecException
282 */
283 public static void AuthSubmitPWColleagues() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
284 Frame currentFrame = DisplayController.getCurrentFrame();
285 Collection<Text> textItems = currentFrame.getTextItems();
286
287 if (!AuthenticatorBrowser.Authenticated) {
288 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
289 return;
290 }
291
292 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo);
293 if (userdata.isPresent()) {
294 Map<AuthenticationTag, String> userData = userdata.get();
295 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
296 Path colleagueOnePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueOne + "-credentials");
297 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
298 Path colleagueTwoPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueTwo + "-credentials");
299 if (!colleagueOnePath.toFile().exists()) {
300 MessageBay.errorMessage("Your nominated colleague: " + colleagueOne + " must exist in your contacts.");
301 } else if (!colleagueTwoPath.toFile().exists()) {
302 MessageBay.errorMessage("Your nominated colleague: " + colleagueTwo + " must exist in your contacts.");
303 } else {
304 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
305 boolean success = submitPWColleagues(userData);
306 if (success) {
307 Collection<Item> toShow = getByData(currentFrame, Constants.DATA_SHOW_ON_PROGRESS);
308 for (Item i: toShow) {
309 i.setVisible(true);
310 }
311 currentFrame.change();
312 MessageBay.displayMessage("-------Messages sent-------");
313 }
314 FrameIO.SaveFrame(currentFrame);
315 DisplayController.requestRefresh(false);
316 }
317 }
318 }
319
320// public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
321// if (!UserSettings.Authenticated.get()) {
322// MessageBay.errorMessage("You must be logged in to perform this action.");
323// } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
324// Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
325// DisplayController.setCurrentFrame(registerEmailFrame, true);
326// } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
327// Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
328// DisplayController.setCurrentFrame(submitColleaguesFrame, true);
329// } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
330// MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
331// + " You will be alerted on Expeditee startup when they have both responded.");
332// } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
333// MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
334// }
335// }
336
337 public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) {
338
339 }
340
341 public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException,
342 KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
343 denyPasswordColleagueRelationship(colleagueName);
344 }
345
346 public static void AuthClearPWColleaguesNominated() {
347
348 }
349
350 /**
351 * Create a user account using the specified information in userdata. Creates and stores user keys.
352 * @param userdata Should contain username, password and email.
353 */
354 private static void createAccount(Map<AuthenticationTag, String> userdata) throws InvalidFramesetNameException, ExistingFramesetException,
355 KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException {
356 // Track progress
357 String message = "Creating new user account...";
358
359 // Extract user details
360 String username = userdata.get(AuthenticationTag.Username);
361 String password = userdata.get(AuthenticationTag.Password);
362 String email = userdata.get(AuthenticationTag.Email);
363
364 System.out.println(message + "Generating Keys.");
365
366 // Generate keys
367 // Personal key
368 Random rand = new SecureRandom();
369 byte[] keyBytes = new byte[16];
370 rand.nextBytes(keyBytes);
371 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
372 AuthenticatorBrowser.getInstance().putKey(username, password, key);
373 String personalKey = Base64.getEncoder().encodeToString(key.getEncoded());
374 // Public and private keys
375 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm);
376 keyGen.initialize(1024);
377 KeyPair keyPair = keyGen.generateKeyPair();
378 String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
379 String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
380
381 System.out.println(message + "Creating Profile Frameset.");
382
383 // Update in memory settings
384 System.setProperty("user.name", username);
385 UserSettings.UserName.set(username);
386 UserSettings.ProfileName.set(username);
387 UserSettings.setupDefaultFolders();
388
389 // Establish the initial settings for the created user.
390 Map<String, Setting> initialSettings = new HashMap<String, Setting>();
391 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PERSONAL_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PERSONAL_KEY, "PersonalKey", personalKey));
392 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PRIVATE_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PRIVATE_KEY, "PrivateKey", privateKey));
393 initialSettings.put(Constants.SETTINGS_AUTH_PUBLIC_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PUBLIC_KEY, "PublicKey", publicKey));
394 initialSettings.put(Constants.SETTINGS_AUTH_EMAIL, constructGenericSetting(String.class, Constants.TOOLTIP_SETTING_EMAIL, "Email", email, username));
395 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_USER_NAME, constructGenericSetting(String.class, Constants.LABEL_USERNAME, Constants.LABEL_USERNAME, username, username));
396 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_PROFILE_NAME, constructGenericSetting(String.class, Constants.LABEL_PROFILENAME, Constants.LABEL_PROFILENAME, username, username));
397 initialSettings.put("settings.UserSettings.HomeFrame", constructGenericSetting(String.class, "The home frame", "HomeFrame", username + 1, username));
398 initialSettings.put("org.expeditee.gui.folders.FolderSettings.FrameDirs", FolderSettings.FrameDirs);
399 initialSettings.put("org.expeditee.gui.folders.FolderSettings.ImageDirs", FolderSettings.ImageDirs);
400 initialSettings.put("org.expeditee.gui.folders.FolderSettings.AudioDirs", FolderSettings.AudioDirs);
401
402 // Record the credentials frame number
403 Map<String, Consumer<Frame>> notifiers = new HashMap<String, Consumer<Frame>>();
404 notifiers.put(Constants.SETTINGS_AUTH, frame -> {
405 AuthenticatorBrowser.CREDENTIALS_FRAME = frame.getNumber();
406 Collection<Text> textItems = frame.getTextItems();
407 for (Text t: textItems) {
408 if (t.getText().equals("Secrets")) {
409 t.setPermission(new PermissionPair(UserAppliedPermission.followLinks, UserAppliedPermission.denied));
410 break;
411 }
412 }
413 });
414
415 // Create users profile
416 Frame profile = FrameIO.CreateNewProfile(username, initialSettings, notifiers);
417 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
418 for (int i = 1; i <= lastNumber; i++) {
419 Frame f = FrameIO.LoadFrame(profile.getFramesetName() + i);
420 Text titleItem = f.getTitleItem();
421 if (i == 1 && titleItem != null) {
422 titleItem.delete();
423 f.setBackgroundColor(new Colour(1, 1, 0.39f));
424 }
425 f.setOwner(username);
426 f.getAllItems().stream().forEach(item -> item.setOwner(username));
427 f.setChanged(true);
428 if (f.getNumber() != AuthenticatorBrowser.CREDENTIALS_FRAME) {
429 f.setEncryptionLabel("Profile");
430 }
431 Collection<Item> secretsLink = getByContent(f, "Secrets");
432 Collection<Item> publicKeyItem = getByContent(f, "PublicKey");
433 if (!secretsLink.isEmpty() && !publicKeyItem.isEmpty()) {
434 //Then we are on credentials frame
435 f.addToData("MultiuserCredentials");
436 }
437 Text backupPersonalKey = KeyList.PersonalKey.get();
438 Text tempPersonalKey = KeyList.PersonalKey.generateText();
439 tempPersonalKey.setData(personalKey);
440 KeyList.PersonalKey.setSetting(tempPersonalKey);
441 FrameIO.SaveFrame(f);
442 KeyList.PersonalKey.setSetting(backupPersonalKey);
443 }
444
445 if (AuthenticatorBrowser.CREDENTIALS_FRAME == -1) {
446 System.err.println("authActions::Unable to establish credentials frame for new profile frame. Account creation failed.");
447 return;
448 }
449
450 System.out.println(message + "Establishing user credentials.");
451
452 // Create credentials
453 File credentialsDir = new File(profile.getFramesetPath() + username + "-credentials");
454 credentialsDir.mkdir();
455 // credentials.inf file.
456 String credentialsPath = credentialsDir.getAbsolutePath() + File.separator + "credentials.inf";
457 File credentialsFile = new File(credentialsPath);
458 credentialsFile.createNewFile();
459 FileWriter out = new FileWriter(credentialsFile);
460 out.write(AuthenticatorBrowser.CREDENTIALS_FRAME + ".exp");
461 out.flush();
462 out.close();
463 // migrate credentials frame
464 Frame credentialsFrame = FrameIO.LoadFrame(username + AuthenticatorBrowser.CREDENTIALS_FRAME);
465 Path destinationDirectory = Paths.get(credentialsDir.getAbsolutePath());
466 Path destinationFile = destinationDirectory.resolve(AuthenticatorBrowser.CREDENTIALS_FRAME + ExpReader.EXTENTION);
467 FrameIO.migrateFrame(credentialsFrame, destinationFile);
468
469 System.out.println(message + "Creating Individual Space.");
470
471 // Copy private resources to personal area
472 Path personalResources = FrameIO.setupPersonalResources(username);
473
474 File contactsDir = new File(personalResources.resolve("contacts").toAbsolutePath().toString());
475 contactsDir.mkdir();
476
477 System.out.println(message + "Creating Space For Dead Drops");
478
479 File deadDropsDir = new File(personalResources.resolve("deaddrops").toAbsolutePath().toString());
480 deadDropsDir.mkdir();
481
482 System.err.println("**** Hardwired call in Apollo's AuthioPathManager");
483 AudioPathManager.activateAndScanAudioDir(); // ****
484
485 System.out.println(message + "Done.");
486 }
487
488 /*
489 * Function used to authenticate as a specified user (via function arguments).
490 */
491 private static void login(Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, ParseException {
492 String username = userdata.get(AuthenticationTag.Username);
493 String password = userdata.get(AuthenticationTag.Password);
494
495 if (username.equals(Browser.USER_NOBODY)) {
496 return;
497 }
498
499 SecretKey personalKey = null;
500
501 try {
502 personalKey = AuthenticatorBrowser.getInstance().getSecretKey(username, password);
503 } catch (Exception e) {
504 // leave personalKey null
505 }
506
507 if (personalKey == null) {
508 // Incorrect username and password
509 MessageBay.errorMessage("The username + password combination was incorrect.");
510 return;
511 }
512
513 // **** DB
514 // Have not been able to test the following as auth + login not currently working
515 // 'out of the box'
516
517 // Currently causing a concurrent modification setting related to InputManager.distributeGesture (preGesture)
518
519 // initialize Apollo
520// EcosystemManager.getMiscManager().runOnGIOThread(new BlockingRunnable() {
521// public void execute() {
522// ApolloSystem.initialize();
523// }
524// });
525
526 Frame oneFrame = null;
527 if (!username.equals(AuthenticatorBrowser.ADMINACCOUNT)) {
528 // Load in and cache the profile frame using the personal key fetched from keystore.
529 // Reset the personal key once finished so that setting parsing can correctly set it.
530 FrameIO.ClearCache();
531 Text personalKeyText = KeyList.PersonalKey.generateText();
532 personalKeyText.setData(Base64.getEncoder().encodeToString(personalKey.getEncoded()));
533 KeyList.PersonalKey.setSetting(personalKeyText);
534 UserSettings.UserName.set(username);
535 oneFrame = FrameIO.LoadProfile(username);
536 for (int i = 1; i <= FrameIO.getLastNumber(username); i++) {
537 Frame f = FrameIO.LoadFrame(oneFrame.getFramesetName() + i);
538 if (f != null && f.getData() != null && f.getData().contains("MultiuserCredentials")) {
539 AuthenticatorBrowser.CREDENTIALS_FRAME = f.getNumber();
540 }
541 }
542
543 // Update default folders.
544 UserSettings.setupDefaultFolders();
545
546 // Parse the settings frame to update the settings datastructure.
547 Text fakeLink = new Text("settings");
548 fakeLink.setLink(oneFrame.getFramesetName() + "2");
549 Settings.parseSettings(fakeLink);
550
551 // Check mail
552 MailBay.clear();
553 AuthenticatorBrowser.getInstance().loadMailDatabase();
554 Text keyItem = org.expeditee.settings.identity.secrets.KeyList.PrivateKey.get();
555 if (keyItem.getData() != null) {
556 String keyEncoded = keyItem.getData().get(0);
557 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
558 PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
559 List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key);
560 for (MailEntry mail: mailForLoggingInUser) {
561 MailBay.addMessage(mail.timestamp, mail.message, mail.message2, mail.options);
562 }
563 }
564 Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
565 for (File connectionDir: deadDropPath.toFile().listFiles()) {
566 if (connectionDir.isDirectory()) {
567 Path deaddropforcontactPath = Paths.get(connectionDir.getAbsolutePath());
568 AuthenticatorBrowser.getInstance().updateLastReadMailTime(deaddropforcontactPath);
569 }
570 }
571
572 } else {
573 UserSettings.UserName.set(AuthenticatorBrowser.ADMINACCOUNT);
574 oneFrame = FrameIO.LoadFrame("multiuser1");
575 }
576
577 Collection<Item> usernameFields = getByData(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), "txtUsername");
578 usernameFields.forEach(usernameField -> usernameField.setText(username));
579
580 Frame requestedFrame = FrameIO.LoadFrame(Browser.getStartFrame());
581 Frame homeFrame = FrameIO.LoadFrame("home1");
582 Frame choice = requestedFrame != null ? requestedFrame : homeFrame != null ? homeFrame : oneFrame;
583 DisplayController.setCurrentFrame(choice, false);
584 }
585
586 /*
587 * Function to share a specified frameset.
588 * Currently, this moves the frameset to the 'Shared By Me' directory and then relies on the user to use Google Drive functionality to share it appropriately.
589 */
590 private static void shareFrameset(Frame toShare) throws IOException {
591 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
592 File sourceDir = new File(toShare.getFramesetPath());
593
594 if (destinationDir.exists()) {
595 MessageBay.errorMessage("A frameset by this name already exists.");
596 return;
597 }
598
599 destinationDir.mkdir();
600 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
601 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
602
603 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ". Google Drive functionality can now be used to share it with colleagues.");
604 }
605
606 private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
607 String time = org.expeditee.stats.Formatter.getDateTime();
608 String sender = UserSettings.UserName.get();
609 String message = "You have received a reply from " + sender + " reguarding your request for assistance.";
610 String message2 = "Unfortunately " + sender + " has indicated that they are unable to help you with your potential password recovery.";
611 Map<String, String> options = new HashMap<String, String>();
612 options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated");
613 MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options);
614 Mail.sendMail(mail, colleagueName);
615 }
616
617 private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
618 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
619 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
620 PublicKey colleagueOneKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueOne);
621 PublicKey colleagueTwoKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueTwo);
622 if (colleagueOneKey == null) {
623 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne);
624 return false;
625 } else if (colleagueTwoKey == null) {
626 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo);
627 return false;
628 } else {
629 String time = org.expeditee.stats.Formatter.getDateTime();
630 String sender = userData.get(AuthenticationTag.Username);
631 String topic = "You have received a request for cooperation from your colleague " + sender;
632 String message = "Should " + sender + " forget their password, they would like your help recoverying it.";
633 Map<String, String> arguments = new HashMap<String, String>();
634 arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
635 arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
636 MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments);
637 Mail.sendMail(mail, colleagueOne);
638 mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments);
639 Mail.sendMail(mail, colleagueTwo);
640 AuthenticatorBrowser.getInstance().markRequestedColleagues(UserSettings.UserName.get());
641 return true;
642 }
643 }
644
645
646 private static TextSetting constructTextSetting(String tooltip, String text, String data) {
647 return new TextSetting(tooltip, text) {
648 @Override
649 public Text generateText() {
650 Text t = new Text(text);
651 t.setData(data);
652 return t;
653 }
654 };
655 }
656
657 private static <T> GenericSetting<T> constructGenericSetting(Class<T> type, String tooltip, String name, T value, String frameset) {
658 return new GenericSetting<T>(type, tooltip, name, value) {
659 @Override
660 public Text generateRepresentation(String name, String frameset) {
661 Text t = new Text(name + ": " + value);
662 return t;
663 }
664 };
665 }
666
667 /*
668 * Changes the recorded password for a user in the key store.
669 */
670 private static void changePassword(final Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
671 final String username = userdata.get(AuthenticationTag.Username);
672 final String password = userdata.get(AuthenticationTag.Password);
673 final String newpassword = userdata.get(AuthenticationTag.NewPassword);
674
675 final SecretKey key = AuthenticatorBrowser.getInstance().getSecretKey(username, password);
676 if (key == null) {
677 MessageBay.errorMessage("The username + existing password combination was incorrect.");
678 } else {
679 AuthenticatorBrowser.getInstance().putKey(username, newpassword, key);
680 MessageBay.displayMessage("Password changed successfully.");
681 }
682 }
683
684// // establish properties
685// final String from = "[email protected]";
686// final Properties properties = System.getProperties();
687//
688// properties.setProperty("mail.transport.protocol", "smtp");
689// properties.setProperty("mail.smtp.host", "smtp.gmail.com");
690// properties.setProperty("mail.smtp.port", "465");
691// properties.setProperty("mail.smtp.starttls.enable", "true");
692// properties.setProperty("mail.smtp.auth", "true");
693// properties.setProperty("mail.smtp.debug", "true");
694// properties.setProperty("mail.smtp.auth", "true");
695// properties.setProperty("mail.smtp.socketFactory.port", "465");
696// properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
697// properties.setProperty("mail.smtp.socketFactory.fallback", "false");
698//
699// final Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
700// @Override
701// protected PasswordAuthentication getPasswordAuthentication() {
702// return new PasswordAuthentication("noreply.expeditee", "intergalacticnumber");
703// };
704// });
705
706// // construct email message
707// final MimeMessage message = new MimeMessage(session);
708// message.setFrom(new InternetAddress(from));
709// message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
710// message.setSubject("Expeditee Password Recovery");
711// message.setText(intergalacticNumber);
712//
713// // send email message
714// Transport.send(message);
715
716
717 public static void TickBox(final Text item) {
718 if (item.getBackgroundColor() != Colour.RED) {
719 item.setBackgroundColor(Colour.RED);
720 } else {
721 item.setBackgroundColor(Colour.GREEN);
722 }
723 }
724
725 /*
726 * Gets all items on a specified frame that contain the specified data.
727 */
728 public static Collection<Item> getByData(final Frame frame, final String data) {
729 final Collection<Item> allItems = frame.getAllItems();
730 allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
731 return allItems;
732 }
733
734 public static Collection<Item> getByContent(final Frame frame, final String content) {
735 final Collection<Item> allItems = frame.getAllItems();
736 allItems.removeIf(i -> i.getText().compareTo(content) != 0);
737 return allItems;
738 }
739}
Note: See TracBrowser for help on using the repository browser.