This commit is contained in:
Vladimir Krivosheev
2016-07-13 07:36:41 +02:00
parent 35acdbe690
commit 5aeee8a94f
3 changed files with 26 additions and 37 deletions
@@ -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);
}
@@ -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;
@@ -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()];