gnome-keyring r1185 - in trunk: . gp11 gp11/tests
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1185 - in trunk: . gp11 gp11/tests
- Date: Sun, 20 Jul 2008 02:56:07 +0000 (UTC)
Author: nnielsen
Date: Sun Jul 20 02:56:06 2008
New Revision: 1185
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1185&view=rev
Log:
* gp11/gp11.h:
* gp11/gp11-call.c:
* gp11/gp11-marshal.list:
* gp11/gp11-private.h:
* gp11/gp11-session.c:
* gp11/gp11-slot.c:
* gp11/Makefile.am:
* gp11/tests/gp11-test-module.c:
* gp11/tests/unit-test-gp11-session.c: Auto login of sessions when
and where necessary.
Added:
trunk/gp11/gp11-marshal.list
Modified:
trunk/ChangeLog
trunk/gp11/Makefile.am
trunk/gp11/gp11-call.c
trunk/gp11/gp11-private.h
trunk/gp11/gp11-session.c
trunk/gp11/gp11-slot.c
trunk/gp11/gp11.h
trunk/gp11/tests/gp11-test-module.c
trunk/gp11/tests/unit-test-gp11-session.c
Modified: trunk/gp11/Makefile.am
==============================================================================
--- trunk/gp11/Makefile.am (original)
+++ trunk/gp11/Makefile.am Sun Jul 20 02:56:06 2008
@@ -11,6 +11,9 @@
$(GTHREAD_CFLAGS) \
$(GLIB_CFLAGS)
+BUILT_SOURCES = \
+ gp11-marshal.c gp11-marshal.h
+
lib_LTLIBRARIES = libgp11.la
libgp11_la_SOURCES = \
@@ -21,7 +24,8 @@
gp11-module.c \
gp11-object.c \
gp11-session.c \
- gp11-slot.c
+ gp11-slot.c \
+ $(BUILT_SOURCES)
libgp11_la_LDFLAGS = \
-version-info $(GP11_LT_RELEASE) \
@@ -33,6 +37,13 @@
$(GIO_LIBS) \
$(GLIB_LIBS)
+gp11-marshal.h: gp11-marshal.list $(GLIB_GENMARSHAL)
+ $(GLIB_GENMARSHAL) $< --header --prefix=_gp11_marshal > $@
+
+gp11-marshal.c: gp11-marshal.list $(GLIB_GENMARSHAL)
+ echo "#include \"gp11-marshal.h\"" > $@ && \
+ $(GLIB_GENMARSHAL) $< --body --prefix=_gp11_marshal >> $@
+
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gp11-$(GP11_MAJOR).pc
Modified: trunk/gp11/gp11-call.c
==============================================================================
--- trunk/gp11/gp11-call.c (original)
+++ trunk/gp11/gp11-call.c Sun Jul 20 02:56:06 2008
@@ -1,6 +1,7 @@
#include "gp11-private.h"
+#include <string.h>
static GThreadPool *thread_pool = NULL;
static GAsyncQueue *completed_queue = NULL;
@@ -48,12 +49,27 @@
process_async_call (gpointer data, gpointer unused)
{
GP11Call *call = GP11_CALL (data);
+ CK_ULONG pin_len;
+
g_assert (GP11_IS_CALL (call));
-
- g_assert (call->rv == CKR_OK);
- call->rv = perform_call (call->func, call->cancellable,
- call->args);
+ /* Try to login to the token, with the provided password */
+ if (call->do_login) {
+ call->do_login = FALSE;
+
+ pin_len = call->password ? strlen (call->password) : 0;
+ call->rv = (call->args->pkcs11->C_Login) (call->args->handle, CKU_USER,
+ (CK_UTF8CHAR_PTR)call->password,
+ pin_len);
+
+ /* Fix the result so that we'll try the login again */
+ if (call->rv == CKR_PIN_INCORRECT)
+ call->rv = CKR_USER_NOT_LOGGED_IN;
+
+ /* An actual call */
+ } else {
+ call->rv = perform_call (call->func, call->cancellable, call->args);
+ }
g_async_queue_push (completed_queue, call);
@@ -69,9 +85,28 @@
if (call->cancellable) {
/* Don't call the callback when cancelled */
if (g_cancellable_is_cancelled (call->cancellable))
- return;
+ call->rv = CKR_FUNCTION_CANCELED;
+ }
+
+ /*
+ * Now if this is a session call, and the slot wants does
+ * auto-login, then we try to get a password and do auto login.
+ */
+ if (call->rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (call->object)) {
+ g_free (call->password);
+ call->password = NULL;
+ call->do_login = _gp11_slot_token_authentication (GP11_SESSION (call->object)->slot,
+ &call->password);
+ }
+
+ /* If we're supposed to do a login, then queue this call again */
+ if (call->do_login) {
+ g_object_ref (call);
+ g_thread_pool_push (thread_pool, call, NULL);
+ return;
}
+ /* All done, finish processing */
if (call->callback) {
g_assert (G_IS_OBJECT (call->object));
(call->callback) (G_OBJECT (call->object), G_ASYNC_RESULT (call),
@@ -154,6 +189,10 @@
call->destroy = NULL;
call->args = NULL;
+ if (call->password)
+ g_free (call->password);
+ call->password = NULL;
+
G_OBJECT_CLASS (_gp11_call_parent_class)->finalize (obj);
}
@@ -247,7 +286,9 @@
GCancellable *cancellable, GError **err)
{
GP11Arguments *args = (GP11Arguments*)data;
- GP11Module *module;
+ gchar *password = NULL;
+ GP11Module *module = NULL;
+ CK_ULONG pin_len;
CK_RV rv;
g_assert (G_IS_OBJECT (object));
@@ -261,9 +302,32 @@
g_object_unref (module);
rv = perform_call ((GP11CallFunc)func, cancellable, args);
+
+ /*
+ * Now if this is a session call, and the slot wants does
+ * auto-login, then we try to get a password and do auto login.
+ */
+ if (rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (object)) {
+
+ do {
+ if (!_gp11_slot_token_authentication (GP11_SESSION (object)->slot,
+ &password)) {
+ rv = CKR_USER_NOT_LOGGED_IN;
+ } else {
+ pin_len = password ? strlen (password) : 0;
+ rv = (args->pkcs11->C_Login) (args->handle, CKU_USER,
+ (CK_UTF8CHAR_PTR)password, pin_len);
+ }
+ } while (rv == CKR_PIN_INCORRECT);
+
+ /* If we logged in successfully then try again */
+ if (rv == CKR_OK)
+ rv = perform_call ((GP11CallFunc)func, cancellable, args);
+ }
+
if (rv == CKR_OK)
return TRUE;
-
+
g_set_error (err, GP11_ERROR, rv, gp11_message_from_rv (rv));
return FALSE;
}
Added: trunk/gp11/gp11-marshal.list
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-marshal.list Sun Jul 20 02:56:06 2008
@@ -0,0 +1,2 @@
+BOOLEAN:POINTER
+BOOLEAN:OBJECT,POINTER
Modified: trunk/gp11/gp11-private.h
==============================================================================
--- trunk/gp11/gp11-private.h (original)
+++ trunk/gp11/gp11-private.h Sun Jul 20 02:56:06 2008
@@ -26,6 +26,13 @@
CK_ATTRIBUTE_PTR _gp11_attributes_raw (GP11Attributes *attrs);
/* ----------------------------------------------------------------------------
+ * SLOT
+ */
+
+gboolean _gp11_slot_token_authentication (GP11Slot *slot,
+ gchar **password);
+
+/* ----------------------------------------------------------------------------
* CALL
*/
@@ -42,7 +49,7 @@
} GP11Arguments;
-#define GP11_ARGUMENTS_INIT { NULL, NULL, 0 }
+#define GP11_ARGUMENTS_INIT { NULL, NULL, 0 }
#define GP11_TYPE_CALL (_gp11_call_get_type())
#define GP11_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_CALL, GP11Call))
@@ -67,6 +74,10 @@
gpointer object;
GAsyncReadyCallback callback;
gpointer user_data;
+
+ /* For authenticating */
+ gboolean do_login;
+ gchar *password;
};
struct _GP11CallClass {
Modified: trunk/gp11/gp11-session.c
==============================================================================
--- trunk/gp11/gp11-session.c (original)
+++ trunk/gp11/gp11-session.c Sun Jul 20 02:56:06 2008
@@ -14,7 +14,8 @@
enum {
PROP_0,
PROP_MODULE,
- PROP_HANDLE
+ PROP_HANDLE,
+ PROP_SLOT
};
G_DEFINE_TYPE (GP11Session, gp11_session, G_TYPE_OBJECT);
@@ -44,6 +45,9 @@
case PROP_HANDLE:
g_value_set_uint (value, session->handle);
break;
+ case PROP_SLOT:
+ g_value_set_object(value, session->slot);
+ break;
}
}
@@ -63,6 +67,11 @@
g_return_if_fail (!session->handle);
session->handle = g_value_get_uint (value);
break;
+ case PROP_SLOT:
+ g_return_if_fail (!session->slot);
+ session->slot = g_value_dup_object (value);
+ g_return_if_fail (session->slot);
+ break;
}
}
@@ -91,10 +100,14 @@
session->handle = 0;
}
+ if (session->slot)
+ g_object_unref (session->slot);
+ session->slot = NULL;
+
if (session->module)
g_object_unref (session->module);
session->module = NULL;
-
+
G_OBJECT_CLASS (gp11_session_parent_class)->dispose (obj);
}
@@ -128,6 +141,10 @@
g_object_class_install_property (gobject_class, PROP_HANDLE,
g_param_spec_uint ("handle", "Session Handle", "PKCS11 Session Handle",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_SLOT,
+ g_param_spec_object ("slot", "Slot that this session uses", "PKCS11 Slot",
+ GP11_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
signals[DISCARD_HANDLE] = g_signal_new ("discard-handle", GP11_TYPE_SESSION,
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GP11SessionClass, discard_handle),
@@ -151,7 +168,8 @@
gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle)
{
g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
- return g_object_new (GP11_TYPE_SESSION, "module", slot->module, "handle", handle, NULL);
+ return g_object_new (GP11_TYPE_SESSION, "module", slot->module,
+ "handle", handle, "slot", slot, NULL);
}
GP11SessionInfo*
Modified: trunk/gp11/gp11-slot.c
==============================================================================
--- trunk/gp11/gp11-slot.c (original)
+++ trunk/gp11/gp11-slot.c Sun Jul 20 02:56:06 2008
@@ -3,6 +3,7 @@
#include "gp11.h"
#include "gp11-private.h"
+#include "gp11-marshal.h"
#include <string.h>
@@ -10,12 +11,23 @@
PROP_0,
PROP_MODULE,
PROP_HANDLE,
- PROP_REUSE_SESSIONS
+ PROP_REUSE_SESSIONS,
+ PROP_AUTO_LOGIN
+};
+
+enum {
+ AUTHENTICATE_TOKEN,
+#ifdef UNIMPLEMENTED
+ AUTHENTICATE_KEY,
+ SLOT_EVENT
+#endif
+ LAST_SIGNAL
};
typedef struct _GP11SlotPrivate {
- gboolean reuse_sessions;
+ gboolean auto_login;
GHashTable *open_sessions;
+ GP11TokenInfo *token_info;
} GP11SlotPrivate;
G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT);
@@ -29,6 +41,8 @@
GSList *sessions; /* list of CK_SESSION_HANDLE */
} SessionPool;
+static guint signals[LAST_SIGNAL] = { 0 };
+
/* ----------------------------------------------------------------------------
* HELPERS
*/
@@ -206,6 +220,14 @@
return session;
}
+static void
+ensure_token_info (GP11Slot *slot)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ if (!pv->token_info)
+ pv->token_info = gp11_slot_get_token_info (slot);
+}
+
/* ----------------------------------------------------------------------------
* OBJECT
*/
@@ -230,6 +252,9 @@
case PROP_HANDLE:
g_value_set_uint (value, slot->handle);
break;
+ case PROP_AUTO_LOGIN:
+ g_value_set_boolean (value, pv->auto_login);
+ break;
case PROP_REUSE_SESSIONS:
g_value_set_boolean (value, pv->open_sessions != NULL);
break;
@@ -240,6 +265,7 @@
gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value,
GParamSpec *pspec)
{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (obj);
GP11Slot *slot = GP11_SLOT (obj);
switch (prop_id) {
@@ -253,6 +279,9 @@
g_return_if_fail (!slot->handle);
slot->handle = g_value_get_uint (value);
break;
+ case PROP_AUTO_LOGIN:
+ pv->auto_login = g_value_get_boolean (value);
+ break;
case PROP_REUSE_SESSIONS:
if (g_value_get_boolean (value))
create_session_table (slot);
@@ -308,14 +337,54 @@
g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class, PROP_AUTO_LOGIN,
+ g_param_spec_boolean ("auto-login", "Auto Login", "Auto Login to Token when necessary",
+ FALSE, G_PARAM_READWRITE));
+
g_object_class_install_property (gobject_class, PROP_REUSE_SESSIONS,
g_param_spec_boolean ("reuse-sessions", "Reuse Sessions", "Reuse sessions?",
FALSE, G_PARAM_READWRITE));
+ signals[AUTHENTICATE_TOKEN] = g_signal_new ("authenticate-token", GP11_TYPE_SLOT,
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GP11SlotClass, authenticate_token),
+ g_signal_accumulator_true_handled, NULL, _gp11_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+
g_type_class_add_private (gobject_class, sizeof (GP11SlotPrivate));
}
/* ----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+gboolean
+_gp11_slot_token_authentication (GP11Slot *slot, gchar **password)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), FALSE);
+ g_return_val_if_fail (password, FALSE);
+
+ if (!pv->auto_login)
+ return FALSE;
+
+ /*
+ * If it's a protected authentication path style token, then
+ * we don't prompt here, the hardware/software is expected
+ * to prompt the user in some other way.
+ */
+ ensure_token_info (slot);
+ if (pv->token_info && (pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
+ *password = NULL;
+ return TRUE;
+ }
+
+ g_signal_emit (slot, signals[AUTHENTICATE_TOKEN], 0, password, &ret);
+ return ret;
+}
+
+/* ----------------------------------------------------------------------------
* PUBLIC
*/
@@ -363,6 +432,20 @@
g_object_set (slot, "reuse-sessions", reuse, NULL);
}
+gboolean
+gp11_slot_get_auto_login (GP11Slot *slot)
+{
+ gboolean auto_login = FALSE;
+ g_object_get (slot, "auto-login", &auto_login, NULL);
+ return auto_login;
+}
+
+void
+gp11_slot_set_auto_login (GP11Slot *slot, gboolean auto_login)
+{
+ g_object_set (slot, "auto-login", auto_login, NULL);
+}
+
GP11SlotInfo*
gp11_slot_get_info (GP11Slot *slot)
{
Modified: trunk/gp11/gp11.h
==============================================================================
--- trunk/gp11/gp11.h (original)
+++ trunk/gp11/gp11.h Sun Jul 20 02:56:06 2008
@@ -296,8 +296,16 @@
struct _GP11SlotClass {
GObjectClass parent;
+
+ gboolean (*authenticate_token) (GP11Slot *slot, gchar **password);
+#ifdef UNIMPLEMENTED
+ gboolean (*authenticate_key) (GP11Slot *slot, GP11Object *object,
+ gchar **password);
+
void (*slot_event) (GP11Slot *slot);
+#endif
+
};
GType gp11_slot_get_type (void) G_GNUC_CONST;
@@ -307,6 +315,13 @@
void gp11_slot_set_reuse_sessions (GP11Slot *slot,
gboolean reuse);
+gboolean gp11_slot_get_auto_login (GP11Slot *slot);
+
+void gp11_slot_set_auto_login (GP11Slot *slot,
+ gboolean auto_login);
+
+gint gp11_slot_get_max_pin_length (GP11Slot *slot);
+
GP11SlotInfo* gp11_slot_get_info (GP11Slot *slot);
GP11TokenInfo* gp11_slot_get_token_info (GP11Slot *slot);
@@ -382,6 +397,7 @@
struct _GP11Session {
GObject parent;
+ GP11Slot *slot;
GP11Module *module;
CK_SESSION_HANDLE handle;
};
Modified: trunk/gp11/tests/gp11-test-module.c
==============================================================================
--- trunk/gp11/tests/gp11-test-module.c (original)
+++ trunk/gp11/tests/gp11-test-module.c Sun Jul 20 02:56:06 2008
@@ -104,8 +104,6 @@
static CK_RV
test_C_Finalize (CK_VOID_PTR pReserved)
{
-
-
g_assert (pReserved == NULL && "Invalid reserved pointer");
g_assert (initialized == TRUE && "Finalize without being initialized");
@@ -199,8 +197,6 @@
static CK_RV
test_C_GetSlotInfo (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
-
-
g_assert (pInfo != NULL && "Invalid pInfo");
if (slotID == TEST_SLOT_ONE) {
@@ -220,7 +216,7 @@
"TEST MANUFACTURER ",
"TEST MODEL ",
"TEST SERIAL ",
- CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_TOKEN_INITIALIZED,
+ CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_TOKEN_INITIALIZED,
1,
2,
3,
@@ -239,8 +235,6 @@
static CK_RV
test_C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
{
-
-
g_assert (pInfo != NULL && "Invalid pInfo");
if (slotID == TEST_SLOT_ONE) {
@@ -297,8 +291,6 @@
test_C_GetMechanismInfo (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo)
{
-
-
g_assert (slotID == TEST_SLOT_ONE && "Invalid slotID");
g_assert (pInfo != NULL && "Invalid pInfo");
@@ -507,7 +499,7 @@
{
GP11Attributes *attrs;
Session *session;
- gboolean token;
+ gboolean token, priv;
CK_ULONG i;
g_assert (phObject != NULL);
@@ -516,11 +508,18 @@
g_assert (session != NULL && "No such session found");
if (!session)
return CKR_SESSION_HANDLE_INVALID;
-
+
attrs = gp11_attributes_new ();
for (i = 0; i < ulCount; ++i)
gp11_attributes_add_data (attrs, pTemplate[i].type, pTemplate[i].pValue, pTemplate[i].ulValueLen);
+ if (gp11_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
+ if (!session->logged_in) {
+ gp11_attributes_unref (attrs);
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+ }
+
*phObject = ++unique_identifier;
if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phObject), attrs);
@@ -543,19 +542,28 @@
static CK_RV
test_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
{
+ GP11Attributes *attrs;
Session *session;
+ gboolean priv;
session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
g_assert (session != NULL && "No such session found");
if (!session)
return CKR_SESSION_HANDLE_INVALID;
- if (!g_hash_table_remove (the_objects, GUINT_TO_POINTER (hObject)) &&
- !g_hash_table_remove (session->objects, GUINT_TO_POINTER (hObject))) {
+ attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
+ if (!attrs)
+ attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
+ if (!attrs) {
g_assert_not_reached (); /* "no such object found" */
return CKR_OBJECT_HANDLE_INVALID;
}
-
+
+ if (gp11_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
+ if (!session->logged_in)
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
return CKR_OK;
}
Modified: trunk/gp11/tests/unit-test-gp11-session.c
==============================================================================
--- trunk/gp11/tests/unit-test-gp11-session.c (original)
+++ trunk/gp11/tests/unit-test-gp11-session.c Sun Jul 20 02:56:06 2008
@@ -194,3 +194,64 @@
result = NULL;
}
+
+static gboolean
+authenticate_token (GP11Slot *slot, gchar **password, gpointer unused)
+{
+ g_assert (unused == GUINT_TO_POINTER (35));
+ g_assert (password != NULL);
+ g_assert (*password == NULL);
+ g_assert (GP11_IS_SLOT (slot));
+
+ *password = g_strdup ("booo");
+ return TRUE;
+}
+
+DEFINE_TEST(auto_login)
+{
+ GP11Object *object;
+ GAsyncResult *result = NULL;
+ GError *err = NULL;
+ GP11Attributes *attrs;
+ gboolean ret;
+
+ attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST OBJECT",
+ CKA_PRIVATE, GP11_BOOLEAN, CK_TRUE,
+ -1);
+
+ /* Try to do something that requires a login */
+ object = gp11_session_create_object_full (session, attrs, NULL, &err);
+ g_assert (!object);
+ g_assert (err && err->code == CKR_USER_NOT_LOGGED_IN);
+ g_clear_error (&err);
+
+ /* Setup for auto login */
+ g_assert (gp11_slot_get_auto_login (slot) == FALSE);
+ gp11_slot_set_auto_login (slot, TRUE);
+ g_assert (gp11_slot_get_auto_login (slot) == TRUE);
+
+ g_signal_connect (slot, "authenticate-token", G_CALLBACK (authenticate_token), GUINT_TO_POINTER (35));
+
+ /* Try again to do something that requires a login */
+ object = gp11_session_create_object_full (session, attrs, NULL, &err);
+ SUCCESS_RES (object, err);
+ g_object_unref (object);
+
+ /* We should now be logged in, try to log out */
+ ret = gp11_session_logout (session, &err);
+ SUCCESS_RES (ret, err);
+
+ /* Now try the same thing, but asyncronously */
+ gp11_session_create_object_async (session, attrs, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ g_assert (result != NULL);
+ object = gp11_session_create_object_finish (session, result, &err);
+ SUCCESS_RES (object, err);
+ g_object_unref (result);
+ g_object_unref (object);
+
+ /* We should now be logged in, try to log out */
+ ret = gp11_session_logout (session, &err);
+ SUCCESS_RES (ret, err);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]