1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
/* gkr-keyring.c - represents a keyring in memory, and functionality save/load
4
Copyright (C) 2003 Red Hat, Inc
5
Copyright (C) 2007 Stefan Walter
7
Gnome keyring is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the
10
License, or (at your option) any later version.
12
Gnome keyring is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
Author: Alexander Larsson <alexl@redhat.com>
22
Author: Stef Walter <stef@memberwebs.com>
27
#include "gkr-keyring.h"
28
#include "gkr-keyring-item.h"
29
#include "gkr-keyring-login.h"
30
#include "gkr-keyrings.h"
32
#include "egg/egg-buffer.h"
33
#include "egg/egg-secure-memory.h"
35
#include "library/gnome-keyring-private.h"
36
#include "library/gnome-keyring-proto.h"
38
#include "util/gkr-location.h"
41
#include <glib/gi18n.h>
45
#include <sys/types.h>
54
/* -----------------------------------------------------------------------------
70
static guint signals[LAST_SIGNAL] = { 0 };
72
G_DEFINE_TYPE (GkrKeyring, gkr_keyring, G_TYPE_OBJECT);
74
/* -----------------------------------------------------------------------------
79
write_all (int fd, const guchar *buf, size_t len)
86
res = write (fd, buf + bytes, len - bytes);
88
if (errno != EINTR && errno != EAGAIN) {
89
perror ("write_all write failure:");
100
get_default_location_for_name (GQuark volume, const char *keyring_name)
103
gchar *base, *filename;
108
g_assert (keyring_name && keyring_name[0]);
110
base = g_filename_from_utf8 (keyring_name, -1, NULL, NULL, NULL);
112
base = g_strdup ("keyring");
119
filename = g_strdup_printf ("%s/keyrings/%s.keyring",
120
g_quark_to_string (volume), base);
122
filename = g_strdup_printf ("%s/keyrings/%s%d.keyring",
123
g_quark_to_string (volume), base, version);
125
loc = gkr_location_from_string (filename);
128
path = gkr_location_to_path (loc);
129
g_return_val_if_fail (path, 0);
132
} while (g_file_test (path, G_FILE_TEST_EXISTS));
136
loc = gkr_location_from_path (path);
141
/* -----------------------------------------------------------------------------
146
gkr_keyring_init (GkrKeyring *keyring)
148
keyring->ctime = keyring->mtime = time (NULL);
150
/* Default values: */
151
keyring->lock_on_idle = FALSE;
152
keyring->lock_timeout = 0;
156
gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
159
GkrKeyring *keyring = GKR_KEYRING (obj);
163
g_value_set_string (value, keyring->keyring_name);
166
g_value_set_uint (value, keyring->location);
172
gkr_keyring_dispose (GObject *obj)
174
GkrKeyring *keyring = GKR_KEYRING (obj);
175
GkrKeyringItem *item;
178
/* Remove all references to items */
179
for (l = keyring->items; l; l = g_list_next (l)) {
180
item = GKR_KEYRING_ITEM (l->data);
181
g_object_unref (item);
184
g_list_free (keyring->items);
185
keyring->items = NULL;
187
egg_secure_strfree (keyring->password);
188
keyring->password = NULL;
190
G_OBJECT_CLASS (gkr_keyring_parent_class)->dispose (obj);
194
gkr_keyring_finalize (GObject *obj)
196
GkrKeyring *keyring = GKR_KEYRING (obj);
198
g_free (keyring->keyring_name);
199
g_assert (keyring->password == NULL);
201
G_OBJECT_CLASS (gkr_keyring_parent_class)->finalize (obj);
205
gkr_keyring_class_init (GkrKeyringClass *klass)
207
GObjectClass *gobject_class = (GObjectClass*)klass;
209
gkr_keyring_parent_class = g_type_class_peek_parent (klass);
211
gobject_class->get_property = gkr_keyring_get_property;
212
gobject_class->dispose = gkr_keyring_dispose;
213
gobject_class->finalize = gkr_keyring_finalize;
215
g_object_class_install_property (gobject_class, PROP_NAME,
216
g_param_spec_string ("name", "Name", "Keyring Name",
217
NULL, G_PARAM_READABLE));
219
g_object_class_install_property (gobject_class, PROP_LOCATION,
220
g_param_spec_uint ("location", "Location", "File Location",
221
0, G_MAXUINT, 0, G_PARAM_READABLE));
223
signals[ITEM_ADDED] = g_signal_new ("item-added", GKR_TYPE_KEYRING,
224
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkrKeyringClass, item_added),
225
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
226
G_TYPE_NONE, 1, GKR_TYPE_KEYRING_ITEM);
228
signals[ITEM_REMOVED] = g_signal_new ("item-removed", GKR_TYPE_KEYRING,
229
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkrKeyringClass, item_removed),
230
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
231
G_TYPE_NONE, 1, GKR_TYPE_KEYRING_ITEM);
234
/* -----------------------------------------------------------------------------
239
gkr_keyring_new (const char *name, GQuark location)
243
/* TODO: This should be done using properties */
245
keyring = g_object_new (GKR_TYPE_KEYRING, NULL);
247
keyring->keyring_name = g_strdup (name);
248
keyring->location = location;
254
gkr_keyring_create (GQuark location, const gchar *keyring_name, const gchar *password)
259
location = GKR_LOCATION_VOLUME_LOCAL;
260
if (gkr_location_is_volume (location))
261
location = get_default_location_for_name (location, keyring_name);
263
keyring = gkr_keyring_new (keyring_name, 0);
264
if (keyring != NULL) {
265
keyring->location = location;
266
keyring->locked = FALSE;
267
keyring->password = egg_secure_strdup (password);
268
keyring->salt_valid = FALSE;
269
gkr_keyring_save_to_disk (keyring);
275
gkr_keyring_get_new_id (GkrKeyring *keyring)
277
GkrKeyringItem *item;
281
g_assert (GKR_IS_KEYRING (keyring));
284
for (l = keyring->items; l ; l = g_list_next (l)) {
289
/* Naive unique id lookup, but avoid rollaround at lest: */
291
if (max == 0xffffffff)
298
gkr_keyring_get_item (GkrKeyring *keyring, guint id)
300
GkrKeyringItem *item;
303
for (l = keyring->items; l; l = g_list_next (l)) {
304
item = GKR_KEYRING_ITEM (l->data);
313
gkr_keyring_find_item (GkrKeyring *keyring, GnomeKeyringItemType type,
314
GnomeKeyringAttributeList *attrs, gboolean match_all)
316
GkrKeyringItem *item;
319
for (l = keyring->items; l; l = g_list_next (l)) {
320
item = GKR_KEYRING_ITEM (l->data);
321
if (gkr_keyring_item_match (item, type, attrs, match_all))
329
gkr_keyring_add_item (GkrKeyring* keyring, GkrKeyringItem* item)
331
g_assert (GKR_IS_KEYRING (keyring));
332
g_assert (GKR_IS_KEYRING_ITEM (item));
334
/* Must not be added twice */
335
g_assert (g_list_find (keyring->items, item) == NULL);
337
keyring->items = g_list_append (keyring->items, item);
340
g_signal_emit (keyring, signals[ITEM_ADDED], 0, item);
345
gkr_keyring_remove_item (GkrKeyring* keyring, GkrKeyringItem* item)
347
g_assert (GKR_IS_KEYRING (keyring));
348
g_assert (GKR_IS_KEYRING_ITEM (item));
350
if (g_list_find (keyring->items, item)) {
351
keyring->items = g_list_remove (keyring->items, item);
353
/* Must not be added twice */
354
g_assert (g_list_find (keyring->items, item) == NULL);
356
/* Keep the reference until after the signal */
357
g_signal_emit (keyring, signals[ITEM_REMOVED], 0, item);
359
g_object_unref (item);
364
gkr_keyring_update_from_disk (GkrKeyring *keyring)
368
guchar *contents = NULL;
372
if (!keyring->location)
375
if (!gkr_location_read_file (keyring->location, &contents, &len, &err)) {
376
g_warning ("couldn't read keyring: %s", err && err->message ? err->message : "");
377
g_clear_error (&err);
381
egg_buffer_init_static (&buffer, contents, len);
383
result = gkr_keyring_binary_parse (keyring, &buffer);
385
result = gkr_keyring_textual_parse (keyring, &buffer);
387
egg_buffer_uninit (&buffer);
394
g_warning ("keyring has unknown format");
396
g_warning ("error parsing keyring");
402
gkr_keyring_remove_from_disk (GkrKeyring *keyring)
407
/* Cannot remove session or memory based keyring */
408
if (!keyring->location)
411
file = gkr_location_to_path (keyring->location);
422
gkr_keyring_save_to_disk (GkrKeyring *keyring)
433
/* Can't save locked keyrings */
437
/* Not file backed */
438
if (!keyring->location)
441
file = gkr_location_to_path (keyring->location);
445
egg_buffer_init_full (&out, 4096, g_realloc);
448
if (!keyring->password || !keyring->password[0])
449
result = gkr_keyring_textual_generate (keyring, &out);
451
result = gkr_keyring_binary_generate (keyring, &out);
453
/* And write it to disk */
455
dirname = g_path_get_dirname (file);
456
if (g_mkdir_with_parents (dirname, S_IRWXU) < 0)
457
g_warning ("unable to create keyring dir");
458
template = g_build_filename (dirname, ".keyringXXXXXX", NULL);
460
fd = g_mkstemp (template);
462
fchmod (fd, S_IRUSR | S_IWUSR);
463
if (write_all (fd, out.buf, out.len) == 0) {
468
if (rename (template, file) == 0) {
469
if (stat (file, &statbuf) == 0)
470
gkr_location_manager_note_mtime (NULL,
471
keyring->location, statbuf.st_mtime);
479
g_warning ("Can't open keyring save file %s", template);
480
perror ("mkstemp error: ");
486
g_warning ("Internal error: Unable to generate data for keyring %s\n", keyring->keyring_name);
490
egg_buffer_uninit (&out);
496
gkr_keyring_lock (GkrKeyring *keyring)
501
/* Never lock the session keyring */
502
if (!keyring->location)
505
/* Password will be null for textual keyrings */
506
if (keyring->password != NULL) {
507
egg_secure_strfree (keyring->password);
508
keyring->password = NULL;
511
if (!gkr_keyring_update_from_disk (keyring)) {
512
/* Failed to re-read, remove the keyring */
513
g_warning ("Couldn't re-read keyring %s\n", keyring->keyring_name);
514
gkr_keyrings_remove (keyring);
521
gkr_keyring_unlock (GkrKeyring *keyring, const gchar *password)
523
if (!keyring->locked)
526
g_return_val_if_fail (keyring->password == NULL, FALSE);
528
keyring->password = egg_secure_strdup (password);
529
if (!gkr_keyring_update_from_disk (keyring)) {
530
egg_secure_strfree (keyring->password);
531
keyring->password = NULL;
533
if (keyring->locked) {
534
g_assert (keyring->password == NULL);
537
g_assert (keyring->password != NULL);
543
gkr_keyring_is_insecure (GkrKeyring *keyring)
545
/* It's locked, must have encryption */
549
/* Only in memory == secure */
550
if (!keyring->location)
553
/* No or empty password == insecure */
554
if (!keyring->password || !keyring->password[0])
561
gkr_keyring_ask_check_unlock (GkrAskRequest* ask)
564
const gchar *password;
567
keyring = GKR_KEYRING (gkr_ask_request_get_object (ask));
568
g_assert (GKR_IS_KEYRING (keyring));
570
if (!keyring->locked) {
571
ask->response = GKR_ASK_RESPONSE_ALLOW;
572
return GKR_ASK_STOP_REQUEST;
575
/* If they typed a password, try it out */
576
if (ask->response >= GKR_ASK_RESPONSE_ALLOW) {
578
g_assert (ask->typed_password);
579
if (!gkr_keyring_unlock (keyring, ask->typed_password)) {
580
/* Bad password, try again */
581
ask->response = GKR_ASK_RESPONSE_NONE;
582
return GKR_ASK_CONTINUE_REQUEST;
585
/* Did they ask us to remember the password? */
587
display = g_strdup_printf (_("Unlock password for %s keyring"),
588
keyring->keyring_name);
589
gkr_keyring_login_attach_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD,
590
display, ask->typed_password,
591
"keyring", gkr_location_to_string (keyring->location), NULL);
597
* We can automatically unlock keyrings that have their password
598
* stored in the 'login' keyring.
600
password = gkr_keyring_login_lookup_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD,
601
"keyring", gkr_location_to_string (keyring->location), NULL);
603
if (gkr_keyring_unlock (keyring, password)) {
605
/* A good password, unlocked, all done */
606
ask->response = GKR_ASK_RESPONSE_ALLOW;
607
return GKR_ASK_STOP_REQUEST;
611
/* A bad internal password */
612
gkr_keyring_login_remove_secret (GNOME_KEYRING_ITEM_CHAINED_KEYRING_PASSWORD,
613
"keyring", gkr_location_to_string (keyring->location), NULL);
617
/* If the keyring is unlocked then no need to continue */
618
if (!keyring->locked) {
619
ask->response = GKR_ASK_RESPONSE_ALLOW;
620
return GKR_ASK_STOP_REQUEST;
623
return GKR_ASK_DONT_CARE;