From f97226ba6e080900fc8cff004148cad34b863425 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
And remove 'arch' attribute of 'o.e.equinox.security.linux' in the
'o.e.equinox.core.sdk' feature to reflect that the fragment is
architecture-independent.
---
.../META-INF/MANIFEST.MF | 1 -
.../security/linux/LinuxPasswordProvider.java | 82 +++++--------------
.../META-INF/MANIFEST.MF | 2 +-
.../pom.xml | 2 +-
.../internal/security/win32/WinCrypto.java | 31 +++----
.../storage/provider/PasswordProvider.java | 15 +---
.../org.eclipse.equinox.core.sdk/feature.xml | 2 -
7 files changed, 42 insertions(+), 93 deletions(-)
diff --git a/bundles/org.eclipse.equinox.security.linux/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.security.linux/META-INF/MANIFEST.MF
index 8e684c4bd46..501e164a2b4 100644
--- a/bundles/org.eclipse.equinox.security.linux/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.security.linux/META-INF/MANIFEST.MF
@@ -10,5 +10,4 @@ Bundle-Localization: fragment
Eclipse-PlatformFilter: (osgi.os=linux)
Export-Package: org.eclipse.equinox.internal.security.linux;x-internal:=true
Automatic-Module-Name: org.eclipse.equinox.security.linux
-Eclipse-BundleShape: dir
Require-Bundle: com.sun.jna;bundle-version="[5.8.0,6.0.0)"
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..6e7ba0b883a 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);
@@ -97,31 +84,16 @@ private void unlockSecretService() {
PointerByReference gerror = new PointerByReference();
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);
- }
+ requireNoError(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);
- }
+ requireNoError(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);
- }
+ requireNoError(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$
}
@@ -132,23 +104,10 @@ private void unlockSecretService() {
fLibSecret.secret_service_unlock_sync(secretService, list, Pointer.NULL, unlocked, gerror);
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);
- }
- }
- }
-
- private boolean canUnlock() {
- try {
- unlockSecretService();
- } catch (SecurityException e) {
- return false;
+ requireNoError(gerror, "Unable to unlock: "); //$NON-NLS-1$
}
- return true;
+
}
private String getMasterPassword() throws SecurityException {
@@ -156,12 +115,8 @@ private String getMasterPassword() throws SecurityException {
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);
- } else if (password == null) {
+ requireNoError(gerror, ""); //$NON-NLS-1$
+ if (password == null) {
throw new SecurityException("Unable to find password"); //$NON-NLS-1$
}
@@ -171,20 +126,22 @@ 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);
+ String passwordUTF8 = 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);
+ requireNoError(gerror, ""); //$NON-NLS-1$
+ }
+
+ private void requireNoError(PointerByReference gerror, String details) {
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 new SecurityException(details + message);
}
}
@@ -224,7 +181,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/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.security.win32.x86_64/META-INF/MANIFEST.MF
index 4778a524a71..717621bea93 100644
--- a/bundles/org.eclipse.equinox.security.win32.x86_64/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.security.win32.x86_64/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %fragmentName
Bundle-SymbolicName: org.eclipse.equinox.security.win32.x86_64;singleton:=true
-Bundle-Version: 1.2.200.qualifier
+Bundle-Version: 1.2.300.qualifier
Bundle-Vendor: %providerName
Fragment-Host: org.eclipse.equinox.security;bundle-version="[1.0.0,2.0.0)"
Bundle-RequiredExecutionEnvironment: JavaSE-17
diff --git a/bundles/org.eclipse.equinox.security.win32.x86_64/pom.xml b/bundles/org.eclipse.equinox.security.win32.x86_64/pom.xml
index 02abb7e7fec..e88730690e9 100644
--- a/bundles/org.eclipse.equinox.security.win32.x86_64/pom.xml
+++ b/bundles/org.eclipse.equinox.security.win32.x86_64/pom.xml
@@ -18,7 +18,7 @@
../../
org.eclipse.equinox.security.win32.x86_64
- 1.2.200-SNAPSHOT
+ 1.2.300-SNAPSHOT
eclipse-plugin
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
diff --git a/features/org.eclipse.equinox.core.sdk/feature.xml b/features/org.eclipse.equinox.core.sdk/feature.xml
index 65124b9c048..47984dc8214 100644
--- a/features/org.eclipse.equinox.core.sdk/feature.xml
+++ b/features/org.eclipse.equinox.core.sdk/feature.xml
@@ -86,13 +86,11 @@