diff options
Diffstat (limited to 'sm/keydb.c')
-rw-r--r-- | sm/keydb.c | 557 |
1 files changed, 355 insertions, 202 deletions
diff --git a/sm/keydb.c b/sm/keydb.c index b12ba1df3..ef839edfb 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -28,19 +28,12 @@ #include <sys/stat.h> #include <unistd.h> -#include "util.h" -#include "options.h" -#include "keybox.h" +#include "gpgsm.h" +#include "../kbx/keybox.h" #include "keydb.h" #include "i18n.h" -static struct { - const char *homedir; - int dry_run; - int quiet; - int verbose; - int preserve_permissions; -} keydbopt; +#define DIRSEP_C '/' static int active_handles; @@ -87,25 +80,24 @@ keydb_add_resource (const char *url, int force, int secret) { static int any_secret, any_public; const char *resname = url; - IOBUF iobuf = NULL; char *filename = NULL; - int rc = 0; + int rc = 0; KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; - const char *created_fname = NULL; +/* const char *created_fname = NULL; */ /* Do we have an URL? * gnupg-ring:filename := this is a plain keybox * filename := See what is is, but create as plain keybox. */ if (strlen (resname) > 11) { - if (!strncmp( resname, "gnupg-ring:", 11) ) { + if (!strncmp( resname, "gnupg-kbx:", 10) ) { rt = KEYDB_RESOURCE_TYPE_KEYBOX; resname += 11; } #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) else if (strchr (resname, ':')) { log_error ("invalid key resource URL `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ @@ -115,59 +107,62 @@ keydb_add_resource (const char *url, int force, int secret) if (strchr(resname, DIRSEP_C) ) filename = make_filename (resname, NULL); else - filename = make_filename (keydbopt.homedir, resname, NULL); + filename = make_filename (opt.homedir, resname, NULL); } else - filename = m_strdup (resname); + filename = xstrdup (resname); if (!force) force = secret? !any_secret : !any_public; /* see whether we can determine the filetype */ if (rt == KEYDB_RESOURCE_TYPE_NONE) { - FILE *fp = fopen( filename, "rb" ); + FILE *fp2 = fopen( filename, "rb" ); - if (fp) { + if (fp2) { u32 magic; - if (fread( &magic, 4, 1, fp) == 1 ) { + /* FIXME: check for the keybox magic */ + if (fread( &magic, 4, 1, fp2) == 1 ) + { if (magic == 0x13579ace || magic == 0xce9a5713) - ; /* GDBM magic - no more support */ + ; /* GDBM magic - no more support */ else - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - } + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } else /* maybe empty: assume ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - fclose( fp ); + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + fclose (fp2); } else /* no file yet: create ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; + rt = KEYDB_RESOURCE_TYPE_KEYBOX; } switch (rt) { case KEYDB_RESOURCE_TYPE_NONE: log_error ("unknown type of key resource `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; case KEYDB_RESOURCE_TYPE_KEYBOX: - iobuf = iobuf_open (filename); +#if 0 + fp = fopen (filename); if (!iobuf && !force) { rc = G10ERR_OPEN_FILE; goto leave; } - if (!iobuf) { + if (!fp) { char *last_slash_in_filename; last_slash_in_filename = strrchr (filename, DIRSEP_C); *last_slash_in_filename = 0; if (access(filename, F_OK)) { - /* on the first time we try to create the default homedir and - * in this case the process will be terminated, so that on the - * next invocation it can read the options file in on startup - */ + /* on the first time we try to create the default + homedir and in this case the process will be + terminated, so that on the next invocation it can + read the options file in on startup */ try_make_homedir (filename); rc = G10ERR_OPEN_FILE; *last_slash_in_filename = DIRSEP_C; @@ -185,7 +180,7 @@ keydb_add_resource (const char *url, int force, int secret) } else { #ifndef HAVE_DOSISH_SYSTEM - if (secret && !keydbopt.preserve_permissionws) { + if (secret && !opt.preserve_permissionws) { if (chmod (filename, S_IRUSR | S_IWUSR) ) { log_error (_("changing permission of " " `%s' failed: %s\n"), @@ -195,7 +190,7 @@ keydb_add_resource (const char *url, int force, int secret) } } #endif - if (!keydbopt.quiet) + if (!opt.quiet) log_info (_("keybox `%s' created\n"), filename); created_fname = filename; } @@ -204,12 +199,13 @@ keydb_add_resource (const char *url, int force, int secret) iobuf = NULL; if (created_fname) /* must invalidate that ugly cache */ iobuf_ioctl (NULL, 2, 0, (char*)created_fname); +#endif { - void *token = keybox_register_filename (filename, secret); + void *token = keybox_register_file (filename, secret); if (!token) ; /* already registered - ignore it */ else if (used_resources >= MAX_KEYDB_RESOURCES) - rc = G10ERR_RESOURCE_LIMIT; + rc = GPGSM_Resource_Limit; else { all_resources[used_resources].type = rt; @@ -223,7 +219,7 @@ keydb_add_resource (const char *url, int force, int secret) default: log_error ("resource type of `%s' not supported\n", url); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; } @@ -231,12 +227,12 @@ keydb_add_resource (const char *url, int force, int secret) leave: if (rc) - log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc)); + log_error ("keyblock resource `%s': %s\n", filename, gpgsm_strerror(rc)); else if (secret) any_secret = 1; else any_public = 1; - m_free (filename); + xfree (filename); return rc; } @@ -249,7 +245,7 @@ keydb_new (int secret) KEYDB_HANDLE hd; int i, j; - hd = m_alloc_clear (sizeof *hd); + hd = xcalloc (1, sizeof *hd); hd->found = -1; assert (used_resources <= MAX_KEYDB_RESOURCES); @@ -267,7 +263,7 @@ keydb_new (int secret) hd->active[j].secret = all_resources[i].secret; hd->active[j].u.kr = keybox_new (all_resources[i].token, secret); if (!hd->active[j].u.kr) { - m_free (hd); + xfree (hd); return NULL; /* fixme: release all previously allocated handles*/ } j++; @@ -283,95 +279,101 @@ keydb_new (int secret) void keydb_release (KEYDB_HANDLE hd) { - int i; - - if (!hd) - return; - assert (active_handles > 0); - active_handles--; + int i; + + if (!hd) + return; + assert (active_handles > 0); + active_handles--; - unlock_all (hd); - for (i=0; i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_release (hd->active[i].u.kr); - break; + unlock_all (hd); + for (i=0; i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + keybox_release (hd->active[i].u.kr); + break; } } - m_free (hd); + xfree (hd); } -/* - * Return the name of the current resource. This is function first - * looks for the last found found, then for the current search - * position, and last returns the first available resource. The - * returned string is only valid as long as the handle exists. This - * function does only return NULL if no handle is specified, in all - * other error cases an empty string is returned. - */ +/* Return the name of the current resource. This is function first + looks for the last found found, then for the current search + position, and last returns the first available resource. The + returned string is only valid as long as the handle exists. This + function does only return NULL if no handle is specified, in all + other error cases an empty string is returned. */ const char * keydb_get_resource_name (KEYDB_HANDLE hd) { - int idx; - const char *s = NULL; - - if (!hd) - return NULL; + int idx; + const char *s = NULL; + + if (!hd) + return NULL; - if ( hd->found >= 0 && hd->found < hd->used) - idx = hd->found; - else if ( hd->current >= 0 && hd->current < hd->used) - idx = hd->current; - else - idx = 0; + if ( hd->found >= 0 && hd->found < hd->used) + idx = hd->found; + else if ( hd->current >= 0 && hd->current < hd->used) + idx = hd->current; + else + idx = 0; - switch (hd->active[idx].type) { - case KEYDB_RESOURCE_TYPE_NONE: - s = NULL; - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - s = keybox_get_resource_name (hd->active[idx].u.kr); - break; + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + s = NULL; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + s = keybox_get_resource_name (hd->active[idx].u.kr); + break; } - - return s? s: ""; + + return s? s: ""; } - + static int lock_all (KEYDB_HANDLE hd) { - int i, rc = 0; - - for (i=0; !rc && i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_lock (hd->active[i].u.kr, 1); - break; + int i, rc = 0; + + for (i=0; !rc && i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + /* FIXME rc = keybox_lock (hd->active[i].u.kr, 1);*/ + break; } } - if (rc) { + if (rc) + { /* revert the already set locks */ - for (i--; i >= 0; i--) { - switch (hd->active[i].type) { + for (i--; i >= 0; i--) + { + switch (hd->active[i].type) + { case KEYDB_RESOURCE_TYPE_NONE: break; case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_lock (hd->active[i].u.kr, 0); + /* Fixme: keybox_lock (hd->active[i].u.kr, 0);*/ break; - } - } - } + } + } + } else - hd->locked = 1; + hd->locked = 1; return rc; } @@ -379,24 +381,27 @@ lock_all (KEYDB_HANDLE hd) 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) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_lock (hd->active[i].u.kr, 0); - break; + int i; + + if (!hd->locked) + return; + + for (i=hd->used-1; i >= 0; i--) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + /* fixme: keybox_lock (hd->active[i].u.kr, 0);*/ + break; } } - hd->locked = 0; + hd->locked = 0; } - + +#if 0 /* * Return the last found keybox. Caller must free it. * The returned keyblock has the kbode flag bit 0 set for the node with @@ -440,7 +445,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ - if( keydbopt.dry_run ) + if( opt.dry_run ) return 0; rc = lock_all (hd); @@ -473,7 +478,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) if (!hd) return G10ERR_INV_ARG; - if( keydbopt.dry_run ) + if( opt.dry_run ) return 0; if ( hd->found >= 0 && hd->found < hd->used) @@ -500,41 +505,157 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) return rc; } +#endif /*disabled code*/ + + + +/* + Return the last found keybox. Caller must free it. The returned + keyblock has the kbode flag bit 0 set for the node with the public + key used to locate the keyblock or flag bit 1 set for the user ID + node. */ +int +keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) +{ + int rc = 0; + + if (!hd) + return GPGSM_Invalid_Value; + + if ( hd->found < 0 || hd->found >= hd->used) + return -1; /* nothing found */ + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert); + break; + } + + return rc; +} /* - * The current keyblock will be deleted. + * Insert a new Certificate into one of the resources. */ int -keydb_delete_keyblock (KEYDB_HANDLE hd) +keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) { - int rc = -1; + int rc = -1; + int idx; + char digest[20]; + + if (!hd) + return GPGSM_Invalid_Value; - if (!hd) - return G10ERR_INV_ARG; + if (opt.dry_run) + return 0; + + if ( hd->found >= 0 && hd->found < hd->used) + idx = hd->found; + else if ( hd->current >= 0 && hd->current < hd->used) + idx = hd->current; + else + return GPGSM_General_Error; + + rc = lock_all (hd); + if (rc) + return rc; - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ - if( keydbopt.dry_run ) - return 0; + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest); + break; + } + + unlock_all (hd); + return rc; +} - rc = lock_all (hd); - if (rc) - return rc; - switch (hd->active[hd->found].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_delete_keyblock (hd->active[hd->found].u.kr); - break; + +/* update the current keyblock with KB */ +int +keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert) +{ + int rc = 0; + char digest[20]; + + if (!hd) + return GPGSM_Invalid_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 = GPGSM_General_Error; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest); + break; } - unlock_all (hd); + unlock_all (hd); + return rc; +} + + +/* + * The current keyblock or cert will be deleted. + */ +int +keydb_delete (KEYDB_HANDLE hd) +{ + int rc = -1; + + if (!hd) + return GPGSM_Invalid_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; + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_delete (hd->active[hd->found].u.kr); + break; + } + + unlock_all (hd); + return rc; } + /* * Locate the default writable key resource, so that the next @@ -547,12 +668,12 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) int rc; if (!hd) - return G10ERR_INV_ARG; + return GPGSM_Invalid_Value; rc = keydb_search_reset (hd); /* this does reset hd->current */ if (rc) return rc; - + for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) { switch (hd->active[hd->current].type) @@ -576,7 +697,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) void keydb_rebuild_caches (void) { - int i, rc; + int i; for (i=0; i < used_resources; i++) { @@ -587,10 +708,10 @@ keydb_rebuild_caches (void) case KEYDB_RESOURCE_TYPE_NONE: /* ignore */ break; case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_rebuild_cache (all_resources[i].token); - if (rc) - log_error (_("failed to rebuild keybox cache: %s\n"), - g10_errstr (rc)); +/* rc = keybox_rebuild_cache (all_resources[i].token); */ +/* if (rc) */ +/* log_error (_("failed to rebuild keybox cache: %s\n"), */ +/* g10_errstr (rc)); */ break; } } @@ -604,27 +725,29 @@ keydb_rebuild_caches (void) int keydb_search_reset (KEYDB_HANDLE hd) { - int i, rc = 0; - - if (!hd) - return G10ERR_INV_ARG; + int i, rc = 0; + + if (!hd) + return GPGSM_Invalid_Value; - hd->current = 0; - hd->found = -1; - /* and reset all resources */ - for (i=0; !rc && i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search_reset (hd->active[i].u.kr); - break; + hd->current = 0; + hd->found = -1; + /* and reset all resources */ + for (i=0; !rc && i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_search_reset (hd->active[i].u.kr); + break; } } - return rc; + return rc; /* fixme: we need to map error codes or share them with + all modules*/ } - /* * Search through all keydb resources, starting at the current position, * for a keyblock which contains one of the keys described in the DESC array. @@ -632,71 +755,101 @@ keydb_search_reset (KEYDB_HANDLE hd) int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) { - int rc = -1; - - if (!hd) - return G10ERR_INV_ARG; + int rc = -1; + + if (!hd) + return GPGSM_Invalid_Value; - while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { - switch (hd->active[hd->current].type) { - case KEYDB_RESOURCE_TYPE_NONE: - BUG(); /* we should never see it here */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); - break; + while (rc == -1 && hd->current >= 0 && hd->current < hd->used) + { + switch (hd->active[hd->current].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + BUG(); /* we should never see it here */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); + break; } - if (rc == -1) /* EOF -> switch to next resource */ - hd->current++; - else if (!rc) - hd->found = hd->current; + if (rc == -1) /* EOF -> switch to next resource */ + hd->current++; + else if (!rc) + hd->found = hd->current; } - - return rc; + + return rc; } int keydb_search_first (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + return keydb_search (hd, &desc, 1); } int keydb_search_next (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_NEXT; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_NEXT; + return keydb_search (hd, &desc, 1); } int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_LONG_KID; - desc.u.kid[0] = kid[0]; - desc.u.kid[1] = kid[1]; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_LONG_KID; +/* desc.u.kid[0] = kid[0]; */ +/* desc.u.kid[1] = kid[1]; */ + return keydb_search (hd, &desc, 1); } int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr) { - KEYDB_SEARCH_DESC desc; + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FPR; + memcpy (desc.u.fpr, fpr, 20); + return keydb_search (hd, &desc, 1); +} - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FPR; - memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN); - return keydb_search (hd, &desc, 1); +int +keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; +} + +int +keydb_search_issuer_sn (KEYDB_HANDLE hd, + const char *issuer, const unsigned char *serial) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN; + desc.sn = serial; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; } |