diff options
Diffstat (limited to 'sm/keydb.c')
-rw-r--r-- | sm/keydb.c | 101 |
1 files changed, 41 insertions, 60 deletions
@@ -58,7 +58,6 @@ static int any_registered; struct keydb_handle { - int locked; int found; int saved_found; int current; @@ -147,7 +146,7 @@ maybe_create_keybox (char *filename, int force, int *r_created) } *last_slash_in_filename = save_slash; - /* To avoid races with other instances of gpg trying to create or + /* To avoid races with other instances of gpg/gpgsm trying to create or update the keybox (it is removed during an update for a short time), we do the next stuff in a locked state. */ lockhd = dotlock_create (filename, 0); @@ -175,7 +174,7 @@ maybe_create_keybox (char *filename, int force, int *r_created) } /* Now the real test while we are locked. */ - if (!access(filename, F_OK)) + if (!gnupg_access(filename, F_OK)) { rc = 0; /* Okay, we may access the file now. */ goto leave; @@ -375,6 +374,23 @@ keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created) } +/* This is a helper requyired under Windows to close all files so that + * a rename will work. */ +void +keydb_close_all_files (void) +{ +#ifdef HAVE_W32_SYSTEM + int i; + + log_assert (used_resources <= MAX_KEYDB_RESOURCES); + for (i=0; i < used_resources; i++) + if (all_resources[i].type == KEYDB_RESOURCE_TYPE_KEYBOX) + keybox_close_all_files (all_resources[i].token); +#endif +} + + + KEYDB_HANDLE keydb_new (void) { @@ -505,22 +521,22 @@ keydb_set_ephemeral (KEYDB_HANDLE hd, int yes) } + /* If the keyring has not yet been locked, lock it now. This - operation is required before any update operation; it is optional - for an insert operation. The lock is released with - keydb_released. */ + operation is required before any update operation; On Windows it is + always required to disallow other processes to open the file which + in turn would inhibit our copy+update+rename method. The lock is + released with keydb_released. */ gpg_error_t keydb_lock (KEYDB_HANDLE hd) { if (!hd) return gpg_error (GPG_ERR_INV_HANDLE); - if (hd->locked) - return 0; /* Already locked. */ return lock_all (hd); } - +/* Same as keydb_lock but no check for an invalid HD. */ static int lock_all (KEYDB_HANDLE hd) { @@ -560,8 +576,6 @@ lock_all (KEYDB_HANDLE hd) } } } - else - hd->locked = 1; /* make_dotlock () does not yet guarantee that errno is set, thus we can't rely on the error reason and will simply use @@ -569,14 +583,12 @@ lock_all (KEYDB_HANDLE hd) return rc? gpg_error (GPG_ERR_EACCES) : 0; } + static void unlock_all (KEYDB_HANDLE hd) { int i; - if (!hd->locked) - return; - for (i=hd->used-1; i >= 0; i--) { switch (hd->active[i].type) @@ -589,7 +601,6 @@ unlock_all (KEYDB_HANDLE hd) break; } } - hd->locked = 0; } @@ -719,7 +730,7 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value) if ( hd->found < 0 || hd->found >= hd->used) return gpg_error (GPG_ERR_NOTHING_FOUND); - if (!hd->locked) + if (!dotlock_is_locked (hd->active[hd->found].lockhandle)) return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) @@ -758,7 +769,7 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert) else return gpg_error (GPG_ERR_GENERAL); - if (!hd->locked) + if (!dotlock_is_locked (hd->active[idx].lockhandle)) return gpg_error (GPG_ERR_NOT_LOCKED); gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ @@ -778,44 +789,6 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert) } - -/* Update the current keyblock with KB. */ -int -keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert) -{ - int rc = 0; - unsigned char digest[20]; - - if (!hd) - return gpg_error (GPG_ERR_INV_VALUE); - - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ - - if (opt.dry_run) - return 0; - - rc = lock_all (hd); - if (rc) - return rc; - - gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ - - switch (hd->active[hd->found].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - rc = gpg_error (GPG_ERR_GENERAL); /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest); - break; - } - - unlock_all (hd); - return rc; -} - - /* * The current keyblock or cert will be deleted. */ @@ -833,7 +806,7 @@ keydb_delete (KEYDB_HANDLE hd, int unlock) if( opt.dry_run ) return 0; - if (!hd->locked) + if (!dotlock_is_locked (hd->active[hd->found].lockhandle)) return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) @@ -952,7 +925,7 @@ int keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) { - int rc = -1; + int rc; unsigned long skipped; if (!hd) @@ -965,6 +938,11 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd, return gpg_error (GPG_ERR_NOT_FOUND); } + rc = lock_all (hd); + if (rc) + return rc; + rc = -1; + while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { switch (hd->active[hd->current].type) @@ -1118,6 +1096,7 @@ keydb_store_cert (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, int *existed) records. */ keydb_set_ephemeral (kh, 1); + keydb_close_all_files (); rc = lock_all (kh); if (rc) return rc; @@ -1203,7 +1182,8 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, if (ephemeral) keydb_set_ephemeral (kh, 1); - err = keydb_lock (kh); + keydb_close_all_files (); + err = lock_all (kh); if (err) { log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); @@ -1301,7 +1281,8 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names) } } - err = keydb_lock (hd); + keydb_close_all_files (); + err = lock_all (hd); if (err) { log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); @@ -1333,7 +1314,7 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names) } } if (rc && rc != -1) - log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); + log_error ("%s failed: %s\n", __func__, gpg_strerror (rc)); leave: xfree (desc); |