~noskcaj/ubuntu/vivid/gnome-keyring/3.15.90

« back to all changes in this revision

Viewing changes to pkcs11/gnome2-store/gkm-gnome2-storage.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-14 22:13:02 UTC
  • mfrom: (1.3.1)
  • mto: (80.2.8 experimental) (1.1.77)
  • mto: This revision was merged to the branch mainline in revision 148.
  • Revision ID: package-import@ubuntu.com-20120514221302-0l3gjmqpe6xopond
ImportĀ upstreamĀ versionĀ 3.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include "gkm-gnome2-storage.h"
28
28
 
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"
34
36
#include "gkm/gkm-serializable.h"
35
37
#include "gkm/gkm-util.h"
36
38
 
 
39
#include "egg/dotlock.h"
37
40
#include "egg/egg-asn1x.h"
38
41
#include "egg/egg-asn1-defs.h"
39
42
#include "egg/egg-dn.h"
84
87
 
85
88
G_DEFINE_TYPE (GkmGnome2Storage, gkm_gnome2_storage, GKM_TYPE_STORE);
86
89
 
87
 
#define MAX_LOCK_TRIES 20
 
90
#define LOCK_TIMEOUT  4000  /*(4 seconds)*/
88
91
 
89
92
#define UNWANTED_IDENTIFIER_CHARS  ":/\\<>|\t\n\r\v "
90
93
 
91
 
/* -----------------------------------------------------------------------------
92
 
 * HELPERS
93
 
 */
94
 
 
95
 
#ifndef HAVE_FLOCK
96
 
#define LOCK_SH 1
97
 
#define LOCK_EX 2
98
 
#define LOCK_NB 4
99
 
#define LOCK_UN 8
100
 
 
101
 
static int flock(int fd, int operation)
102
 
{
103
 
        struct flock flock;
104
 
 
105
 
        switch (operation & ~LOCK_NB) {
106
 
        case LOCK_SH:
107
 
                flock.l_type = F_RDLCK;
108
 
                break;
109
 
        case LOCK_EX:
110
 
                flock.l_type = F_WRLCK;
111
 
                break;
112
 
        case LOCK_UN:
113
 
                flock.l_type = F_UNLCK;
114
 
                break;
115
 
        default:
116
 
                errno = EINVAL;
117
 
                return -1;
118
 
        }
119
 
 
120
 
        flock.l_whence = 0;
121
 
        flock.l_start = 0;
122
 
        flock.l_len = 0;
123
 
 
124
 
        return fcntl (fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
125
 
}
126
 
#endif /* !HAVE_FLOCK */
127
 
 
128
 
/* -----------------------------------------------------------------------------
129
 
 * INTERNAL
130
 
 */
131
 
 
132
 
 
133
94
static gchar*
134
95
name_for_subject (const guchar *subject, gsize n_subject)
135
96
{
218
179
        return type_from_extension (ext);
219
180
}
220
181
 
 
182
static dotlock_t
 
183
lock_and_open_file (const gchar *filename,
 
184
                    gint flags)
 
185
{
 
186
        dotlock_t lockh;
 
187
        gint fd = -1;
 
188
 
 
189
        /*
 
190
         * In this function we don't actually put the object into a 'write' state,
 
191
         * that's the callers job if necessary.
 
192
         */
 
193
 
 
194
        fd = open (filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
 
195
        if (fd == -1) {
 
196
                g_message ("couldn't open store file: %s: %s",
 
197
                           filename, g_strerror (errno));
 
198
                return NULL;
 
199
        }
 
200
 
 
201
        lockh = dotlock_create (filename, 0);
 
202
        if (!lockh) {
 
203
                g_message ("couldn't create lock for store file: %s: %s",
 
204
                           filename, g_strerror (errno));
 
205
                close (fd);
 
206
                return NULL;
 
207
        }
 
208
 
 
209
        if (dotlock_take (lockh, LOCK_TIMEOUT)) {
 
210
                if (errno == EACCES)
 
211
                        g_message ("couldn't write to store file:"
 
212
                                   " %s: file is locked", filename);
 
213
                else
 
214
                        g_message ("couldn't lock store file: %s: %s",
 
215
                                   filename, g_strerror (errno));
 
216
                dotlock_destroy (lockh);
 
217
                close (fd);
 
218
                return NULL;
 
219
        }
 
220
 
 
221
        /* Successfully opened file */;
 
222
        dotlock_set_fd (lockh, fd);
 
223
        return lockh;
 
224
}
 
225
 
221
226
static gboolean
222
227
complete_lock_file (GkmTransaction *transaction, GObject *object, gpointer data)
223
228
{
224
 
        int fd = GPOINTER_TO_INT (data);
225
 
 
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);
 
232
 
 
233
        gkm_debug ("closing: %s", self->filename);
 
234
 
 
235
        /*
 
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.
 
239
         */
 
240
        dotlock_release (lockh);
 
241
        dotlock_destroy (lockh);
227
242
        close (fd);
228
243
 
229
244
        /* Completed successfully */
233
248
static gint
234
249
begin_lock_file (GkmGnome2Storage *self, GkmTransaction *transaction)
235
250
{
236
 
        guint tries = 0;
237
 
        gint fd = -1;
 
251
        dotlock_t lockh;
238
252
 
239
253
        /*
240
254
         * In this function we don't actually put the object into a 'write' state,
245
259
        g_assert (GKM_IS_TRANSACTION (transaction));
246
260
 
247
261
        g_return_val_if_fail (!gkm_transaction_get_failed (transaction), -1);
248
 
 
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);
254
 
                        return -1;
255
 
                }
256
 
 
257
 
                fd = open (self->filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
258
 
                if (fd == -1) {
259
 
                        g_message ("couldn't open store file: %s: %s", self->filename, g_strerror (errno));
260
 
                        gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
261
 
                        return -1;
262
 
                }
263
 
 
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));
267
 
                                close (fd);
268
 
                                gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
269
 
                                return -1;
270
 
                        }
271
 
 
272
 
                        close (fd);
273
 
                        fd = -1;
274
 
                        g_usleep (200000);
275
 
                        continue;
276
 
                }
277
 
 
278
 
                /* Successfully opened file */;
279
 
                gkm_transaction_add (transaction, self, complete_lock_file, GINT_TO_POINTER (fd));
280
 
                return fd;
 
262
        gkm_debug ("modifying: %s", self->filename);
 
263
 
 
264
        lockh = lock_and_open_file (self->filename, O_RDONLY | O_CREAT);
 
265
        if (!lockh) {
 
266
                gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
 
267
                return -1;
281
268
        }
282
269
 
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);
284
273
}
285
274
 
286
275
static gboolean
386
375
begin_modification_state (GkmGnome2Storage *self, GkmTransaction *transaction)
387
376
{
388
377
        GkmDataResult res;
389
 
        struct stat sb;
390
 
        CK_RV rv;
 
378
        CK_RV rv = CKR_OK;
 
379
 
 
380
        /* Already in write state for this transaction? */
 
381
        if (self->transaction != NULL) {
 
382
                g_return_val_if_fail (self->transaction == transaction, FALSE);
 
383
                return TRUE;
 
384
        }
391
385
 
392
386
        if (!begin_write_state (self, transaction))
393
387
                return FALSE;
394
388
 
395
389
        /* See if file needs updating */
396
 
        if (fstat (self->read_fd, &sb) >= 0 && sb.st_mtime != self->last_mtime) {
397
 
 
398
 
                res = gkm_gnome2_file_read_fd (self->file, self->read_fd, self->login);
399
 
                switch (res) {
400
 
                case GKM_DATA_FAILURE:
401
 
                        g_message ("failure updating user store file: %s", self->filename);
402
 
                        rv = CKR_FUNCTION_FAILED;
403
 
                        break;
404
 
                case GKM_DATA_LOCKED:
405
 
                        rv = CKR_USER_NOT_LOGGED_IN;
406
 
                        break;
407
 
                case GKM_DATA_UNRECOGNIZED:
408
 
                        g_message ("unrecognized or invalid user store file: %s", self->filename);
409
 
                        rv = CKR_FUNCTION_FAILED;
410
 
                        break;
411
 
                case GKM_DATA_SUCCESS:
412
 
                        rv = CKR_OK;
413
 
                        break;
414
 
                default:
415
 
                        g_assert_not_reached ();
416
 
                        break;
417
 
                }
418
 
 
419
 
                if (rv != CKR_OK) {
420
 
                        gkm_transaction_fail (transaction, rv);
421
 
                        return FALSE;
422
 
                }
 
390
        res = gkm_gnome2_file_read_fd (self->file, self->read_fd, self->login);
 
391
        switch (res) {
 
392
        case GKM_DATA_FAILURE:
 
393
                g_message ("failure updating user store file: %s", self->filename);
 
394
                rv = CKR_FUNCTION_FAILED;
 
395
                break;
 
396
        case GKM_DATA_LOCKED:
 
397
                rv = CKR_USER_NOT_LOGGED_IN;
 
398
                break;
 
399
        case GKM_DATA_UNRECOGNIZED:
 
400
                g_message ("unrecognized or invalid user store file: %s", self->filename);
 
401
                rv = CKR_FUNCTION_FAILED;
 
402
                break;
 
403
        case GKM_DATA_SUCCESS:
 
404
                rv = CKR_OK;
 
405
                break;
 
406
        default:
 
407
                g_assert_not_reached ();
 
408
                break;
 
409
        }
 
410
 
 
411
        if (rv != CKR_OK) {
 
412
                gkm_transaction_fail (transaction, rv);
 
413
                return FALSE;
423
414
        }
424
415
 
425
416
        /* Write out the data once completed with modifications */
708
699
refresh_with_login (GkmGnome2Storage *self, GkmSecret *login)
709
700
{
710
701
        GkmDataResult res;
 
702
        dotlock_t lockh;
711
703
        struct stat sb;
712
704
        CK_RV rv;
713
705
        int fd;
714
706
 
715
707
        g_assert (GKM_GNOME2_STORAGE (self));
 
708
        gkm_debug ("refreshing: %s", self->filename);
716
709
 
717
710
        /* Open the file for reading */
718
 
        fd = open (self->filename, O_RDONLY, 0);
719
 
        if (fd == -1) {
 
711
        lockh = lock_and_open_file (self->filename, O_RDONLY);
 
712
        if (!lockh) {
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;
725
718
        }
726
719
 
 
720
        fd = dotlock_get_fd (lockh);
 
721
 
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;
755
750
 
 
751
        gkm_debug ("closing: %s", self->filename);
 
752
 
 
753
        /*
 
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.
 
757
         */
 
758
        dotlock_release (lockh);
 
759
        dotlock_destroy (lockh);
756
760
        close (fd);
 
761
 
757
762
        return rv;
758
763
}
759
764
 
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);
777
782
 
778
 
        identifier = g_hash_table_lookup (self->object_to_identifier, object);
779
 
        if (!identifier)
780
 
                return CKR_ATTRIBUTE_TYPE_INVALID;
781
 
 
782
783
        if (self->last_mtime == 0) {
783
784
                rv = gkm_gnome2_storage_refresh (self);
784
785
                if (rv != CKR_OK)
785
786
                        return rv;
786
787
        }
787
788
 
 
789
        identifier = g_hash_table_lookup (self->object_to_identifier, object);
 
790
        if (!identifier)
 
791
                return CKR_ATTRIBUTE_TYPE_INVALID;
 
792
 
788
793
        res = gkm_gnome2_file_read_value (self->file, identifier, attr->type, &value, &n_value);
789
794
        switch (res) {
790
795
        case GKM_DATA_FAILURE:
817
822
        g_return_if_fail (!gkm_transaction_get_failed (transaction));
818
823
        g_return_if_fail (attr);
819
824
 
 
825
        if (!begin_modification_state (self, transaction))
 
826
                return;
 
827
 
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);
823
831
                return;
824
832
        }
825
833
 
826
 
        if (self->last_mtime == 0) {
827
 
                rv = gkm_gnome2_storage_refresh (self);
828
 
                if (rv != CKR_OK) {
829
 
                        gkm_transaction_fail (transaction, rv);
830
 
                        return;
831
 
                }
832
 
        }
833
 
 
834
834
        res = gkm_gnome2_file_write_value (self->file, identifier, attr->type, attr->pValue, attr->ulValueLen);
835
835
        switch (res) {
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
        args.self = self;
1237
1238
        gkm_gnome2_file_foreach_entry (file, relock_each_object, &args);
1238
1239
 
1239
1240
        if (!gkm_transaction_get_failed (transaction) && self->login) {