diff --git a/platform/platform-api/src/com/intellij/ide/passwordSafe/MasterPasswordUnavailableException.java b/platform/platform-api/src/com/intellij/ide/passwordSafe/MasterPasswordUnavailableException.java index 2757e2304077..5617c9c11072 100644 --- a/platform/platform-api/src/com/intellij/ide/passwordSafe/MasterPasswordUnavailableException.java +++ b/platform/platform-api/src/com/intellij/ide/passwordSafe/MasterPasswordUnavailableException.java @@ -18,7 +18,7 @@ package com.intellij.ide.passwordSafe; /** * This exception is thrown when master password is not available (process of entering password is cancelled, or IDEA is running headless mode) */ -public class MasterPasswordUnavailableException extends PasswordSafeException { +public class MasterPasswordUnavailableException extends RuntimeException { public MasterPasswordUnavailableException(String message) { super(message); } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index c755bcd24ff9..42fc03bfd22a 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -153,22 +153,25 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { @NotNull @Override - protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException { + protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) { Object key = myKey.get().get(); if (key instanceof byte[]) { return (byte[])key; } + if (key instanceof PasswordSafeException && ((PasswordSafeException)key).justHappened()) { throw (PasswordSafeException)key; } - if (isPasswordEncrypted()) { + if (SystemInfo.isWindows) { try { - setMasterPassword(decryptPassword(myDatabase.getPasswordInfo())); + setMasterPassword(new String(WindowsCryptUtils.unprotect(myDatabase.getPasswordInfo()), CharsetToolkit.UTF8_CHARSET)); key = myKey.get().get(); - if (key instanceof byte[]) return (byte[])key; + if (key instanceof byte[]) { + return (byte[])key; + } } - catch (PasswordSafeException e) { + catch (Exception ignored) { // ignore exception and ask password } } @@ -179,14 +182,12 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return key1; } try { - if (myDatabase.isEmpty()) { - if (!MasterPasswordDialog.resetMasterPasswordDialog(project, this).showAndGet()) { - throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database."); - } - } - else { + if (!myDatabase.isEmpty()) { MasterPasswordDialog.askPassword(project, this, requestor); } + else if (!MasterPasswordDialog.resetMasterPasswordDialog(project, this).showAndGet()) { + throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database."); + } } catch (PasswordSafeException e) { myKey.get().set(e); @@ -194,8 +195,12 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } return myKey.get().get(); }, project == null ? Conditions.alwaysFalse() : project.getDisposed()); - if (key instanceof byte[]) return (byte[])key; - if (key instanceof PasswordSafeException) throw (PasswordSafeException)key; + if (key instanceof byte[]) { + return (byte[])key; + } + if (key instanceof PasswordSafeException) { + throw (PasswordSafeException)key; + } throw new AssertionError(); } @@ -298,13 +303,10 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return setMasterPassword(""); } - @SuppressWarnings("MethodMayBeStatic") public boolean isOsProtectedPasswordSupported() { - // TODO extension point needed? return SystemInfo.isWindows; } - /** * Encrypt master password * @@ -318,22 +320,10 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return WindowsCryptUtils.protect(EncryptionUtil.getUTF8Bytes(pw)); } - /** - * Decrypt master password - * - * @param pw the password to decrypt - * @return the decrypted password - * @throws MasterPasswordUnavailableException - * if decryption fails - */ - private static String decryptPassword(byte[] pw) throws MasterPasswordUnavailableException { - if (!SystemInfo.isWindows) throw new AssertionError("Windows OS expected"); - - return new String(WindowsCryptUtils.unprotect(pw), CharsetToolkit.UTF8_CHARSET); - } - public boolean isPasswordEncrypted() { - if (!isOsProtectedPasswordSupported()) return false; + if (!isOsProtectedPasswordSupported()) { + return false; + } byte[] info = myDatabase.getPasswordInfo(); return info != null && info.length > 0; diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/windows/WindowsCryptUtils.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/windows/WindowsCryptUtils.java index 2858fb554607..0b7c5e00e83a 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/windows/WindowsCryptUtils.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/windows/WindowsCryptUtils.java @@ -15,7 +15,6 @@ */ package com.intellij.ide.passwordSafe.impl.providers.masterKey.windows; -import com.intellij.ide.passwordSafe.MasterPasswordUnavailableException; import com.intellij.util.containers.ContainerUtil; import com.sun.jna.Memory; import com.sun.jna.Native; @@ -52,7 +51,7 @@ public class WindowsCryptUtils { * @param data the data to protect * @return the the protected form the data */ - public static byte[] protect(byte[] data) throws MasterPasswordUnavailableException { + public static byte[] protect(byte[] data) { if(data.length == 0) { return data; } @@ -75,7 +74,7 @@ public class WindowsCryptUtils { * @param data the data to protect * @return the the protected form the data */ - public static byte[] unprotect(byte[] data) throws MasterPasswordUnavailableException { + public static byte[] unprotect(byte[] data) { if(data.length == 0) { return data; } @@ -92,10 +91,10 @@ public class WindowsCryptUtils { return getBytes(out, kernel, rc); } - private static byte[] getBytes(Crypt32.DATA_BLOB out, Kernel32 kernel, boolean rc) throws MasterPasswordUnavailableException { + private static byte[] getBytes(Crypt32.DATA_BLOB out, Kernel32 kernel, boolean rc) { if (!rc) { W32API.DWORD drc = kernel.GetLastError(); - throw new MasterPasswordUnavailableException("CryptProtectData failed: " + drc.intValue()); + throw new RuntimeException("CryptProtectData failed: " + drc.intValue()); } else { byte[] output = new byte[out.cbData.intValue()];