mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Improve certificate chain construction.
Extend PKITS framework
This commit is contained in:
parent
a75c21ed8a
commit
f13c5a48fc
60 changed files with 1283 additions and 588 deletions
17
sm/ChangeLog
17
sm/ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2008-02-18 Werner Koch <wk@g10code.com>
|
||||
|
||||
* 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 <wk@g10code.com>
|
||||
|
||||
* server.c (option_handler): Add option allow-pinentry-notify.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
15
sm/gpgsm.c
15
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 );
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue