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 @@