int composite_insert(int fd, struct keydb_column *tuple) { // Inserts the given list of key components into the keydb. int64_t pos = 0; int64_t previous_pos = 0; keydb_lock(pos); previous_pos = pos; pos = keydb_insert(fd, tuple->column, pos, false); keydb_unlock(previous_pos); if (pos == -1) { return -1; } tuple = tuple->next; while (tuple) { keydb_lock(pos); previous_pos = pos; pos = keydb_insert(fd, tuple->column, pos, true); keydb_unlock(previous_pos); if (pos == -1){ return -1; } tuple = tuple->next; }; return 0; }
int composite_delete(int fd, struct keydb_column *tuple) { // Reduces the refcounts of the given list of key components into the keydb. int64_t pos = 0; struct keydb_node *node; //sem_wait(KEYDB_LOCK); while (tuple) { keydb_lock(pos); // Lock the tree we're deleting from. node = keydb_find(fd, tuple->column, pos); if (node == NULL) { //sem_post(KEYDB_LOCK); keydb_unlock(pos); return -1; } if (node->refcount == 0) { // nothing here. We can't lower refcount below zero. free(node); //sem_post(KEYDB_LOCK); keydb_unlock(pos); return(-1); } keydb_unlock(pos); pos = node->pos; keydb_lock(pos); node->refcount--; if ((pwrite(fd, node, sizeof(struct keydb_node), pos)) == -1) { fprintf(stderr, "Problem writing node at %llu in composite_delete().\n", pos); keydb_unlock(pos); return(-1); free(node); }; keydb_unlock(pos); pos = node->next; tuple = tuple->next; free(node); } //sem_post(KEYDB_LOCK); return 0; }
/* Reset all the certificate flags we have stored with the certificates for performance reasons. */ void keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names) { gpg_error_t err; KEYDB_HANDLE hd = NULL; KEYDB_SEARCH_DESC *desc = NULL; int ndesc; strlist_t sl; int rc=0; unsigned int old_value, value; (void)ctrl; hd = keydb_new (0); if (!hd) { log_error ("keydb_new failed\n"); goto leave; } if (!names) ndesc = 1; else { for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) ; } desc = xtrycalloc (ndesc, sizeof *desc); if (!ndesc) { log_error ("allocating memory failed: %s\n", gpg_strerror (out_of_core ())); goto leave; } if (!names) desc[0].mode = KEYDB_SEARCH_MODE_FIRST; else { for (ndesc=0, sl=names; sl; sl = sl->next) { rc = classify_user_id (sl->d, desc+ndesc, 0); if (rc) { log_error ("key '%s' not found: %s\n", sl->d, gpg_strerror (rc)); rc = 0; } else ndesc++; } } err = keydb_lock (hd); if (err) { log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); goto leave; } while (!(rc = keydb_search (hd, desc, ndesc))) { if (!names) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value); if (err) { log_error (_("error getting stored flags: %s\n"), gpg_strerror (err)); goto leave; } value = (old_value & ~VALIDITY_REVOKED); if (value != old_value) { err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value); if (err) { log_error (_("error storing flags: %s\n"), gpg_strerror (err)); goto leave; } } } if (rc && rc != -1) log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); leave: xfree (desc); keydb_release (hd); }
/* This is basically keydb_set_flags but it implements a complete transaction by locating the certificate in the DB and updating the flags. */ gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int ephemeral, int which, int idx, unsigned int mask, unsigned int value) { KEYDB_HANDLE kh; gpg_error_t err; unsigned char fpr[20]; unsigned int old_value; if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL)) { log_error (_("failed to get the fingerprint\n")); return gpg_error (GPG_ERR_GENERAL); } kh = keydb_new (0); if (!kh) { log_error (_("failed to allocate keyDB handle\n")); return gpg_error (GPG_ERR_ENOMEM);; } if (ephemeral) keydb_set_ephemeral (kh, 1); err = keydb_lock (kh); if (err) { log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); keydb_release (kh); return err; } err = keydb_search_fpr (kh, fpr); if (err) { if (err == -1) err = gpg_error (GPG_ERR_NOT_FOUND); else log_error (_("problem re-searching certificate: %s\n"), gpg_strerror (err)); keydb_release (kh); return err; } err = keydb_get_flags (kh, which, idx, &old_value); if (err) { log_error (_("error getting stored flags: %s\n"), gpg_strerror (err)); keydb_release (kh); return err; } value = ((old_value & ~mask) | (value & mask)); if (value != old_value) { err = keydb_set_flags (kh, which, idx, value); if (err) { log_error (_("error storing flags: %s\n"), gpg_strerror (err)); keydb_release (kh); return err; } } keydb_release (kh); return 0; }
/* Delete a certificate or an secret key from a key database. */ static int delete_one (ctrl_t ctrl, const char *username) { int rc = 0; KEYDB_SEARCH_DESC desc; KEYDB_HANDLE kh = NULL; ksba_cert_t cert = NULL; int duplicates = 0; int is_ephem = 0; rc = keydb_classify_name (username, &desc); if (rc) { log_error (_("certificate `%s' not found: %s\n"), username, gpg_strerror (rc)); gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "1", NULL); goto leave; } kh = keydb_new (0); if (!kh) { log_error ("keydb_new failed\n"); goto leave; } /* If the key is specified in a unique way, include ephemeral keys in the search. */ if ( desc.mode == KEYDB_SEARCH_MODE_FPR || desc.mode == KEYDB_SEARCH_MODE_FPR20 || desc.mode == KEYDB_SEARCH_MODE_FPR16 || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP ) { is_ephem = 1; keydb_set_ephemeral (kh, 1); } rc = keydb_search (kh, &desc, 1); if (!rc) rc = keydb_get_cert (kh, &cert); if (!rc && !is_ephem) { unsigned char fpr[20]; gpgsm_get_fingerprint (cert, 0, fpr, NULL); next_ambigious: rc = keydb_search (kh, &desc, 1); if (rc == -1) rc = 0; else if (!rc) { ksba_cert_t cert2 = NULL; unsigned char fpr2[20]; /* We ignore all duplicated certificates which might have been inserted due to program bugs. */ if (!keydb_get_cert (kh, &cert2)) { gpgsm_get_fingerprint (cert2, 0, fpr2, NULL); ksba_cert_release (cert2); if (!memcmp (fpr, fpr2, 20)) { duplicates++; goto next_ambigious; } } rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); } } if (rc) { if (rc == -1) rc = gpg_error (GPG_ERR_NO_PUBKEY); log_error (_("certificate `%s' not found: %s\n"), username, gpg_strerror (rc)); gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL); goto leave; } /* We need to search again to get back to the right position. */ rc = keydb_lock (kh); if (rc) { log_error (_("error locking keybox: %s\n"), gpg_strerror (rc)); goto leave; } do { keydb_search_reset (kh); rc = keydb_search (kh, &desc, 1); if (rc) { log_error ("problem re-searching certificate: %s\n", gpg_strerror (rc)); goto leave; } rc = keydb_delete (kh, duplicates ? 0 : 1); if (rc) goto leave; if (opt.verbose) { if (duplicates) log_info (_("duplicated certificate `%s' deleted\n"), username); else log_info (_("certificate `%s' deleted\n"), username); } } while (duplicates--); leave: keydb_release (kh); ksba_cert_release (cert); return rc; }