# HG changeset patch # User Severin Gehwolf # Date 1444060681 14400 # Node ID 2ae8438ee9d27a3962f45d1b3c235756c39fef46 # Parent 96c0923a42e3ecfb4bd6afcdc19ec09f7f102c3e Keyring service might block forever storing passwords on newer distributions Add a libsecret based JNI implementation which is preferred over an libgnome-keyring based one. The JNI build is now autotools based so as to be able to select an implementation at build time. PR2660 Reviewed-by: neugens, omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-October/016616.html Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-October/016640.html diff -r 96c0923a42e3 -r 2ae8438ee9d2 .hgignore --- a/.hgignore Thu Oct 01 14:24:31 2015 +0200 +++ b/.hgignore Mon Oct 05 11:58:01 2015 -0400 @@ -3,6 +3,20 @@ # pom. As it's derivable, hgignore it :) integration-tests/standalone/dependency-reduced-pom.xml +# Keyring autogenerated files +keyring/Makefile.in +keyring/Makefile +keyring/aclocal.m4 +keyring/autom4* +keyring/compile +keyring/config.log +keyring/config.status +keyring/configure +keyring/install-sh +keyring/missing +keyring/src/main/native/Makefile +keyring/src/main/native/Makefile.in + syntax: glob target/* bin/* diff -r 96c0923a42e3 -r 2ae8438ee9d2 README --- a/README Thu Oct 01 14:24:31 2015 +0200 +++ b/README Mon Oct 05 11:58:01 2015 -0400 @@ -43,7 +43,7 @@ correctly with just a JRE. * Maven (it will download all the java dependencies for you) -* Make + GCC +* Make, GCC + autoconf * MongoDB server Thermostat requires mongodb (http://www.mongodb.org/) server >= 2.0.0. @@ -53,7 +53,8 @@ yum install mongodb-server * Either a /etc/os-release file or lsb_release -* Gnome Keyring Daemon development libraries plus pkg-configs +* Gnome Keyring Daemon development libraries plus pkg-configs. Either libsecret + based or a libgnome-keyring based solution is supported. * GTK 2+ development libraries plus pkg-configs Gnome Keyring/GTK2+ development libraries are required at build time. @@ -61,6 +62,10 @@ You should check your distribution for the exact name of the libraries, on Fedora based distributions you can obtain it via: + dnf install libsecret-devel gtk2-devel + + or + yum install libgnome-keyring-devel gtk2-devel on RHEL/CentOS 6.x via: diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/Makefile --- a/keyring/Makefile Thu Oct 01 14:24:31 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -CC = gcc -JAVAH = javah -MYCFLAGS = -c -Wall -fPIC -MYLDFLAGS = -fPIC -shared -COPY = cp -a - -CLASSPATH = target/classes/ -TARGET_DIR = target - -INCLUDE = -I $(TARGET_DIR) -I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux -SOURCES = src/main/native/GnomeKeyringLibraryNative.c -TARGET = $(TARGET_DIR)/GnomeKeyringLibraryNative.c -OBJECTS = $(TARGET:.c=.o) - -EXECUTABLE = libGnomeKeyringWrapper.so - -MYCFLAGS += `pkg-config --cflags gnome-keyring-1` -MYLDFLAGS += `pkg-config --libs gnome-keyring-1` - -.PHONY: -JNI_LIST = com.redhat.thermostat.utils.keyring.impl.KeyringImpl - -$(JNI_LIST): - $(JAVAH) -force -classpath $(CLASSPATH) -d $(TARGET_DIR) $(JNI_LIST) - -all: $(JNI_LIST) init $(SOURCES) $(EXECUTABLE) - -.PHONY: -init: - $(COPY) $(SOURCES) $(TARGET) - -$(EXECUTABLE): $(OBJECTS) - $(CC) $(OBJECTS) -o $(TARGET_DIR)/$@ $(MYLDFLAGS) $(LDFLAGS) - -.c.o: - $(CC) $(MYCFLAGS) $(CFLAGS) $(INCLUDE) $< -o $@ - -clean-lib: - rm $(TARGET_DIR)/$(EXECUTABLE) - -clean-obj: - rm $(OBJECTS) $(TARGET) - -clean: clean-obj clean-lib - diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/Makefile.am Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,2 @@ +SUBDIRS = src/main/native +dist_doc_DATA = README diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/README Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,14 @@ +Thermostat Keyring service's JNI library. + +- A libsecret based implementation is preferred over +- A libgnome-keyring based implementation + +If libsecret is not available a libgnome-keyring based implementation will be +built. If both libgnome-keyring and libsecret are available, the libsecret +based implementation will take precedence. + +Please ensure you have the preferred library's devel packages installed. + +$ autoreconf --install +$ ./configure +$ make diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/configure.ac --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/configure.ac Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,13 @@ +AC_INIT([thermostat-keyring-native], [1.0], [thermostat@icedtea.classpath.org]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_PROG_CC +PKG_CHECK_MODULES(LIBSECRET, [libsecret-1], + [AC_SUBST([JNI_SOURCE_DIR], [libsecret])], + [PKG_CHECK_MODULES([LIBGNOME_KEYRING], [gnome-keyring-1], + [AC_SUBST([JNI_SOURCE_DIR], [libgnome-keyring])]) +]) +AC_CONFIG_FILES([ + Makefile + src/main/native/Makefile +]) +AC_OUTPUT diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/pom.xml --- a/keyring/pom.xml Thu Oct 01 14:24:31 2015 +0200 +++ b/keyring/pom.xml Mon Oct 05 11:58:01 2015 -0400 @@ -87,24 +87,48 @@ 1.2.1 + id1 + compile + + exec + + + autoreconf + + --install + + + + + id2 compile exec + + ./configure + + + + id3 + compile + + exec + + + make + + all + + + + JAVA_HOME + ${java.home} + + + - - make - - all - - - - JAVA_HOME - ${java.home} - - - diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/GnomeKeyringLibraryNative.c --- a/keyring/src/main/native/GnomeKeyringLibraryNative.c Thu Oct 01 14:24:31 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -#include "com_redhat_thermostat_utils_keyring_impl_KeyringImpl.h" - -#include -#include -#include -#include -#include - -GnomeKeyringPasswordSchema thermostat_schema = { - GNOME_KEYRING_ITEM_GENERIC_SECRET, - { - { "username", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, - { "url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, - { NULL, 0 } - } -}; - -static void init(void) { - if (g_get_application_name() == NULL) { - g_set_application_name("Thermostat"); - } -} - -JNIEXPORT jboolean JNICALL -Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperSavePasswordNative - (JNIEnv *env, jclass GnomeKeyringLibraryNativeClass, jstring jurl, jstring juserName, jbyteArray jpassword, jstring jdescription) -{ - int passIndex; - const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); - if (url == NULL) { - return JNI_FALSE; - } - const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); - if (userName == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - return JNI_FALSE; - } - - jsize passwordLength = (*env)->GetArrayLength(env, jpassword); - jbyte *password = (*env)->GetByteArrayElements(env, jpassword, NULL); - if (password == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - return JNI_FALSE; - } - - /* Make into null terminated (g)char * to make gnome api happy */ - gchar *gpassword = malloc(sizeof(gchar) * (passwordLength + 1)); - if (gpassword == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { - password[passIndex] = '\0'; - } - (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); - return JNI_FALSE; - } - for (passIndex = 0; passIndex < passwordLength; passIndex++) { - gpassword[passIndex] = (gchar) (password[passIndex]); - } - gpassword[passwordLength] = (gchar) '\0'; - - /* Overwrite original array, release back to java-land. */ - for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { - password[passIndex] = '\0'; - } - (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); - - const char *description = (*env)->GetStringUTFChars(env, jdescription, NULL); - if (description == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { - gpassword[passIndex] = (gchar) '\0'; - } - free(gpassword); - return JNI_FALSE; - } - - init(); - GnomeKeyringResult res = gnome_keyring_store_password_sync(&thermostat_schema, - GNOME_KEYRING_DEFAULT, - description, - gpassword, - "username", userName, - "url", url, - NULL); - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { - gpassword[passIndex] = '\0'; - } - free(gpassword); - (*env)->ReleaseStringUTFChars(env, jdescription, description); - - return (res == GNOME_KEYRING_RESULT_OK) ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT jbyteArray JNICALL -Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperGetPasswordNative - (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) -{ - const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); - if (url == NULL) { - - return NULL; - } - - const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); - if (userName == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - return NULL; - } - - gchar *password = NULL; - GnomeKeyringResult res; - - init(); - res = gnome_keyring_find_password_sync(&thermostat_schema, - &password, - "username", userName, - "url", url, - NULL); - - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - - if (res == GNOME_KEYRING_RESULT_OK) { - const jbyte *jbytePassword = (const jbyte *) password; - - jsize passwordLength = strlen(password); - jbyteArray jpassword = (*env)->NewByteArray(env, passwordLength); - (*env)->SetByteArrayRegion(env, jpassword, 0, passwordLength, jbytePassword); - gnome_keyring_free_password(password); - return jpassword; - } else { - return NULL; - } -} - -JNIEXPORT jboolean JNICALL -Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperClearPasswordNative - (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) -{ - const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); - if (url == NULL) { - return JNI_FALSE; - } - const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); - if (userName == NULL) { - (*env)->ReleaseStringUTFChars(env, jurl, url); - return JNI_FALSE; - } - - init(); - GnomeKeyringResult res = gnome_keyring_delete_password_sync(&thermostat_schema, - "username", userName, - "url", url, - NULL); - - (*env)->ReleaseStringUTFChars(env, jurl, url); - (*env)->ReleaseStringUTFChars(env, juserName, userName); - - return (res == GNOME_KEYRING_RESULT_OK) ? JNI_TRUE : JNI_FALSE; -} - diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/src/main/native/Makefile.am Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,1 @@ +SUBDIRS = @JNI_SOURCE_DIR@ diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/libgnome-keyring/GnomeKeyringLibraryNative.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/src/main/native/libgnome-keyring/GnomeKeyringLibraryNative.c Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,202 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +#include "com_redhat_thermostat_utils_keyring_impl_KeyringImpl.h" + +#include +#include +#include +#include +#include + +GnomeKeyringPasswordSchema thermostat_schema = { + GNOME_KEYRING_ITEM_GENERIC_SECRET, + { + { "username", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { "url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, 0 } + } +}; + +static void init(void) { + if (g_get_application_name() == NULL) { + g_set_application_name("Thermostat"); + } +} + +JNIEXPORT jboolean JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperSavePasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNativeClass, jstring jurl, jstring juserName, jbyteArray jpassword, jstring jdescription) +{ + int passIndex; + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + return JNI_FALSE; + } + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return JNI_FALSE; + } + + jsize passwordLength = (*env)->GetArrayLength(env, jpassword); + jbyte *password = (*env)->GetByteArrayElements(env, jpassword, NULL); + if (password == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + return JNI_FALSE; + } + + /* Make into null terminated (g)char * to make gnome api happy */ + gchar *gpassword = malloc(sizeof(gchar) * (passwordLength + 1)); + if (gpassword == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + password[passIndex] = '\0'; + } + (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); + return JNI_FALSE; + } + for (passIndex = 0; passIndex < passwordLength; passIndex++) { + gpassword[passIndex] = (gchar) (password[passIndex]); + } + gpassword[passwordLength] = (gchar) '\0'; + + /* Overwrite original array, release back to java-land. */ + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + password[passIndex] = '\0'; + } + (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); + + const char *description = (*env)->GetStringUTFChars(env, jdescription, NULL); + if (description == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + gpassword[passIndex] = (gchar) '\0'; + } + free(gpassword); + return JNI_FALSE; + } + + init(); + GnomeKeyringResult res = gnome_keyring_store_password_sync(&thermostat_schema, + GNOME_KEYRING_DEFAULT, + description, + gpassword, + "username", userName, + "url", url, + NULL); + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + gpassword[passIndex] = '\0'; + } + free(gpassword); + (*env)->ReleaseStringUTFChars(env, jdescription, description); + + return (res == GNOME_KEYRING_RESULT_OK) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperGetPasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) +{ + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + + return NULL; + } + + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return NULL; + } + + gchar *password = NULL; + GnomeKeyringResult res; + + init(); + res = gnome_keyring_find_password_sync(&thermostat_schema, + &password, + "username", userName, + "url", url, + NULL); + + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + + if (res == GNOME_KEYRING_RESULT_OK) { + const jbyte *jbytePassword = (const jbyte *) password; + + jsize passwordLength = strlen(password); + jbyteArray jpassword = (*env)->NewByteArray(env, passwordLength); + (*env)->SetByteArrayRegion(env, jpassword, 0, passwordLength, jbytePassword); + gnome_keyring_free_password(password); + return jpassword; + } else { + return NULL; + } +} + +JNIEXPORT jboolean JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperClearPasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) +{ + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + return JNI_FALSE; + } + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return JNI_FALSE; + } + + init(); + GnomeKeyringResult res = gnome_keyring_delete_password_sync(&thermostat_schema, + "username", userName, + "url", url, + NULL); + + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + + return (res == GNOME_KEYRING_RESULT_OK) ? JNI_TRUE : JNI_FALSE; +} + diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/libgnome-keyring/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/src/main/native/libgnome-keyring/Makefile Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,45 @@ +CC = gcc +JAVAH = javah +MYCFLAGS = -c -Wall -fPIC +MYLDFLAGS = -fPIC -shared +COPY = cp -a + +CLASSPATH = ../../../../target/classes/ +TARGET_DIR = ../../../../target + +INCLUDE = -I $(TARGET_DIR) -I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux +SOURCES = GnomeKeyringLibraryNative.c +TARGET = $(TARGET_DIR)/GnomeKeyringLibraryNative.c +OBJECTS = $(TARGET:.c=.o) + +EXECUTABLE = libGnomeKeyringWrapper.so + +MYCFLAGS += `pkg-config --cflags gnome-keyring-1` +MYLDFLAGS += `pkg-config --libs gnome-keyring-1` + +.PHONY: +JNI_LIST = com.redhat.thermostat.utils.keyring.impl.KeyringImpl + +$(JNI_LIST): + $(JAVAH) -force -classpath $(CLASSPATH) -d $(TARGET_DIR) $(JNI_LIST) + +all: $(JNI_LIST) init $(SOURCES) $(EXECUTABLE) + +.PHONY: +init: + $(COPY) $(SOURCES) $(TARGET) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(OBJECTS) -o $(TARGET_DIR)/$@ $(MYLDFLAGS) $(LDFLAGS) + +.c.o: + $(CC) $(MYCFLAGS) $(CFLAGS) $(INCLUDE) $< -o $@ + +clean-lib: + rm -f $(TARGET_DIR)/$(EXECUTABLE) + +clean-obj: + rm -f $(OBJECTS) $(TARGET) + +clean: clean-obj clean-lib + diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/libsecret/LibsecretKeyringLibraryNative.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/src/main/native/libsecret/LibsecretKeyringLibraryNative.c Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,223 @@ +/* + * Copyright 2012-2015 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +#include "com_redhat_thermostat_utils_keyring_impl_KeyringImpl.h" + +#include +#include +#include +#include +#include + +SecretSchema thermostat_schema = { + "com.redhat.thermostat.password", SECRET_SCHEMA_NONE, + { + { "username", SECRET_SCHEMA_ATTRIBUTE_STRING }, + { "url", SECRET_SCHEMA_ATTRIBUTE_STRING }, + { "NULL", 0 } + } + }; + +static void init(void) { + if (g_get_application_name() == NULL) { + g_set_application_name("Thermostat"); + } +} + +JNIEXPORT jboolean JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperSavePasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNativeClass, jstring jurl, jstring juserName, jbyteArray jpassword, jstring jdescription) +{ + int passIndex; + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + return JNI_FALSE; + } + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return JNI_FALSE; + } + + jsize passwordLength = (*env)->GetArrayLength(env, jpassword); + jbyte *password = (*env)->GetByteArrayElements(env, jpassword, NULL); + if (password == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + return JNI_FALSE; + } + + /* Make into null terminated (g)char * to make gnome api happy */ + gchar *gpassword = malloc(sizeof(gchar) * (passwordLength + 1)); + if (gpassword == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + password[passIndex] = '\0'; + } + (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); + return JNI_FALSE; + } + for (passIndex = 0; passIndex < passwordLength; passIndex++) { + gpassword[passIndex] = (gchar) (password[passIndex]); + } + gpassword[passwordLength] = (gchar) '\0'; + + /* Overwrite original array, release back to java-land. */ + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + password[passIndex] = '\0'; + } + (*env)->ReleaseByteArrayElements(env, jpassword, password, JNI_ABORT); + + const char *description = (*env)->GetStringUTFChars(env, jdescription, NULL); + if (description == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + gpassword[passIndex] = (gchar) '\0'; + } + free(gpassword); + return JNI_FALSE; + } + + init(); + GError *error = NULL; + jboolean is_success = JNI_TRUE; + secret_password_store_sync(&thermostat_schema, + SECRET_COLLECTION_DEFAULT, + description, + gpassword, + NULL, + &error, + "username", userName, + "url", url, + NULL); + if (error != NULL) { + is_success = JNI_FALSE; + g_error_free (error); + } + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + for (passIndex = 0; passIndex < (int) passwordLength; passIndex++) { + gpassword[passIndex] = '\0'; + } + free(gpassword); + (*env)->ReleaseStringUTFChars(env, jdescription, description); + + return is_success; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperGetPasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) +{ + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + return NULL; + } + + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return NULL; + } + + gchar *password = NULL; + GError *error = NULL; + + init(); + password = secret_password_lookup_sync(&thermostat_schema, + NULL, + &error, + "username", userName, + "url", url, + NULL); + + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + + if (error == NULL) { + // Password may be null if not found in secret store + if (password == NULL) { + return NULL; + } + const jbyte *jbytePassword = (const jbyte *) password; + + jsize passwordLength = strlen(password); + jbyteArray jpassword = (*env)->NewByteArray(env, passwordLength); + (*env)->SetByteArrayRegion(env, jpassword, 0, passwordLength, jbytePassword); + secret_password_free(password); + return jpassword; + } else { + g_error_free(error); + return NULL; + } +} + +JNIEXPORT jboolean JNICALL +Java_com_redhat_thermostat_utils_keyring_impl_KeyringImpl_gnomeKeyringWrapperClearPasswordNative + (JNIEnv *env, jclass GnomeKeyringLibraryNative, jstring jurl, jstring juserName) +{ + const char *url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (url == NULL) { + return JNI_FALSE; + } + const char *userName = (*env)->GetStringUTFChars(env, juserName, NULL); + if (userName == NULL) { + (*env)->ReleaseStringUTFChars(env, jurl, url); + return JNI_FALSE; + } + + init(); + GError *error = NULL; + jboolean is_success = JNI_TRUE; + secret_password_clear_sync(&thermostat_schema, + NULL, + &error, + "username", userName, + "url", url, + NULL); + + if (error != NULL) { + is_success = JNI_FALSE; + g_error_free (error); + } + (*env)->ReleaseStringUTFChars(env, jurl, url); + (*env)->ReleaseStringUTFChars(env, juserName, userName); + + return is_success; +} + diff -r 96c0923a42e3 -r 2ae8438ee9d2 keyring/src/main/native/libsecret/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring/src/main/native/libsecret/Makefile Mon Oct 05 11:58:01 2015 -0400 @@ -0,0 +1,45 @@ +CC = gcc +JAVAH = javah +MYCFLAGS = -c -Wall -fPIC +MYLDFLAGS = -fPIC -shared +COPY = cp -a + +CLASSPATH = ../../../../target/classes/ +TARGET_DIR = ../../../../target + +INCLUDE = -I $(TARGET_DIR) -I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux +SOURCES = LibsecretKeyringLibraryNative.c +TARGET = $(TARGET_DIR)/LibsecretKeyringLibraryNative.c +OBJECTS = $(TARGET:.c=.o) + +EXECUTABLE = libGnomeKeyringWrapper.so + +MYCFLAGS += `pkg-config --cflags libsecret-1` +MYLDFLAGS += `pkg-config --libs libsecret-1` + +.PHONY: +JNI_LIST = com.redhat.thermostat.utils.keyring.impl.KeyringImpl + +$(JNI_LIST): + $(JAVAH) -force -classpath $(CLASSPATH) -d $(TARGET_DIR) $(JNI_LIST) + +all: $(JNI_LIST) init $(SOURCES) $(EXECUTABLE) + +.PHONY: +init: + $(COPY) $(SOURCES) $(TARGET) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(OBJECTS) -o $(TARGET_DIR)/$@ $(MYLDFLAGS) $(LDFLAGS) + +.c.o: + $(CC) $(MYCFLAGS) $(CFLAGS) $(INCLUDE) $< -o $@ + +clean-lib: + rm -f $(TARGET_DIR)/$(EXECUTABLE) + +clean-obj: + rm -f $(OBJECTS) $(TARGET) + +clean: clean-obj clean-lib +