aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2002-01-15 13:02:47 +0000
committerWerner Koch <[email protected]>2002-01-15 13:02:47 +0000
commita9979e26a5705f73ef80ae453d2c1ba1362f0426 (patch)
treec5a6f1feb34cabb1610165ddc144edbf9f6b608e
parent* keybox-search.c (blob_cmp_fpr): New. (diff)
downloadgnupg-a9979e26a5705f73ef80ae453d2c1ba1362f0426.tar.gz
gnupg-a9979e26a5705f73ef80ae453d2c1ba1362f0426.zip
* import.c (gpgsm_import): Just do a basic cert check before
storing it. * certpath.c (gpgsm_basic_cert_check): New. * keydb.c (keydb_store_cert): New. * import.c (store_cert): Removed and change all caller to use the new function. * verify.c (store_cert): Ditto. * certlist.c (gpgsm_add_to_certlist): Validate the path * certpath.c (gpgsm_validate_path): Check the trust list. * call-agent.c (gpgsm_agent_istrusted): New.
-rw-r--r--sm/ChangeLog16
-rw-r--r--sm/call-agent.c29
-rw-r--r--sm/call-dirmngr.c5
-rw-r--r--sm/certchain.c125
-rw-r--r--sm/certlist.c8
-rw-r--r--sm/certpath.c125
-rw-r--r--sm/gpgsm.h2
-rw-r--r--sm/import.c30
-rw-r--r--sm/keydb.c55
-rw-r--r--sm/keydb.h2
-rw-r--r--sm/verify.c35
11 files changed, 352 insertions, 80 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 86423339e..5ea6e0c2f 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,19 @@
+2002-01-15 Werner Koch <[email protected]>
+
+ * import.c (gpgsm_import): Just do a basic cert check before
+ storing it.
+ * certpath.c (gpgsm_basic_cert_check): New.
+
+ * keydb.c (keydb_store_cert): New.
+ * import.c (store_cert): Removed and change all caller to use
+ the new function.
+ * verify.c (store_cert): Ditto.
+
+ * certlist.c (gpgsm_add_to_certlist): Validate the path
+
+ * certpath.c (gpgsm_validate_path): Check the trust list.
+ * call-agent.c (gpgsm_agent_istrusted): New.
+
2002-01-14 Werner Koch <[email protected]>
* call-dirmngr.c (inq_certificate): Changed for new interface semantic.
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 87b10248a..54c2d4e07 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -182,7 +182,8 @@ start_agent (void)
return seterr (Not_Implemented);
}
- log_debug ("connection to agent established\n");
+ if (DBG_AGENT)
+ log_debug ("connection to agent established\n");
return 0;
}
@@ -400,5 +401,31 @@ gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
return 0;
}
+
+/* Ask the agent whether the certificate is in the list of trusted
+ keys */
+int
+gpgsm_agent_istrusted (KsbaCert cert)
+{
+ int rc;
+ char *fpr;
+ char line[ASSUAN_LINELENGTH];
+ rc = start_agent ();
+ if (rc)
+ return rc;
+ fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+ if (!fpr)
+ {
+ log_error ("error getting the fingerprint\n");
+ return seterr (General_Error);
+ }
+
+ 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);
+ return map_assuan_err (rc);
+}
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 3a1253452..2323e761c 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -113,7 +113,8 @@ start_dirmngr (void)
return seterr (Not_Implemented);
}
- log_debug ("connection to dirmngr established\n");
+ if (DBG_AGENT)
+ log_debug ("connection to dirmngr established\n");
return 0;
}
@@ -206,3 +207,5 @@ gpgsm_dirmngr_isvalid (KsbaCert cert)
rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, inq_certificate, &parm);
return map_assuan_err (rc);
}
+
+
diff --git a/sm/certchain.c b/sm/certchain.c
index 69a9c55fb..e8c594eb6 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -50,10 +50,13 @@ gpgsm_validate_path (KsbaCert cert)
goto leave;
}
- gpgsm_dump_cert ("subject", cert);
+ if (DBG_X509)
+ gpgsm_dump_cert ("subject", cert);
subject_cert = cert;
+ /* FIXME: We need to check that none of the certs didexpire */
+
for (;;)
{
xfree (issuer);
@@ -100,11 +103,33 @@ gpgsm_validate_path (KsbaCert cert)
{
if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
{
- log_debug ("selfsigned certificate has a BAD signatures\n");
+ log_error ("selfsigned certificate has a BAD signatures\n");
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
goto leave;
}
- log_debug ("selfsigned certificate is good\n");
+ rc = gpgsm_agent_istrusted (subject_cert);
+ if (!rc)
+ ;
+ else if (rc == GNUPG_Not_Trusted)
+ {
+ char *fpr = gpgsm_get_fingerprint_string (subject_cert,
+ GCRY_MD_SHA1);
+ log_error (_("root certificate is not marked trusted\n"));
+ log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
+ xfree (fpr);
+ /* fixme: print a note while we have not yet the code to
+ ask whether the cert should be netered into the trust
+ list */
+ gpgsm_dump_cert ("issuer", subject_cert);
+ log_info ("after checking the fingerprint, you may want "
+ "to enter it into \"~/.gnupg-test/trustlist.txt\"\n");
+ }
+ else
+ {
+ log_error (_("checking the trust list failed: %s\n"),
+ gnupg_strerror (rc));
+ }
+
break; /* okay, a self-signed certicate is an end-point */
}
@@ -116,7 +141,7 @@ gpgsm_validate_path (KsbaCert cert)
rc = keydb_search_subject (kh, issuer);
if (rc)
{
- log_debug ("failed to find issuer's certificate: rc=%d\n", rc);
+ log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = GNUPG_Missing_Certificate;
goto leave;
}
@@ -125,21 +150,25 @@ gpgsm_validate_path (KsbaCert cert)
rc = keydb_get_cert (kh, &issuer_cert);
if (rc)
{
- log_debug ("failed to get cert: rc=%d\n", rc);
+ log_error ("failed to get cert: rc=%d\n", rc);
rc = GNUPG_General_Error;
goto leave;
}
- log_debug ("got issuer's certificate:\n");
- gpgsm_dump_cert ("issuer", issuer_cert);
+ if (DBG_X509)
+ {
+ log_debug ("got issuer's certificate:\n");
+ gpgsm_dump_cert ("issuer", issuer_cert);
+ }
if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
{
- log_debug ("certificate has a BAD signatures\n");
+ log_error ("certificate has a BAD signatures\n");
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
- log_debug ("certificate is good\n");
+ if (opt.verbose)
+ log_info ("certificate is good\n");
keydb_search_reset (kh);
subject_cert = issuer_cert;
@@ -159,3 +188,81 @@ gpgsm_validate_path (KsbaCert cert)
return rc;
}
+
+/* Check that the given certificate is valid but DO NOT check any
+ constraints. We assume that the issuers certificate is already in
+ the DB and that this one is valid; which it should be because it
+ has been checked using this function. */
+int
+gpgsm_basic_cert_check (KsbaCert cert)
+{
+ int rc = 0;
+ char *issuer = NULL;
+ char *subject = NULL;
+ KEYDB_HANDLE kh = keydb_new (0);
+ KsbaCert issuer_cert = NULL;
+
+ if (!kh)
+ {
+ log_error (_("failed to allocated keyDB handle\n"));
+ rc = GNUPG_General_Error;
+ goto leave;
+ }
+
+ issuer = ksba_cert_get_issuer (cert, 0);
+ subject = ksba_cert_get_subject (cert, 0);
+ if (!issuer)
+ {
+ if (DBG_X509)
+ log_debug ("ERROR: issuer missing\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+
+ if (subject && !strcmp (issuer, subject))
+ {
+ if (gpgsm_check_cert_sig (cert, cert) )
+ {
+ log_error ("selfsigned certificate has a BAD signatures\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+ }
+ else
+ {
+ /* find the next cert up the tree */
+ keydb_search_reset (kh);
+ rc = keydb_search_subject (kh, issuer);
+ if (rc)
+ {
+ log_error ("failed to find issuer's certificate: rc=%d\n", rc);
+ rc = GNUPG_Missing_Certificate;
+ goto leave;
+ }
+
+ ksba_cert_release (issuer_cert); issuer_cert = NULL;
+ rc = keydb_get_cert (kh, &issuer_cert);
+ if (rc)
+ {
+ log_error ("failed to get cert: rc=%d\n", rc);
+ rc = GNUPG_General_Error;
+ goto leave;
+ }
+
+ if (gpgsm_check_cert_sig (issuer_cert, cert) )
+ {
+ log_error ("certificate has a BAD signatures\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+ if (opt.verbose)
+ log_info ("certificate is good\n");
+ }
+
+ leave:
+ xfree (issuer);
+ keydb_release (kh);
+ ksba_cert_release (issuer_cert);
+ return rc;
+}
+
diff --git a/sm/certlist.c b/sm/certlist.c
index 0035d527c..c5b8c861f 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -33,7 +33,8 @@
#include "gpgsm.h"
#include "keydb.h"
-
+/* add a certificate to a list of certificate and make sure that it is
+ a valid certificate */
int
gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
{
@@ -55,6 +56,8 @@ gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
if (!rc)
rc = keydb_get_cert (kh, &cert);
if (!rc)
+ rc = gpgsm_validate_path (cert);
+ if (!rc)
{
CERTLIST cl = xtrycalloc (1, sizeof *cl);
if (!cl)
@@ -87,7 +90,8 @@ gpgsm_release_certlist (CERTLIST list)
}
-/* Like gpgsm_add_to_certlist, but lookonly for one certificate */
+/* Like gpgsm_add_to_certlist, but look only for one certificate. No
+ path validation is done */
int
gpgsm_find_cert (const char *name, KsbaCert *r_cert)
{
diff --git a/sm/certpath.c b/sm/certpath.c
index 69a9c55fb..e8c594eb6 100644
--- a/sm/certpath.c
+++ b/sm/certpath.c
@@ -50,10 +50,13 @@ gpgsm_validate_path (KsbaCert cert)
goto leave;
}
- gpgsm_dump_cert ("subject", cert);
+ if (DBG_X509)
+ gpgsm_dump_cert ("subject", cert);
subject_cert = cert;
+ /* FIXME: We need to check that none of the certs didexpire */
+
for (;;)
{
xfree (issuer);
@@ -100,11 +103,33 @@ gpgsm_validate_path (KsbaCert cert)
{
if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
{
- log_debug ("selfsigned certificate has a BAD signatures\n");
+ log_error ("selfsigned certificate has a BAD signatures\n");
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
goto leave;
}
- log_debug ("selfsigned certificate is good\n");
+ rc = gpgsm_agent_istrusted (subject_cert);
+ if (!rc)
+ ;
+ else if (rc == GNUPG_Not_Trusted)
+ {
+ char *fpr = gpgsm_get_fingerprint_string (subject_cert,
+ GCRY_MD_SHA1);
+ log_error (_("root certificate is not marked trusted\n"));
+ log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
+ xfree (fpr);
+ /* fixme: print a note while we have not yet the code to
+ ask whether the cert should be netered into the trust
+ list */
+ gpgsm_dump_cert ("issuer", subject_cert);
+ log_info ("after checking the fingerprint, you may want "
+ "to enter it into \"~/.gnupg-test/trustlist.txt\"\n");
+ }
+ else
+ {
+ log_error (_("checking the trust list failed: %s\n"),
+ gnupg_strerror (rc));
+ }
+
break; /* okay, a self-signed certicate is an end-point */
}
@@ -116,7 +141,7 @@ gpgsm_validate_path (KsbaCert cert)
rc = keydb_search_subject (kh, issuer);
if (rc)
{
- log_debug ("failed to find issuer's certificate: rc=%d\n", rc);
+ log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = GNUPG_Missing_Certificate;
goto leave;
}
@@ -125,21 +150,25 @@ gpgsm_validate_path (KsbaCert cert)
rc = keydb_get_cert (kh, &issuer_cert);
if (rc)
{
- log_debug ("failed to get cert: rc=%d\n", rc);
+ log_error ("failed to get cert: rc=%d\n", rc);
rc = GNUPG_General_Error;
goto leave;
}
- log_debug ("got issuer's certificate:\n");
- gpgsm_dump_cert ("issuer", issuer_cert);
+ if (DBG_X509)
+ {
+ log_debug ("got issuer's certificate:\n");
+ gpgsm_dump_cert ("issuer", issuer_cert);
+ }
if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
{
- log_debug ("certificate has a BAD signatures\n");
+ log_error ("certificate has a BAD signatures\n");
rc = GNUPG_Bad_Certificate_Path;
goto leave;
}
- log_debug ("certificate is good\n");
+ if (opt.verbose)
+ log_info ("certificate is good\n");
keydb_search_reset (kh);
subject_cert = issuer_cert;
@@ -159,3 +188,81 @@ gpgsm_validate_path (KsbaCert cert)
return rc;
}
+
+/* Check that the given certificate is valid but DO NOT check any
+ constraints. We assume that the issuers certificate is already in
+ the DB and that this one is valid; which it should be because it
+ has been checked using this function. */
+int
+gpgsm_basic_cert_check (KsbaCert cert)
+{
+ int rc = 0;
+ char *issuer = NULL;
+ char *subject = NULL;
+ KEYDB_HANDLE kh = keydb_new (0);
+ KsbaCert issuer_cert = NULL;
+
+ if (!kh)
+ {
+ log_error (_("failed to allocated keyDB handle\n"));
+ rc = GNUPG_General_Error;
+ goto leave;
+ }
+
+ issuer = ksba_cert_get_issuer (cert, 0);
+ subject = ksba_cert_get_subject (cert, 0);
+ if (!issuer)
+ {
+ if (DBG_X509)
+ log_debug ("ERROR: issuer missing\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+
+ if (subject && !strcmp (issuer, subject))
+ {
+ if (gpgsm_check_cert_sig (cert, cert) )
+ {
+ log_error ("selfsigned certificate has a BAD signatures\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+ }
+ else
+ {
+ /* find the next cert up the tree */
+ keydb_search_reset (kh);
+ rc = keydb_search_subject (kh, issuer);
+ if (rc)
+ {
+ log_error ("failed to find issuer's certificate: rc=%d\n", rc);
+ rc = GNUPG_Missing_Certificate;
+ goto leave;
+ }
+
+ ksba_cert_release (issuer_cert); issuer_cert = NULL;
+ rc = keydb_get_cert (kh, &issuer_cert);
+ if (rc)
+ {
+ log_error ("failed to get cert: rc=%d\n", rc);
+ rc = GNUPG_General_Error;
+ goto leave;
+ }
+
+ if (gpgsm_check_cert_sig (issuer_cert, cert) )
+ {
+ log_error ("certificate has a BAD signatures\n");
+ rc = GNUPG_Bad_Certificate;
+ goto leave;
+ }
+ if (opt.verbose)
+ log_info ("certificate is good\n");
+ }
+
+ leave:
+ xfree (issuer);
+ keydb_release (kh);
+ ksba_cert_release (issuer_cert);
+ return rc;
+}
+
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 481bd2bf7..43755a9d0 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -158,6 +158,7 @@ int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo,
/*-- certpath.c --*/
int gpgsm_validate_path (KsbaCert cert);
+int gpgsm_basic_cert_check (KsbaCert cert);
/*-- cetlist.c --*/
int gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr);
@@ -195,6 +196,7 @@ int gpgsm_agent_pkdecrypt (const char *keygrip,
KsbaConstSexp ciphertext,
char **r_buf, size_t *r_buflen);
int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey);
+int gpgsm_agent_istrusted (KsbaCert cert);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (KsbaCert cert);
diff --git a/sm/import.c b/sm/import.c
index 0e9618ca8..02db65555 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -35,32 +35,6 @@
#include "i18n.h"
-static void
-store_cert (KsbaCert cert)
-{
- KEYDB_HANDLE kh;
- int rc;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- return;
- }
- rc = keydb_locate_writable (kh, 0);
- if (rc)
- log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc));
-
- rc = keydb_insert_cert (kh, cert);
- if (rc)
- {
- log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc));
- }
- keydb_release (kh);
-}
-
-
-
int
gpgsm_import (CTRL ctrl, int in_fd)
@@ -100,8 +74,8 @@ gpgsm_import (CTRL ctrl, int in_fd)
goto leave;
}
- if ( !gpgsm_validate_path (cert) )
- store_cert (cert);
+ if ( !gpgsm_basic_cert_check (cert) )
+ keydb_store_cert (cert);
leave:
ksba_cert_release (cert);
diff --git a/sm/keydb.c b/sm/keydb.c
index 17074e800..34e7adc9d 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -1143,3 +1143,58 @@ keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
return 0;
}
+
+/* Store the certificate in the key Db but make sure that it does not
+ already exists. We do this simply by comparing the fingerprint */
+int
+keydb_store_cert (KsbaCert cert)
+{
+ KEYDB_HANDLE kh;
+ int rc;
+ unsigned char fpr[20];
+
+ if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
+ {
+ log_error (_("failed to get the fingerprint\n"));
+ return GNUPG_General_Error;
+ }
+
+ kh = keydb_new (0);
+ if (!kh)
+ {
+ log_error (_("failed to allocate keyDB handle\n"));
+ return GNUPG_Out_Of_Core;
+ }
+
+ rc = keydb_search_fpr (kh, fpr);
+ if (rc != -1)
+ {
+ keydb_release (kh);
+ if (!rc)
+ return 0; /* okay */
+ log_error (_("problem looking for existing certificate: %s\n"),
+ gnupg_strerror (rc));
+ return rc;
+ }
+
+ rc = keydb_locate_writable (kh, 0);
+ if (rc)
+ {
+ log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc));
+ keydb_release (kh);
+ return rc;
+ }
+
+ rc = keydb_insert_cert (kh, cert);
+ if (rc)
+ {
+ log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc));
+ keydb_release (kh);
+ return rc;
+ }
+ keydb_release (kh);
+ return 0;
+}
+
+
+
diff --git a/sm/keydb.h b/sm/keydb.h
index 4fdda9d6d..9032c5296 100644
--- a/sm/keydb.h
+++ b/sm/keydb.h
@@ -62,6 +62,8 @@ int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer);
int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
+int keydb_store_cert (KsbaCert cert);
+
#endif /*GNUPG_KEYDB_H*/
diff --git a/sm/verify.c b/sm/verify.c
index 350e4f42c..3dd85c02f 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -57,32 +57,6 @@ strtimestamp (time_t atime)
-/* fixme: duplicated from import.c */
-static void
-store_cert (KsbaCert cert)
-{
- KEYDB_HANDLE kh;
- int rc;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- return;
- }
- rc = keydb_locate_writable (kh, 0);
- if (rc)
- log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc));
-
- rc = keydb_insert_cert (kh, cert);
- if (rc)
- {
- log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc));
- }
- keydb_release (kh);
-}
-
-
/* Hash the data for a detached signature */
static void
hash_data (int fd, GCRY_MD_HD md)
@@ -265,10 +239,11 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
{
- log_debug ("storing certifcate %d\n", i);
- /* Fixme: we should mark the stored certificates as temporary
- and put them in a cache first */
- store_cert (cert);
+ /* Fixme: it might be better to check the validity of the
+ certificate first before entering it into the DB. This way
+ we would avoid cluttering the DB with invalid
+ certificates. */
+ keydb_store_cert (cert);
ksba_cert_release (cert);
}