You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ma...@apache.org on 2021/04/22 20:08:44 UTC
[netbeans] branch master updated: NETBEANS-4150 added a
KeyringProvider using libsecret for new versions of Gnome
This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 887a663 NETBEANS-4150 added a KeyringProvider using libsecret for new versions of Gnome
new 3b964b0 Merge pull request #2906 from premek/NETBEANS-4150-libsecret-keyring-provider
887a663 is described below
commit 887a66372051aca686d8bf6b5e124807f5b59d2d
Author: Premysl Vyhnal <pr...@gmail.com>
AuthorDate: Sun Apr 18 23:25:00 2021 +0200
NETBEANS-4150 added a KeyringProvider using libsecret for new versions of Gnome
---
.../modules/keyring/gnome/libsecret/Gio.java | 35 ++++
.../modules/keyring/gnome/libsecret/Glib.java | 39 +++++
.../gnome/libsecret/GnomeLibSecretProvider.java | 178 +++++++++++++++++++++
.../modules/keyring/gnome/libsecret/LibSecret.java | 72 +++++++++
.../libsecret/GnomeLibSecretProviderTest.java | 35 ++++
5 files changed, 359 insertions(+)
diff --git a/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Gio.java b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Gio.java
new file mode 100644
index 0000000..f76708c
--- /dev/null
+++ b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Gio.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.keyring.gnome.libsecret;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+
+public interface Gio extends Library {
+
+ Gio INSTANCE = Native.load("gio-2.0", Gio.class);
+
+ class GCancelable {
+
+ public GCancelable() {
+ throw new RuntimeException("CANCELING NOT IMPLEMENTED!");
+ }
+
+ }
+}
diff --git a/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Glib.java b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Glib.java
new file mode 100644
index 0000000..7ad406c
--- /dev/null
+++ b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/Glib.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.keyring.gnome.libsecret;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+
+public interface Glib extends Library {
+
+ Glib INSTANCE = Native.load("glib-2.0", Glib.class);
+
+ public void g_error_free(Pointer gerror);
+
+ @Structure.FieldOrder({"domain", "code", "message"})
+ class GError extends Structure {
+
+ public int domain;
+ public int code;
+ public String message;
+ }
+}
diff --git a/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProvider.java b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProvider.java
new file mode 100644
index 0000000..540c0eb
--- /dev/null
+++ b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProvider.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.keyring.gnome.libsecret;
+
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+import com.sun.jna.ptr.PointerByReference;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.modules.keyring.gnome.libsecret.Glib.GError;
+import org.netbeans.modules.keyring.gnome.libsecret.LibSecret.SecretSchema;
+import org.netbeans.modules.keyring.gnome.libsecret.LibSecret.SecretSchemaAttribute;
+import org.netbeans.spi.keyring.KeyringProvider;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+
+@ServiceProvider(service = KeyringProvider.class, position = 90)
+public class GnomeLibSecretProvider implements KeyringProvider {
+
+ private static final Logger LOG = Logger.getLogger(GnomeLibSecretProvider.class.getName());
+ private static final String KEY = "key"; // NOI18N
+ private static final Charset CHARSET = Charset.forName(Native.getDefaultStringEncoding());
+
+ private final String appName;
+
+ private SecretSchema secretSchema = null;
+
+ public GnomeLibSecretProvider() {
+ appName = getAppName();
+ }
+
+ private SecretSchema getSchema() {
+ if (secretSchema != null) {
+ return secretSchema;
+ }
+
+ secretSchema = new SecretSchema();
+ secretSchema.name = appName;
+ secretSchema.flags = LibSecret.SECRET_SCHEMA_NONE;
+ secretSchema.attributes[0] = new SecretSchemaAttribute();
+ secretSchema.attributes[0].name = KEY;
+ secretSchema.attributes[0].type = LibSecret.SECRET_SCHEMA_ATTRIBUTE_STRING;
+ return secretSchema;
+ }
+
+ private String getAppName() {
+ try {
+ return MessageFormat.format(
+ NbBundle.getBundle("org.netbeans.core.windows.view.ui.Bundle").getString("CTL_MainWindow_Title_No_Project"),
+ "…");
+ } catch (MissingResourceException x) {
+ return "NetBeans"; // NOI18N
+ }
+ }
+
+ @Override
+ public boolean enabled() {
+ if (Boolean.getBoolean("netbeans.keyring.no.native")) {
+ LOG.fine("native keyring integration disabled");
+ return false;
+ }
+
+ try {
+ read("NoNeXiStEnT"); // NOI18N
+ return true;
+ } catch (RuntimeException e) {
+ LOG.log(Level.WARNING, null, e);
+ return false;
+ } catch (UnsatisfiedLinkError e) {
+ LOG.log(Level.FINE, null, e);
+ return false;
+ }
+ }
+
+ @Override
+ public char[] read(String key) {
+ PointerByReference gerrorBuffer = new PointerByReference();
+ SecretSchema schema = getSchema();
+
+ Pointer pointer = LibSecret.INSTANCE.secret_password_lookup_sync(schema, null, gerrorBuffer, KEY, key);
+
+ if (gerrorBuffer.getValue() != null) {
+ processError(gerrorBuffer);
+ return null;
+ }
+
+ if (pointer == null) {
+ return null;
+ }
+
+ return decode(readZeroTerminatedBytes(pointer));
+ }
+
+ @Override
+ public void save(String key, char[] password, String description) {
+ PointerByReference gerrorBuffer = new PointerByReference();
+ SecretSchema schema = getSchema();
+
+ String label = appName + " - " + (description != null ? description : key);
+ LibSecret.INSTANCE.secret_password_store_sync(schema, LibSecret.SECRET_COLLECTION_DEFAULT, label, encode(password), null, gerrorBuffer, KEY, key);
+
+ if (gerrorBuffer.getValue() != null) {
+ processError(gerrorBuffer);
+ }
+ }
+
+ @Override
+ public void delete(String key) {
+ PointerByReference gerrorBuffer = new PointerByReference();
+ SecretSchema schema = getSchema();
+
+ LibSecret.INSTANCE.secret_password_clear_sync(schema, null, gerrorBuffer, KEY, key);
+
+ if (gerrorBuffer.getValue() != null) {
+ processError(gerrorBuffer);
+ }
+ }
+
+ private void processError(PointerByReference gerrorBuffer) throws IllegalArgumentException {
+ try {
+ GError gerror = Structure.newInstance(GError.class, gerrorBuffer.getValue());
+ gerror.read();
+ LOG.warning(String.format("%d/%d: %s", gerror.domain, gerror.code, gerror.message));
+ } finally {
+ Glib.INSTANCE.g_error_free(gerrorBuffer.getValue());
+ }
+ }
+
+ private byte[] encode(char[] password) {
+ ByteBuffer encodedPasswordBuffer = CHARSET.encode(CharBuffer.wrap(password));
+ byte[] encodedPassword = new byte[encodedPasswordBuffer.limit() + 1]; // zero terminated
+ encodedPasswordBuffer.get(encodedPassword, 0, encodedPasswordBuffer.limit());
+ return encodedPassword;
+ }
+
+ private char[] decode(byte[] bytes) {
+ CharBuffer decodedPasswordBuffer = CHARSET.decode(ByteBuffer.wrap(bytes));
+ char[] decodedPassword = new char[decodedPasswordBuffer.limit()];
+ decodedPasswordBuffer.get(decodedPassword, 0, decodedPasswordBuffer.limit());
+ return decodedPassword;
+ }
+
+ private byte[] readZeroTerminatedBytes(Pointer pointer) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < 100000; i++) {
+ byte curVal = pointer.getByte(i);
+ if (curVal == 0) {
+ break;
+ }
+ baos.write(curVal);
+ }
+ return baos.toByteArray();
+ }
+
+}
diff --git a/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/LibSecret.java b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/LibSecret.java
new file mode 100644
index 0000000..9411e49
--- /dev/null
+++ b/platform/keyring.impl/src/org/netbeans/modules/keyring/gnome/libsecret/LibSecret.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.keyring.gnome.libsecret;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+import com.sun.jna.ptr.PointerByReference;
+import org.netbeans.modules.keyring.gnome.libsecret.Gio.GCancelable;
+
+public interface LibSecret extends Library {
+
+ LibSecret INSTANCE = Native.load("secret-1", LibSecret.class);
+
+ Pointer secret_password_lookup_sync(SecretSchema schema, GCancelable cancellable, PointerByReference gerror, Object... attributes);
+
+ Pointer secret_password_store_sync(SecretSchema schema, String collection, String label, byte[] password, GCancelable cancelable, PointerByReference gerror, Object... attributes);
+
+ Pointer secret_password_clear_sync(SecretSchema schema, GCancelable cancellable, PointerByReference gerror, Object... attributes);
+
+ void secret_password_free(Pointer pointer);
+
+ @Structure.FieldOrder({"name", "flags", "attributes", "reserved", "reserved1", "reserved2", "reserved3", "reserved4", "reserved5", "reserved6", "reserved7"})
+ class SecretSchema extends Structure {
+
+ public String name;
+ public int flags;
+ public SecretSchemaAttribute[] attributes = new SecretSchemaAttribute[32];
+ public int reserved;
+ public Pointer reserved1;
+ public Pointer reserved2;
+ public Pointer reserved3;
+ public Pointer reserved4;
+ public Pointer reserved5;
+ public Pointer reserved6;
+ public Pointer reserved7;
+ }
+
+ @Structure.FieldOrder({"name", "type"})
+ class SecretSchemaAttribute extends Structure {
+
+ public String name;
+ public int type;
+ }
+
+ final int SECRET_SCHEMA_ATTRIBUTE_STRING = 0;
+ final int SECRET_SCHEMA_ATTRIBUTE_INTEGER = 1;
+ final int SECRET_SCHEMA_ATTRIBUTE_BOOLEAN = 2;
+
+ final int SECRET_SCHEMA_NONE = 0;
+ final int SECRET_SCHEMA_DONT_MATCH_NAME = 1;
+
+ final String SECRET_COLLECTION_DEFAULT = "default";
+ final String SECRET_COLLECTION_SESSION = "session";
+}
diff --git a/platform/keyring.impl/test/unit/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProviderTest.java b/platform/keyring.impl/test/unit/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProviderTest.java
new file mode 100644
index 0000000..0d03722
--- /dev/null
+++ b/platform/keyring.impl/test/unit/src/org/netbeans/modules/keyring/gnome/libsecret/GnomeLibSecretProviderTest.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.keyring.gnome.libsecret;
+
+import org.netbeans.modules.keyring.KeyringProviderTestBase;
+import org.netbeans.spi.keyring.KeyringProvider;
+
+public class GnomeLibSecretProviderTest extends KeyringProviderTestBase {
+
+ public GnomeLibSecretProviderTest(String n) {
+ super(n);
+ }
+
+ @Override
+ protected KeyringProvider createProvider() {
+ return new GnomeLibSecretProvider();
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists