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