From f6d7b3f1ee5eed32bc3257c99cb878091d26c482 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 7 Jan 2013 21:14:52 +0100 Subject: [PATCH] gpg: Set the node flags while retrieving a keyblock. * g10/keydb.c (parse_keyblock_image): Add args PK_NO and UID_NO and set the note flags accordingly. (keydb_get_keyblock): Transfer PK_NO and UID_NO to parse_keyblock_image. * kbx/keybox-search.c (blob_cmp_fpr, blob_cmp_fpr_part) (blob_cmp_name, blob_cmp_mail): Return the key/user number. (keybox_search): Set the key and user number into the found struct. (keybox_get_keyblock): Add args R_PK_NO and R_UID_NO and set them from the found struct. -- getkey.c needs to know whether the correct subkey was found. Thus we need to set the node flags the same way we did it with the keyring storage. --- g10/keydb.c | 33 ++++++++++++++++++++++--- kbx/keybox-search.c | 60 +++++++++++++++++++++++++++++++-------------- kbx/keybox.h | 5 ++-- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/g10/keydb.c b/g10/keydb.c index d29394814..186f0171c 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, 2011 Free Software Foundation, Inc. + * 2008, 2009, 2011, 2013 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -617,7 +617,8 @@ unlock_all (KEYDB_HANDLE hd) static gpg_error_t -parse_keyblock_image (iobuf_t iobuf, const u32 *sigstatus, kbnode_t *r_keyblock) +parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no, + const u32 *sigstatus, kbnode_t *r_keyblock) { gpg_error_t err; PACKET *pkt; @@ -625,6 +626,7 @@ parse_keyblock_image (iobuf_t iobuf, const u32 *sigstatus, kbnode_t *r_keyblock) kbnode_t node, *tail; int in_cert, save_mode; u32 n_sigs; + int pk_count, uid_count; *r_keyblock = NULL; @@ -636,6 +638,7 @@ parse_keyblock_image (iobuf_t iobuf, const u32 *sigstatus, kbnode_t *r_keyblock) in_cert = 0; n_sigs = 0; tail = NULL; + pk_count = uid_count = 0; while ((err = parse_packet (iobuf, pkt)) != -1) { if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET) @@ -714,6 +717,26 @@ parse_keyblock_image (iobuf_t iobuf, const u32 *sigstatus, kbnode_t *r_keyblock) } node = new_kbnode (pkt); + + switch (pkt->pkttype) + { + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + case PKT_SECRET_KEY: + case PKT_SECRET_SUBKEY: + if (++pk_count == pk_no) + node->flag |= 1; + break; + + case PKT_USER_ID: + if (++uid_count == uid_no) + node->flag |= 2; + break; + + default: + break; + } + if (!keyblock) keyblock = node; else @@ -779,12 +802,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) { iobuf_t iobuf; u32 *sigstatus; + int pk_no, uid_no; err = keybox_get_keyblock (hd->active[hd->found].u.kb, - &iobuf, &sigstatus); + &iobuf, &pk_no, &uid_no, &sigstatus); if (!err) { - err = parse_keyblock_image (iobuf, sigstatus, ret_kb); + err = parse_keyblock_image (iobuf, pk_no, uid_no, sigstatus, + ret_kb); xfree (sigstatus); iobuf_close (iobuf); } diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index a12216b3e..5e6432fa6 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -1,5 +1,6 @@ /* keybox-search.c - Search operations - * Copyright (C) 2001, 2002, 2003, 2004, 2012 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2012, + * 2013 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -233,6 +234,9 @@ blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) } +/* Returns 0 if not found or the number of the key which was found. + For X.509 this is always 1, for OpenPGP this is 1 for the primary + key and 2 and more for the subkeys. */ static int blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr) { @@ -259,7 +263,7 @@ blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr) { off = pos + idx*keyinfolen; if (!memcmp (buffer + off, fpr, 20)) - return 1; /* found */ + return idx+1; /* found */ } return 0; /* not found */ } @@ -291,7 +295,7 @@ blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr, { off = pos + idx*keyinfolen; if (!memcmp (buffer + off + fproff, fpr, fprlen)) - return 1; /* found */ + return idx+1; /* found */ } return 0; /* not found */ } @@ -352,15 +356,14 @@ blob_cmp_name (KEYBOXBLOB blob, int idx, if (substr) { if (ascii_memcasemem (buffer+off, len, name, namelen)) - return 1; /* found */ + return idx+1; /* found */ } else { if (len == namelen && !memcmp (buffer+off, name, len)) - return 1; /* found */ + return idx+1; /* found */ } } - return 0; /* not found */ } else { @@ -376,13 +379,16 @@ blob_cmp_name (KEYBOXBLOB blob, int idx, if (substr) { - return !!ascii_memcasemem (buffer+off, len, name, namelen); + if (ascii_memcasemem (buffer+off, len, name, namelen)) + return idx+1; /* found */ } else { - return len == namelen && !memcmp (buffer+off, name, len); + if (len == namelen && !memcmp (buffer+off, name, len)) + return idx+1; /* found */ } } + return 0; /* not found */ } @@ -458,12 +464,12 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr, if (substr) { if (ascii_memcasemem (buffer+off+1, len, name, namelen)) - return 1; /* found */ + return idx+1; /* found */ } else { if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len)) - return 1; /* found */ + return idx+1; /* found */ } } return 0; /* not found */ @@ -734,6 +740,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) int need_words, any_skip; KEYBOXBLOB blob = NULL; struct sn_array_s *sn_array = NULL; + int pk_no, uid_no; if (!hd) return gpg_error (GPG_ERR_INV_VALUE); @@ -850,6 +857,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) } + pk_no = uid_no = 0; for (;;) { unsigned int blobflags; @@ -875,19 +883,23 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) never_reached (); break; case KEYDB_SEARCH_MODE_EXACT: - if (has_username (blob, desc[n].u.name, 0)) + uid_no = has_username (blob, desc[n].u.name, 0); + if (uid_no) goto found; break; case KEYDB_SEARCH_MODE_MAIL: - if (has_mail (blob, desc[n].u.name, 0)) + uid_no = has_mail (blob, desc[n].u.name, 0); + if (uid_no) goto found; break; case KEYDB_SEARCH_MODE_MAILSUB: - if (has_mail (blob, desc[n].u.name, 1)) + uid_no = has_mail (blob, desc[n].u.name, 1); + if (uid_no) goto found; break; case KEYDB_SEARCH_MODE_SUBSTR: - if (has_username (blob, desc[n].u.name, 1)) + uid_no = has_username (blob, desc[n].u.name, 1); + if (uid_no) goto found; break; case KEYDB_SEARCH_MODE_MAILEND: @@ -914,16 +926,19 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) goto found; break; case KEYDB_SEARCH_MODE_SHORT_KID: - if (has_short_kid (blob, desc[n].u.kid[1])) + pk_no = has_short_kid (blob, desc[n].u.kid[1]); + if (pk_no) goto found; break; case KEYDB_SEARCH_MODE_LONG_KID: - if (has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1])) + pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]); + if (pk_no) goto found; break; case KEYDB_SEARCH_MODE_FPR: case KEYDB_SEARCH_MODE_FPR20: - if (has_fingerprint (blob, desc[n].u.fpr)) + pk_no = has_fingerprint (blob, desc[n].u.fpr); + if (pk_no) goto found; break; case KEYDB_SEARCH_MODE_KEYGRIP: @@ -956,6 +971,8 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) if (!rc) { hd->found.blob = blob; + hd->found.pk_no = pk_no; + hd->found.uid_no = uid_no; } else if (rc == -1) { @@ -985,9 +1002,12 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) /* Return the last found keyblock. Returns 0 on success and stores a new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS - in that case. */ + in that case. R_UID_NO and R_PK_NO are used to retun the number of + the key or user id which was matched the search criteria; if not + known they are set to 0. */ gpg_error_t -keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, u32 **r_sigstatus) +keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, + int *r_pk_no, int *r_uid_no, u32 **r_sigstatus) { gpg_error_t err; const unsigned char *buffer, *p; @@ -1029,6 +1049,8 @@ keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, u32 **r_sigstatus) for (n=1; n <= n_sigs; n++, p += sigilen) sigstatus[n] = get32 (p); + *r_pk_no = hd->found.pk_no; + *r_uid_no = hd->found.uid_no; *r_sigstatus = sigstatus; *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len); return 0; diff --git a/kbx/keybox.h b/kbx/keybox.h index 03a9245a3..4f7e23da0 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -81,8 +81,8 @@ int keybox_lock (KEYBOX_HANDLE hd, int yes); int _keybox_write_header_blob (FILE *fp); /*-- keybox-search.c --*/ -gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, - iobuf_t *r_iobuf, u32 **sigstatus); +gpg_error_t keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, + int *r_uid_no, int *r_pk_no, u32 **sigstatus); #ifdef KEYBOX_WITH_X509 int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert); #endif /*KEYBOX_WITH_X509*/ @@ -114,7 +114,6 @@ int keybox_compress (KEYBOX_HANDLE hd); /*-- --*/ #if 0 -int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb); int keybox_locate_writable (KEYBOX_HANDLE hd); int keybox_search_reset (KEYBOX_HANDLE hd); int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);