diff --git a/g10/ChangeLog b/g10/ChangeLog index cbd370614..b8d3232bb 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2011-04-29 Werner Koch + + * keydb.c (keydb_get_keyblock, keydb_add_resource): Use gpg_error. + (keydb_get_keyblock): Return VALUE_NOT_FOUND instead of -1. + (keydb_update_keyblock, keydb_insert_keyblock) + (keydb_delete_keyblock): Ditto. + (keydb_locate_writable): Ditto. + (keydb_search_reset): Ditto. + (keydb_search2): Return GPG_ERR_NOT_FOUND instead of -1. Change + all callers. + (keydb_search_first, keydb_search_next, keydb_search_kid) + (keydb_search_fpr): Ditto. + 2011-04-29 Marcus Brinkmann * import.c (import_secret_one): Leave all checks to import_one. diff --git a/g10/export.c b/g10/export.c index 2e35eea9f..1b575dd9e 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1185,7 +1185,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret, iobuf_put (out, ')'); iobuf_put (out, '\n'); } - if (err == -1) + if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) err = 0; leave: diff --git a/g10/getkey.c b/g10/getkey.c index 171f17781..b80695db4 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -431,7 +431,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid) hd = keydb_new (); rc = keydb_search_kid (hd, keyid); - if (rc == -1) + if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) { keydb_release (hd); return G10ERR_NO_PUBKEY; @@ -992,7 +992,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk, hd = keydb_new (); rc = keydb_search_fpr (hd, fprbuf); - if (rc == -1) + if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) { keydb_release (hd); return G10ERR_NO_PUBKEY; @@ -2488,7 +2488,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret) } found: - if (rc && rc != -1) + if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("keydb_search failed: %s\n", g10_errstr (rc)); if (!rc) @@ -2496,9 +2496,9 @@ found: *ret_keyblock = ctx->keyblock; /* Return the keyblock. */ ctx->keyblock = NULL; } - else if (rc == -1 && no_suitable_key) + else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key) rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; - else if (rc == -1) + else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; release_kbnode (ctx->keyblock); diff --git a/g10/keydb.c b/g10/keydb.c index d9e01dced..f7642485a 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1,6 +1,6 @@ /* keydb.c - key database dispatcher * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2008, 2009 Free Software Foundation, Inc. + * 2008, 2009, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -39,10 +39,11 @@ static int active_handles; -typedef enum { +typedef enum + { KEYDB_RESOURCE_TYPE_NONE = 0, KEYDB_RESOURCE_TYPE_KEYRING -} KeydbResourceType; + } KeydbResourceType; #define MAX_KEYDB_RESOURCES 40 struct resource_item @@ -58,11 +59,12 @@ static struct resource_item all_resources[MAX_KEYDB_RESOURCES]; static int used_resources; static void *primary_keyring=NULL; -struct keydb_handle { +struct keydb_handle +{ int locked; int found; int current; - int used; /* items in active */ + int used; /* Number of items in ACTIVE. */ struct resource_item active[MAX_KEYDB_RESOURCES]; }; @@ -212,122 +214,132 @@ maybe_create_keyring (char *filename, int force) * Flag 4 - This is a default resources. * Flag 8 - Open as read-only. */ -int +gpg_error_t keydb_add_resource (const char *url, int flags) { - static int any_public; - const char *resname = url; - char *filename = NULL; - int force = (flags&1); - int read_only = !!(flags&8); - int rc = 0; - KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; - void *token; + static int any_public; + const char *resname = url; + char *filename = NULL; + int force = (flags&1); + int read_only = !!(flags&8); + int rc = 0; + KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; + void *token; - if (read_only) - force = 0; + if (read_only) + force = 0; - /* Do we have an URL? - * gnupg-ring:filename := this is a plain keyring - * filename := See what is is, but create as plain keyring. - */ - if (strlen (resname) > 11) { - if (!strncmp( resname, "gnupg-ring:", 11) ) { - rt = KEYDB_RESOURCE_TYPE_KEYRING; - resname += 11; + /* Do we have an URL? + * gnupg-ring:filename := this is a plain keyring + * filename := See what is is, but create as plain keyring. + */ + if (strlen (resname) > 11) + { + if (!strncmp( resname, "gnupg-ring:", 11) ) + { + rt = KEYDB_RESOURCE_TYPE_KEYRING; + 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; - goto leave; - } + else if (strchr (resname, ':')) + { + log_error ("invalid key resource URL `%s'\n", url ); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ } - if (*resname != DIRSEP_C ) { /* do tilde expansion etc */ - if (strchr(resname, DIRSEP_C) ) - filename = make_filename (resname, NULL); - else - filename = make_filename (opt.homedir, resname, NULL); + if (*resname != DIRSEP_C ) + { + /* Do tilde expansion etc. */ + if (strchr(resname, DIRSEP_C) ) + filename = make_filename (resname, NULL); + else + filename = make_filename (opt.homedir, resname, NULL); } - else - filename = xstrdup (resname); + else + filename = xstrdup (resname); - if (!force && !read_only) - force = !any_public; + if (!force && !read_only) + force = !any_public; - /* See whether we can determine the filetype. */ - if (rt == KEYDB_RESOURCE_TYPE_NONE) { - FILE *fp = fopen( filename, "rb" ); + /* See whether we can determine the filetype. */ + if (rt == KEYDB_RESOURCE_TYPE_NONE) + { + FILE *fp = fopen (filename, "rb"); - if (fp) { - u32 magic; + if (fp) + { + u32 magic; - if (fread( &magic, 4, 1, fp) == 1 ) { - if (magic == 0x13579ace || magic == 0xce9a5713) - ; /* GDBM magic - no more support */ - else - rt = KEYDB_RESOURCE_TYPE_KEYRING; + if (fread( &magic, 4, 1, fp) == 1 ) + { + if (magic == 0x13579ace || magic == 0xce9a5713) + ; /* GDBM magic - not anymore supported. */ + else + rt = KEYDB_RESOURCE_TYPE_KEYRING; } - else /* maybe empty: assume ring */ - rt = KEYDB_RESOURCE_TYPE_KEYRING; - fclose( fp ); + else /* Maybe empty: assume keyring. */ + rt = KEYDB_RESOURCE_TYPE_KEYRING; + + fclose( fp ); } - else /* no file yet: create ring */ - rt = KEYDB_RESOURCE_TYPE_KEYRING; + else /* No file yet: create keyring. */ + rt = KEYDB_RESOURCE_TYPE_KEYRING; } - switch (rt) { - case KEYDB_RESOURCE_TYPE_NONE: - log_error ("unknown type of key resource `%s'\n", url ); - rc = G10ERR_GENERAL; - goto leave; + switch (rt) + { + case KEYDB_RESOURCE_TYPE_NONE: + log_error ("unknown type of key resource `%s'\n", url ); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; - case KEYDB_RESOURCE_TYPE_KEYRING: - rc = maybe_create_keyring (filename, force); - if (rc) - goto leave; + case KEYDB_RESOURCE_TYPE_KEYRING: + rc = maybe_create_keyring (filename, force); + if (rc) + goto leave; - if(keyring_register_filename (filename, read_only, &token)) - { - if (used_resources >= MAX_KEYDB_RESOURCES) - rc = G10ERR_RESOURCE_LIMIT; - else - { - if(flags&2) - primary_keyring=token; - all_resources[used_resources].type = rt; - all_resources[used_resources].u.kr = NULL; /* Not used here */ - all_resources[used_resources].token = token; - used_resources++; - } - } - else - { - /* This keyring was already registered, so ignore it. - However, we can still mark it as primary even if it was - already registered. */ - if(flags&2) - primary_keyring=token; - } - break; + if (keyring_register_filename (filename, read_only, &token)) + { + if (used_resources >= MAX_KEYDB_RESOURCES) + rc = gpg_error (GPG_ERR_RESOURCE_LIMIT); + else + { + if (flags&2) + primary_keyring = token; + all_resources[used_resources].type = rt; + all_resources[used_resources].u.kr = NULL; /* Not used here */ + all_resources[used_resources].token = token; + used_resources++; + } + } + else + { + /* This keyring was already registered, so ignore it. + However, we can still mark it as primary even if it was + already registered. */ + if (flags&2) + primary_keyring = token; + } + break; default: log_error ("resource type of `%s' not supported\n", url); - rc = G10ERR_GENERAL; + rc = gpg_error (GPG_ERR_GENERAL); goto leave; } /* fixme: check directory permissions and print a warning */ - leave: - if (rc) - log_error (_("keyblock resource `%s': %s\n"), filename, g10_errstr(rc)); - else - any_public = 1; - xfree (filename); - return rc; + leave: + if (rc) + log_error (_("keyblock resource `%s': %s\n"), filename, gpg_strerror (rc)); + else + any_public = 1; + xfree (filename); + return rc; } @@ -370,25 +382,27 @@ keydb_new (void) void keydb_release (KEYDB_HANDLE hd) { - int i; + int i; - if (!hd) - return; - assert (active_handles > 0); - active_handles--; + 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_KEYRING: - keyring_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_KEYRING: + keyring_release (hd->active[i].u.kr); + break; } } - xfree (hd); + xfree (hd); } @@ -403,29 +417,30 @@ keydb_release (KEYDB_HANDLE hd) const char * keydb_get_resource_name (KEYDB_HANDLE hd) { - int idx; - const char *s = NULL; + int idx; + const char *s = NULL; - if (!hd) - return 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_KEYRING: - s = keyring_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_KEYRING: + s = keyring_get_resource_name (hd->active[idx].u.kr); + break; } - return s? s: ""; + return s? s: ""; } @@ -433,54 +448,62 @@ keydb_get_resource_name (KEYDB_HANDLE hd) static int lock_all (KEYDB_HANDLE hd) { - int i, rc = 0; + 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_KEYRING: - rc = keyring_lock (hd->active[i].u.kr, 1); - break; + for (i=0; !rc && i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + rc = keyring_lock (hd->active[i].u.kr, 1); + break; } } - if (rc) { - /* revert the already set locks */ - for (i--; i >= 0; i--) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYRING: - keyring_lock (hd->active[i].u.kr, 0); - break; + if (rc) + { + /* Revert the already set locks. */ + for (i--; i >= 0; i--) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + keyring_lock (hd->active[i].u.kr, 0); + break; } } } - else - hd->locked = 1; + else + hd->locked = 1; - return rc; + return rc; } + static void unlock_all (KEYDB_HANDLE hd) { - int i; + int i; - if (!hd->locked) - return; + 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_KEYRING: - keyring_lock (hd->active[i].u.kr, 0); - break; + for (i=hd->used-1; i >= 0; i--) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + keyring_lock (hd->active[i].u.kr, 0); + break; } } - hd->locked = 0; + hd->locked = 0; } @@ -490,148 +513,153 @@ unlock_all (KEYDB_HANDLE hd) * the public key used to locate the keyblock or flag bit 1 set for * the user ID node. */ -int +gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) { - int rc = 0; + gpg_error_t err = 0; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ + if (hd->found < 0 || hd->found >= hd->used) + return gpg_error (GPG_ERR_VALUE_NOT_FOUND); - switch (hd->active[hd->found].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYRING: - rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb); - break; + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + err = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb); + break; } - return rc; + return err; } /* - * update the current keyblock with KB + * Update the current keyblock with the keyblock KB */ -int -keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) +gpg_error_t +keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb) { - int rc = 0; + gpg_error_t rc; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ + if (hd->found < 0 || hd->found >= hd->used) + return gpg_error (GPG_ERR_VALUE_NOT_FOUND); - if( opt.dry_run ) - return 0; + if (opt.dry_run) + return 0; - rc = lock_all (hd); - if (rc) - 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_KEYRING: - rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb); - break; + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb); + break; } - unlock_all (hd); - return rc; + unlock_all (hd); + return rc; } /* * Insert a new KB into one of the resources. */ -int -keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) +gpg_error_t +keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb) { - int rc = -1; - int idx; + int rc; + int idx; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - if( opt.dry_run ) - return 0; + 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 G10ERR_GENERAL; + 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 gpg_error (GPG_ERR_GENERAL); - rc = lock_all (hd); - if (rc) - return rc; + rc = lock_all (hd); + if (rc) + return rc; - switch (hd->active[idx].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYRING: - rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb); - break; + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb); + break; } - unlock_all (hd); - return rc; + unlock_all (hd); + return rc; } /* - * The current keyblock will be deleted. + * Delete the current keyblock. */ -int +gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd) { - int rc = -1; + gpg_error_t rc; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ + if (hd->found < 0 || hd->found >= hd->used) + return gpg_error (GPG_ERR_VALUE_NOT_FOUND); - if( opt.dry_run ) - return 0; + if (opt.dry_run) + return 0; - rc = lock_all (hd); - if (rc) - 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_KEYRING: - rc = keyring_delete_keyblock (hd->active[hd->found].u.kr); - break; + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = gpg_error (GPG_ERR_GENERAL); + break; + case KEYDB_RESOURCE_TYPE_KEYRING: + rc = keyring_delete_keyblock (hd->active[hd->found].u.kr); + break; } - unlock_all (hd); - return rc; + unlock_all (hd); + return rc; } + /* * Locate the default writable key resource, so that the next * operation (which is only relevant for inserts) will be done on this * resource. */ -int +gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) { - int rc; + gpg_error_t rc; (void)reserved; @@ -643,7 +671,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) return rc; /* If we have a primary set, try that one first */ - if(primary_keyring) + if (primary_keyring) { for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) { @@ -675,7 +703,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) } } - return -1; + return gpg_error (GPG_ERR_NOT_FOUND); } /* @@ -709,101 +737,116 @@ keydb_rebuild_caches (int noisy) /* * Start the next search on this handle right at the beginning */ -int +gpg_error_t keydb_search_reset (KEYDB_HANDLE hd) { - int i, rc = 0; + gpg_error_t rc = 0; + int i; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - 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_KEYRING: - rc = keyring_search_reset (hd->active[i].u.kr); - break; + hd->current = 0; + hd->found = -1; + /* Now 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_KEYRING: + rc = keyring_search_reset (hd->active[i].u.kr); + break; } } - return rc; + return rc; } /* - * Search through all keydb resources, starting at the current position, - * for a keyblock which contains one of the keys described in the DESC array. + * Search through all keydb resources, starting at the current + * position, for a keyblock which contains one of the keys described + * in the DESC array. Returns GPG_ERR_NOT_FOUND if no matching + * keyring was found. */ -int +gpg_error_t keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex) { - int rc = -1; + gpg_error_t rc; - if (!hd) - return G10ERR_INV_ARG; + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); - 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_KEYRING: - rc = keyring_search (hd->active[hd->current].u.kr, desc, - ndesc, descindex); - break; + rc = -1; + while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) + && 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_KEYRING: + rc = keyring_search (hd->active[hd->current].u.kr, desc, + ndesc, descindex); + break; } - if (rc == -1) /* EOF -> switch to next resource */ - hd->current++; - else if (!rc) - hd->found = hd->current; + if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) + { + /* EOF -> switch to next resource */ + hd->current++; + } + else if (!rc) + hd->found = hd->current; } - return rc; + return ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) + ? gpg_error (GPG_ERR_NOT_FOUND) + : rc); } -int + +gpg_error_t keydb_search_first (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; + KEYDB_SEARCH_DESC desc; - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - return keydb_search (hd, &desc, 1); + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + return keydb_search (hd, &desc, 1); } -int +gpg_error_t keydb_search_next (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; + KEYDB_SEARCH_DESC desc; - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_NEXT; - return keydb_search (hd, &desc, 1); + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_NEXT; + return keydb_search (hd, &desc, 1); } -int +gpg_error_t keydb_search_kid (KEYDB_HANDLE hd, u32 *kid) { - KEYDB_SEARCH_DESC desc; + 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); + 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 +gpg_error_t 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, MAX_FINGERPRINT_LEN); - 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); } diff --git a/g10/keydb.h b/g10/keydb.h index f3a95297a..22c2b673e 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -132,25 +132,24 @@ union pref_hint Flag 1 == force Flag 2 == default */ -int keydb_add_resource (const char *url, int flags); +gpg_error_t keydb_add_resource (const char *url, int flags); KEYDB_HANDLE keydb_new (void); void keydb_release (KEYDB_HANDLE hd); const char *keydb_get_resource_name (KEYDB_HANDLE hd); -int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); -int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb); -int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb); -int keydb_delete_keyblock (KEYDB_HANDLE hd); -int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved); +gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); +gpg_error_t keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb); +gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb); +gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd); +gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved); void keydb_rebuild_caches (int noisy); -int keydb_search_reset (KEYDB_HANDLE hd); +gpg_error_t keydb_search_reset (KEYDB_HANDLE hd); #define keydb_search(a,b,c) keydb_search2((a),(b),(c),NULL) -int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, - size_t ndesc, size_t *descindex); -int keydb_search_first (KEYDB_HANDLE hd); -int keydb_search_next (KEYDB_HANDLE hd); -int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); -int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr); - +gpg_error_t keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex); +gpg_error_t keydb_search_first (KEYDB_HANDLE hd); +gpg_error_t keydb_search_next (KEYDB_HANDLE hd); +gpg_error_t keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); +gpg_error_t keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr); /*-- pkclist.c --*/ void show_revocation_reason( PKT_public_key *pk, int mode ); diff --git a/g10/keylist.c b/g10/keylist.c index db7467d3d..f6b8cffb2 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -434,12 +434,12 @@ list_all (int secret) hd = keydb_new (); if (!hd) - rc = G10ERR_GENERAL; + rc = gpg_error (GPG_ERR_GENERAL); else rc = keydb_search_first (hd); if (rc) { - if (rc != -1) + if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("keydb_search_first failed: %s\n", g10_errstr (rc)); goto leave; } @@ -479,7 +479,7 @@ list_all (int secret) keyblock = NULL; } while (!(rc = keydb_search_next (hd))); - if (rc && rc != -1) + if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("keydb_search_next failed: %s\n", g10_errstr (rc)); if (opt.check_sigs && !opt.with_colons) diff --git a/g10/keyserver.c b/g10/keyserver.c index 5cc7438ad..68dd15567 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1236,8 +1236,8 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) } } - if(rc==-1) - rc=0; + if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) + rc = 0; leave: if(rc) diff --git a/g10/trustdb.c b/g10/trustdb.c index c6ff6922d..006db04f4 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -2107,7 +2107,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, desc.skipfnc = search_skipfnc; desc.skipfncvalue = full_trust; rc = keydb_search (hd, &desc, 1); - if (rc == -1) + if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) { keys[nkeys].keyblock = NULL; return keys; @@ -2181,7 +2181,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, keyblock = NULL; } while ( !(rc = keydb_search (hd, &desc, 1)) ); - if (rc && rc != -1) + if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND) { log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); xfree (keys); diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 947aaaa43..9e77118a5 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,12 @@ +2011-04-28 Werner Koch + + * keybox-openpgp.c: Include ../common/openpgpdefs.h. + (enum packet_types): Remove. + (_keybox_parse_openpgp): Update NPARSED also on errors. + (parse_key): Take care of ecc algorithms. + * kbxutil.c (import_openpgp): Do not print an error for non-RSA v3 + packets. + 2010-07-23 Werner Koch * keybox-blob.c (_keybox_create_x509_blob): Fix reallocation bug. @@ -365,7 +374,7 @@ Copyright 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008 Free Software Foundation, Inc. + 2007, 2008, 2011 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index b1fd3348d..333c28695 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -1,5 +1,5 @@ /* kbxutil.c - The Keybox utility - * Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2004, 2007, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -389,8 +389,18 @@ import_openpgp (const char *filename) { if (gpg_err_code (err) == GPG_ERR_NO_DATA) break; - log_info ("%s: failed to parse OpenPGP keyblock: %s\n", - filename, gpg_strerror (err)); + if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM) + { + /* This is likely a v3 key packet with a non-RSA + algorithm. These are keys from very early versions + of GnuPG (pre-OpenPGP). */ + } + else + { + fflush (stdout); + log_info ("%s: failed to parse OpenPGP keyblock: %s\n", + filename, gpg_strerror (err)); + } } else { diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 30f99ecc8..4306ed1b0 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -1,5 +1,5 @@ /* keybox-openpgp.c - OpenPGP key parsing - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,41 +35,16 @@ #include - -enum packet_types - { - PKT_NONE =0, - PKT_PUBKEY_ENC =1, /* public key encrypted packet */ - PKT_SIGNATURE =2, /* secret key encrypted packet */ - PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/ - PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/ - PKT_SECRET_KEY =5, /* secret key */ - PKT_PUBLIC_KEY =6, /* public key */ - PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */ - PKT_COMPRESSED =8, /* compressed data packet */ - PKT_ENCRYPTED =9, /* conventional encrypted data */ - PKT_MARKER =10, /* marker packet (OpenPGP) */ - PKT_PLAINTEXT =11, /* plaintext data with filename and mode */ - PKT_RING_TRUST =12, /* keyring trust packet */ - PKT_USER_ID =13, /* user id packet */ - PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ - PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ - PKT_ATTRIBUTE =17, /* PGP's attribute packet */ - PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */ - PKT_MDC =19, /* manipulation detection code packet */ - PKT_COMMENT =61, /* new comment packet (private) */ - PKT_GPG_CONTROL =63 /* internal control packet */ - }; - +#include "../common/openpgpdefs.h" /* Assume a valid OpenPGP packet at the address pointed to by BUFBTR - which is of amaximum length as stored at BUFLEN. Return the header + which has a maximum length as stored at BUFLEN. Return the header information of that packet and advance the pointer stored at BUFPTR to the next packet; also adjust the length stored at BUFLEN to match the remaining bytes. If there are no more packets, store NULL at BUFPTR. Return an non-zero error code on failure or the - follwing data on success: + following data on success: R_DATAPKT = Pointer to the begin of the packet data. R_DATALEN = Length of this data. This has already been checked to fit @@ -166,8 +141,8 @@ next_packet (unsigned char const **bufptr, size_t *buflen, return gpg_error (GPG_ERR_UNEXPECTED); } - if (pktlen == 0xffffffff) - return gpg_error (GPG_ERR_INV_PACKET); + if (pktlen == (unsigned long)(-1)) + return gpg_error (GPG_ERR_INV_PACKET); if (pktlen > len) return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */ @@ -201,6 +176,7 @@ parse_key (const unsigned char *data, size_t datalen, const unsigned char *mpi_n = NULL; size_t mpi_n_len = 0, mpi_e_len = 0; gcry_md_hd_t md; + int is_ecc = 0; if (datalen < 5) return gpg_error (GPG_ERR_INV_PACKET); @@ -219,7 +195,6 @@ parse_key (const unsigned char *data, size_t datalen, return gpg_error (GPG_ERR_INV_PACKET); ndays = ((data[0]<<8)|(data[1])); data +=2; datalen -= 2; - if (ndays) expiredate = ndays? (timestamp + ndays * 86400L) : 0; } else @@ -245,9 +220,11 @@ parse_key (const unsigned char *data, size_t datalen, break; case 18: /* ECDH */ npkey = 3; + is_ecc = 1; break; case 19: /* ECDSA */ npkey = 2; + is_ecc = 1; break; default: /* Unknown algorithm. */ return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); @@ -259,20 +236,34 @@ parse_key (const unsigned char *data, size_t datalen, if (datalen < 2) return gpg_error (GPG_ERR_INV_PACKET); - nbits = ((data[0]<<8)|(data[1])); - data += 2; datalen -=2; - nbytes = (nbits+7) / 8; - if (datalen < nbytes) - return gpg_error (GPG_ERR_INV_PACKET); - /* For use by v3 fingerprint calculation we need to know the RSA - modulus and exponent. */ - if (i==0) + + if (is_ecc && (i == 0 || i == 2)) { - mpi_n = data; - mpi_n_len = nbytes; + nbytes = data[0]; + if (nbytes < 2 || nbytes > 254) + return gpg_error (GPG_ERR_INV_PACKET); + nbytes++; /* The size byte itself. */ + if (datalen < nbytes) + return gpg_error (GPG_ERR_INV_PACKET); + } + else + { + nbits = ((data[0]<<8)|(data[1])); + data += 2; + datalen -= 2; + nbytes = (nbits+7) / 8; + if (datalen < nbytes) + return gpg_error (GPG_ERR_INV_PACKET); + /* For use by v3 fingerprint calculation we need to know the RSA + modulus and exponent. */ + if (i==0) + { + mpi_n = data; + mpi_n_len = nbytes; + } + else if (i==1) + mpi_e_len = nbytes; } - else if (i==1) - mpi_e_len = nbytes; data += nbytes; datalen -= nbytes; } @@ -297,7 +288,7 @@ parse_key (const unsigned char *data, size_t datalen, if (mpi_n_len < 8) { /* Moduli less than 64 bit are out of the specs scope. Zero - them out becuase this is what gpg does too. */ + them out because this is what gpg does too. */ memset (ki->keyid, 0, 8); } else @@ -307,10 +298,10 @@ parse_key (const unsigned char *data, size_t datalen, { /* Its a pitty that we need to prefix the buffer with the tag and a length header: We can't simply pass it to the fast - hashing fucntion for that reason. It might be a good idea to + hashing function for that reason. It might be a good idea to have a scatter-gather enabled hash function. What we do here is to use a static buffer if this one is large enough and - only use the regular hash fucntions if this buffer is not + only use the regular hash functions if this buffer is not large enough. */ if ( 3 + n < sizeof hashbuffer ) { @@ -344,19 +335,19 @@ parse_key (const unsigned char *data, size_t datalen, /* The caller must pass the address of an INFO structure which will get filled on success with information pertaining to the OpenPGP keyblock IMAGE of length IMAGELEN. Note that a caller does only - need to release this INFO structure when the function returns + need to release this INFO structure if the function returns success. If NPARSED is not NULL the actual number of bytes parsed will be stored at this address. */ gpg_error_t _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, - size_t *nparsed, - keybox_openpgp_info_t info) + size_t *nparsed, keybox_openpgp_info_t info) { gpg_error_t err = 0; const unsigned char *image_start, *data; size_t n, datalen; int pkttype; int first = 1; + int read_error = 0; struct _keybox_openpgp_key_info *k, **ktail = NULL; struct _keybox_openpgp_uid_info *u, **utail = NULL; @@ -369,7 +360,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, { err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n); if (err) - break; + { + read_error = 1; + break; + } if (first) { @@ -380,6 +374,8 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, else { err = gpg_error (GPG_ERR_UNEXPECTED); + if (nparsed) + *nparsed += n; break; } first = 0; @@ -439,9 +435,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, if (err) { info->nsubkeys--; - if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM) - break; /* We ignore subkeys with unknown algorithms. */ + if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM + || gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM) + err = 0; + if (err) + break; } else ktail = &info->subkeys.next; @@ -459,9 +458,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, { xfree (k); info->nsubkeys--; - if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM) - break; /* We ignore subkeys with unknown algorithms. */ + if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM + || gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM) + err = 0; + if (err) + break; } else { @@ -475,11 +477,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, if (err) { _keybox_destroy_openpgp_info (info); - if (!first - && (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM - || gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM)) + if (!read_error) { - /* We are able to skip to the end of this keyblock. */ + /* Packet parsing worked, thus we should be able to skip the + rest of the keyblock. */ while (image) { if (next_packet (&image, &imagelen,