27
27
#include "gkm-gnome2-storage.h"
29
29
#include "gkm/gkm-certificate.h"
30
#define DEBUG_FLAG GKM_DEBUG_STORAGE
31
#include "gkm/gkm-debug.h"
30
32
#include "gkm/gkm-data-asn1.h"
31
33
#include "gkm/gkm-manager.h"
32
34
#include "gkm/gkm-module.h"
85
88
G_DEFINE_TYPE (GkmGnome2Storage, gkm_gnome2_storage, GKM_TYPE_STORE);
87
#define MAX_LOCK_TRIES 20
90
#define LOCK_TIMEOUT 4000 /*(4 seconds)*/
89
92
#define UNWANTED_IDENTIFIER_CHARS ":/\\<>|\t\n\r\v "
91
/* -----------------------------------------------------------------------------
101
static int flock(int fd, int operation)
105
switch (operation & ~LOCK_NB) {
107
flock.l_type = F_RDLCK;
110
flock.l_type = F_WRLCK;
113
flock.l_type = F_UNLCK;
124
return fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
126
#endif /* !HAVE_FLOCK */
128
/* -----------------------------------------------------------------------------
134
95
name_for_subject (const guchar *subject, gsize n_subject)
218
179
return type_from_extension (ext);
183
lock_and_open_file (const gchar *filename,
190
* In this function we don't actually put the object into a 'write' state,
191
* that's the callers job if necessary.
194
fd = open (filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
196
g_message ("couldn't open store file: %s: %s",
197
filename, g_strerror (errno));
201
lockh = dotlock_create (filename, 0);
203
g_message ("couldn't create lock for store file: %s: %s",
204
filename, g_strerror (errno));
209
if (dotlock_take (lockh, LOCK_TIMEOUT)) {
211
g_message ("couldn't write to store file:"
212
" %s: file is locked", filename);
214
g_message ("couldn't lock store file: %s: %s",
215
filename, g_strerror (errno));
216
dotlock_destroy (lockh);
221
/* Successfully opened file */;
222
dotlock_set_fd (lockh, fd);
222
227
complete_lock_file (GkmTransaction *transaction, GObject *object, gpointer data)
224
int fd = GPOINTER_TO_INT (data);
226
/* This also unlocks the file */
229
GkmGnome2Storage *self = GKM_GNOME2_STORAGE (object);
230
dotlock_t lockh = data;
231
int fd = dotlock_get_fd (lockh);
233
gkm_debug ("closing: %s", self->filename);
236
* Note that there is no error checking for release and
237
* destroy. These functions will log errors anyway and we
238
* can't do much else than logging those errors.
240
dotlock_release (lockh);
241
dotlock_destroy (lockh);
229
244
/* Completed successfully */
245
259
g_assert (GKM_IS_TRANSACTION (transaction));
247
261
g_return_val_if_fail (!gkm_transaction_get_failed (transaction), -1);
249
/* File lock retry loop */
250
for (tries = 0; TRUE; ++tries) {
251
if (tries > MAX_LOCK_TRIES) {
252
g_message ("couldn't write to store file: %s: file is locked", self->filename);
253
gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
257
fd = open (self->filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
259
g_message ("couldn't open store file: %s: %s", self->filename, g_strerror (errno));
260
gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
264
if (flock (fd, LOCK_EX | LOCK_NB) < 0) {
265
if (errno != EWOULDBLOCK) {
266
g_message ("couldn't lock store file: %s: %s", self->filename, g_strerror (errno));
268
gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
278
/* Successfully opened file */;
279
gkm_transaction_add (transaction, self, complete_lock_file, GINT_TO_POINTER (fd));
262
gkm_debug ("modifying: %s", self->filename);
264
lockh = lock_and_open_file (self->filename, O_RDONLY | O_CREAT);
266
gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
283
g_assert_not_reached ();
270
/* Successfully opened file */;
271
gkm_transaction_add (transaction, self, complete_lock_file, lockh);
272
return dotlock_get_fd (lockh);
386
375
begin_modification_state (GkmGnome2Storage *self, GkmTransaction *transaction)
388
377
GkmDataResult res;
380
/* Already in write state for this transaction? */
381
if (self->transaction != NULL) {
382
g_return_val_if_fail (self->transaction == transaction, FALSE);
392
386
if (!begin_write_state (self, transaction))
395
389
/* See if file needs updating */
396
if (fstat (self->read_fd, &sb) >= 0 && sb.st_mtime != self->last_mtime) {
398
res = gkm_gnome2_file_read_fd (self->file, self->read_fd, self->login);
400
case GKM_DATA_FAILURE:
401
g_message ("failure updating user store file: %s", self->filename);
402
rv = CKR_FUNCTION_FAILED;
404
case GKM_DATA_LOCKED:
405
rv = CKR_USER_NOT_LOGGED_IN;
407
case GKM_DATA_UNRECOGNIZED:
408
g_message ("unrecognized or invalid user store file: %s", self->filename);
409
rv = CKR_FUNCTION_FAILED;
411
case GKM_DATA_SUCCESS:
415
g_assert_not_reached ();
420
gkm_transaction_fail (transaction, rv);
390
res = gkm_gnome2_file_read_fd (self->file, self->read_fd, self->login);
392
case GKM_DATA_FAILURE:
393
g_message ("failure updating user store file: %s", self->filename);
394
rv = CKR_FUNCTION_FAILED;
396
case GKM_DATA_LOCKED:
397
rv = CKR_USER_NOT_LOGGED_IN;
399
case GKM_DATA_UNRECOGNIZED:
400
g_message ("unrecognized or invalid user store file: %s", self->filename);
401
rv = CKR_FUNCTION_FAILED;
403
case GKM_DATA_SUCCESS:
407
g_assert_not_reached ();
412
gkm_transaction_fail (transaction, rv);
425
416
/* Write out the data once completed with modifications */
708
699
refresh_with_login (GkmGnome2Storage *self, GkmSecret *login)
710
701
GkmDataResult res;
715
707
g_assert (GKM_GNOME2_STORAGE (self));
708
gkm_debug ("refreshing: %s", self->filename);
717
710
/* Open the file for reading */
718
fd = open (self->filename, O_RDONLY, 0);
711
lockh = lock_and_open_file (self->filename, O_RDONLY);
720
713
/* No file, no worries */
721
714
if (errno == ENOENT)
722
715
return login ? CKR_USER_PIN_NOT_INITIALIZED : CKR_OK;
724
717
return CKR_FUNCTION_FAILED;
720
fd = dotlock_get_fd (lockh);
727
722
/* Try and update the last read time */
728
723
if (fstat (fd, &sb) >= 0)
729
724
self->last_mtime = sb.st_mtime;
753
748
if (rv == CKR_FUNCTION_FAILED)
754
749
self->last_mtime = 0;
751
gkm_debug ("closing: %s", self->filename);
754
* Note that there is no error checking for release and
755
* destroy. These functions will log errors anyway and we
756
* can't do much else than logging those errors.
758
dotlock_release (lockh);
759
dotlock_destroy (lockh);
775
780
g_return_val_if_fail (GKM_IS_OBJECT (object), CKR_GENERAL_ERROR);
776
781
g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
778
identifier = g_hash_table_lookup (self->object_to_identifier, object);
780
return CKR_ATTRIBUTE_TYPE_INVALID;
782
783
if (self->last_mtime == 0) {
783
784
rv = gkm_gnome2_storage_refresh (self);
784
785
if (rv != CKR_OK)
789
identifier = g_hash_table_lookup (self->object_to_identifier, object);
791
return CKR_ATTRIBUTE_TYPE_INVALID;
788
793
res = gkm_gnome2_file_read_value (self->file, identifier, attr->type, &value, &n_value);
790
795
case GKM_DATA_FAILURE:
817
822
g_return_if_fail (!gkm_transaction_get_failed (transaction));
818
823
g_return_if_fail (attr);
825
if (!begin_modification_state (self, transaction))
820
828
identifier = g_hash_table_lookup (self->object_to_identifier, object);
821
829
if (!identifier) {
822
830
gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY);
826
if (self->last_mtime == 0) {
827
rv = gkm_gnome2_storage_refresh (self);
829
gkm_transaction_fail (transaction, rv);
834
834
res = gkm_gnome2_file_write_value (self->file, identifier, attr->type, attr->pValue, attr->ulValueLen);
836
836
case GKM_DATA_FAILURE:
1234
1234
args.transaction = transaction;
1235
1235
args.old_login = old_login;
1236
1236
args.new_login = new_login;
1237
1238
gkm_gnome2_file_foreach_entry (file, relock_each_object, &args);
1239
1240
if (!gkm_transaction_get_failed (transaction) && self->login) {