diff options
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 13 | ||||
-rw-r--r-- | sm/call-agent.c | 28 | ||||
-rw-r--r-- | sm/certchain.c | 41 | ||||
-rw-r--r-- | sm/gpgsm.h | 13 | ||||
-rw-r--r-- | sm/keylist.c | 8 |
5 files changed, 87 insertions, 16 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index 3d67226e9..be3b60142 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2006-09-25 Werner Koch <[email protected]> + + * gpgsm.h (struct rootca_flags_s): New. + * call-agent.c (istrusted_status_cb): New. + (gpgsm_agent_istrusted): New arg ROOTCA_FLAGS. + * keylist.c (list_cert_colon): Use dummy for new arg. + * certchain.c (gpgsm_validate_chain): Make use of the relax flag + for root certificates. + (unknown_criticals): Ignore a GPG_ERR_NO_VALUE. + 2006-09-20 Werner Koch <[email protected]> * gpgsm.c: Add alias command --dump-cert. @@ -1672,7 +1682,8 @@ * server.c (rc_to_assuan_status): New. Use it for all commands. - Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004, 2005, + 2006 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/sm/call-agent.c b/sm/call-agent.c index 2ab52ab7c..35ad1b83b 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -494,15 +494,36 @@ gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip, } + +static int +istrusted_status_cb (void *opaque, const char *line) +{ + struct rootca_flags_s *flags = opaque; + + if (!strncmp (line, "TRUSTLISTFLAG", 13) && (line[13]==' ' || !line[13])) + { + for (line += 13; *line == ' '; line++) + ; + if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5])) + flags->relax = 1; + } + return 0; +} + + + /* Ask the agent whether the certificate is in the list of trusted - keys */ + keys. ROOTCA_FLAGS is guaranteed to be cleared on error. */ int -gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert) +gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, + struct rootca_flags_s *rootca_flags) { int rc; char *fpr; char line[ASSUAN_LINELENGTH]; + memset (rootca_flags, 0, sizeof *rootca_flags); + rc = start_agent (ctrl); if (rc) return rc; @@ -518,7 +539,8 @@ gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert) line[DIM(line)-1] = 0; xfree (fpr); - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, + istrusted_status_cb, rootca_flags); return rc; } diff --git a/sm/certchain.c b/sm/certchain.c index 6be6fbe5a..8a3a84c93 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -117,12 +117,21 @@ unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT); } } - if (err && gpg_err_code (err) != GPG_ERR_EOF) + /* We ignore the error codes EOF as well as no-value. The later will + occur for certificates with no extensions at all. */ + if (err + && gpg_err_code (err) != GPG_ERR_EOF + && gpg_err_code (err) != GPG_ERR_NO_VALUE) rc = err; return rc; } + +/* Check whether CERT is an allowed certificate. This requires that + CERT matches all requirements for such a CA, i.e. the + BasicConstraints extension. The function returns 0 on success and + the awlloed length of the chain at CHAINLEN. */ static int allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp) { @@ -773,6 +782,19 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Is this a self-issued certificate? */ if (subject && !strcmp (issuer, subject)) { /* Yes. */ + gpg_error_t istrusted_rc; + struct rootca_flags_s rootca_flags; + + /* Check early whether the certificate is listed as trusted. + We used to do this only later but changed it to call the + check right here so that we can access special flags + associated with that specific root certificate. */ + istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert, + &rootca_flags); + + /* Note, that we could save the following signature check + because nobody would be so dump to set up a faked chain + and fail in creating a valid self-signed certificate. */ if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) { do_list (1, lm, fp, @@ -785,10 +807,13 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, : GPG_ERR_BAD_CERT); goto leave; } - rc = allowed_ca (subject_cert, NULL, listmode, fp); - if (rc) - goto leave; - + if (!rootca_flags.relax) + { + rc = allowed_ca (subject_cert, NULL, listmode, fp); + if (rc) + goto leave; + } + /* Set the flag for qualified signatures. This flag is deduced from a list of root certificates allowed for @@ -835,8 +860,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } - /* Check whether we really trust this root certificate. */ - rc = gpgsm_agent_istrusted (ctrl, subject_cert); + /* Act on the check for a trusted root certificates. */ + rc = istrusted_rc; if (!rc) ; else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) @@ -882,7 +907,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) ; - else if (opt.no_trusted_cert_crl_check) + else if (opt.no_trusted_cert_crl_check || rootca_flags.relax) ; else rc = is_cert_still_valid (ctrl, lm, fp, diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 84cfeb675..ba0ea3d27 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -179,6 +179,16 @@ struct certlist_s }; typedef struct certlist_s *certlist_t; + +/* A structure carrying information about trusted root certificates. */ +struct rootca_flags_s +{ + unsigned int relax:1; /* Relax checking of root certificates. */ + +}; + + + /*-- gpgsm.c --*/ void gpgsm_exit (int rc); void gpgsm_init_default_ctrl (struct server_control_s *ctrl); @@ -319,7 +329,8 @@ int gpgsm_agent_genkey (ctrl_t ctrl, ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); int gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip, ksba_sexp_t *r_pubkey); -int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert); +int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, + struct rootca_flags_s *rootca_flags); int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip); int gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert); int gpgsm_agent_learn (ctrl_t ctrl); diff --git a/sm/keylist.c b/sm/keylist.c index f2aac11f5..3994afedc 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -401,12 +401,14 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, *truststring = 'i'; } - /* Is we have no truststring yet (i.e. the certificate might be + /* If we have no truststring yet (i.e. the certificate might be good) and this is a root certificate, we ask the agent whether this is a trusted root certificate. */ if (!*truststring && is_root) { - rc = gpgsm_agent_istrusted (ctrl, cert); + struct rootca_flags_s dummy_flags; + + rc = gpgsm_agent_istrusted (ctrl, cert, &dummy_flags); if (!rc) *truststring = 'u'; /* Yes, we trust this one (ultimately). */ else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) @@ -680,7 +682,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, else fputs ("[?]\n", fp); - fputs (" keyUsage: ", fp); + fputs (" keyUsage:", fp); err = ksba_cert_get_key_usage (cert, &kusage); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { |