aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog13
-rw-r--r--sm/call-agent.c28
-rw-r--r--sm/certchain.c41
-rw-r--r--sm/gpgsm.h13
-rw-r--r--sm/keylist.c8
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)
{