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

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

Moved the static field USER_NOBODY to AuthenticatorBrowser from Browser as it makes more sense there.
Added functionality to log out, equiv to closing Expeditee and starting it again.

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