From 55591ec7b93b0e3f5da88f47f182eddf5303078a Mon Sep 17 00:00:00 2001
From: Hannes Wellmann
Date: Sun, 24 Mar 2024 15:04:46 +0100
Subject: [PATCH] Clean-up and simplify LinuxPasswordProvider and WinCrypto
---
.../security/linux/LinuxPasswordProvider.java | 78 ++++++-------------
.../internal/security/win32/WinCrypto.java | 31 ++++----
.../storage/provider/PasswordProvider.java | 15 +---
3 files changed, 42 insertions(+), 82 deletions(-)
diff --git a/bundles/org.eclipse.equinox.security.linux/src/org/eclipse/equinox/internal/security/linux/LinuxPasswordProvider.java b/bundles/org.eclipse.equinox.security.linux/src/org/eclipse/equinox/internal/security/linux/LinuxPasswordProvider.java
index 76531b55c18..1c5e38be861 100644
--- a/bundles/org.eclipse.equinox.security.linux/src/org/eclipse/equinox/internal/security/linux/LinuxPasswordProvider.java
+++ b/bundles/org.eclipse.equinox.security.linux/src/org/eclipse/equinox/internal/security/linux/LinuxPasswordProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017, 2021 IBM Corporation and others.
+ * Copyright (c) 2017, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -17,7 +17,6 @@
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
-import java.util.HashMap;
import java.util.Map;
import javax.crypto.spec.PBEKeySpec;
@@ -42,26 +41,14 @@ public class LinuxPasswordProvider extends PasswordProvider implements IValidati
private static final int PASSWORD_LENGTH = 64;
private static final String SECRET_COLLECTION_DEFAULT = "default"; //$NON-NLS-1$
- private static final Map LIB_LOAD_OPTIONS = new HashMap<>();
+ // open flags = (RTLD_NODELETE | RTLD_GLOBAL | RTLD_LAZY)
+ private static final Map LIB_LOAD_OPTIONS = Map.of(Library.OPTION_OPEN_FLAGS, 0x1101);
- private SecretSchema fEquinoxSchema;
+ private final SecretSchema fEquinoxSchema = new SecretSchema("org.eclipse.equinox", //$NON-NLS-1$
+ SecretSchemaFlags.SECRET_SCHEMA_NONE, new SecretSchemaAttribute(null, 0));
private LibSecret fLibSecret;
private LibGio fLibGio;
- static {
- // open flags = (RTLD_NODELETE | RTLD_GLOBAL | RTLD_LAZY)
- LIB_LOAD_OPTIONS.put(Library.OPTION_OPEN_FLAGS, 0x1101);
- }
-
- public LinuxPasswordProvider() {
- initEquinoxSchema();
- }
-
- private void initEquinoxSchema() {
- fEquinoxSchema = new SecretSchema("org.eclipse.equinox", //$NON-NLS-1$
- SecretSchemaFlags.SECRET_SCHEMA_NONE, new SecretSchemaAttribute(null, 0));
- }
-
private interface LibGio extends Library {
Pointer g_bus_get_sync(int bus_type, Pointer cancellable, PointerByReference gerror);
@@ -98,29 +85,20 @@ private void unlockSecretService() {
gerror.setValue(Pointer.NULL);
fLibGio.g_bus_get_sync(GBusType.G_BUS_TYPE_SESSION, Pointer.NULL, gerror);
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = "Unable to get DBus session bus: " + error.message; //$NON-NLS-1$
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, "Unable to get DBus session bus: "); //$NON-NLS-1$
}
fLibSecret = Native.load("secret-1", LibSecret.class, LIB_LOAD_OPTIONS); //$NON-NLS-1$
Pointer secretService = fLibSecret.secret_service_get_sync(SecretServiceFlags.SECRET_SERVICE_LOAD_COLLECTIONS,
Pointer.NULL, gerror);
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = "Unable to get secret service: " + error.message; //$NON-NLS-1$
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, "Unable to get secret service: "); //$NON-NLS-1$
}
Pointer defaultCollection = fLibSecret.secret_collection_for_alias_sync(secretService,
SECRET_COLLECTION_DEFAULT, SecretCollectionFlags.SECRET_COLLECTION_NONE, Pointer.NULL, gerror);
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = "Unable to get secret collection: " + error.message; //$NON-NLS-1$
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, "Unable to get secret collection: "); //$NON-NLS-1$
}
if (defaultCollection == Pointer.NULL) {
throw new SecurityException("Unable to find default secret collection"); //$NON-NLS-1$
@@ -133,34 +111,19 @@ private void unlockSecretService() {
fLibGio.g_error_free(unlocked.getValue());
fLibGio.g_error_free(list.getPointer());
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = "Unable to unlock: " + error.message; //$NON-NLS-1$
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, "Unable to unlock: "); //$NON-NLS-1$
}
}
}
- private boolean canUnlock() {
- try {
- unlockSecretService();
- } catch (SecurityException e) {
- return false;
- }
- return true;
- }
-
private String getMasterPassword() throws SecurityException {
unlockSecretService();
PointerByReference gerror = new PointerByReference();
String password = fLibSecret.secret_password_lookup_sync(fEquinoxSchema, Pointer.NULL, gerror, Pointer.NULL);
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = error.message;
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, ""); //$NON-NLS-1$
} else if (password == null) {
throw new SecurityException("Unable to find password"); //$NON-NLS-1$
}
@@ -171,23 +134,25 @@ private String getMasterPassword() throws SecurityException {
private void saveMasterPassword(String password) throws SecurityException {
unlockSecretService();
- String passwordUTF8 = password;
PointerByReference gerror = new PointerByReference();
- byte[] utfbytes = password.getBytes();
- passwordUTF8 = new String(utfbytes, StandardCharsets.UTF_8);
+ password = new String(password.getBytes(), StandardCharsets.UTF_8);
fLibSecret.secret_password_store_sync(fEquinoxSchema, SECRET_COLLECTION_DEFAULT, "Equinox master password", //$NON-NLS-1$
- passwordUTF8, Pointer.NULL, gerror, Pointer.NULL);
+ password, Pointer.NULL, gerror, Pointer.NULL);
if (gerror.getValue() != Pointer.NULL) {
- GError error = new GError(gerror.getValue());
- String message = error.message;
- fLibGio.g_error_free(gerror.getValue());
- throw new SecurityException(message);
+ throw toSecurityException(gerror, ""); //$NON-NLS-1$
}
}
+ private SecurityException toSecurityException(PointerByReference gerror, String string) {
+ GError error = new GError(gerror.getValue());
+ String message = string + error.message;
+ fLibGio.g_error_free(gerror.getValue());
+ return new SecurityException(message);
+ }
+
@Override
public PBEKeySpec getPassword(IPreferencesContainer container, int passwordType) {
@@ -224,7 +189,8 @@ public PBEKeySpec getPassword(IPreferencesContainer container, int passwordType)
@Override
public boolean isValid() {
try {
- return canUnlock();
+ unlockSecretService();
+ return true;
} catch (SecurityException e) {
return false;
}
diff --git a/bundles/org.eclipse.equinox.security.win32.x86_64/src/org/eclipse/equinox/internal/security/win32/WinCrypto.java b/bundles/org.eclipse.equinox.security.win32.x86_64/src/org/eclipse/equinox/internal/security/win32/WinCrypto.java
index 7ccedabb118..6988fa0e971 100644
--- a/bundles/org.eclipse.equinox.security.win32.x86_64/src/org/eclipse/equinox/internal/security/win32/WinCrypto.java
+++ b/bundles/org.eclipse.equinox.security.win32.x86_64/src/org/eclipse/equinox/internal/security/win32/WinCrypto.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2017 IBM Corporation and others.
+ * Copyright (c) 2008, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
- *
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
@@ -41,21 +41,22 @@ public class WinCrypto extends PasswordProvider {
System.loadLibrary("jnicrypt64");
}
- private final static String WIN_PROVIDER_NODE = "/org.eclipse.equinox.secure.storage/windows64";
- private final static String PASSWORD_KEY = "encryptedPassword";
+ private static final String WIN_PROVIDER_NODE = "/org.eclipse.equinox.secure.storage/windows64";
+ private static final String PASSWORD_KEY = "encryptedPassword";
/**
* The length of the randomly generated password in bytes
*/
- private final static int PASSWORD_LENGTH = 250;
+ private static final int PASSWORD_LENGTH = 250;
@Override
public PBEKeySpec getPassword(IPreferencesContainer container, int passwordType) {
byte[] encryptedPassword;
- if ((passwordType & CREATE_NEW_PASSWORD) == 0)
+ if ((passwordType & CREATE_NEW_PASSWORD) == 0) {
encryptedPassword = getEncryptedPassword(container);
- else
+ } else {
encryptedPassword = null;
+ }
if (encryptedPassword != null) {
byte[] decryptedPassword = windecrypt(encryptedPassword);
@@ -78,24 +79,24 @@ public PBEKeySpec getPassword(IPreferencesContainer container, int passwordType)
random.setSeed(System.currentTimeMillis());
random.nextBytes(rawPassword);
String password = Base64.encode(rawPassword);
- if (savePassword(password, container))
+ if (savePassword(password, container)) {
return new PBEKeySpec(password.toCharArray());
- else
+ } else {
return null;
+ }
}
private byte[] getEncryptedPassword(IPreferencesContainer container) {
ISecurePreferences node = container.getPreferences().node(WIN_PROVIDER_NODE);
- String passwordHint;
try {
- passwordHint = node.get(PASSWORD_KEY, null);
+ String passwordHint = node.get(PASSWORD_KEY, null);
+ if (passwordHint != null) {
+ return Base64.decode(passwordHint);
+ }
} catch (StorageException e) { // should never happen in this scenario
AuthPlugin.getDefault().logError(WinCryptoMessages.decryptPasswordFailed, e);
- return null;
}
- if (passwordHint == null)
- return null;
- return Base64.decode(passwordHint);
+ return null;
}
private boolean savePassword(String password, IPreferencesContainer container) {
diff --git a/bundles/org.eclipse.equinox.security/src/org/eclipse/equinox/security/storage/provider/PasswordProvider.java b/bundles/org.eclipse.equinox.security/src/org/eclipse/equinox/security/storage/provider/PasswordProvider.java
index 18aec921551..c65abf982cd 100644
--- a/bundles/org.eclipse.equinox.security/src/org/eclipse/equinox/security/storage/provider/PasswordProvider.java
+++ b/bundles/org.eclipse.equinox.security/src/org/eclipse/equinox/security/storage/provider/PasswordProvider.java
@@ -31,7 +31,7 @@
* password provider module to the secure storage system.
*
*/
-abstract public class PasswordProvider {
+public abstract class PasswordProvider {
/**
* Bit mask for the password type field of the
@@ -40,7 +40,7 @@ abstract public class PasswordProvider {
* otherwise this is a request for the password previously used for this secure
* storage.
*/
- final public static int CREATE_NEW_PASSWORD = 1 << 0;
+ public static final int CREATE_NEW_PASSWORD = 1 << 0;
/**
* Bit mask for the password type field of the
@@ -48,7 +48,7 @@ abstract public class PasswordProvider {
* set to 1
, it indicates that a new password is requested as a
* part of the password change operation.
*/
- final public static int PASSWORD_CHANGE = 1 << 1;
+ public static final int PASSWORD_CHANGE = 1 << 1;
/**
* This method should return the password used to encrypt entries in the secure
@@ -63,14 +63,7 @@ abstract public class PasswordProvider {
* @return password used to encrypt entries in the secure preferences,
* null
if unable to obtain password
*/
- abstract public PBEKeySpec getPassword(IPreferencesContainer container, int passwordType);
-
- /**
- * Constructor.
- */
- public PasswordProvider() {
- // placeholder
- }
+ public abstract PBEKeySpec getPassword(IPreferencesContainer container, int passwordType);
/**
* The framework might call this method if it suspects that the password is