diff options
author | Werner Koch <wk@gnupg.org> | 2005-04-18 12:44:46 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2005-04-18 12:44:46 +0200 |
commit | eff62d82bfcb9df1b85ce596f0f5b6ef00d3a0ca (patch) | |
tree | f865ac069a4f50caa0c4b62fc232a3d4e2331b4c /sm | |
parent | 2005-04-15 Marcus Brinkmann <marcus@g10code.de> (diff) | |
download | gnupg2-eff62d82bfcb9df1b85ce596f0f5b6ef00d3a0ca.tar.xz gnupg2-eff62d82bfcb9df1b85ce596f0f5b6ef00d3a0ca.zip |
* configure.ac: Require libksba 0.9.11.
sm/
* call-dirmngr.c (inq_certificate): Add new inquire SENDCERT_SKI.
* certlist.c (gpgsm_find_cert): Add new arg KEYID and implement
this filter. Changed all callers.
* certchain.c (find_up_search_by_keyid): New helper.
(find_up): Also try using the AKI.keyIdentifier.
(find_up_external): Ditto.
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 15 | ||||
-rw-r--r-- | sm/call-dirmngr.c | 21 | ||||
-rw-r--r-- | sm/certchain.c | 113 | ||||
-rw-r--r-- | sm/certdump.c | 1 | ||||
-rw-r--r-- | sm/certlist.c | 40 | ||||
-rw-r--r-- | sm/gpgsm.c | 2 | ||||
-rw-r--r-- | sm/gpgsm.h | 2 | ||||
-rw-r--r-- | sm/keylist.c | 35 |
8 files changed, 194 insertions, 35 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index e74381bd5..7b67407ad 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,18 @@ +2005-04-17 Werner Koch <wk@g10code.com> + + * call-dirmngr.c (inq_certificate): Add new inquire SENDCERT_SKI. + * certlist.c (gpgsm_find_cert): Add new arg KEYID and implement + this filter. Changed all callers. + + * certchain.c (find_up_search_by_keyid): New helper. + (find_up): Also try using the AKI.keyIdentifier. + (find_up_external): Ditto. + +2005-04-15 Werner Koch <wk@g10code.com> + + * keylist.c (list_cert_raw): Print the subjectKeyIdentifier as + well as the keyIdentifier part of the authorityKeyIdentifier. + 2005-03-31 Werner Koch <wk@g10code.com> * call-dirmngr.c (start_dirmngr): Use PATHSEP_C instead of ':'. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 5988ea952..847e78490 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -1,5 +1,5 @@ /* call-dirmngr.c - communication with the dromngr - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -266,11 +266,25 @@ inq_certificate (void *opaque, const char *line) const unsigned char *der; size_t derlen; int issuer_mode = 0; + ksba_sexp_t ski = NULL; if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])) { line += 8; } + else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12])) + { + size_t n; + + /* Send a certificate where a sourceKeyidentifier is included. */ + line += 12; + while (*line == ' ') + line++; + ski = make_simple_sexp_from_hexstr (line, &n); + line += n; + while (*line == ' ') + line++; + } else if (!strncmp (line, "SENDISSUERCERT", 14) && (line[14] == ' ' || !line[14])) { @@ -304,7 +318,7 @@ inq_certificate (void *opaque, const char *line) ksba_cert_t cert; - err = gpgsm_find_cert (line, &cert); + err = gpgsm_find_cert (line, ski, &cert); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); @@ -321,6 +335,7 @@ inq_certificate (void *opaque, const char *line) } } + xfree (ski); return rc; } @@ -717,7 +732,7 @@ run_command_inq_cb (void *opaque, const char *line) if (!*line) return ASSUAN_Inquire_Error; - err = gpgsm_find_cert (line, &cert); + err = gpgsm_find_cert (line, NULL, &cert); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); diff --git a/sm/certchain.c b/sm/certchain.c index 514ee23a5..a5fdbc622 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -266,6 +266,42 @@ check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist) } +/* Helper fucntion for find_up. This resets the key handle and search + for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns + 0 obn success or -1 when not found. */ +static int +find_up_search_by_keyid (KEYDB_HANDLE kh, + const char *issuer, ksba_sexp_t keyid) +{ + int rc; + ksba_cert_t cert = NULL; + ksba_sexp_t subj = NULL; + + keydb_search_reset (kh); + while (!(rc = keydb_search_subject (kh, issuer))) + { + ksba_cert_release (cert); cert = NULL; + rc = keydb_get_cert (kh, &cert); + if (rc) + { + log_error ("keydb_get_cert() failed: rc=%d\n", rc); + rc = -1; + break; + } + xfree (subj); + if (!ksba_cert_get_subj_key_id (cert, NULL, &subj)) + { + if (!cmp_simple_canon_sexp (keyid, subj)) + break; /* Found matching cert. */ + } + } + + ksba_cert_release (cert); + xfree (subj); + return rc? -1:0; +} + + static void find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) { @@ -275,13 +311,13 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) } - /* Helper for find_up(). Locate the certificate for ISSUER using an external lookup. KH is the keydb context we are currently using. On success 0 is returned and the certificate may be retrieved from - the keydb using keydb_get_cert().*/ + the keydb using keydb_get_cert(). KEYID is the keyIdentifier from + the AKI or NULL. */ static int -find_up_external (KEYDB_HANDLE kh, const char *issuer) +find_up_external (KEYDB_HANDLE kh, const char *issuer, ksba_sexp_t keyid) { int rc; strlist_t names = NULL; @@ -324,8 +360,13 @@ find_up_external (KEYDB_HANDLE kh, const char *issuer) /* The issuers are currently stored in the ephemeral key DB, so we temporary switch to ephemeral mode. */ old = keydb_set_ephemeral (kh, 1); - keydb_search_reset (kh); - rc = keydb_search_subject (kh, issuer); + if (keyid) + rc = find_up_search_by_keyid (kh, issuer, keyid); + else + { + keydb_search_reset (kh); + rc = keydb_search_subject (kh, issuer); + } keydb_set_ephemeral (kh, old); } return rc; @@ -343,9 +384,10 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) { ksba_name_t authid; ksba_sexp_t authidno; + ksba_sexp_t keyid; int rc = -1; - if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno)) + if (!ksba_cert_get_auth_key_id (cert, &keyid, &authid, &authidno)) { const char *s = ksba_name_enum (authid, 0); if (s && *authidno) @@ -369,28 +411,57 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) keydb_set_ephemeral (kh, old); } - /* If we didn't found it, try an external lookup. */ - if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) - rc = find_up_external (kh, issuer); } + if (rc == -1 && keyid && !find_next) + { + /* Not found by AIK.issuer_sn. Lets try the AIY.ki + instead. Loop over all certificates with that issuer as + subject and stop for the one with a matching + subjectKeyIdentifier. */ + rc = find_up_search_by_keyid (kh, issuer, keyid); + if (rc) + { + int old = keydb_set_ephemeral (kh, 1); + if (!old) + rc = find_up_search_by_keyid (kh, issuer, keyid); + keydb_set_ephemeral (kh, old); + } + if (rc) + rc = -1; /* Need to make sure to have this error code. */ + } + + /* If we still didn't found it, try an external lookup. */ + if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) + rc = find_up_external (kh, issuer, keyid); + /* Print a note so that the user does not feel too helpless when an issuer certificate was found and gpgsm prints BAD signature because it is not the correct one. */ if (rc == -1) { - log_info ("%sissuer certificate (#", find_next?"next ":""); - gpgsm_dump_serial (authidno); - log_printf ("/"); - gpgsm_dump_string (s); - log_printf (") not found using authorityKeyIdentifier\n"); + log_info ("%sissuer certificate ", find_next?"next ":""); + if (keyid) + { + log_printf ("{"); + gpgsm_dump_serial (keyid); + log_printf ("} "); + } + if (authidno) + { + log_printf ("(#"); + gpgsm_dump_serial (authidno); + log_printf ("/"); + gpgsm_dump_string (s); + log_printf (") "); + } + log_printf ("not found using authorityKeyIdentifier\n"); } else if (rc) log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); + xfree (keyid); ksba_name_release (authid); xfree (authidno); - /* Fixme: There is no way to do an external lookup with - serial+issuer. */ } if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */ @@ -409,7 +480,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) /* Still not found. If enabled, try an external lookup. */ if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) - rc = find_up_external (kh, issuer); + rc = find_up_external (kh, issuer, NULL); return rc; } @@ -468,7 +539,7 @@ gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next) rc = keydb_get_cert (kh, r_next); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); } @@ -791,7 +862,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, rc = keydb_get_cert (kh, &issuer_cert); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } @@ -818,6 +889,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, might have been used. This is required because some CAs are reusing the issuer and subject DN for new root certificates. */ + /* FIXME: Do this only if we don't have an + AKI.keyIdentifier */ rc = find_up (kh, subject_cert, issuer, 1); if (!rc) { @@ -1008,7 +1081,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) rc = keydb_get_cert (kh, &issuer_cert); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } diff --git a/sm/certdump.c b/sm/certdump.c index cdf4edcc1..26510c70d 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -75,6 +75,7 @@ gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p) } +/* Dump the serial number or any other simple S-expression. */ void gpgsm_dump_serial (ksba_const_sexp_t p) { diff --git a/sm/certlist.c b/sm/certlist.c index 018ad47ff..b036a85d7 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -1,5 +1,5 @@ /* certlist.c - build list of certificates - * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -412,9 +412,11 @@ gpgsm_release_certlist (CERTLIST list) /* Like gpgsm_add_to_certlist, but look only for one certificate. No - chain validation is done */ + chain validation is done. If KEYID is not NULL it is take as an + additional filter value which must match the + subjectKeyIdentifier. */ int -gpgsm_find_cert (const char *name, ksba_cert_t *r_cert) +gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert) { int rc; KEYDB_SEARCH_DESC desc; @@ -429,10 +431,38 @@ gpgsm_find_cert (const char *name, ksba_cert_t *r_cert) rc = gpg_error (GPG_ERR_ENOMEM); else { + nextone: rc = keydb_search (kh, &desc, 1); if (!rc) - rc = keydb_get_cert (kh, r_cert); - if (!rc) + { + rc = keydb_get_cert (kh, r_cert); + if (!rc && keyid) + { + ksba_sexp_t subj; + + rc = ksba_cert_get_subj_key_id (*r_cert, NULL, &subj); + if (!rc) + { + if (cmp_simple_canon_sexp (keyid, subj)) + { + xfree (subj); + goto nextone; + } + xfree (subj); + /* Okay: Here we know that the certificate's + subjectKeyIdentifier matches the requested + one. */ + } + else if (gpg_err_code (rc) == GPG_ERR_NO_DATA) + goto nextone; + } + } + + /* If we don't have the KEYID filter we need to check for + ambigious search results. Note, that it is somehwat + reasonable to assume that a specification of a KEYID + won't lead to ambiguous names. */ + if (!rc && !keyid) { rc = keydb_search (kh, &desc, 1); if (rc == -1) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index ff404dc69..dae547702 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1566,7 +1566,7 @@ main ( int argc, char **argv) ksba_cert_t cert = NULL; char *grip = NULL; - rc = gpgsm_find_cert (*argv, &cert); + rc = gpgsm_find_cert (*argv, NULL, &cert); if (rc) ; else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 17ad21ed6..aafc4815d 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -252,7 +252,7 @@ int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, certlist_t *listaddr, int is_encrypt_to); void gpgsm_release_certlist (certlist_t list); -int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert); +int gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert); /*-- keylist.c --*/ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, STRLIST names, diff --git a/sm/keylist.c b/sm/keylist.c index aa6db46c3..8e1233341 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1,6 +1,6 @@ -/* keylist.c +/* keylist.c - Print certificates in various formats. * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -122,7 +122,7 @@ static struct { { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" }, /* X.509 id-ce */ - { "2.5.29.14", "subjectKeyIdentifier"}, + { "2.5.29.14", "subjectKeyIdentifier", 1}, { "2.5.29.15", "keyUsage", 1 }, { "2.5.29.16", "privateKeyUsagePeriod" }, { "2.5.29.17", "subjectAltName", 1 }, @@ -512,7 +512,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, { gpg_error_t err; size_t off, len; - ksba_sexp_t sexp; + ksba_sexp_t sexp, keyid; char *dn; ksba_isotime_t t; int idx, i; @@ -588,9 +588,27 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, fprintf (fp, " keyType: %u bit %s\n", nbits, algoname? algoname:"?"); } + /* subjectKeyIdentifier */ + fputs (" subjKeyId: ", fp); + err = ksba_cert_get_subj_key_id (cert, NULL, &keyid); + if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) + { + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + fputs ("[none]\n", fp); + else + { + gpgsm_print_serial (fp, keyid); + ksba_free (keyid); + putc ('\n', fp); + } + } + else + fputs ("[?]\n", fp); + + /* authorityKeyIdentifier */ fputs (" authKeyId: ", fp); - err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp); + err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp); if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) { if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name) @@ -603,6 +621,13 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, print_names_raw (fp, -15, name); ksba_name_release (name); } + if (keyid) + { + fputs (" authKeyId.ki: ", fp); + gpgsm_print_serial (fp, keyid); + ksba_free (keyid); + putc ('\n', fp); + } } else fputs ("[?]\n", fp); |