diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/Makefile.am | 73 | ||||
-rw-r--r-- | library/gnome-keyring-1-uninstalled.pc.in | 11 | ||||
-rw-r--r-- | library/gnome-keyring-1.pc.in | 11 | ||||
-rw-r--r-- | library/gnome-keyring-private.h | 69 | ||||
-rw-r--r-- | library/gnome-keyring-proto.c | 1704 | ||||
-rw-r--r-- | library/gnome-keyring-proto.h | 247 | ||||
-rw-r--r-- | library/gnome-keyring-utils.c | 270 | ||||
-rw-r--r-- | library/gnome-keyring.c | 2825 | ||||
-rw-r--r-- | library/gnome-keyring.h | 459 | ||||
-rw-r--r-- | library/list-keyrings.c | 225 | ||||
-rw-r--r-- | library/test.c | 502 |
11 files changed, 6396 insertions, 0 deletions
diff --git a/library/Makefile.am b/library/Makefile.am new file mode 100644 index 00000000..96eee60a --- /dev/null +++ b/library/Makefile.am @@ -0,0 +1,73 @@ +libgnomekeyringincludedir = $(includedir)/gnome-keyring-1/ + +noinst_PROGRAMS= \ + list-keyrings \ + test-keyring \ + test-keyring-two + +lib_LTLIBRARIES=libgnome-keyring.la + +noinst_LTLIBRARIES=libgnome-keyring-common.la + +INCLUDES= \ + -DPREFIX=\""$(prefix)"\" \ + -DBINDIR=\""$(bindir)"\" \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GTK_CFLAGS) \ + $(GLIB_CFLAGS) + +libgnome_keyring_common_la_SOURCES = \ + gnome-keyring-private.h \ + gnome-keyring-proto.c \ + gnome-keyring-proto.h \ + gnome-keyring-utils.c + +libgnome_keyring_common_la_LIBADD = \ + $(GLIB_LIBS) + +libgnome_keyring_la_SOURCES = \ + gnome-keyring.c \ + gnome-keyring.h + +libgnomekeyringinclude_HEADERS = \ + gnome-keyring.h + + +libgnome_keyring_la_LIBADD = \ + libgnome-keyring-common.la \ + $(GLIB_LIBS) + +libgnome_keyring_la_LDFLAGS = \ + -version-info $(LIB_GNOME_KEYRING_LT_VERSION) \ + -no-undefined + +list_keyrings_SOURCES = \ + list-keyrings.c + +list_keyrings_LDADD = \ + libgnome-keyring.la \ + $(GTK_LIBS) + +test_keyring_SOURCES = \ + test.c + +test_keyring_LDADD = \ + libgnome-keyring.la \ + $(GTK_LIBS) + +test_keyring_two_SOURCES = \ + test.c + +test_keyring_two_LDADD = \ + libgnome-keyring.la \ + $(GTK_LIBS) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gnome-keyring-1.pc + +EXTRA_DIST = \ + gnome-keyring-1-uninstalled.pc.in + diff --git a/library/gnome-keyring-1-uninstalled.pc.in b/library/gnome-keyring-1-uninstalled.pc.in new file mode 100644 index 00000000..d5293b03 --- /dev/null +++ b/library/gnome-keyring-1-uninstalled.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnome-keyring +Description: The GNOME keyring libraries +Version: @VERSION@ +Requires: glib-2.0 +Libs: ${pc_top_builddir}/${pcfiledir}/libgnome-keyring-common.la ${pc_top_builddir}/${pcfiledir}/libgnome-keyring.la +Cflags: -I${pc_top_builddir}/${pcfiledir} diff --git a/library/gnome-keyring-1.pc.in b/library/gnome-keyring-1.pc.in new file mode 100644 index 00000000..cc053bec --- /dev/null +++ b/library/gnome-keyring-1.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnome-keyring +Description: The GNOME keyring libraries +Version: @VERSION@ +Requires: glib-2.0 +Libs: -L${libdir} -lgnome-keyring +Cflags: -I${includedir}/gnome-keyring-1 diff --git a/library/gnome-keyring-private.h b/library/gnome-keyring-private.h new file mode 100644 index 00000000..f1c17a76 --- /dev/null +++ b/library/gnome-keyring-private.h @@ -0,0 +1,69 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring-private.h - private header for keyring + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ + +#ifndef GNOME_KEYRING_PRIVATE_H +#define GNOME_KEYRING_PRIVATE_H + +#include "gnome-keyring.h" + +struct GnomeKeyringApplicationRef { + char *display_name; + char *pathname; +}; + +struct GnomeKeyringAccessControl { + GnomeKeyringApplicationRef *application; /* null for all */ + GnomeKeyringAccessType types_allowed; +}; + +struct GnomeKeyringInfo { + gboolean lock_on_idle; + guint32 lock_timeout; + time_t mtime; + time_t ctime; + gboolean is_locked; +}; + +struct GnomeKeyringItemInfo { + GnomeKeyringItemType type; + char *display_name; + char *secret; + time_t mtime; + time_t ctime; +}; + +typedef enum { + GNOME_KEYRING_ASK_RESPONSE_FAILURE, + GNOME_KEYRING_ASK_RESPONSE_DENY, + GNOME_KEYRING_ASK_RESPONSE_ALLOW_ONCE, + GNOME_KEYRING_ASK_RESPONSE_ALLOW_FOREVER +} GnomeKeyringAskResponse; + +#ifdef WITH_DBUS +#define GNOME_KEYRING_DAEMON_SERVICE "org.gnome.keyring" +#define GNOME_KEYRING_DAEMON_PATH "/org/gnome/keyring/daemon" +#define GNOME_KEYRING_DAEMON_INTERFACE "org.gnome.keyring.Daemon" +#endif + +#endif /* GNOME_KEYRING_PRIVATE_H */ + diff --git a/library/gnome-keyring-proto.c b/library/gnome-keyring-proto.c new file mode 100644 index 00000000..aee7c39b --- /dev/null +++ b/library/gnome-keyring-proto.c @@ -0,0 +1,1704 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring-proto.c - helper code for the keyring daemon protocol + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ +#include "config.h" + +#include <string.h> +#include <stdarg.h> + +#include "gnome-keyring-proto.h" +#include "gnome-keyring-private.h" + +gboolean +gnome_keyring_proto_set_uint32 (GString *buffer, gsize offset, guint32 val) +{ + unsigned char *ptr; + + if (buffer->len < 4 || + offset > buffer->len - 4) { + return FALSE; + } + + ptr = (unsigned char *)buffer->str + offset; + ptr[0] = (val >> 24) & 0xff; + ptr[1] = (val >> 16) & 0xff; + ptr[2] = (val >> 8) & 0xff; + ptr[3] = (val >> 0) & 0xff; + + return TRUE; +} + +void +gnome_keyring_proto_add_uint32 (GString *buffer, guint32 val) +{ + g_string_append_c (buffer, (val >> 24) & 0xff); + g_string_append_c (buffer, (val >> 16) & 0xff); + g_string_append_c (buffer, (val >> 8) & 0xff); + g_string_append_c (buffer, (val >> 0) & 0xff); +} + +void +gnome_keyring_proto_add_time (GString *buffer, time_t time) +{ + guint64 val; + + val = time; + gnome_keyring_proto_add_uint32 (buffer, ((val >> 32) & 0xffffffff)); + gnome_keyring_proto_add_uint32 (buffer, (val & 0xffffffff)); +} + +gboolean +gnome_keyring_proto_get_uint32 (GString *buffer, + gsize offset, + gsize *next_offset, + guint32 *val) +{ + unsigned char *ptr; + + if (buffer->len < 4 || + offset > buffer->len - 4) { + return FALSE; + } + + ptr = (unsigned char *)buffer->str + offset; + if (val != NULL) { + *val = ptr[0] << 24 | + ptr[1] << 16 | + ptr[2] << 8 | + ptr[3]; + } + + if (next_offset != NULL) { + *next_offset = offset + 4; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_get_time (GString *buffer, + gsize offset, + gsize *next_offset, + time_t *time) +{ + guint32 a, b; + guint64 val; + + if (!gnome_keyring_proto_get_uint32 (buffer, + offset, &offset, &a)) { + return FALSE; + } + if (!gnome_keyring_proto_get_uint32 (buffer, + offset, &offset, &b)) { + return FALSE; + } + + val = ((guint64)a) << 32 | b; + + *next_offset = offset; + *time = (time_t) val; + + return TRUE; +} + + +static gboolean +gnome_keyring_proto_add_string (GString *buffer, const char *str, gsize len) +{ + if (len >= 0x7fffffff) { + return FALSE; + } + + if (str != NULL && memchr(str, 0, len) != NULL) { + return FALSE; + } + + if (str == NULL) { + gnome_keyring_proto_add_uint32 (buffer, 0xffffffff); + } else { + gnome_keyring_proto_add_uint32 (buffer, len); + g_string_append_len (buffer, str, len); + } + return TRUE; +} + +gboolean +gnome_keyring_proto_add_utf8_string (GString *buffer, const char *str) +{ + gsize len; + + if (str != NULL) { + len = strlen (str); + + if (!g_utf8_validate (str, len, NULL)) { + return FALSE; + } + } else { + len = 0; + } + + return gnome_keyring_proto_add_string (buffer, str, len); +} + +gboolean +gnome_keyring_proto_get_bytes (GString *buffer, + gsize offset, + gsize *next_offset, + guchar *out, gsize n_bytes) +{ + if (buffer->len < n_bytes || + offset > buffer->len - n_bytes) { + return FALSE; + } + + memcpy (out, buffer->str + offset, n_bytes); + *next_offset = offset + n_bytes; + + return TRUE; +} + + +static gboolean +gnome_keyring_proto_get_string (GString *buffer, + gsize offset, + gsize *next_offset, + char **str_ret, gsize *len_ret) +{ + guint32 len; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &len)) { + return FALSE; + } + if (len == 0xffffffff) { + *next_offset = offset; + *len_ret = 0; + *str_ret = NULL; + return TRUE; + } else if (len >= 0x7fffffff) { + return FALSE; + } + + if (buffer->len < len || + offset > buffer->len - len) { + return FALSE; + } + + *str_ret = g_memdup (buffer->str + offset, len+1); + /* Always zero terminate */ + (*str_ret)[len] = 0; + *len_ret = len; + *next_offset = offset + len; + + return TRUE; +} + +gboolean +gnome_keyring_proto_get_utf8_string (GString *buffer, + gsize offset, + gsize *next_offset, + char **str_ret) +{ + gsize len; + char *str; + + if (!gnome_keyring_proto_get_string (buffer, + offset, + &offset, + &str, + &len)) { + return FALSE; + } + + if (str != NULL) { + if (memchr (str, 0, len) != NULL) { + g_free (str); + return FALSE; + } + + if (!g_utf8_validate (str, len, NULL)) { + g_free (str); + return FALSE; + } + } + + if (next_offset != NULL) { + *next_offset = offset; + } + if (str_ret != NULL) { + *str_ret = str; + } else { + g_free (str); + } + return TRUE; +} + +static gboolean +gnome_keyring_proto_start_operation (GString *buffer, + GnomeKeyringOpCode op, + gsize *op_start) +{ + gsize appname_pos; + const char *name; + + appname_pos = buffer->len; + gnome_keyring_proto_add_uint32 (buffer, 0); + + name = g_get_application_name (); + if (name != NULL && !g_utf8_validate (name, -1, NULL)) { + g_warning ("g_application_name not utf8 encoded"); + name = NULL; + } else if (name == NULL) { + g_warning ("g_set_application_name not set."); + } + if (name == NULL) { + /* General name if none set */ + name = "Application"; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, name)) { + return FALSE; + } + + /* backpatch application name size */ + if (!gnome_keyring_proto_set_uint32 (buffer, appname_pos, buffer->len)) { + return FALSE; + } + + + /* Make space for packet size */ + *op_start = buffer->len; + gnome_keyring_proto_add_uint32 (buffer, 0); + gnome_keyring_proto_add_uint32 (buffer, op); + + return TRUE; +} + +static gboolean +gnome_keyring_proto_end_operation (GString *buffer, + gsize op_start) +{ + if (!gnome_keyring_proto_set_uint32 (buffer, op_start, buffer->len - op_start)) { + return FALSE; + } + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_packet_size (GString *buffer, + guint32 *size) +{ + return gnome_keyring_proto_get_uint32 (buffer, 0, NULL, size); +} + +gboolean +gnome_keyring_proto_decode_packet_operation (GString *buffer, + GnomeKeyringOpCode *op) +{ + guint32 op_nr; + gboolean res; + + res = gnome_keyring_proto_get_uint32 (buffer, 4, NULL, &op_nr); + *op = op_nr; + return res; +} + +gboolean +gnome_keyring_proto_encode_op_only (GString *buffer, + GnomeKeyringOpCode op) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_op_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str)) { + return FALSE; + } + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_op_string_int (GString *buffer, + GnomeKeyringOpCode op, + const char *str, + guint32 val) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, val); + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_op_string_int_int (GString *buffer, + GnomeKeyringOpCode op, + const char *str, + guint32 integer1, + guint32 integer2) +{ + gsize op_start; + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) + return FALSE; + if (!gnome_keyring_proto_add_utf8_string (buffer, str)) + return FALSE; + gnome_keyring_proto_add_uint32 (buffer, integer1); + gnome_keyring_proto_add_uint32 (buffer, integer2); + if (!gnome_keyring_proto_end_operation (buffer, op_start)) + return FALSE; + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_op_string_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str1, + const char *str2) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str1)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str2)) { + return FALSE; + } + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_op_string_string_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str1, + const char *str2, + const char *str3) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str1)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str2)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + str3)) { + return FALSE; + } + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_find (GString *buffer, + GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes) +{ + gsize op_start; + + gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_FIND, + &op_start); + + gnome_keyring_proto_add_uint32 (buffer, type); + + if (!gnome_keyring_proto_add_attribute_list (buffer, attributes)) { + goto bail; + } + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + goto bail; + } + + return TRUE; + + bail: + g_string_set_size (buffer, op_start); + return FALSE; +} + +gboolean +gnome_keyring_proto_encode_create_item (GString *buffer, + const char *keyring, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + GnomeKeyringItemType type, + gboolean update_if_exists) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_CREATE_ITEM, + &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + keyring)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + display_name)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + secret)) { + return FALSE; + } + if (!gnome_keyring_proto_add_attribute_list (buffer, + attributes)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, type); + gnome_keyring_proto_add_uint32 (buffer, update_if_exists); + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_create_item (GString *buffer, + char **keyring, + char **display_name, + GnomeKeyringAttributeList **attributes, + char **secret, + GnomeKeyringItemType *type, + gboolean *update_if_exists) +{ + gsize offset; + GnomeKeyringOpCode op; + guint val; + + if (keyring != NULL) { + *keyring = NULL; + } + if (display_name != NULL) { + *display_name = NULL; + } + if (secret != NULL) { + *secret = NULL; + } + if (attributes != NULL) { + *attributes = NULL; + } + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_CREATE_ITEM) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + keyring)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + display_name)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + secret)) { + goto bail; + } + + if (!gnome_keyring_proto_decode_attribute_list (buffer, + offset, &offset, + attributes)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &val)) { + goto bail; + } + if (type != NULL) { + *type = val; + } + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &val)) { + goto bail; + } + if (update_if_exists != NULL) { + *update_if_exists = val; + } + + return TRUE; + + bail: + if (attributes != NULL) { + gnome_keyring_attribute_list_free (*attributes); + } + if (keyring != NULL) { + g_free (*keyring); + } + if (display_name != NULL) { + g_free (*display_name); + } + if (secret != NULL) { + gnome_keyring_free_password (*secret); + } + return FALSE; + +} + + +gboolean +gnome_keyring_proto_encode_set_attributes (GString *buffer, + const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_SET_ITEM_ATTRIBUTES, + &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + keyring)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, id); + + if (!gnome_keyring_proto_add_attribute_list (buffer, attributes)) { + return FALSE; + } + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_set_acl (GString *buffer, + const char *keyring, + guint32 id, + GList *acl) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_SET_ITEM_ACL, + &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + keyring)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, id); + + if (!gnome_keyring_proto_add_acl (buffer, acl)) { + return FALSE; + } + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + + +gboolean +gnome_keyring_proto_encode_set_item_info (GString *buffer, + const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_SET_ITEM_INFO, + &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + keyring)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, id); + + gnome_keyring_proto_add_uint32 (buffer, info->type); + if (!gnome_keyring_proto_add_utf8_string (buffer, + info->display_name)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + info->secret)) { + return FALSE; + } + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_encode_set_keyring_info (GString *buffer, + const char *keyring, + GnomeKeyringInfo *info) +{ + gsize op_start; + + if (!gnome_keyring_proto_start_operation (buffer, + GNOME_KEYRING_OP_SET_KEYRING_INFO, + &op_start)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + keyring)) { + return FALSE; + } + + gnome_keyring_proto_add_uint32 (buffer, info->lock_on_idle); + gnome_keyring_proto_add_uint32 (buffer, info->lock_timeout); + + if (!gnome_keyring_proto_end_operation (buffer, op_start)) { + return FALSE; + } + + return TRUE; +} + + +gboolean +gnome_keyring_proto_decode_attribute_list (GString *buffer, + gsize offset, gsize *next_offset, + GnomeKeyringAttributeList **attributes_out) +{ + guint32 list_size; + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + char *name; + guint32 type; + char *str; + guint32 val; + int i; + + attributes = NULL; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &list_size)) { + goto bail; + } + + attributes = gnome_keyring_attribute_list_new (); + for (i = 0; i < list_size; i++) { + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &name)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &type)) { + g_free (name); + goto bail; + } + switch (type) { + case GNOME_KEYRING_ATTRIBUTE_TYPE_STRING: + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &str)) { + g_free (name); + goto bail; + } + attribute.name = name; + attribute.type = type; + attribute.value.string = str; + g_array_append_val (attributes, attribute); + break; + case GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32: + if (!gnome_keyring_proto_get_uint32 (buffer, + offset, &offset, + &val)) { + g_free (name); + goto bail; + } + attribute.name = name; + attribute.type = type; + attribute.value.integer = val; + g_array_append_val (attributes, attribute); + break; + default: + g_free (name); + goto bail; + } + } + + if (attributes_out != NULL) { + *attributes_out = attributes; + } else { + gnome_keyring_attribute_list_free (attributes); + } + *next_offset = offset; + return TRUE; + + bail: + gnome_keyring_attribute_list_free (attributes); + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_acl (GString *buffer, + gsize offset, gsize *next_offset, + GList **acl_out) +{ + guint32 list_size; + GList *acl; + GnomeKeyringAccessControl *ac; + GnomeKeyringApplicationRef *ref; + char *display_name; + char *pathname; + guint32 types_allowed; + int i; + + acl = NULL; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &list_size)) { + goto bail; + } + + for (i = 0; i < list_size; i++) { + ac = g_new0 (GnomeKeyringAccessControl, 1); + ref = g_new0 (GnomeKeyringApplicationRef, 1); + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &display_name)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &pathname)) { + g_free (display_name); + goto bail; + } + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &types_allowed)) { + g_free (display_name); + g_free (pathname); + goto bail; + } + ref->display_name = display_name; + ref->pathname = pathname; + ac->application = ref; + ac->types_allowed = types_allowed; + acl = g_list_append (acl, ac); + } + + if (acl_out != NULL) { + *acl_out = acl; + } else { + g_list_free (acl); + } + *next_offset = offset; + return TRUE; + + bail: + g_list_free (acl); + return FALSE; +} + + +gboolean +gnome_keyring_proto_add_attribute_list (GString *buffer, + GnomeKeyringAttributeList *attributes) +{ + int i; + GnomeKeyringAttribute *array; + + array = (GnomeKeyringAttribute *)attributes->data; + + i = 0; + gnome_keyring_proto_add_uint32 (buffer, attributes->len); + + for (i = 0; i < attributes->len; i++) { + if (!gnome_keyring_proto_add_utf8_string (buffer, + array[i].name)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, array[i].type); + switch (array[i].type) { + case GNOME_KEYRING_ATTRIBUTE_TYPE_STRING: + if (!gnome_keyring_proto_add_utf8_string (buffer, + array[i].value.string)) { + return FALSE; + } + break; + case GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32: + gnome_keyring_proto_add_uint32 (buffer, array[i].value.integer); + break; + default: + g_assert_not_reached (); + } + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_add_acl (GString *buffer, + GList *acl) +{ + int length; + GnomeKeyringAccessControl *ac; + GList *tmp; + + length = g_list_length (acl); + + gnome_keyring_proto_add_uint32 (buffer, length); + + for (tmp = acl; tmp != NULL; tmp = tmp->next) { + ac = (GnomeKeyringAccessControl *)tmp->data; + if (!gnome_keyring_proto_add_utf8_string (buffer, + ac->application->display_name)) { + return FALSE; + } + if (!gnome_keyring_proto_add_utf8_string (buffer, + ac->application->pathname)) { + return FALSE; + } + gnome_keyring_proto_add_uint32 (buffer, ac->types_allowed); + } + + return TRUE; +} + + + +gboolean +gnome_keyring_proto_decode_result_reply (GString *buffer, + GnomeKeyringResult *result) +{ + gsize offset; + guint32 res; + + offset = 4; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *result = res; + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_result_string_reply (GString *buffer, + GnomeKeyringResult *result, + char **str) +{ + gsize offset; + guint32 res; + + offset = 4; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *result = res; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str)) { + return FALSE; + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_result_string_list_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list) +{ + gsize offset; + guint32 res; + guint32 list_size, i; + GList *names; + char *str; + + offset = 4; + names = NULL; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &list_size)) { + goto bail; + } + + for (i = 0; i < list_size; i++) { + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &str)) { + goto bail; + } + names = g_list_prepend (names, str); + } + + *result = res; + *list = g_list_reverse (names); + + return TRUE; + + bail: + g_list_foreach (names, (GFunc) g_free, NULL); + g_list_free (names); + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_find_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list_out) +{ + GList *list; + gsize offset; + guint32 res; + GnomeKeyringFound *found; + + offset = 4; + + *list_out = NULL; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *result = res; + + if (res != GNOME_KEYRING_RESULT_OK) { + return TRUE; + } + + list = NULL; + while (offset < buffer->len) { + found = g_new0 (GnomeKeyringFound, 1); + list = g_list_prepend (list, found); + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &found->keyring)) { + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &found->item_id)) { + return FALSE; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &found->secret)) { + goto bail; + } + if (!gnome_keyring_proto_decode_attribute_list (buffer, offset, &offset, + &found->attributes)) { + goto bail; + } + } + + *list_out = g_list_reverse (list); + return TRUE; + + bail: + g_list_foreach (list, (GFunc)gnome_keyring_found_free, NULL); + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_find (GString *buffer, + GnomeKeyringItemType *type, + GnomeKeyringAttributeList **attributes) +{ + gsize offset; + GnomeKeyringOpCode op; + guint32 t; + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_FIND) { + return FALSE; + } + + offset = 8; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &t)) { + return FALSE; + } + *type = t; + return gnome_keyring_proto_decode_attribute_list (buffer, + offset, &offset, + attributes); +} + +gboolean +gnome_keyring_proto_decode_op_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1) +{ + gsize offset; + + if (str1 != NULL) { + *str1 = NULL; + } + if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str1)) { + goto bail; + } + + return TRUE; + bail: + if (str1 != NULL) { + g_free (*str1); + *str1 = NULL; + } + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_op_string_int (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1, + guint32 *val) +{ + gsize offset; + + if (str1 != NULL) { + *str1 = NULL; + } + if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str1)) { + goto bail; + } + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, + val)) { + return FALSE; + } + + return TRUE; + bail: + if (str1 != NULL) { + g_free (*str1); + *str1 = NULL; + } + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_get_item_info (GString *buffer, + GnomeKeyringOpCode *op_out, + char **keyring, + guint32 *item_id, + guint32 *flags) +{ + gsize offset = 8; + *keyring = NULL; + if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) + return FALSE; + if (!gnome_keyring_proto_get_utf8_string (buffer, offset, &offset, keyring)) + goto bail; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, item_id)) + goto bail; + if (*op_out == GNOME_KEYRING_OP_GET_ITEM_INFO_FULL) { + /* Pull in lookup flags/parts, find out which ones */ + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, flags)) + goto bail; + } else { + /* All parts of the item by default */ + *flags = GNOME_KEYRING_ITEM_INFO_ALL; + } + + return TRUE; + bail: + g_free (*keyring); + *keyring = NULL; + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_op_string_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1, + char **str2) +{ + gsize offset; + + if (str1 != NULL) { + *str1 = NULL; + } + if (str2 != NULL) { + *str2 = NULL; + } + if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str1)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str2)) { + goto bail; + } + + return TRUE; + bail: + if (str1 != NULL) { + g_free (*str1); + *str1 = NULL; + } + if (str2 != NULL) { + g_free (*str2); + *str2 = NULL; + } + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_op_string_string_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1, + char **str2, + char **str3) +{ + gsize offset; + + if (str1 != NULL) { + *str1 = NULL; + } + if (str2 != NULL) { + *str2 = NULL; + } + if (str3 != NULL) { + *str3 = NULL; + } + if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str1)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str2)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + str3)) { + goto bail; + } + + return TRUE; + bail: + if (str1 != NULL) { + g_free (*str1); + *str1 = NULL; + } + if (str2 != NULL) { + g_free (*str2); + *str2 = NULL; + } + if (str3 != NULL) { + g_free (*str3); + *str3 = NULL; + } + return FALSE; +} + + +gboolean +gnome_keyring_proto_decode_get_attributes_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringAttributeList **attributes) +{ + gsize offset; + guint32 res; + + offset = 4; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *attributes = NULL; + *result = res; + if (res == GNOME_KEYRING_RESULT_OK) { + if (!gnome_keyring_proto_decode_attribute_list (buffer, + offset, &offset, + attributes)) { + return FALSE; + } + + } + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_get_acl_reply (GString *buffer, + GnomeKeyringResult *result, + GList **acl) +{ + gsize offset; + guint32 res; + + offset = 4; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *acl = NULL; + *result = res; + if (res == GNOME_KEYRING_RESULT_OK) { + if (!gnome_keyring_proto_decode_acl (buffer, + offset, &offset, + acl)) { + return FALSE; + } + + } + + return TRUE; +} + + +gboolean +gnome_keyring_proto_decode_get_item_info_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringItemInfo **info_out) +{ + gsize offset; + guint32 res, type; + GnomeKeyringItemInfo *info; + time_t mtime, ctime; + char *name; + char *secret; + + info = NULL; + + offset = 4; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + if (res == GNOME_KEYRING_RESULT_OK) { + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, + &type)) { + return FALSE; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &name)) { + return FALSE; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + &secret)) { + g_free (name); + return FALSE; + } + + if (!gnome_keyring_proto_get_time (buffer, offset, &offset, + &mtime)) { + g_free (name); + gnome_keyring_free_password (secret); + return FALSE; + } + if (!gnome_keyring_proto_get_time (buffer, offset, &offset, + &ctime)) { + g_free (name); + gnome_keyring_free_password (secret); + return FALSE; + } + + info = g_new (GnomeKeyringItemInfo, 1); + info->type = type; + info->display_name = name; + info->secret = secret; + info->mtime = mtime; + info->ctime = ctime; + } + + *result = res; + *info_out = info; + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_get_keyring_info_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringInfo **info_out) +{ + gsize offset; + guint32 res; + GnomeKeyringInfo *info; + guint32 lock_on_idle, lock_timeout, is_locked; + time_t mtime, ctime; + + info = NULL; + + offset = 4; + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + if (res == GNOME_KEYRING_RESULT_OK) { + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, + &lock_on_idle)) { + return FALSE; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, + &lock_timeout)) { + return FALSE; + } + if (!gnome_keyring_proto_get_time (buffer, offset, &offset, + &mtime)) { + return FALSE; + } + if (!gnome_keyring_proto_get_time (buffer, offset, &offset, + &ctime)) { + return FALSE; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, + &is_locked)) { + return FALSE; + } + info = g_new (GnomeKeyringInfo, 1); + info->lock_on_idle = lock_on_idle; + info->lock_timeout = lock_timeout; + info->mtime = mtime; + info->ctime = ctime; + info->is_locked = is_locked; + } + + *result = res; + *info_out = info; + + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_set_item_info (GString *buffer, + char **keyring, + guint32 *item_id, + GnomeKeyringItemType *type, + char **display_name, + char **secret) +{ + gsize offset; + GnomeKeyringOpCode op; + guint32 typeint; + + *keyring = NULL; + *display_name = NULL; + *secret = NULL; + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_SET_ITEM_INFO) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + keyring)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, item_id)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &typeint)) { + goto bail; + } + *type = typeint; + + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + display_name)) { + goto bail; + } + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + secret)) { + goto bail; + } + + return TRUE; + + bail: + g_free (*keyring); + g_free (*display_name); + gnome_keyring_free_password (*secret); + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_set_keyring_info (GString *buffer, + char **keyring, + gboolean *lock_on_idle, + guint32 *lock_timeout) + +{ + gsize offset; + GnomeKeyringOpCode op; + guint32 lock_int; + + *keyring = NULL; + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_SET_KEYRING_INFO) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + keyring)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &lock_int)) { + goto bail; + } + *lock_on_idle = lock_int; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, lock_timeout)) { + goto bail; + } + + return TRUE; + + bail: + g_free (*keyring); + return FALSE; +} + +gboolean +gnome_keyring_proto_decode_set_attributes (GString *buffer, + char **keyring, + guint32 *item_id, + GnomeKeyringAttributeList **attributes) +{ + gsize offset; + GnomeKeyringOpCode op; + + *keyring = NULL; + *attributes = NULL; + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_SET_ITEM_ATTRIBUTES) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + keyring)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, item_id)) { + goto bail; + } + + if (!gnome_keyring_proto_decode_attribute_list (buffer, + offset, &offset, + attributes)) { + goto bail; + } + + return TRUE; + + bail: + g_free (*keyring); + return FALSE; +} + + +gboolean +gnome_keyring_proto_decode_set_acl (GString *buffer, + char **keyring, + guint32 *item_id, + GList **acl) +{ + gsize offset; + GnomeKeyringOpCode op; + + *keyring = NULL; + *acl = NULL; + + if (!gnome_keyring_proto_decode_packet_operation (buffer, &op)) { + return FALSE; + } + if (op != GNOME_KEYRING_OP_SET_ITEM_ACL) { + return FALSE; + } + offset = 8; + if (!gnome_keyring_proto_get_utf8_string (buffer, + offset, &offset, + keyring)) { + goto bail; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, item_id)) { + goto bail; + } + + if (!gnome_keyring_proto_decode_acl (buffer, + offset, &offset, + acl)) { + goto bail; + } + + return TRUE; + + bail: + g_free (*keyring); + return FALSE; +} + + + +gboolean +gnome_keyring_proto_decode_result_int_list_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list) +{ + gsize offset; + guint32 res, len, i, id; + + *list = NULL; + + offset = 4; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + *result = res; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &len)) { + return FALSE; + } + + for (i = 0; i < len; i++) { + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &id)) { + g_list_free (*list); + *list = NULL; + return FALSE; + } + *list = g_list_prepend (*list, GUINT_TO_POINTER (id)); + + } + *list = g_list_reverse (*list); + return TRUE; +} + +gboolean +gnome_keyring_proto_decode_result_integer_reply (GString *buffer, + GnomeKeyringResult *result, + guint32 *integer) +{ + gsize offset; + guint32 res, val; + + offset = 4; + + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &res)) { + return FALSE; + } + if (!gnome_keyring_proto_get_uint32 (buffer, offset, &offset, &val)) { + return FALSE; + } + + *result = res; + if (integer != NULL) { + *integer = val; + } + + return TRUE; +} + diff --git a/library/gnome-keyring-proto.h b/library/gnome-keyring-proto.h new file mode 100644 index 00000000..67d5880d --- /dev/null +++ b/library/gnome-keyring-proto.h @@ -0,0 +1,247 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring-proto.h - helper code for the keyring daemon protocol + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ +#ifndef GNOME_KEYRING_PROTO_H +#define GNOME_KEYRING_PROTO_H + +#include <stdarg.h> +#include "gnome-keyring.h" + +typedef enum { + GNOME_KEYRING_OP_LOCK_ALL, + GNOME_KEYRING_OP_SET_DEFAULT_KEYRING, + GNOME_KEYRING_OP_GET_DEFAULT_KEYRING, + GNOME_KEYRING_OP_LIST_KEYRINGS, + GNOME_KEYRING_OP_CREATE_KEYRING, + GNOME_KEYRING_OP_LOCK_KEYRING, + GNOME_KEYRING_OP_UNLOCK_KEYRING, + GNOME_KEYRING_OP_DELETE_KEYRING, + GNOME_KEYRING_OP_GET_KEYRING_INFO, + GNOME_KEYRING_OP_SET_KEYRING_INFO, + GNOME_KEYRING_OP_LIST_ITEMS, + GNOME_KEYRING_OP_FIND, + GNOME_KEYRING_OP_CREATE_ITEM, + GNOME_KEYRING_OP_DELETE_ITEM, + GNOME_KEYRING_OP_GET_ITEM_INFO, + GNOME_KEYRING_OP_SET_ITEM_INFO, + GNOME_KEYRING_OP_GET_ITEM_ATTRIBUTES, + GNOME_KEYRING_OP_SET_ITEM_ATTRIBUTES, + GNOME_KEYRING_OP_GET_ITEM_ACL, + GNOME_KEYRING_OP_SET_ITEM_ACL, + GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD, + GNOME_KEYRING_OP_SET_DAEMON_DISPLAY, + GNOME_KEYRING_OP_GET_ITEM_INFO_FULL, + + /* Add new ops here */ + + GNOME_KEYRING_NUM_OPS +} GnomeKeyringOpCode; + +/* request: + uint32 package size + uint32 operation + ... op data + + reply: + uint32 reply size + uint32 result +*/ + +/* Core buffer ops */ +void gnome_keyring_proto_add_uint32 (GString *buffer, + guint32 val); +gboolean gnome_keyring_proto_set_uint32 (GString *buffer, + gsize offset, + guint32 val); +gboolean gnome_keyring_proto_get_uint32 (GString *buffer, + gsize offset, + gsize *next_offset, + guint32 *val); +gboolean gnome_keyring_proto_get_bytes (GString *buffer, + gsize offset, + gsize *next_offset, + guchar *out, + gsize n_bytes); +void gnome_keyring_proto_add_time (GString *buffer, + time_t val); +gboolean gnome_keyring_proto_get_time (GString *buffer, + gsize offset, + gsize *next_offset, + time_t *time); +gboolean gnome_keyring_proto_add_utf8_string (GString *buffer, + const char *str); +gboolean gnome_keyring_proto_get_utf8_string (GString *buffer, + gsize offset, + gsize *next_offset, + char **str_ret); +gboolean gnome_keyring_proto_add_attribute_list (GString *buffer, + GnomeKeyringAttributeList *attributes); +gboolean gnome_keyring_proto_add_acl (GString *buffer, + GList *acl); + + +/* marshallers */ +gboolean gnome_keyring_proto_encode_op_only (GString *buffer, + GnomeKeyringOpCode op); +gboolean gnome_keyring_proto_encode_op_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str); +gboolean gnome_keyring_proto_encode_op_string_int (GString *buffer, + GnomeKeyringOpCode op, + const char *str, + guint32 integer); +gboolean gnome_keyring_proto_encode_op_string_int_int (GString *buffer, + GnomeKeyringOpCode op, + const char *str, + guint32 integer1, + guint32 integer2); +gboolean gnome_keyring_proto_encode_op_string_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str1, + const char *str2); +gboolean gnome_keyring_proto_encode_op_string_string_string (GString *buffer, + GnomeKeyringOpCode op, + const char *str1, + const char *str2, + const char *str3); +gboolean gnome_keyring_proto_encode_find (GString *buffer, + GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes); +gboolean gnome_keyring_proto_encode_create_item (GString *buffer, + const char *keyring, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + GnomeKeyringItemType type, + gboolean update_if_exists); +gboolean gnome_keyring_proto_encode_set_attributes (GString *buffer, + const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes); +gboolean gnome_keyring_proto_encode_set_acl (GString *buffer, + const char *keyring, + guint32 id, + GList *acl); +gboolean gnome_keyring_proto_encode_set_item_info (GString *buffer, + const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info); +gboolean gnome_keyring_proto_encode_set_keyring_info (GString *buffer, + const char *keyring, + GnomeKeyringInfo *info); + + +/* demarshallers */ +gboolean gnome_keyring_proto_decode_packet_operation (GString *buffer, + GnomeKeyringOpCode *op); +gboolean gnome_keyring_proto_decode_packet_size (GString *buffer, + guint32 *size); +gboolean gnome_keyring_proto_decode_attribute_list (GString *buffer, + gsize offset, + gsize *next_offset, + GnomeKeyringAttributeList **attributes_out); +gboolean gnome_keyring_proto_decode_acl (GString *buffer, + gsize offset, + gsize *next_offset, + GList **attributes_out); +gboolean gnome_keyring_proto_decode_result_reply (GString *buffer, + GnomeKeyringResult *result); +gboolean gnome_keyring_proto_decode_result_string_reply (GString *buffer, + GnomeKeyringResult *result, + char **str); +gboolean gnome_keyring_proto_decode_result_string_list_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list); +gboolean gnome_keyring_proto_decode_op_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str_out); +gboolean gnome_keyring_proto_decode_op_string_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1_out, + char **str2_out); +gboolean gnome_keyring_proto_decode_op_string_string_string (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1_out, + char **str2_out, + char **str3_out); +gboolean gnome_keyring_proto_decode_op_string_int (GString *buffer, + GnomeKeyringOpCode *op_out, + char **str1, + guint32 *val); +gboolean gnome_keyring_proto_decode_get_item_info (GString *buffer, + GnomeKeyringOpCode *op_out, + char **keyring, + guint32 *item_id, + guint32 *flags); +gboolean gnome_keyring_proto_decode_find (GString *buffer, + GnomeKeyringItemType *type, + GnomeKeyringAttributeList **attributes); +gboolean gnome_keyring_proto_decode_find_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list_out); +gboolean gnome_keyring_proto_decode_get_attributes_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringAttributeList **attributes); +gboolean gnome_keyring_proto_decode_get_acl_reply (GString *buffer, + GnomeKeyringResult *result, + GList **acl); +gboolean gnome_keyring_proto_decode_get_item_info_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringItemInfo **info); +gboolean gnome_keyring_proto_decode_get_keyring_info_reply (GString *buffer, + GnomeKeyringResult *result, + GnomeKeyringInfo **info); +gboolean gnome_keyring_proto_decode_result_int_list_reply (GString *buffer, + GnomeKeyringResult *result, + GList **list); +gboolean gnome_keyring_proto_decode_result_integer_reply (GString *buffer, + GnomeKeyringResult *result, + guint32 *integer); +gboolean gnome_keyring_proto_decode_create_item (GString *packet, + char **keyring, + char **display_name, + GnomeKeyringAttributeList **attributes, + char **secret, + GnomeKeyringItemType *type_out, + gboolean *update_if_exists); +gboolean gnome_keyring_proto_decode_set_item_info (GString *buffer, + char **keyring, + guint32 *item_id, + GnomeKeyringItemType *type, + char **display_name, + char **secret); +gboolean gnome_keyring_proto_decode_set_keyring_info (GString *buffer, + char **keyring, + gboolean *lock_on_idle, + guint32 *lock_timeout); +gboolean gnome_keyring_proto_decode_set_attributes (GString *buffer, + char **keyring, + guint32 *item_id, + GnomeKeyringAttributeList **attributes); +gboolean gnome_keyring_proto_decode_set_acl (GString *buffer, + char **keyring, + guint32 *item_id, + GList **acl); + + + +#endif /* GNOME_KEYRING_PROTO_H */ diff --git a/library/gnome-keyring-utils.c b/library/gnome-keyring-utils.c new file mode 100644 index 00000000..c802ca02 --- /dev/null +++ b/library/gnome-keyring-utils.c @@ -0,0 +1,270 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring-proto.c - shared utility functions + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ +#include "config.h" + +#include <string.h> +#include <glib.h> + +#include "gnome-keyring-private.h" + +/* Functions used by both the library and the daemon */ + +/** + * gnome_keyring_free_password(): + * @str: the password to be freed + * + * Clears the memory used by password by filling with '\0' and frees the memory + * after doing this. You should use this function instead of g_free() for + * secret information. + */ +void +gnome_keyring_free_password (char *str) +{ + if (str != NULL) { + memset (str, 0, strlen (str)); + g_free (str); + } +} + +/** + * gnome_keyring_found_free(): + * @found: a #GnomeKeyringFound + * + * Free the memory used by a #GnomeKeyringFound item. + * + * You usually want to use gnome_keyring_found_list_free() on the list of + * results. + */ +void +gnome_keyring_found_free (GnomeKeyringFound *found) +{ + g_free (found->keyring); + g_free (found->secret); + gnome_keyring_attribute_list_free (found->attributes); + g_free (found); +} + +/** + * gnome_keyring_found_list_free(): + * @found_list: a #GList of #GnomeKeyringFound + * + * Free the memory used by the #GnomeKeyringFound items in @found_list. + */ +void +gnome_keyring_found_list_free (GList *found_list) +{ + g_list_foreach (found_list, (GFunc) gnome_keyring_found_free, NULL); + g_list_free (found_list); +} + +/** + * gnome_keyring_attribute_list_free(): + * @attributes: a #GnomeKeyringAttributeList + * + * Free the memory used by @attributes. + */ +void +gnome_keyring_attribute_list_free (GnomeKeyringAttributeList *attributes) +{ + GnomeKeyringAttribute *array; + int i; + + if (attributes == NULL) { + return; + } + + array = (GnomeKeyringAttribute *)attributes->data; + for (i = 0; i < attributes->len; i++) { + g_free (array[i].name); + if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + g_free (array[i].value.string); + } + } + + g_array_free (attributes, TRUE); +} + +GnomeKeyringAttributeList * +gnome_keyring_attribute_list_copy (GnomeKeyringAttributeList *attributes) +{ + GnomeKeyringAttribute *array; + GnomeKeyringAttributeList *copy; + int i; + + if (attributes == NULL) { + return NULL; + } + + copy = g_array_sized_new (FALSE, FALSE, sizeof (GnomeKeyringAttribute), attributes->len); + + copy->len = attributes->len; + memcpy (copy->data, attributes->data, sizeof (GnomeKeyringAttribute) * attributes->len); + + array = (GnomeKeyringAttribute *)copy->data; + for (i = 0; i < copy->len; i++) { + array[i].name = g_strdup (array[i].name); + if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + array[i].value.string = g_strdup (array[i].value.string); + } + } + return copy; +} + +void +gnome_keyring_info_free (GnomeKeyringInfo *keyring_info) +{ + g_free (keyring_info); +} + +GnomeKeyringInfo * +gnome_keyring_info_copy (GnomeKeyringInfo *keyring_info) +{ + GnomeKeyringInfo *copy; + + copy = g_new (GnomeKeyringInfo, 1); + memcpy (copy, keyring_info, sizeof (GnomeKeyringInfo)); + + return copy; +} + + +void +gnome_keyring_item_info_free (GnomeKeyringItemInfo *item_info) +{ + if (item_info != NULL) { + g_free (item_info->display_name); + if (item_info->secret != NULL) { + /* clear the secret on free */ + memset (item_info->secret, 0, strlen (item_info->secret)); + g_free (item_info->secret); + } + g_free (item_info); + } +} + +GnomeKeyringItemInfo * +gnome_keyring_item_info_new (void) +{ + GnomeKeyringItemInfo *info; + + info = g_new0 (GnomeKeyringItemInfo, 1); + + info->type = GNOME_KEYRING_ITEM_NO_TYPE; + + return info; +} + +GnomeKeyringItemInfo * +gnome_keyring_item_info_copy (GnomeKeyringItemInfo *item_info) +{ + GnomeKeyringItemInfo *copy; + + copy = g_new (GnomeKeyringItemInfo, 1); + memcpy (copy, item_info, sizeof (GnomeKeyringItemInfo)); + + copy->display_name = g_strdup (copy->display_name); + copy->secret = g_strdup (copy->secret); + + return copy; +} + +GnomeKeyringApplicationRef * +gnome_keyring_application_ref_new (void) +{ + GnomeKeyringApplicationRef *app_ref; + + app_ref = g_new0 (GnomeKeyringApplicationRef, 1); + + return app_ref; +} + +void +gnome_keyring_application_ref_free (GnomeKeyringApplicationRef *app_ref) +{ + g_free (app_ref->display_name); + g_free (app_ref->pathname); + g_free (app_ref); +} + +GnomeKeyringApplicationRef * +gnome_keyring_application_ref_copy (const GnomeKeyringApplicationRef *app) +{ + GnomeKeyringApplicationRef *copy; + + copy = g_new (GnomeKeyringApplicationRef, 1); + copy->display_name = g_strdup (app->display_name); + copy->pathname = g_strdup (app->pathname); + + return copy; +} + +GnomeKeyringAccessControl * +gnome_keyring_access_control_new (const GnomeKeyringApplicationRef *application, + GnomeKeyringAccessType types_allowed) +{ + GnomeKeyringAccessControl *ac; + ac = g_new (GnomeKeyringAccessControl, 1); + + ac->application = gnome_keyring_application_ref_copy (application); + ac->types_allowed = types_allowed; + + return ac; +} + +void +gnome_keyring_access_control_free (GnomeKeyringAccessControl *ac) +{ + gnome_keyring_application_ref_free (ac->application); + g_free (ac); +} + +GnomeKeyringAccessControl * +gnome_keyring_access_control_copy (GnomeKeyringAccessControl *ac) +{ + GnomeKeyringAccessControl *ret; + + ret = gnome_keyring_access_control_new (gnome_keyring_application_ref_copy (ac->application), ac->types_allowed); + + return ret; +} + +GList * +gnome_keyring_acl_copy (GList *list) +{ + GList *ret, *l; + + ret = g_list_copy (list); + for (l = ret; l != NULL; l = l->next) { + l->data = gnome_keyring_access_control_copy (l->data); + } + + return ret; +} + +void +gnome_keyring_acl_free (GList *acl) +{ + g_list_foreach (acl, (GFunc)gnome_keyring_access_control_free, NULL); + g_list_free (acl); +} + diff --git a/library/gnome-keyring.c b/library/gnome-keyring.c new file mode 100644 index 00000000..000089c8 --- /dev/null +++ b/library/gnome-keyring.c @@ -0,0 +1,2825 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring.c - library for talking to the keyring daemon. + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ + +#include "config.h" + +#include "gnome-keyring.h" +#include "gnome-keyring-private.h" +#include "gnome-keyring-proto.h" + +#include <time.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <stdarg.h> + +#ifdef WITH_DBUS +#include <dbus/dbus.h> +#endif + +typedef enum { + CALLBACK_DONE, + CALLBACK_GET_STRING, + CALLBACK_GET_INT, + CALLBACK_GET_LIST, + CALLBACK_GET_KEYRING_INFO, + CALLBACK_GET_ITEM_INFO, + CALLBACK_GET_ATTRIBUTES, + CALLBACK_GET_ACL +} KeyringCallbackType; + +typedef enum { + STATE_FAILED, + STATE_WRITING_CREDS, + STATE_WRITING_PACKET, + STATE_READING_REPLY +} KeyringState; + +typedef struct GnomeKeyringOperation GnomeKeyringOperation; + +typedef void (*KeyringHandleReply) (GnomeKeyringOperation *op); + +struct GnomeKeyringOperation { + int socket; + + KeyringState state; + GnomeKeyringResult result; + + guint io_watch; + + GString *send_buffer; + gsize send_pos; + + GString *receive_buffer; + gsize receive_pos; + + KeyringCallbackType user_callback_type; + gpointer user_callback; + gpointer user_data; + GDestroyNotify destroy_user_data; + + KeyringHandleReply reply_handler; +}; + +#ifdef WITH_DBUS + +static gchar* +find_daemon_via_dbus () +{ + DBusConnection *dconn; + DBusMessage *reply; + DBusMessage *msg; + DBusMessageIter args; + DBusError derr; + char* socket = NULL; + + dbus_error_init (&derr); + dconn = dbus_bus_get (DBUS_BUS_SESSION, &derr); + if (!dconn) { + g_warning ("couldn't connect to dbus session bus: %s", derr.message); + return NULL; + } + + msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE, + GNOME_KEYRING_DAEMON_PATH, + GNOME_KEYRING_DAEMON_INTERFACE, + "GetSocketPath"); + if (!msg) { + g_warning ("couldn't create dbus message"); + dbus_connection_unref (dconn); + return NULL; + } + + /* Send message and get a handle for a reply */ + reply = dbus_connection_send_with_reply_and_block (dconn, msg, 1000, &derr); + dbus_message_unref (msg); + if (!reply) { + g_warning ("couldn't communicate with gnome keyring daemon via dbus: %s", derr.message); + dbus_connection_unref (dconn); + return NULL; + } + + /* Read the return value */ + if (!dbus_message_iter_init(reply, &args) || + dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) { + g_warning ("gnome-keyring-daemon sent back an invalid reply"); + } else { + dbus_message_iter_get_basic(&args, &socket); + socket = g_strdup (socket); + } + + dbus_message_unref (reply); + dbus_connection_unref (dconn); + + return socket; +} + +#endif + +static int +connect_to_daemon_at (const gchar *path) +{ + struct sockaddr_un addr; + int sock; + + addr.sun_family = AF_UNIX; + strncpy (addr.sun_path, path, sizeof (addr.sun_path)); + + sock = socket (AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + return -1; + } + + /* close on exec */ + if (fcntl (sock, F_SETFD, 1) == -1) { + close (sock); + return -1; + } + + if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) { + close (sock); + return -1; + } + + return sock; +} + +static int +connect_to_daemon (gboolean non_blocking) +{ + const gchar *epath = NULL; + int sock = -1; + int val; + + /* Try using the environment variable */ + epath = g_getenv ("GNOME_KEYRING_SOCKET"); + if (epath && epath[0]) { + sock = connect_to_daemon_at (epath); + if (sock < 0) { + g_warning ("couldn't connect to daemon at $GNOME_KEYRING_SOCKET: %s: %s", + epath, g_strerror (errno)); + } + } + +#ifdef WITH_DBUS + /* Try using DBus to find daemon */ + if (sock < 0) { + gchar *dpath = find_daemon_via_dbus (); + if (dpath) { + sock = connect_to_daemon_at (dpath); + g_free (dpath); + if (sock < 0) { + g_warning ("couldn't connect to daemon at DBus discovered socket: %s: %s", + dpath, g_strerror (errno)); + } + } + } +#endif + + if (sock < 0) + return -1; + + /* Setup non blocking */ + if (non_blocking) { + val = fcntl (sock, F_GETFL, 0); + if (val < 0) { + close (sock); + return -1; + } + + if (fcntl (sock, F_SETFL, val | O_NONBLOCK) < 0) { + close (sock); + return -1; + } + } + + return sock; +} + + +static void +gnome_keyring_operation_free (GnomeKeyringOperation *op) +{ + if (op->io_watch != 0) { + g_source_remove (op->io_watch); + op->io_watch = 0; + } + if (op->destroy_user_data != NULL) { + (*op->destroy_user_data) (op->user_data); + } + if (op->send_buffer != NULL) { + g_string_free (op->send_buffer, TRUE); + } + if (op->receive_buffer != NULL) { + g_string_free (op->receive_buffer, TRUE); + } + close (op->socket); + g_free (op); +} + +static gboolean +op_failed (gpointer data) +{ + GnomeKeyringOperation *op; + + op = data; + + switch (op->user_callback_type) { + case CALLBACK_DONE: + ((GnomeKeyringOperationDoneCallback)op->user_callback) (op->result, op->user_data); + break; + case CALLBACK_GET_STRING: + ((GnomeKeyringOperationGetStringCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + case CALLBACK_GET_INT: + ((GnomeKeyringOperationGetIntCallback)op->user_callback) (op->result, 0, op->user_data); + break; + case CALLBACK_GET_LIST: + ((GnomeKeyringOperationGetListCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + case CALLBACK_GET_KEYRING_INFO: + ((GnomeKeyringOperationGetKeyringInfoCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + case CALLBACK_GET_ITEM_INFO: + ((GnomeKeyringOperationGetItemInfoCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + case CALLBACK_GET_ATTRIBUTES: + ((GnomeKeyringOperationGetAttributesCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + case CALLBACK_GET_ACL: + ((GnomeKeyringOperationGetListCallback)op->user_callback) (op->result, NULL, op->user_data); + break; + } + + gnome_keyring_operation_free (op); + + return FALSE; +} + + +static void +schedule_op_failed (GnomeKeyringOperation *op, + GnomeKeyringResult result) +{ + if (op->io_watch != 0) { + g_source_remove (op->io_watch); + op->io_watch = 0; + } + op->state = STATE_FAILED; + op->result = result; + g_idle_add (op_failed, op); +} + +static int +read_all (int fd, char *buf, size_t len) +{ + size_t bytes; + ssize_t res; + + bytes = 0; + while (bytes < len) { + res = read (fd, buf + bytes, len - bytes); + if (res <= 0) { + if (res == 0) + res = -1; + return res; + } + bytes += res; + } + return 0; +} + + +static int +write_all (int fd, const char *buf, size_t len) +{ + size_t bytes; + ssize_t res; + + bytes = 0; + while (bytes < len) { + res = write (fd, buf + bytes, len - bytes); + if (res < 0) { + if (errno != EINTR && + errno != EAGAIN) { + perror ("write_all write failure:"); + return -1; + } + } else { + bytes += res; + } + } + return 0; +} + +static GnomeKeyringResult +write_credentials_byte_sync (int socket) +{ + char buf; + int bytes_written; +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + union { + struct cmsghdr hdr; + char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; + } cmsg; + struct iovec iov; + struct msghdr msg; +#endif + + buf = 0; +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + iov.iov_base = &buf; + iov.iov_len = 1; + + memset (&msg, 0, sizeof (msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t) &cmsg; + msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); + memset (&cmsg, 0, sizeof (cmsg)); + cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDS; +#endif + + again: + +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + bytes_written = sendmsg (socket, &msg, 0); +#else + bytes_written = write (socket, &buf, 1); +#endif + + if (bytes_written < 0 && errno == EINTR) + goto again; + + if (bytes_written <= 0) { + return GNOME_KEYRING_RESULT_IO_ERROR; + } else { + return GNOME_KEYRING_RESULT_OK; + } +} + + +static void +write_credentials_byte (GnomeKeyringOperation *op) +{ + char buf; + int bytes_written; +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + union { + struct cmsghdr hdr; + char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; + } cmsg; + struct iovec iov; + struct msghdr msg; +#endif + + buf = 0; +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + iov.iov_base = &buf; + iov.iov_len = 1; + + memset (&msg, 0, sizeof (msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t) &cmsg; + msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); + memset (&cmsg, 0, sizeof (cmsg)); + cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDS; +#endif + + again: + +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__)) + bytes_written = sendmsg (op->socket, &msg, 0); +#else + bytes_written = write (op->socket, &buf, 1); +#endif + + if (bytes_written < 0 && errno == EINTR) + goto again; + + if (bytes_written <= 0) { + if (errno == EAGAIN) { + return; + } + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + return; + } else { + op->state = STATE_WRITING_PACKET; + return; + } +} + + + +static gboolean +operation_io (GIOChannel *io_channel, + GIOCondition cond, + gpointer callback_data) +{ + GIOChannel *channel; + GnomeKeyringOperation *op; + int res; + guint32 packet_size; + + op = callback_data; + + if (cond & G_IO_HUP && !(cond & G_IO_IN)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + } + + if (op->state == STATE_WRITING_CREDS && (cond & G_IO_OUT)) { + write_credentials_byte (op); + } + if (op->state == STATE_WRITING_PACKET && (cond & G_IO_OUT)) { + res = write (op->socket, + op->send_buffer->str + op->send_pos, + op->send_buffer->len - op->send_pos); + if (res <= 0) { + if (errno != EAGAIN && + errno != EINTR) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + } + } else { + op->send_pos += res; + + if (op->send_pos == op->send_buffer->len) { + op->state = STATE_READING_REPLY; + op->receive_buffer = g_string_new (NULL); + op->receive_pos = 0; + + g_source_remove (op->io_watch); + channel = g_io_channel_unix_new (op->socket); + op->io_watch = g_io_add_watch (channel, + G_IO_IN | G_IO_HUP, + operation_io, op); + g_io_channel_unref (channel); + } + } + } + + if (op->state == STATE_READING_REPLY && (cond & G_IO_IN)) { + if (op->receive_pos < 4) { + g_string_set_size (op->receive_buffer, 4); + res = read (op->socket, + op->receive_buffer->str + op->receive_pos, + 4 - op->receive_pos); + if (res <= 0) { + if (errno != EAGAIN && + errno != EINTR) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + } + } else { + op->receive_pos += res; + } + } + + if (op->receive_pos >= 4) { + if (!gnome_keyring_proto_decode_packet_size (op->receive_buffer, + &packet_size) || + packet_size < 4) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + } + + g_assert (op->receive_pos <= packet_size); + g_string_set_size (op->receive_buffer, packet_size); + + res = read (op->socket, op->receive_buffer->str + op->receive_pos, + packet_size - op->receive_pos); + if (res <= 0) { + if (errno != EAGAIN && + errno != EINTR) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_IO_ERROR); + } + } else { + op->receive_pos += res; + + if (op->receive_pos == packet_size) { + g_source_remove (op->io_watch); + op->io_watch = 0; + op->result = GNOME_KEYRING_RESULT_OK; + + (*op->reply_handler) (op); + gnome_keyring_operation_free (op); + } + } + } + } + + + return TRUE; +} + + +static GnomeKeyringOperation * +start_operation (gpointer callback, KeyringCallbackType callback_type, + gpointer user_data, GDestroyNotify destroy_user_data) +{ + GnomeKeyringOperation *op; + GIOChannel *channel; + + op = g_new0 (GnomeKeyringOperation, 1); + + /* Start in failed mode */ + op->state = STATE_FAILED; + op->result = GNOME_KEYRING_RESULT_OK; + + op->user_callback_type = callback_type; + op->user_callback = callback; + op->user_data = user_data; + op->destroy_user_data = destroy_user_data; + + op->socket = connect_to_daemon (TRUE); + + if (op->socket < 0) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON); + } else { + op->state = STATE_WRITING_CREDS; + op->send_buffer = g_string_new (NULL); + op->send_pos = 0; + + channel = g_io_channel_unix_new (op->socket); + op->io_watch = g_io_add_watch (channel, + G_IO_OUT | G_IO_HUP, + operation_io, op); + g_io_channel_unref (channel); + } + + return op; +} + +static GnomeKeyringResult +run_sync_operation (GString *buffer, + GString *receive_buffer) +{ + GnomeKeyringResult res; + int socket; + guint32 packet_size; + + g_assert (buffer != NULL); + g_assert (receive_buffer != NULL); + + socket = connect_to_daemon (FALSE); + if (socket < 0) { + return GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON; + } + res = write_credentials_byte_sync (socket); + if (res != GNOME_KEYRING_RESULT_OK) { + close (socket); + return res; + } + + if (write_all (socket, + buffer->str, buffer->len) < 0) { + close (socket); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + + g_string_set_size (receive_buffer, 4); + if (read_all (socket, receive_buffer->str, 4) < 0) { + close (socket); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + + if (!gnome_keyring_proto_decode_packet_size (receive_buffer, + &packet_size) || + packet_size < 4) { + close (socket); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + + g_string_set_size (receive_buffer, packet_size); + if (read_all (socket, receive_buffer->str + 4, packet_size - 4) < 0) { + close (socket); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + close (socket); + + return GNOME_KEYRING_RESULT_OK; +} + +/** + * gnome_keyring_is_available(): + * + * Check whether you can communicate with a Gnome Keyring Daemon. + * + * Returns %FALSE if you can't communicate with the daemon (so you can't load + * and save passwords). + */ +gboolean +gnome_keyring_is_available (void) +{ + int socket; + + socket = connect_to_daemon (FALSE); + if (socket < 0) { + return FALSE; + } + close (socket); + return TRUE; +} + + +void +gnome_keyring_cancel_request (gpointer request) +{ + GnomeKeyringOperation *op; + + op = request; + + schedule_op_failed (op, GNOME_KEYRING_RESULT_CANCELLED); +} + +static void +gnome_keyring_standard_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationDoneCallback callback; + + g_assert (op->user_callback_type == CALLBACK_DONE); + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_result_reply (op->receive_buffer, &result)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, op->user_data); + } else { + (*callback) (result, op->user_data); + } +} + +static void +gnome_keyring_string_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetStringCallback callback; + char *string; + + g_assert (op->user_callback_type == CALLBACK_GET_STRING); + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_result_string_reply (op->receive_buffer, &result, &string)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, string, op->user_data); + g_free (string); + } +} + +static void +gnome_keyring_int_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetIntCallback callback; + guint32 integer; + + g_assert (op->user_callback_type == CALLBACK_GET_INT); + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_result_integer_reply (op->receive_buffer, &result, &integer)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, 0, op->user_data); + } else { + (*callback) (result, integer, op->user_data); + } +} + +gpointer +gnome_keyring_set_default_keyring (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string (op->send_buffer, + GNOME_KEYRING_OP_SET_DEFAULT_KEYRING, + keyring)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + return op; +} + +GnomeKeyringResult +gnome_keyring_set_default_keyring_sync (const char *keyring) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_SET_DEFAULT_KEYRING, + keyring)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_get_default_keyring (GnomeKeyringOperationGetStringCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_STRING, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_only (op->send_buffer, + GNOME_KEYRING_OP_GET_DEFAULT_KEYRING)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_string_reply; + return op; +} + +GnomeKeyringResult +gnome_keyring_get_default_keyring_sync (char **keyring) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *keyring = NULL; + + if (!gnome_keyring_proto_encode_op_only (send, + GNOME_KEYRING_OP_GET_DEFAULT_KEYRING)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_string_reply (receive, &res, keyring)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +static void +gnome_keyring_list_keyring_names_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetListCallback callback; + GList *names; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_result_string_list_reply (op->receive_buffer, &result, &names)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, names, op->user_data); + g_list_foreach (names, (GFunc) g_free, NULL); + g_list_free (names); + } +} + +gpointer +gnome_keyring_list_keyring_names (GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_LIST, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_only (op->send_buffer, + GNOME_KEYRING_OP_LIST_KEYRINGS)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_list_keyring_names_reply; + return op; +} + +GnomeKeyringResult +gnome_keyring_list_keyring_names_sync (GList **keyrings) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *keyrings = NULL; + + if (!gnome_keyring_proto_encode_op_only (send, + GNOME_KEYRING_OP_LIST_KEYRINGS)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_string_list_reply (receive, &res, keyrings)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_lock_all (GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_only (op->send_buffer, + GNOME_KEYRING_OP_LOCK_ALL)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + return op; +} + +GnomeKeyringResult +gnome_keyring_lock_all_sync (void) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_only (send, + GNOME_KEYRING_OP_LOCK_ALL)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + + + +/* NULL password means ask user */ +gpointer +gnome_keyring_create (const char *keyring_name, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_string (op->send_buffer, + GNOME_KEYRING_OP_CREATE_KEYRING, + keyring_name, password)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_create_sync (const char *keyring_name, + const char *password) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string_string (send, + GNOME_KEYRING_OP_CREATE_KEYRING, + keyring_name, password)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_unlock (const char *keyring, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_string (op->send_buffer, + GNOME_KEYRING_OP_UNLOCK_KEYRING, + keyring, password)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_unlock_sync (const char *keyring, + const char *password) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string_string (send, + GNOME_KEYRING_OP_UNLOCK_KEYRING, + keyring, password)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_lock (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string (op->send_buffer, + GNOME_KEYRING_OP_LOCK_KEYRING, + keyring)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_lock_sync (const char *keyring) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_LOCK_KEYRING, + keyring)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_delete (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string (op->send_buffer, + GNOME_KEYRING_OP_DELETE_KEYRING, + keyring)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_delete_sync (const char *keyring) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_DELETE_KEYRING, + keyring)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_change_password (const char *keyring, + const char *original, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_string_string (op->send_buffer, + GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD, + keyring, original, password)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_change_password_sync (const char *keyring_name, + const char *original, const char *password) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string_string_string (send, + GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD, + keyring_name, original, password)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +static void +gnome_keyring_get_keyring_info_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetKeyringInfoCallback callback; + GnomeKeyringInfo *info; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_get_keyring_info_reply (op->receive_buffer, &result, &info)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, info, op->user_data); + gnome_keyring_info_free (info); + } +} + +gpointer +gnome_keyring_get_info (const char *keyring, + GnomeKeyringOperationGetKeyringInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_KEYRING_INFO, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string (op->send_buffer, + GNOME_KEYRING_OP_GET_KEYRING_INFO, + keyring)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_get_keyring_info_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_get_info_sync (const char *keyring, + GnomeKeyringInfo **info) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *info = NULL; + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_GET_KEYRING_INFO, + keyring)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_get_keyring_info_reply (receive, &res, info)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_set_info (const char *keyring, + GnomeKeyringInfo *info, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_set_keyring_info (op->send_buffer, + keyring, info)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_set_info_sync (const char *keyring, + GnomeKeyringInfo *info) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_set_keyring_info (send, + keyring, info)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + g_string_free (receive, TRUE); + + return res; +} + +static void +gnome_keyring_list_item_ids_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetListCallback callback; + GList *items; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_result_int_list_reply (op->receive_buffer, &result, &items)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, items, op->user_data); + g_list_free (items); + } +} + +gpointer +gnome_keyring_list_item_ids (const char *keyring, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_LIST, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string (op->send_buffer, + GNOME_KEYRING_OP_LIST_ITEMS, + keyring)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_list_item_ids_reply; + return op; +} + +GnomeKeyringResult +gnome_keyring_list_item_ids_sync (const char *keyring, + GList **ids) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *ids = NULL; + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_LIST_ITEMS, + keyring)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_int_list_reply (receive, &res, ids)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +GnomeKeyringResult +gnome_keyring_daemon_set_display_sync (const char *display) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string (send, + GNOME_KEYRING_OP_SET_DAEMON_DISPLAY, + display)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_reply (receive, &res)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +void +gnome_keyring_info_set_lock_on_idle (GnomeKeyringInfo *keyring_info, + gboolean value) +{ + keyring_info->lock_on_idle = value; +} + +gboolean +gnome_keyring_info_get_lock_on_idle (GnomeKeyringInfo *keyring_info) +{ + return keyring_info->lock_on_idle; +} + +void +gnome_keyring_info_set_lock_timeout (GnomeKeyringInfo *keyring_info, + guint32 value) +{ + keyring_info->lock_timeout = value; +} + +guint32 +gnome_keyring_info_get_lock_timeout (GnomeKeyringInfo *keyring_info) +{ + return keyring_info->lock_timeout; +} + +time_t +gnome_keyring_info_get_mtime (GnomeKeyringInfo *keyring_info) +{ + return keyring_info->mtime; +} + +time_t +gnome_keyring_info_get_ctime (GnomeKeyringInfo *keyring_info) +{ + return keyring_info->ctime; +} + +gboolean +gnome_keyring_info_get_is_locked (GnomeKeyringInfo *keyring_info) +{ + return keyring_info->is_locked; +} + +static void +gnome_keyring_find_items_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetListCallback callback; + GList *found_items; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_find_reply (op->receive_buffer, &result, &found_items)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, found_items, op->user_data); + gnome_keyring_found_list_free (found_items); + } +} + +gpointer +gnome_keyring_find_items (GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_LIST, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_find (op->send_buffer, + type, + attributes)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_find_items_reply; + return op; +} + + +static GnomeKeyringAttributeList * +make_attribute_list_va (va_list args) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + char *str; + guint32 val; + + attributes = g_array_new (FALSE, FALSE, sizeof (GnomeKeyringAttribute)); + + while ((attribute.name = va_arg (args, char *)) != NULL) { + attribute.type = va_arg (args, GnomeKeyringAttributeType); + + switch (attribute.type) { + case GNOME_KEYRING_ATTRIBUTE_TYPE_STRING: + str = va_arg (args, char *); + attribute.value.string = str; + g_array_append_val (attributes, attribute); + break; + case GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32: + val = va_arg (args, guint32); + attribute.value.integer = val; + g_array_append_val (attributes, attribute); + break; + default: + g_array_free (attributes, TRUE); + return NULL; + } + } + return attributes; +} + + +gpointer +gnome_keyring_find_itemsv (GnomeKeyringItemType type, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data, + ...) +{ + GnomeKeyringOperation *op; + GnomeKeyringAttributeList *attributes; + va_list args; + + op = start_operation (callback, CALLBACK_GET_LIST, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + va_start (args, destroy_data); + attributes = make_attribute_list_va (args); + va_end (args); + if (attributes == NULL) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + return op; + } + + if (!gnome_keyring_proto_encode_find (op->send_buffer, + type, + attributes)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + g_array_free (attributes, TRUE); + + op->reply_handler = gnome_keyring_find_items_reply; + return op; +} + +/** + * gnome_keyring_find_items_sync: + * @type: a #GnomeKeyringItemType + * @attributes: a #GnomeKeyringAttributeList + * @found: a return location for the found items, must not be %NULL + * + * Find elements of type #GnomeKeyring by matching attributes and @type. + * + * Returns: %GNOME_KEYRING_RESULT_OK if everythink went fine. A #GList of + * #GnomeKeyringFound will be returned into @found, free all results with + * gnome_keyring_found_list_free() or every single item with + * gnome_keyring_found_free() + */ +GnomeKeyringResult +gnome_keyring_find_items_sync (GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes, + GList **found) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *found = NULL; + + if (!gnome_keyring_proto_encode_find (send, type, + attributes)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_find_reply (receive, &res, found)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +GnomeKeyringResult +gnome_keyring_find_itemsv_sync (GnomeKeyringItemType type, + GList **found, + ...) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringResult res; + va_list args; + + va_start (args, found); + attributes = make_attribute_list_va (args); + va_end (args); + if (attributes == NULL) { + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + res = gnome_keyring_find_items_sync (type, attributes, found); + g_array_free (attributes, TRUE); + return res; +} + + +gpointer +gnome_keyring_item_create (const char *keyring, + GnomeKeyringItemType type, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + gboolean update_if_exists, + GnomeKeyringOperationGetIntCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_INT, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_create_item (op->send_buffer, + keyring, + display_name, + attributes, + secret, + type, + update_if_exists)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_int_reply; + + return op; +} + +/** + * gnome_keyring_item_create_sync(): + * @keyring: the keyring name (%NULL for default) + * @type: the #GnomeKeyringItemType of the item to save + * @display_name: the name for this item to be used in the password manager + * @attributes: the attributes specifying the keyring item + * @secret: the secret information (password, passphrase, pin, etc) to be saved + * @update_if_exists: set to %TRUE to update an existing item, if found. Create + * a new one otherwise. Only item @attributes are matched. + * @item_id: return location for the id of the created/updated keyring item. + * + * Create (or update of @update_if_exists is set) a keyring item with the + * specified type, attributes and secret. + * + * Returns %GNOME_KEYRING_RESULT_OK if everything went fine. + */ +GnomeKeyringResult +gnome_keyring_item_create_sync (const char *keyring, + GnomeKeyringItemType type, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + gboolean update_if_exists, + guint32 *item_id) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *item_id = 0; + + if (!gnome_keyring_proto_encode_create_item (send, + keyring, + display_name, + attributes, + secret, + type, + update_if_exists)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_result_integer_reply (receive, &res, item_id)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_item_delete (const char *keyring, + guint32 id, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_int (op->send_buffer, + GNOME_KEYRING_OP_DELETE_ITEM, + keyring, id)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +/** + * gnome_keyring_item_delete_sync(): + * @keyring: the keyring to work with (%NULL for the default keyring) + * @id: the keyring item id to delete + * + * Deletes an item from your keyring. Obtain @id by calling a function like + * gnome_keyring_find_items_sync() or gnome_keyring_item_create_sync(). + * + * Returns %GNOME_KEYRING_RESULT_OK on success, the error code otherwise. + */ +GnomeKeyringResult +gnome_keyring_item_delete_sync (const char *keyring, + guint32 id) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_op_string_int (send, + GNOME_KEYRING_OP_DELETE_ITEM, + keyring, + id)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + g_string_free (receive, TRUE); + + return res; +} + +static void +gnome_keyring_get_item_info_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetItemInfoCallback callback; + GnomeKeyringItemInfo *info; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_get_item_info_reply (op->receive_buffer, &result, &info)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, info, op->user_data); + gnome_keyring_item_info_free (info); + } +} + +gpointer +gnome_keyring_item_get_info (const char *keyring, + guint32 id, + GnomeKeyringOperationGetItemInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_ITEM_INFO, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_int (op->send_buffer, + GNOME_KEYRING_OP_GET_ITEM_INFO, + keyring, id)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_get_item_info_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_get_info_sync (const char *keyring, + guint32 id, + GnomeKeyringItemInfo **info) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *info = NULL; + + if (!gnome_keyring_proto_encode_op_string_int (send, + GNOME_KEYRING_OP_GET_ITEM_INFO, + keyring, id)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_get_item_info_reply (receive, &res, info)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_item_get_info_full (const char *keyring, + guint32 id, + guint32 flags, + GnomeKeyringOperationGetItemInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_ITEM_INFO, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_int_int (op->send_buffer, + GNOME_KEYRING_OP_GET_ITEM_INFO_FULL, + keyring, id, flags)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_get_item_info_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_get_info_full_sync (const char *keyring, + guint32 id, + guint32 flags, + GnomeKeyringItemInfo **info) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *info = NULL; + + if (!gnome_keyring_proto_encode_op_string_int_int (send, + GNOME_KEYRING_OP_GET_ITEM_INFO_FULL, + keyring, id, flags)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_get_item_info_reply (receive, &res, info)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_item_set_info (const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_set_item_info (op->send_buffer, + keyring, id, info)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_set_info_sync (const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_set_item_info (send, + keyring, id, info)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + g_string_free (receive, TRUE); + + return res; +} + +static void +gnome_keyring_get_attributes_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetAttributesCallback callback; + GnomeKeyringAttributeList *attributes; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_get_attributes_reply (op->receive_buffer, &result, &attributes)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, attributes, op->user_data); + gnome_keyring_attribute_list_free (attributes); + } +} + +static void +gnome_keyring_get_acl_reply (GnomeKeyringOperation *op) +{ + GnomeKeyringResult result; + GnomeKeyringOperationGetListCallback callback; + GList *acl; + + callback = op->user_callback; + + if (!gnome_keyring_proto_decode_get_acl_reply (op->receive_buffer, &result, &acl)) { + (*callback) (GNOME_KEYRING_RESULT_IO_ERROR, NULL, op->user_data); + } else { + (*callback) (result, acl, op->user_data); + g_list_free (acl); + } +} + + +gpointer +gnome_keyring_item_get_attributes (const char *keyring, + guint32 id, + GnomeKeyringOperationGetAttributesCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_ATTRIBUTES, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_int (op->send_buffer, + GNOME_KEYRING_OP_GET_ITEM_ATTRIBUTES, + keyring, id)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_get_attributes_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_get_attributes_sync (const char *keyring, + guint32 id, + GnomeKeyringAttributeList **attributes) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *attributes = NULL; + + if (!gnome_keyring_proto_encode_op_string_int (send, + GNOME_KEYRING_OP_GET_ITEM_ATTRIBUTES, + keyring, id)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_get_attributes_reply (receive, &res, attributes)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_item_set_attributes (const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_set_attributes (op->send_buffer, + keyring, id, + attributes)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_set_attributes_sync (const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_set_attributes (send, + keyring, id, + attributes)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + g_string_free (receive, TRUE); + + return res; + +} + +gpointer +gnome_keyring_item_get_acl (const char *keyring, + guint32 id, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_GET_ACL, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_op_string_int (op->send_buffer, + GNOME_KEYRING_OP_GET_ITEM_ACL, + keyring, id)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_get_acl_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_get_acl_sync (const char *keyring, + guint32 id, + GList **acl) +{ + GString *send; + GString *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + *acl = NULL; + + if (!gnome_keyring_proto_encode_op_string_int (send, + GNOME_KEYRING_OP_GET_ITEM_ACL, + keyring, id)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + if (res != GNOME_KEYRING_RESULT_OK) { + g_string_free (receive, TRUE); + return res; + } + + if (!gnome_keyring_proto_decode_get_acl_reply (receive, &res, acl)) { + g_string_free (receive, TRUE); + return GNOME_KEYRING_RESULT_IO_ERROR; + } + g_string_free (receive, TRUE); + + return res; +} + +gpointer +gnome_keyring_item_set_acl (const char *keyring, + guint32 id, + GList *acl, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringOperation *op; + + op = start_operation (callback, CALLBACK_DONE, data, destroy_data); + if (op->state == STATE_FAILED) { + return op; + } + + if (!gnome_keyring_proto_encode_set_acl (op->send_buffer, + keyring, id, + acl)) { + schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + } + + op->reply_handler = gnome_keyring_standard_reply; + + return op; +} + +GnomeKeyringResult +gnome_keyring_item_set_acl_sync (const char *keyring, + guint32 id, + GList *acl) +{ + GString *send, *receive; + GnomeKeyringResult res; + + send = g_string_new (NULL); + + if (!gnome_keyring_proto_encode_set_acl (send, + keyring, id, + acl)) { + g_string_free (send, TRUE); + return GNOME_KEYRING_RESULT_BAD_ARGUMENTS; + } + + receive = g_string_new (NULL); + res = run_sync_operation (send, receive); + g_string_free (send, TRUE); + g_string_free (receive, TRUE); + + return res; +} + +GnomeKeyringResult +gnome_keyring_item_grant_access_rights_sync (const char *keyring, + const char *display_name, + const char *full_path, + const guint32 id, + const GnomeKeyringAccessType rights) +{ + GList *acl_list = NULL; + GnomeKeyringApplicationRef new_app_ref; + GnomeKeyringAccessControl acl; + GnomeKeyringResult res; + + /* setup application structure */ + new_app_ref.display_name = (char *) display_name; + new_app_ref.pathname = (char *) full_path; + acl.application = &new_app_ref; + acl.types_allowed = rights; + + /* get the original acl list */ + res = gnome_keyring_item_get_acl_sync (keyring, + id, + &acl_list); + if (GNOME_KEYRING_RESULT_OK != res) + goto out; + + /* append access rights */ + acl_list = g_list_append (acl_list, (gpointer) &acl); + res = gnome_keyring_item_set_acl_sync (keyring, + id, + acl_list); +out: + if (acl_list) + g_list_free (acl_list); + + return res; +} + +GnomeKeyringItemType +gnome_keyring_item_info_get_type (GnomeKeyringItemInfo *item_info) +{ + return item_info->type; +} + +void +gnome_keyring_item_info_set_type (GnomeKeyringItemInfo *item_info, + GnomeKeyringItemType type) +{ + item_info->type = type; +} + +char * +gnome_keyring_item_info_get_secret (GnomeKeyringItemInfo *item_info) +{ + return g_strdup (item_info->secret); +} + +void +gnome_keyring_item_info_set_secret (GnomeKeyringItemInfo *item_info, + const char *value) +{ + g_free (item_info->secret); + item_info->secret = g_strdup (value); +} + +char * +gnome_keyring_item_info_get_display_name (GnomeKeyringItemInfo *item_info) +{ + return g_strdup (item_info->display_name); +} + +void +gnome_keyring_item_info_set_display_name (GnomeKeyringItemInfo *item_info, + const char *value) +{ + g_free (item_info->display_name); + item_info->display_name = g_strdup (value); +} + +time_t +gnome_keyring_item_info_get_mtime (GnomeKeyringItemInfo *item_info) +{ + return item_info->mtime; +} + +time_t +gnome_keyring_item_info_get_ctime (GnomeKeyringItemInfo *item_info) +{ + return item_info->ctime; +} + +char * +gnome_keyring_item_ac_get_display_name (GnomeKeyringAccessControl *ac) +{ + return g_strdup (ac->application->display_name); +} + +void +gnome_keyring_item_ac_set_display_name (GnomeKeyringAccessControl *ac, + const char *value) +{ + g_free (ac->application->display_name); + ac->application->display_name = g_strdup (value); +} + +char * +gnome_keyring_item_ac_get_path_name (GnomeKeyringAccessControl *ac) +{ + return g_strdup (ac->application->pathname); +} + +void +gnome_keyring_item_ac_set_path_name (GnomeKeyringAccessControl *ac, + const char *value) +{ + g_free (ac->application->pathname); + ac->application->pathname = g_strdup (value); +} + +GnomeKeyringAccessType +gnome_keyring_item_ac_get_access_type (GnomeKeyringAccessControl *ac) +{ + return ac->types_allowed; +} + +void +gnome_keyring_item_ac_set_access_type (GnomeKeyringAccessControl *ac, + const GnomeKeyringAccessType value) +{ + ac->types_allowed = value; +} + + +struct FindNetworkPasswordInfo { + GnomeKeyringOperationGetListCallback callback; + gpointer data; + GDestroyNotify destroy_data; +}; + +static void +free_find_network_password_info (struct FindNetworkPasswordInfo *info) +{ + if (info->destroy_data != NULL) { + info->destroy_data (info->data); + } + g_free (info); +} + +static GList * +found_list_to_nework_password_list (GList *found_list) +{ + GnomeKeyringNetworkPasswordData *data; + GnomeKeyringFound *found; + GnomeKeyringAttribute *attributes; + GList *result, *l; + int i; + + result = NULL; + for (l = found_list; l != NULL; l = l->next) { + found = l->data; + + data = g_new0 (GnomeKeyringNetworkPasswordData, 1); + + result = g_list_prepend (result, data); + + data->keyring = g_strdup (found->keyring); + data->item_id = found->item_id; + data->password = g_strdup (found->secret); + + attributes = (GnomeKeyringAttribute *) found->attributes->data; + for (i = 0; i < found->attributes->len; i++) { + if (strcmp (attributes[i].name, "user") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->user = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "domain") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->domain = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "server") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->server = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "object") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->object = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "protocol") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->protocol = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "authtype") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + data->authtype = g_strdup (attributes[i].value.string); + } else if (strcmp (attributes[i].name, "port") == 0 && + attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { + data->port = attributes[i].value.integer; + } + } + } + + return g_list_reverse (result); +} + +void +gnome_keyring_network_password_free (GnomeKeyringNetworkPasswordData *data) +{ + g_free (data->keyring); + g_free (data->protocol); + g_free (data->server); + g_free (data->object); + g_free (data->authtype); + g_free (data->user); + g_free (data->domain); + g_free (data->password); + + g_free (data); +} + +void +gnome_keyring_network_password_list_free (GList *list) +{ + g_list_foreach (list, (GFunc)gnome_keyring_network_password_free, NULL); + g_list_free (list); +} + +static void +find_network_password_callback (GnomeKeyringResult result, + GList *list, + gpointer data) +{ + struct FindNetworkPasswordInfo *info; + GList *data_list; + + info = data; + + data_list = NULL; + if (result == GNOME_KEYRING_RESULT_OK) { + data_list = found_list_to_nework_password_list (list); + } + info->callback (result, data_list, info->data); + gnome_keyring_network_password_list_free (data_list); + return; +} + +/** + * gnome_keyring_attribute_list_append_string(): + * @attributes: a #GnomeKeyringAttributeList + * @attributename: the name of the new attribute + * @value: the value to store in @attributes + * + * Store a key-value-pair with a string value in @attributes. + */ +void +gnome_keyring_attribute_list_append_string (GnomeKeyringAttributeList *attributes, + const char *attributename, const char *value) +{ + GnomeKeyringAttribute attribute; + + attribute.name = g_strdup (attributename); + attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; + attribute.value.string = g_strdup (value); + + g_array_append_val (attributes, attribute); +} + +/** + * gnome_keyring_attribute_append_uint32: + * @attributes: a #GnomeKeyringAttributeList + * @attributename: the name of the new attribute + * @value: the value to store in @attributes + * + * Store a key-value-pair with an unsigned 32bit number value in @attributes. + */ +void +gnome_keyring_attribute_list_append_uint32 (GnomeKeyringAttributeList *attributes, + const char *attributename, guint32 value) +{ + GnomeKeyringAttribute attribute; + + attribute.name = g_strdup (attributename); + attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32; + attribute.value.integer = value; + g_array_append_val (attributes, attribute); +} + +static GnomeKeyringAttributeList * +make_attribute_list_for_network_password (const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port) +{ + GnomeKeyringAttributeList *attributes; + + attributes = g_array_new (FALSE, FALSE, sizeof (GnomeKeyringAttribute)); + + if (user != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "user", user); + } + if (domain != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "domain", domain); + } + if (server != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "server", server); + } + if (object != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "object", object); + } + if (protocol != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "protocol", protocol); + } + if (authtype != NULL) { + gnome_keyring_attribute_list_append_string (attributes, "authtype", authtype); + } + if (port != 0) { + gnome_keyring_attribute_list_append_uint32 (attributes, "port", port); + } + return attributes; +} + + +gpointer +gnome_keyring_find_network_password (const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + GnomeKeyringOperationGetListCallback callback, + gpointer user_data, + GDestroyNotify destroy_data) +{ + GnomeKeyringAttributeList *attributes; + gpointer request; + struct FindNetworkPasswordInfo *info; + + info = g_new0 (struct FindNetworkPasswordInfo, 1); + info->callback = callback; + info->data = user_data; + info->destroy_data = destroy_data; + + attributes = make_attribute_list_for_network_password (user, + domain, + server, + object, + protocol, + authtype, + port); + + request = gnome_keyring_find_items (GNOME_KEYRING_ITEM_NETWORK_PASSWORD, + attributes, + find_network_password_callback, + info, + (GDestroyNotify)free_find_network_password_info); + + gnome_keyring_attribute_list_free (attributes); + return request; +} + + + +GnomeKeyringResult +gnome_keyring_find_network_password_sync (const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + GList **out_list) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringResult result; + GList *found; + + *out_list = NULL; + attributes = make_attribute_list_for_network_password (user, + domain, + server, + object, + protocol, + authtype, + port); + + result = gnome_keyring_find_items_sync (GNOME_KEYRING_ITEM_NETWORK_PASSWORD, + attributes, + &found); + + gnome_keyring_attribute_list_free (attributes); + + if (result == GNOME_KEYRING_RESULT_OK) { + *out_list = found_list_to_nework_password_list (found); + gnome_keyring_found_list_free (found); + } + + return result; +} + +static char * +get_network_password_display_name (const char *user, + const char *server, + const char *object, + guint32 port) +{ + GString *s; + char *name; + + if (server != NULL) { + s = g_string_new (NULL); + if (user != NULL) { + g_string_append_printf (s, "%s@", user); + } + g_string_append (s, server); + if (port != 0) { + g_string_append_printf (s, ":%d", port); + } + if (object != NULL) { + g_string_append_printf (s, "/%s", object); + } + name = g_string_free (s, FALSE); + } else { + name = g_strdup ("network password"); + } + return name; +} + + + +gpointer +gnome_keyring_set_network_password (const char *keyring, + const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + const char *password, + GnomeKeyringOperationGetIntCallback callback, + gpointer data, + GDestroyNotify destroy_data) +{ + GnomeKeyringAttributeList *attributes; + gpointer req; + char *name; + + name = get_network_password_display_name (user, server, object, port); + + attributes = make_attribute_list_for_network_password (user, + domain, + server, + object, + protocol, + authtype, + port); + + req = gnome_keyring_item_create (keyring, + GNOME_KEYRING_ITEM_NETWORK_PASSWORD, + name, + attributes, + password, + TRUE, + callback, data, destroy_data); + + gnome_keyring_attribute_list_free (attributes); + g_free (name); + + return req; +} + +GnomeKeyringResult +gnome_keyring_set_network_password_sync (const char *keyring, + const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + const char *password, + guint32 *item_id) +{ + GnomeKeyringAttributeList *attributes; + char *name; + GnomeKeyringResult res; + + name = get_network_password_display_name (user, server, object, port); + attributes = make_attribute_list_for_network_password (user, + domain, + server, + object, + protocol, + authtype, + port); + + res = gnome_keyring_item_create_sync (keyring, + GNOME_KEYRING_ITEM_NETWORK_PASSWORD, + name, + attributes, + password, + TRUE, + item_id); + + gnome_keyring_attribute_list_free (attributes); + g_free (name); + + return res; +} diff --git a/library/gnome-keyring.h b/library/gnome-keyring.h new file mode 100644 index 00000000..1739b8a0 --- /dev/null +++ b/library/gnome-keyring.h @@ -0,0 +1,459 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gnome-keyring.h - library for talking to the keyring daemon. + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Keyring Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Keyring Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ + +#ifndef GNOME_KEYRING_H +#define GNOME_KEYRING_H + +#include <glib.h> +#include <time.h> + +typedef enum { + GNOME_KEYRING_RESULT_OK, + GNOME_KEYRING_RESULT_DENIED, + GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON, + GNOME_KEYRING_RESULT_ALREADY_UNLOCKED, + GNOME_KEYRING_RESULT_NO_SUCH_KEYRING, + GNOME_KEYRING_RESULT_BAD_ARGUMENTS, + GNOME_KEYRING_RESULT_IO_ERROR, + GNOME_KEYRING_RESULT_CANCELLED, + GNOME_KEYRING_RESULT_ALREADY_EXISTS +} GnomeKeyringResult; + +typedef enum { + /* The item types */ + GNOME_KEYRING_ITEM_GENERIC_SECRET, + GNOME_KEYRING_ITEM_NETWORK_PASSWORD, + GNOME_KEYRING_ITEM_NOTE, + + /* Used internally */ + GNOME_KEYRING_ITEM_LAST_TYPE, + GNOME_KEYRING_ITEM_TYPE_MASK = 0x0000ffff, + GNOME_KEYRING_ITEM_NO_TYPE = GNOME_KEYRING_ITEM_TYPE_MASK, + + /* Makes a item only for applications in ACL */ + GNOME_KEYRING_ITEM_APPLICATION_SECRET = 0x01000000, + +} GnomeKeyringItemType; + +typedef enum { + GNOME_KEYRING_ACCESS_ASK, + GNOME_KEYRING_ACCESS_DENY, + GNOME_KEYRING_ACCESS_ALLOW +} GnomeKeyringAccessRestriction; + +typedef enum { + GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, + GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 +} GnomeKeyringAttributeType; + +typedef struct GnomeKeyringAccessControl GnomeKeyringAccessControl; +typedef struct GnomeKeyringApplicationRef GnomeKeyringApplicationRef; +typedef GArray GnomeKeyringAttributeList; + +typedef enum { + GNOME_KEYRING_ACCESS_READ = 1<<0, + GNOME_KEYRING_ACCESS_WRITE = 1<<1, + GNOME_KEYRING_ACCESS_REMOVE = 1<<2 +} GnomeKeyringAccessType; + +typedef enum { + GNOME_KEYRING_ITEM_INFO_BASICS = 0, + GNOME_KEYRING_ITEM_INFO_SECRET = 1<<0 +} GnomeKeyringItemInfoFlags; + +/* Add flags here as they are added above */ +#define GNOME_KEYRING_ITEM_INFO_ALL (GNOME_KEYRING_ITEM_INFO_BASICS | GNOME_KEYRING_ITEM_INFO_SECRET) + +typedef struct GnomeKeyringInfo GnomeKeyringInfo; +typedef struct GnomeKeyringItemInfo GnomeKeyringItemInfo; + +typedef struct { + char *name; + GnomeKeyringAttributeType type; + union { + char *string; + guint32 integer; + } value; +} GnomeKeyringAttribute; + +typedef struct { + char *keyring; + guint item_id; + GnomeKeyringAttributeList *attributes; + char *secret; +} GnomeKeyringFound; + +typedef void (*GnomeKeyringOperationDoneCallback) (GnomeKeyringResult result, + gpointer data); +typedef void (*GnomeKeyringOperationGetStringCallback) (GnomeKeyringResult result, + const char *string, + gpointer data); +typedef void (*GnomeKeyringOperationGetIntCallback) (GnomeKeyringResult result, + guint32 val, + gpointer data); +typedef void (*GnomeKeyringOperationGetListCallback) (GnomeKeyringResult result, + GList *list, + gpointer data); +typedef void (*GnomeKeyringOperationGetKeyringInfoCallback) (GnomeKeyringResult result, + GnomeKeyringInfo *info, + gpointer data); +typedef void (*GnomeKeyringOperationGetItemInfoCallback) (GnomeKeyringResult result, + GnomeKeyringItemInfo*info, + gpointer data); +typedef void (*GnomeKeyringOperationGetAttributesCallback) (GnomeKeyringResult result, + GnomeKeyringAttributeList *attributes, + gpointer data); + +#define gnome_keyring_attribute_list_index(a, i) g_array_index ((a), GnomeKeyringAttribute, (i)) +#define gnome_keyring_attribute_list_new() (g_array_new (FALSE, FALSE, sizeof (GnomeKeyringAttribute))) +void gnome_keyring_attribute_list_append_string (GnomeKeyringAttributeList *attributes, + const char *attribute, + const char *value); +void gnome_keyring_attribute_list_append_uint32 (GnomeKeyringAttributeList *attributes, + const char *attribute, + guint32 value); +void gnome_keyring_attribute_list_free (GnomeKeyringAttributeList *attributes); +GnomeKeyringAttributeList *gnome_keyring_attribute_list_copy (GnomeKeyringAttributeList *attributes); + + +gboolean gnome_keyring_is_available (void); + +void gnome_keyring_free_password (char *password); + +void gnome_keyring_found_free (GnomeKeyringFound *found); +void gnome_keyring_found_list_free (GList *found_list); + +void gnome_keyring_cancel_request (gpointer request); + +gpointer gnome_keyring_set_default_keyring (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_set_default_keyring_sync (const char *keyring); +gpointer gnome_keyring_get_default_keyring (GnomeKeyringOperationGetStringCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_get_default_keyring_sync (char **keyring); +gpointer gnome_keyring_list_keyring_names (GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_list_keyring_names_sync (GList **keyrings); +gpointer gnome_keyring_lock_all (GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_lock_all_sync (void); + + +/* NULL password means ask user */ +gpointer gnome_keyring_create (const char *keyring_name, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_create_sync (const char *keyring_name, + const char *password); +gpointer gnome_keyring_unlock (const char *keyring, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_unlock_sync (const char *keyring, + const char *password); +gpointer gnome_keyring_lock (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_lock_sync (const char *keyring); +gpointer gnome_keyring_delete (const char *keyring, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_delete_sync (const char *keyring); +gpointer gnome_keyring_change_password (const char *keyring, + const char *original, + const char *password, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_change_password_sync (const char *keyring, + const char *original, + const char *password); +gpointer gnome_keyring_get_info (const char *keyring, + GnomeKeyringOperationGetKeyringInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_get_info_sync (const char *keyring, + GnomeKeyringInfo **info); +gpointer gnome_keyring_set_info (const char *keyring, + GnomeKeyringInfo *info, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_set_info_sync (const char *keyring, + GnomeKeyringInfo *info); +gpointer gnome_keyring_list_item_ids (const char *keyring, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_list_item_ids_sync (const char *keyring, + GList **ids); + +GnomeKeyringResult gnome_keyring_daemon_set_display_sync (const char *display); + + +void gnome_keyring_info_free (GnomeKeyringInfo *keyring_info); +GnomeKeyringInfo *gnome_keyring_info_copy (GnomeKeyringInfo *keyring_info); +void gnome_keyring_info_set_lock_on_idle (GnomeKeyringInfo *keyring_info, + gboolean value); +gboolean gnome_keyring_info_get_lock_on_idle (GnomeKeyringInfo *keyring_info); +void gnome_keyring_info_set_lock_timeout (GnomeKeyringInfo *keyring_info, + guint32 value); +guint32 gnome_keyring_info_get_lock_timeout (GnomeKeyringInfo *keyring_info); +time_t gnome_keyring_info_get_mtime (GnomeKeyringInfo *keyring_info); +time_t gnome_keyring_info_get_ctime (GnomeKeyringInfo *keyring_info); +gboolean gnome_keyring_info_get_is_locked (GnomeKeyringInfo *keyring_info); + +gpointer gnome_keyring_find_items (GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data); +gpointer gnome_keyring_find_itemsv (GnomeKeyringItemType type, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data, + ...); + +GnomeKeyringResult gnome_keyring_find_items_sync (GnomeKeyringItemType type, + GnomeKeyringAttributeList *attributes, + GList **found); +GnomeKeyringResult gnome_keyring_find_itemsv_sync (GnomeKeyringItemType type, + GList **found, + ...); + +gpointer gnome_keyring_item_create (const char *keyring, + GnomeKeyringItemType type, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + gboolean update_if_exists, + GnomeKeyringOperationGetIntCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_create_sync (const char *keyring, + GnomeKeyringItemType type, + const char *display_name, + GnomeKeyringAttributeList *attributes, + const char *secret, + gboolean update_if_exists, + guint32 *item_id); +gpointer gnome_keyring_item_delete (const char *keyring, + guint32 id, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_delete_sync (const char *keyring, + guint32 id); +gpointer gnome_keyring_item_get_info (const char *keyring, + guint32 id, + GnomeKeyringOperationGetItemInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_get_info_sync (const char *keyring, + guint32 id, + GnomeKeyringItemInfo **info); +gpointer gnome_keyring_item_get_info_full (const char *keyring, + guint32 id, + guint32 flags, + GnomeKeyringOperationGetItemInfoCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_get_info_full_sync (const char *keyring, + guint32 id, + guint32 flags, + GnomeKeyringItemInfo **info); +gpointer gnome_keyring_item_set_info (const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_set_info_sync (const char *keyring, + guint32 id, + GnomeKeyringItemInfo *info); +gpointer gnome_keyring_item_get_attributes (const char *keyring, + guint32 id, + GnomeKeyringOperationGetAttributesCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_get_attributes_sync (const char *keyring, + guint32 id, + GnomeKeyringAttributeList **attributes); +gpointer gnome_keyring_item_set_attributes (const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_set_attributes_sync (const char *keyring, + guint32 id, + GnomeKeyringAttributeList *attributes); +gpointer gnome_keyring_item_get_acl (const char *keyring, + guint32 id, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_get_acl_sync (const char *keyring, + guint32 id, + GList **acl); +gpointer gnome_keyring_item_set_acl (const char *keyring, + guint32 id, + GList *acl, + GnomeKeyringOperationDoneCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_item_set_acl_sync (const char *keyring, + guint32 id, + GList *acl); + +/* + * Will grant the application access rights to the item, provided + * callee has, or is granted, write access to said item. + * + * keyring : Name of keyring to access or NULL for default keyring + * display_name : Display name of application to be granted access rights - As returned by g_get_application_name() + * full_path : Full path of application to be granted access rights + * id : ID of item to access in keyring + * rights : Bitmask of rights to grant the application + */ +GnomeKeyringResult gnome_keyring_item_grant_access_rights_sync (const char *keyring, + const char *display_name, + const char *full_path, + const guint32 id, + const GnomeKeyringAccessType rights); + +void gnome_keyring_item_info_free (GnomeKeyringItemInfo *item_info); +GnomeKeyringItemInfo *gnome_keyring_item_info_new (void); +GnomeKeyringItemInfo *gnome_keyring_item_info_copy (GnomeKeyringItemInfo *item_info); +GnomeKeyringItemType gnome_keyring_item_info_get_type (GnomeKeyringItemInfo *item_info); +void gnome_keyring_item_info_set_type (GnomeKeyringItemInfo *item_info, + GnomeKeyringItemType type); +char * gnome_keyring_item_info_get_secret (GnomeKeyringItemInfo *item_info); +void gnome_keyring_item_info_set_secret (GnomeKeyringItemInfo *item_info, + const char *value); +char * gnome_keyring_item_info_get_display_name (GnomeKeyringItemInfo *item_info); +void gnome_keyring_item_info_set_display_name (GnomeKeyringItemInfo *item_info, + const char *value); +time_t gnome_keyring_item_info_get_mtime (GnomeKeyringItemInfo *item_info); +time_t gnome_keyring_item_info_get_ctime (GnomeKeyringItemInfo *item_info); + +GnomeKeyringApplicationRef * gnome_keyring_application_ref_new (void); +GnomeKeyringApplicationRef * gnome_keyring_application_ref_copy (const GnomeKeyringApplicationRef *app); +void gnome_keyring_application_ref_free (GnomeKeyringApplicationRef *app); + +GnomeKeyringAccessControl * gnome_keyring_access_control_new (const GnomeKeyringApplicationRef *application, + GnomeKeyringAccessType types_allowed); +GnomeKeyringAccessControl * gnome_keyring_access_control_copy (GnomeKeyringAccessControl *ac); + + +void gnome_keyring_access_control_free (GnomeKeyringAccessControl *ac); +GList * gnome_keyring_acl_copy (GList *list); +void gnome_keyring_acl_free (GList *acl); + + +char * gnome_keyring_item_ac_get_display_name (GnomeKeyringAccessControl *ac); +void gnome_keyring_item_ac_set_display_name (GnomeKeyringAccessControl *ac, + const char *value); + +char * gnome_keyring_item_ac_get_path_name (GnomeKeyringAccessControl *ac); +void gnome_keyring_item_ac_set_path_name (GnomeKeyringAccessControl *ac, + const char *value); + + +GnomeKeyringAccessType gnome_keyring_item_ac_get_access_type (GnomeKeyringAccessControl *ac); +void gnome_keyring_item_ac_set_access_type (GnomeKeyringAccessControl *ac, + const GnomeKeyringAccessType value); + +/* Specialized Helpers for network passwords items */ + +typedef struct { + char *keyring; + guint32 item_id; + + char *protocol; + char *server; + char *object; + char *authtype; + guint32 port; + + char *user; + char *domain; + char *password; +} GnomeKeyringNetworkPasswordData; + +void gnome_keyring_network_password_free (GnomeKeyringNetworkPasswordData *data); +void gnome_keyring_network_password_list_free (GList *list); + +gpointer gnome_keyring_find_network_password (const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + GnomeKeyringOperationGetListCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_find_network_password_sync (const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + GList **result); +gpointer gnome_keyring_set_network_password (const char *keyring, + const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + const char *password, + GnomeKeyringOperationGetIntCallback callback, + gpointer data, + GDestroyNotify destroy_data); +GnomeKeyringResult gnome_keyring_set_network_password_sync (const char *keyring, + const char *user, + const char *domain, + const char *server, + const char *object, + const char *protocol, + const char *authtype, + guint32 port, + const char *password, + guint32 *item_id); + + +#endif /* GNOME_KEYRING_H */ diff --git a/library/list-keyrings.c b/library/list-keyrings.c new file mode 100644 index 00000000..8c6219c0 --- /dev/null +++ b/library/list-keyrings.c @@ -0,0 +1,225 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* list-keyrings.c - test app to list keyrings + + Copyright (C) 2003 Red Hat, Inc + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Alexander Larsson <alexl@redhat.com> +*/ +#include "gnome-keyring.h" + +static GMainLoop *loop = NULL; + + +static void +string_callback (GnomeKeyringResult result, + const char *str, + gpointer data) +{ + char **out; + + out = data; + + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("string op failed: %d\n", result); + *out = NULL; + } else { + *out = g_strdup (str); + } + g_main_loop_quit (loop); +} + + +static void +print_keyring_info (GnomeKeyringResult result, + GnomeKeyringInfo *info, + gpointer data) +{ + gboolean *locked; + locked = data; + + *locked = TRUE; + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting keyring info: %d\n", result); + } else { + g_print ("lock_on_idle: %d\n", gnome_keyring_info_get_lock_on_idle (info)); + g_print ("lock timeout: %d\n", gnome_keyring_info_get_lock_timeout (info)); + g_print ("mtime: %lu\n", (unsigned long)gnome_keyring_info_get_mtime (info)); + g_print ("ctime: %lu\n", (unsigned long)gnome_keyring_info_get_ctime (info)); + g_print ("locked: %d\n", gnome_keyring_info_get_is_locked (info)); + *locked = gnome_keyring_info_get_is_locked (info); + } + + g_main_loop_quit (loop); +} + +static void +print_item_info (GnomeKeyringResult result, + GnomeKeyringItemInfo *info, + gpointer data) +{ + char *secret; + char *name; + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting item info: %d\n", result); + } else { + name = gnome_keyring_item_info_get_display_name (info); + secret = gnome_keyring_item_info_get_secret (info); + g_print (" type: %u\n", gnome_keyring_item_info_get_type (info)); + g_print (" name: %s\n", name); + g_print (" secret: %s\n", secret); + g_print (" mtime: %lu\n", (unsigned long)gnome_keyring_item_info_get_mtime (info)); + g_print (" ctime: %lu\n", (unsigned long)gnome_keyring_item_info_get_ctime (info)); + gnome_keyring_free_password (secret); + g_free (name); + } + + g_main_loop_quit (loop); +} + +static void +print_attributes (GnomeKeyringResult result, + GnomeKeyringAttributeList *attributes, + gpointer data) +{ + GnomeKeyringAttribute *array; + int i; + + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting item attributes: %d\n", result); + } else { + array = (GnomeKeyringAttribute *)attributes->data; + g_print (" Attributes:\n"); + for (i = 0; i < attributes->len; i++) { + if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + g_print (" %s = '%s'\n", array[i].name, array[i].value.string); + } else if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { + g_print (" %s = %u\n", array[i].name, array[i].value.integer); + } else { + g_print (" %s = ** unsupported attribute type **\n", array[i].name); + } + } + } + + g_main_loop_quit (loop); +} + +static void +get_items_callback (GnomeKeyringResult result, + GList *list, + gpointer data) +{ + GList **out; + + out = data; + *out = NULL; + + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting item list: %d\n", result); + } else { + *out = g_list_copy (list); + } + + g_main_loop_quit (loop); +} + +static void +string_list_callback (GnomeKeyringResult result, + GList *list, + gpointer data) +{ + GList *l; + char *name; + GList **out; + + out = data; + + *out = NULL; + + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting keyring list: %d\n", result); + } else { + for (l = list; l != NULL; l = l->next) { + name = l->data; + *out = g_list_append (*out, g_strdup (name)); + } + } + + g_main_loop_quit (loop); +} + + +int +main (int argc, char *argv[]) +{ + GList *keyrings, *l, *items, *ll; + char *keyring; + gboolean locked; + guint32 item_id; + + g_set_application_name("list-keyrings"); + loop = g_main_loop_new (NULL, FALSE); + + g_print ("Keyrings:\n"); + gnome_keyring_list_keyring_names (string_list_callback, &keyrings, NULL); + g_main_loop_run (loop); + for (l = keyrings; l != NULL; l = l->next) { + keyring = l->data; + g_print ("\nkeyring: %s\n", keyring); + + gnome_keyring_get_info (keyring, print_keyring_info, &locked, NULL); + g_main_loop_run (loop); + + if (1 || !locked) { + gnome_keyring_list_item_ids (keyring, get_items_callback, &items, NULL); + g_main_loop_run (loop); + + if (items != NULL) { + g_print ("Items: \n"); + } + for (ll = items; ll != NULL; ll = ll->next) { + item_id = GPOINTER_TO_UINT(ll->data); + + g_print ("\n"); + g_print (" id: %u\n", item_id); + gnome_keyring_item_get_info (keyring, + item_id, + print_item_info, NULL, NULL); + g_main_loop_run (loop); + gnome_keyring_item_get_attributes (keyring, + item_id, + print_attributes, NULL, NULL); + g_main_loop_run (loop); + } + g_list_free (items); + } + + g_free (keyring); + } + g_list_free (keyrings); + + gnome_keyring_get_default_keyring (string_callback, &keyring, NULL); + g_main_loop_run (loop); + g_print ("\n"); + if (keyring != NULL) { + g_print ("The default keyring for storage is '%s'\n", keyring); + } else { + g_print ("No default keyring defined\n"); + } + + return 0; +} diff --git a/library/test.c b/library/test.c new file mode 100644 index 00000000..ecdcb64d --- /dev/null +++ b/library/test.c @@ -0,0 +1,502 @@ +#include <stdlib.h> + +#include "gnome-keyring.h" + +static GMainLoop *loop = NULL; + +static void +print_attributes (GnomeKeyringAttributeList *attributes) +{ + GnomeKeyringAttribute *array; + int i; + + array = (GnomeKeyringAttribute *)attributes->data; + g_print (" Attributes:\n"); + for (i = 0; i < attributes->len; i++) { + if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { + g_print (" %s = '%s'\n", array[i].name, array[i].value.string); + } else if (array[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { + g_print (" %s = %u\n", array[i].name, array[i].value.integer); + } else { + g_print (" %s = ** unsupported attribute type **\n", array[i].name); + } + } +} + +static const gchar* result_msg[] = { + "GNOME_KEYRING_RESULT_OK", + "GNOME_KEYRING_RESULT_DENIED", + "GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON", + "GNOME_KEYRING_RESULT_ALREADY_UNLOCKED", + "GNOME_KEYRING_RESULT_NO_SUCH_KEYRING", + "GNOME_KEYRING_RESULT_BAD_ARGUMENTS", + "GNOME_KEYRING_RESULT_IO_ERROR", + "GNOME_KEYRING_RESULT_CANCELLED", + "GNOME_KEYRING_RESULT_ALREADY_EXISTS" +}; + +static const gchar* +get_msg_for_keyring_result (GnomeKeyringResult result) +{ + if (result<=GNOME_KEYRING_RESULT_ALREADY_EXISTS) { + return result_msg[result]; + } else { + return "Unknown GnomeKeyringResult"; + } +} + +static void +ok_cb (GnomeKeyringResult result, + gpointer data) +{ + g_print ("%s: %d (%s)\n", (char *)data, result, get_msg_for_keyring_result (result)); + g_main_loop_quit (loop); +} + +static void +lock_all (void) +{ + gnome_keyring_lock_all (ok_cb, "lock all", NULL); + g_main_loop_run (loop); +} + +static void +lock (char *keyring) +{ + gnome_keyring_lock (keyring, + ok_cb, "lock", NULL); + g_main_loop_run (loop); +} + +static void +unlock (char *keyring, char *password) +{ + gnome_keyring_unlock (keyring, password, + ok_cb, "unlock", NULL); + g_main_loop_run (loop); +} + +static void +find_items_cb (GnomeKeyringResult result, + GList *found_items, + gpointer data) +{ + g_print ("found items: res: %d (%s) nr items: %d\n", result, get_msg_for_keyring_result (result), g_list_length (found_items)); + + if (found_items != NULL) { + GnomeKeyringFound *found = found_items->data; + + g_print ("Found item: keyring=%s, id=%d, secret='%s'\n", found->keyring, found->item_id, found->secret); + print_attributes (found->attributes); + } + + g_main_loop_quit (loop); +} + +static void +find_items (char *attr_val) +{ + gnome_keyring_find_itemsv (GNOME_KEYRING_ITEM_NOTE, + find_items_cb, NULL, NULL, + "testattribute", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, attr_val, + NULL); + g_main_loop_run (loop); +} + +static void +creat_item_cb (GnomeKeyringResult result, + guint32 id, + gpointer data) +{ + g_print ("created item: res: %d (%s) id: %d\n", result, get_msg_for_keyring_result (result), id); + g_main_loop_quit (loop); +} + +static void +create_item (char *name, char *attr_name, gboolean update_if_exists) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + + attribute.name = g_strdup ("testattribute"); + attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; + attribute.value.string = g_strdup (attr_name); + + attributes = gnome_keyring_attribute_list_new (); + g_array_append_val (attributes, attribute); + + gnome_keyring_item_create (NULL, + GNOME_KEYRING_ITEM_NOTE, + name, + attributes, + "secret text", + update_if_exists, + creat_item_cb, NULL, NULL); + gnome_keyring_attribute_list_free (attributes); + g_main_loop_run (loop); +} + +static void +creat_application_item_cb (GnomeKeyringResult result, + guint32 id, + gpointer data) +{ + g_print ("created application item: res: %d (%s) id: %d\n", result, get_msg_for_keyring_result (result), id); + g_main_loop_quit (loop); +} + +static void +create_application_item (char *name, char *attr_name, gboolean update_if_exists) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + + attribute.name = g_strdup ("testattribute"); + attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; + attribute.value.string = g_strdup (attr_name); + + attributes = gnome_keyring_attribute_list_new (); + g_array_append_val (attributes, attribute); + + gnome_keyring_item_create (NULL, + GNOME_KEYRING_ITEM_NOTE | GNOME_KEYRING_ITEM_APPLICATION_SECRET, + name, + attributes, + "application secret text", + update_if_exists, + creat_application_item_cb, NULL, NULL); + gnome_keyring_attribute_list_free (attributes); + g_main_loop_run (loop); +} + +static void +show_item_cb (GnomeKeyringResult result, + GnomeKeyringItemInfo *info, + gpointer data) +{ + char *secret; + char *name; + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting item info: %d (%s)\n", result, get_msg_for_keyring_result (result)); + } else { + name = gnome_keyring_item_info_get_display_name (info); + secret = gnome_keyring_item_info_get_secret (info); + g_print (" type: %u\n", gnome_keyring_item_info_get_type (info)); + g_print (" name: %s\n", name); + g_print (" secret: %s\n", secret); + g_print (" mtime: %lu\n", (unsigned long)gnome_keyring_item_info_get_mtime (info)); + g_print (" ctime: %lu\n", (unsigned long)gnome_keyring_item_info_get_ctime (info)); + gnome_keyring_free_password (secret); + g_free (name); + } + + g_main_loop_quit (loop); +} + +static void +print_attributes_cb (GnomeKeyringResult result, + GnomeKeyringAttributeList *attributes, + gpointer data) +{ + if (result != GNOME_KEYRING_RESULT_OK) { + g_print ("error getting item attributes: %d (%s)\n", result, get_msg_for_keyring_result (result)); + } else { + print_attributes (attributes); + } + + g_main_loop_quit (loop); +} + +static void +show_item (char *keyring, guint32 item_id, guint32 parts) +{ + gnome_keyring_item_get_info_full (keyring, item_id, parts, + show_item_cb, NULL, NULL); + g_main_loop_run (loop); + gnome_keyring_item_get_attributes (keyring, item_id, + print_attributes_cb, NULL, NULL); + g_main_loop_run (loop); +} + +static void +delete_item (char *keyring, guint32 item_id) +{ + gnome_keyring_item_delete (keyring, item_id, + ok_cb, "delete item", NULL); + g_main_loop_run (loop); +} + +static void +set_item_secret (char *keyring, guint32 item_id, char *secret) +{ + GnomeKeyringItemInfo *info; + + info = gnome_keyring_item_info_new (); + gnome_keyring_item_info_set_secret (info, secret); + gnome_keyring_item_set_info (keyring, item_id, info, + ok_cb, "set item", NULL); + gnome_keyring_item_info_free (info); + g_main_loop_run (loop); +} + +static void +set_item_attribute (char *keyring, guint32 item_id, char *value) +{ + GnomeKeyringAttributeList *attributes; + GnomeKeyringAttribute attribute; + + attribute.name = g_strdup ("testattribute"); + attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; + attribute.value.string = g_strdup (value); + + attributes = gnome_keyring_attribute_list_new (); + g_array_append_val (attributes, attribute); + + gnome_keyring_item_set_attributes (keyring, item_id, attributes, + ok_cb, "set attributes", NULL); + gnome_keyring_attribute_list_free (attributes); + g_main_loop_run (loop); +} + +static void +create_keyring (char *name, char *password) +{ + gnome_keyring_create (name, password, + ok_cb, "create keyring", NULL); + g_main_loop_run (loop); +} + +static void +set_default (char *name) +{ + gnome_keyring_set_default_keyring (name, + ok_cb, "set default", NULL); + g_main_loop_run (loop); +} + +static void +set_network_cb (GnomeKeyringResult result, + guint32 id, + gpointer data) +{ + g_print ("set network password: res: %d id: %d\n", result, id); + g_main_loop_quit (loop); +} + + +static void +set_network (char *server, char *password) +{ + gnome_keyring_set_network_password (NULL /* default keyring */, + NULL, + NULL, + server, + NULL, + "smb", + NULL, + 0, + password, + set_network_cb, NULL, NULL); + g_main_loop_run (loop); +} + +static void +set_network_sync (char *server, char *password) +{ + guint32 id; + GnomeKeyringResult res; + res = gnome_keyring_set_network_password_sync (NULL /* default keyring */, + NULL, + NULL, + server, + NULL, + "smb", + NULL, + 0, + password, + &id); + g_print ("set network password: res: %d id: %d\n", res, id); +} + +static void +find_network (char *server) +{ + GnomeKeyringResult res; + GList *list, *l; + + list = NULL; + res = gnome_keyring_find_network_password_sync (NULL, NULL, + server, NULL, + "smb", + NULL, + 0, + &list); + g_print ("find network password, res: %d, len: %d\n", res, g_list_length (list)); + for (l = list; l != NULL; l = l->next) { + GnomeKeyringNetworkPasswordData *data; + data = l->data; + + g_print ("%s:%d - proto: %s, server: %s, object: %s, authtype: %s, port: %d, user: %s, domain: %s, password: %s\n", + data->keyring, + data->item_id, + data->protocol, + data->server, + data->object, + data->authtype, + data->port, + data->user, + data->domain, + data->password); + } +} + +static void +list_items_cb (GnomeKeyringResult result, GList *list, gpointer data) +{ + g_print ("list items: res: %d (%s)\n", result, get_msg_for_keyring_result (result)); + for ( ; list; list = list->next) + g_print (" id: %d\n", GPOINTER_TO_UINT (list->data)); + g_main_loop_quit (loop); +} + +static void +list_items (const char *keyring) +{ + gnome_keyring_list_item_ids (keyring, list_items_cb, NULL, NULL); + g_main_loop_run (loop); +} + +int +main (int argc, char *argv[]) +{ + char arg; + + g_set_application_name("test-keyring"); + loop = g_main_loop_new (NULL, FALSE); + + arg = 0; + if (argc >= 2) { + arg = argv[1][0]; + } + + if (arg == 'L') { + lock_all (); + } else if (arg == 'l') { + if (argc >= 3) { + lock (argv[2]); + } else { + lock (NULL); + } + } else if (arg == 'u') { + if (argc >= 4) { + unlock (argv[2], argv[3]); + } else { + g_print ("unlock requires keyring and password\n"); + } + } else if (arg == 'c') { + if (argc >= 4) { + create_item (argv[2], argv[3], FALSE); + } else { + g_print ("create item requires item name and attr value\n"); + } + } else if (arg == 'C') { + if (argc >= 4) { + create_item (argv[2], argv[3], TRUE); + } else { + g_print ("create item requires item name and attr value\n"); + } + + } else if (arg == 'A') { + if (argc >= 4) { + create_application_item (argv[2], argv[3], FALSE); + } else { + g_print ("create application item requires item name and attr value\n"); + } + + /* Show complete item information */ + } else if (arg == 'i') { + if (argc >= 4) { + show_item (argv[2], atoi(argv[3]), GNOME_KEYRING_ITEM_INFO_SECRET); + } else { + g_print ("must give keyring & item id to show\n"); + } + + /* Show basic item information */ + } else if (arg == 'b') { + if (argc >= 4) { + show_item (argv[2], atoi(argv[3]), GNOME_KEYRING_ITEM_INFO_BASICS); + } else { + g_print ("must give keyring & item id to show\n"); + } + } else if (arg == 'd') { + if (argc >= 4) { + delete_item (argv[2] ,atoi (argv[3])); + } else { + g_print ("must give keyring & item id to delete\n"); + } + } else if (arg == 's') { + if (argc >= 5) { + set_item_secret (argv[2] ,atoi (argv[3]), argv[4]); + } else { + g_print ("must give keyring & item id & secret\n"); + } + } else if (arg == 'a') { + if (argc >= 5) { + set_item_attribute (argv[2] ,atoi (argv[3]), argv[4]); + } else { + g_print ("must give keyring & item id & attribute value\n"); + } + } else if (arg == 'f') { + if (argc >= 3) { + find_items (argv[2]); + } else { + g_print ("must give testattribute value\n"); + } + } else if (arg == 'k') { + if (argc >= 4) { + create_keyring (argv[2], argv[3]); + } else if (argc >= 3) { + create_keyring (argv[2], NULL); + } else { + g_print ("create keyring requires keyring name\n"); + } + } else if (arg == 'D') { + if (argc >= 3) { + set_default (argv[2]); + } else { + set_default (NULL); + } + } else if (arg == 'n') { + if (argc >= 4) { + set_network (argv[2], argv[3]); + } else { + g_print ("need server & password\n"); + } + } else if (arg == 'N') { + if (argc >= 4) { + set_network_sync (argv[2], argv[3]); + } else { + g_print ("need server & password\n"); + } + } else if (arg == 'p') { + if (argc >= 3) { + find_network (argv[2]); + } else { + g_print ("need server\n"); + } + } else if (arg == 't') { + g_print ("gnome keyring is: %s\n", + gnome_keyring_is_available ()?"available":"not available"); + } else if (arg == 'I') { + if (argc >= 3) { + list_items(argv[2]); + } else { + g_print ("need keyring\n"); + } + } else { + g_print ("unsupported test\n"); + } + + + return 0; +} |