From 12366d1e817e0e440646ed0d6ea5b3171264ed76 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 21 Oct 2008 15:03:51 +0000 Subject: [PATCH] Help dirmngr to use supplied trust anchors. --- sm/ChangeLog | 9 +++++++++ sm/call-agent.c | 34 ++++++++++++++++++++++++---------- sm/call-dirmngr.c | 29 +++++++++++++++++++++++++++++ sm/certchain.c | 4 ++-- sm/gpgsm.h | 2 +- sm/keylist.c | 2 +- 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 2404c72f5..2c178ca27 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,12 @@ +2008-10-21 Werner Koch + + * call-dirmngr.c (inq_certificate_parm_s): Add field CTRL. + (gpgsm_dirmngr_isvalid): Supply a value for that field. + (inq_certificate): Add inquiry ISTRUSTED. + + * call-agent.c (gpgsm_agent_istrusted): Add new optional arg + HEXFPR. Changed all callers. + 2008-10-20 Werner Koch * keydb.c (keydb_locate_writable): Mark unused arg. diff --git a/sm/call-agent.c b/sm/call-agent.c index bca44d2d6..0add44aae 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -560,31 +560,45 @@ istrusted_status_cb (void *opaque, const char *line) /* Ask the agent whether the certificate is in the list of trusted - keys. ROOTCA_FLAGS is guaranteed to be cleared on error. */ + keys. The certificate is either specified by the CERT object or by + the fingerprint HEXFPR. 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, const char *hexfpr, struct rootca_flags_s *rootca_flags) { int rc; - char *fpr; char line[ASSUAN_LINELENGTH]; memset (rootca_flags, 0, sizeof *rootca_flags); + if (cert && hexfpr) + return gpg_error (GPG_ERR_INV_ARG); + rc = start_agent (ctrl); if (rc) return rc; - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - if (!fpr) + if (hexfpr) { - log_error ("error getting the fingerprint\n"); - return gpg_error (GPG_ERR_GENERAL); + snprintf (line, DIM(line)-1, "ISTRUSTED %s", hexfpr); + line[DIM(line)-1] = 0; } + else + { + char *fpr; - snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr); - line[DIM(line)-1] = 0; - xfree (fpr); + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + if (!fpr) + { + log_error ("error getting the fingerprint\n"); + return gpg_error (GPG_ERR_GENERAL); + } + + snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr); + line[DIM(line)-1] = 0; + xfree (fpr); + } rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, istrusted_status_cb, rootca_flags); diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 20017dd9e..914fdd03e 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -55,6 +55,7 @@ static int dirmngr2_ctx_locked; static int force_pipe_server = 0; struct inq_certificate_parm_s { + ctrl_t ctrl; assuan_context_t ctx; ksba_cert_t cert; ksba_cert_t issuer_cert; @@ -408,6 +409,33 @@ inq_certificate (void *opaque, const char *line) line += 14; issuer_mode = 1; } + else if (!strncmp (line, "ISTRUSTED", 9) && (line[9]==' ' || !line[9])) + { + /* The server is asking us whether the certificate is a trusted + root certificate. */ + const char *s; + size_t n; + char fpr[41]; + struct rootca_flags_s rootca_flags; + + line += 9; + while (*line == ' ') + line++; + + for (s=line,n=0; hexdigitp (s); s++, n++) + ; + if (*s || n != 40) + return gpg_error (GPG_ERR_ASS_PARAMETER); + for (s=line, n=0; n < 40; s++, n++) + fpr[n] = (*s >= 'a')? (*s & 0xdf): *s; + fpr[n] = 0; + + if (!gpgsm_agent_istrusted (parm->ctrl, NULL, fpr, &rootca_flags)) + rc = assuan_send_data (parm->ctx, "1", 1); + else + rc = 0; + return rc; + } else { log_error ("unsupported inquiry `%s'\n", line); @@ -555,6 +583,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, } parm.ctx = dirmngr_ctx; + parm.ctrl = ctrl; parm.cert = cert; parm.issuer_cert = issuer_cert; diff --git a/sm/certchain.c b/sm/certchain.c index 2d81dbf6c..fbff7c001 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1284,7 +1284,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, 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, + istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert, NULL, rootca_flags); audit_log_cert (ctrl->audit, AUDIT_ROOT_TRUSTED, subject_cert, istrusted_rc); @@ -1565,7 +1565,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, performance reasons. */ if (is_root) { - istrusted_rc = gpgsm_agent_istrusted (ctrl, issuer_cert, + istrusted_rc = gpgsm_agent_istrusted (ctrl, issuer_cert, NULL, rootca_flags); if (!istrusted_rc && rootca_flags->relax) { diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 278c6e5fc..0ee557fe6 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -386,7 +386,7 @@ int gpgsm_agent_genkey (ctrl_t ctrl, ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); int gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, 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, const char *hexfpr, 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); diff --git a/sm/keylist.c b/sm/keylist.c index 2af474948..1e77bfca4 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -429,7 +429,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, { struct rootca_flags_s dummy_flags; - rc = gpgsm_agent_istrusted (ctrl, cert, &dummy_flags); + rc = gpgsm_agent_istrusted (ctrl, cert, NULL, &dummy_flags); if (!rc) *truststring = 'u'; /* Yes, we trust this one (ultimately). */ else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)