diff options
author | Werner Koch <[email protected]> | 2008-02-19 10:33:35 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2008-02-19 10:33:35 +0000 |
commit | f13c5a48fc092d25c6d2fb169ed018473bb24096 (patch) | |
tree | c8ef206fe4a4357da339a65856f8b35cfe8919a7 /sm | |
parent | We better save the description of PKITS along with the test data. (diff) | |
download | gnupg-f13c5a48fc092d25c6d2fb169ed018473bb24096.tar.gz gnupg-f13c5a48fc092d25c6d2fb169ed018473bb24096.zip |
Improve certificate chain construction.
Extend PKITS framework
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 17 | ||||
-rw-r--r-- | sm/call-dirmngr.c | 4 | ||||
-rw-r--r-- | sm/certchain.c | 99 | ||||
-rw-r--r-- | sm/gpgsm.c | 15 | ||||
-rw-r--r-- | sm/gpgsm.h | 1 |
5 files changed, 117 insertions, 19 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index 8f348a5f2..22333698b 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,20 @@ +2008-02-18 Werner Koch <[email protected]> + + * certchain.c (gpgsm_is_root_cert): Factor code out to ... + (is_root_cert): New. Extend test for self-issued certificates + signed by other CAs. + (do_validate_chain, gpgsm_basic_cert_check) + (gpgsm_walk_cert_chain): Use it here. + + * gpgsm.c: Add option --no-common-certs-import. + + * certchain.c (find_up_dirmngr, find_up, do_validate_chain) + (check_cert_policy): Be more silent with --quiet. + + * gpgsm.c: Add option --disable-dirmngr. + * gpgsm.h (opt): Add field DISABLE_DIRMNGR. + * call-dirmngr.c (start_dirmngr): Implement option. + 2008-02-14 Werner Koch <[email protected]> * server.c (option_handler): Add option allow-pinentry-notify. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 83b001b52..02a2ca8d7 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -166,6 +166,9 @@ start_dirmngr (ctrl_t ctrl) assuan_context_t ctx; int try_default = 0; + if (opt.disable_dirmngr) + return gpg_error (GPG_ERR_NO_DIRMNGR); + if (dirmngr_ctx) { prepare_dirmngr (ctrl, dirmngr_ctx, 0); @@ -447,7 +450,6 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, struct inq_certificate_parm_s parm; struct isvalid_status_parm_s stparm; - rc = start_dirmngr (ctrl); if (rc) return rc; diff --git a/sm/certchain.c b/sm/certchain.c index 04b7e05ff..f9751752f 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1,6 +1,6 @@ /* certchain.c - certificate chain validation * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2006, 2007 Free Software Foundation, Inc. + * 2006, 2007, 2008 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -60,6 +60,8 @@ struct chain_item_s typedef struct chain_item_s *chain_item_t; +static int is_root_cert (ksba_cert_t cert, + const char *issuerdn, const char *subjectdn); static int get_regtp_ca_info (ctrl_t ctrl, ksba_cert_t cert, int *chainlen); @@ -331,8 +333,9 @@ check_cert_policy (ksba_cert_t cert, int listmode, estream_t fplist) /* With no critical policies this is only a warning */ if (!any_critical) { - do_list (0, listmode, fplist, - _("note: non-critical certificate policy not allowed")); + if (!opt.quiet) + do_list (0, listmode, fplist, + _("note: non-critical certificate policy not allowed")); return 0; } do_list (1, listmode, fplist, @@ -563,7 +566,7 @@ find_up_dirmngr (ctrl_t ctrl, KEYDB_HANDLE kh, if (opt.verbose) log_info (_("number of matching certificates: %d\n"), count); - if (rc) + if (rc && !opt.quiet) log_info (_("dirmngr cache-only key lookup failed: %s\n"), gpg_strerror (rc)); return (!rc && count)? 0 : -1; @@ -667,7 +670,9 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh, /* 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) + if (rc == -1 && opt.quiet) + ; + else if (rc == -1) { log_info ("%sissuer certificate ", find_next?"next ":""); if (keyid) @@ -752,7 +757,7 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next) goto leave; } - if (!strcmp (issuer, subject)) + if (is_root_cert (start, issuer, subject)) { rc = -1; /* we are at the root */ goto leave; @@ -784,6 +789,75 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next) } +/* Helper for gpgsm_is_root_cert. This one is used if the subject and + issuer DNs are already known. */ +static int +is_root_cert (ksba_cert_t cert, const char *issuerdn, const char *subjectdn) +{ + gpg_error_t err; + int result = 0; + ksba_sexp_t serialno; + ksba_sexp_t ak_keyid; + ksba_name_t ak_name; + ksba_sexp_t ak_sn; + const char *ak_name_str; + ksba_sexp_t subj_keyid = NULL; + + if (!issuerdn || !subjectdn) + return 0; /* No. */ + + if (strcmp (issuerdn, subjectdn)) + return 0; /* No. */ + + err = ksba_cert_get_auth_key_id (cert, &ak_keyid, &ak_name, &ak_sn); + if (err) + { + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + return 1; /* Yes. Without a authorityKeyIdentifier this needs + to be the Root certifcate (our trust anchor). */ + log_error ("error getting authorityKeyIdentifier: %s\n", + gpg_strerror (err)); + return 0; /* Well, it is broken anyway. Return No. */ + } + + serialno = ksba_cert_get_serial (cert); + if (!serialno) + { + log_error ("error getting serialno: %s\n", gpg_strerror (err)); + goto leave; + } + + /* Check whether the auth name's matches the issuer name+sn. If + that is the case this is a root certificate. */ + ak_name_str = ksba_name_enum (ak_name, 0); + if (ak_name_str + && !strcmp (ak_name_str, issuerdn) + && !cmp_simple_canon_sexp (ak_sn, serialno)) + { + result = 1; /* Right, CERT is self-signed. */ + goto leave; + } + + /* Similar for the ak_keyid. */ + if (ak_keyid && !ksba_cert_get_subj_key_id (cert, NULL, &subj_keyid) + && !cmp_simple_canon_sexp (ak_keyid, subj_keyid)) + { + result = 1; /* Right, CERT is self-signed. */ + goto leave; + } + + + leave: + ksba_free (subj_keyid); + ksba_free (ak_keyid); + ksba_name_release (ak_name); + ksba_free (ak_sn); + ksba_free (serialno); + return result; +} + + + /* Check whether the CERT is a root certificate. Returns True if this is the case. */ int @@ -795,7 +869,7 @@ gpgsm_is_root_cert (ksba_cert_t cert) issuer = ksba_cert_get_issuer (cert, 0); subject = ksba_cert_get_subject (cert, 0); - yes = (issuer && subject && !strcmp (issuer, subject)); + yes = is_root_cert (cert, issuer, subject); xfree (issuer); xfree (subject); return yes; @@ -1197,11 +1271,8 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, } - /* Is this a self-issued certificate (i.e. the root - certificate)? This is actually the same test as done by - gpgsm_is_root_cert but here we want to keep the issuer and - subject for later use. */ - is_root = (subject && !strcmp (issuer, subject)); + /* Is this a self-issued certificate (i.e. the root certificate)? */ + is_root = is_root_cert (subject_cert, issuer, subject); if (is_root) { chain->is_root = 1; @@ -1570,7 +1641,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, depth++; } /* End chain traversal. */ - if (!listmode) + if (!listmode && !opt.quiet) { if (opt.no_policy_check) log_info ("policies not checked due to %s option\n", @@ -1771,7 +1842,7 @@ gpgsm_basic_cert_check (ctrl_t ctrl, ksba_cert_t cert) goto leave; } - if (subject && !strcmp (issuer, subject)) + if (is_root_cert (cert, issuer, subject)) { rc = gpgsm_check_cert_sig (cert, cert); if (rc) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 71f8e2cc1..615dfb8e6 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1,6 +1,6 @@ /* gpgsm.c - GnuPG for S/MIME * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2006, 2007 Free Software Foundation, Inc. + * 2006, 2007, 2008 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -122,6 +122,7 @@ enum cmd_and_opt_values { oPreferSystemDirmngr, oDirmngrProgram, + oDisableDirmngr, oProtectToolProgram, oFakedSystemTime, @@ -149,7 +150,6 @@ enum cmd_and_opt_values { oEnablePolicyChecks, oAutoIssuerKeyRetrieve, - oTextmode, oFingerprint, oWithFingerprint, @@ -231,6 +231,7 @@ enum cmd_and_opt_values { oIgnoreTimeConflict, oNoRandomSeedFile, oNoAutoKeyRetrieve, + oNoCommonCertsImport, oUseAgent, oMergeOnly, oTryAllSecrets, @@ -431,10 +432,10 @@ static ARGPARSE_OPTS opts[] = { { oLCmessages, "lc-messages", 2, "@" }, { oXauthority, "xauthority", 2, "@" }, { oDirmngrProgram, "dirmngr-program", 2 , "@" }, + { oDisableDirmngr, "disable-dirmngr", 0 , "@" }, { oProtectToolProgram, "protect-tool-program", 2 , "@" }, { oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */ - { oNoBatch, "no-batch", 0, "@" }, { oWithColons, "with-colons", 0, "@"}, { oWithKeyData,"with-key-data", 0, "@"}, @@ -462,6 +463,7 @@ static ARGPARSE_OPTS opts[] = { { oListOnly, "list-only", 0, "@"}, { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, + { oNoCommonCertsImport, "no-common-certs-import", 0, "@" }, {0} }; @@ -842,6 +844,7 @@ main ( int argc, char **argv) int nogreeting = 0; int debug_wait = 0; int use_random_seed = 1; + int no_common_certs_import = 0; int with_fpr = 0; char *def_digest_string = NULL; char *extra_digest_algo = NULL; @@ -1215,6 +1218,7 @@ main ( int argc, char **argv) case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break; case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; + case oDisableDirmngr: opt.disable_dirmngr = 1; break; case oPreferSystemDirmngr: opt.prefer_system_dirmngr = 1; break; case oProtectToolProgram: opt.protect_tool_program = pargs.r.ret_str; @@ -1307,6 +1311,7 @@ main ( int argc, char **argv) case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; case oNoRandomSeedFile: use_random_seed = 0; break; + case oNoCommonCertsImport: no_common_certs_import = 1; break; case oEnableSpecialFilenames: allow_special_filenames =1; break; @@ -1476,7 +1481,7 @@ main ( int argc, char **argv) int created; keydb_add_resource ("pubring.kbx", 0, 0, &created); - if (created) + if (created && !no_common_certs_import) { /* Import the standard certificates for a new default keybox. */ char *filelist[2]; @@ -1593,6 +1598,8 @@ main ( int argc, char **argv) GC_OPT_FLAG_NONE ); printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE ); + printf ("disable-dirmngr:%lu:\n", + GC_OPT_FLAG_NONE ); #ifndef HAVE_W32_SYSTEM printf ("prefer-system-dirmngr:%lu:\n", GC_OPT_FLAG_NONE ); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 26a191f87..73231671c 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -59,6 +59,7 @@ struct const char *dirmngr_program; int prefer_system_dirmngr; /* Prefer using a system wide drimngr. */ + int disable_dirmngr; /* Do not do any dirmngr calls. */ const char *protect_tool_program; char *outfile; /* name of output file */ |