summaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2002-06-20 12:43:02 +0200
committerWerner Koch <wk@gnupg.org>2002-06-20 12:43:02 +0200
commit42cf865350db37e80ab923bdc53e041cf9487501 (patch)
treef64fd5307b8491083ed07467c3ddee106390508b /sm
parent* call-agent.c (learn_cb): Use log_info instead of log_error on (diff)
downloadgnupg2-42cf865350db37e80ab923bdc53e041cf9487501.tar.xz
gnupg2-42cf865350db37e80ab923bdc53e041cf9487501.zip
* certlist.c (gpgsm_add_to_certlist): Fixed locating of a
certificate with the required key usage. * gpgsm.c (main): Fixed a segv when using --outfile without an argument. * keylist.c (print_capabilities): Also check for non-repudiation and data encipherment. * certlist.c (cert_usage_p): Test for signing and encryption was swapped. Add a case for certification usage, handle non-repudiation and data encipherment. (gpgsm_cert_use_cert_p): New. (gpgsm_add_to_certlist): Added a CTRL argument and changed all callers to pass it. * certpath.c (gpgsm_validate_path): Use it here to print a status message. Added a CTRL argument and changed all callers to pass it. * decrypt.c (gpgsm_decrypt): Print a status message for wrong key usage. * verify.c (gpgsm_verify): Ditto. * keydb.c (classify_user_id): Allow a colon delimited fingerprint.
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog23
-rw-r--r--sm/call-dirmngr.c1
-rw-r--r--sm/certchain.c10
-rw-r--r--sm/certlist.c101
-rw-r--r--sm/certpath.c10
-rw-r--r--sm/decrypt.c8
-rw-r--r--sm/gpgsm.c4
-rw-r--r--sm/gpgsm.h5
-rw-r--r--sm/keydb.c29
-rw-r--r--sm/keylist.c8
-rw-r--r--sm/server.c2
-rw-r--r--sm/verify.c11
12 files changed, 176 insertions, 36 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 87426cbb3..b612c1da8 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,26 @@
+2002-06-20 Werner Koch <wk@gnupg.org>
+
+ * certlist.c (gpgsm_add_to_certlist): Fixed locating of a
+ certificate with the required key usage.
+
+ * gpgsm.c (main): Fixed a segv when using --outfile without an
+ argument.
+
+ * keylist.c (print_capabilities): Also check for non-repudiation
+ and data encipherment.
+ * certlist.c (cert_usage_p): Test for signing and encryption was
+ swapped. Add a case for certification usage, handle
+ non-repudiation and data encipherment.
+ (gpgsm_cert_use_cert_p): New.
+ (gpgsm_add_to_certlist): Added a CTRL argument and changed all
+ callers to pass it.
+ * certpath.c (gpgsm_validate_path): Use it here to print a status
+ message. Added a CTRL argument and changed all callers to pass it.
+ * decrypt.c (gpgsm_decrypt): Print a status message for wrong key
+ usage.
+ * verify.c (gpgsm_verify): Ditto.
+ * keydb.c (classify_user_id): Allow a colon delimited fingerprint.
+
2002-06-19 Werner Koch <wk@gnupg.org>
* call-agent.c (learn_cb): Use log_info instead of log_error on
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 312886692..1cdf3e243 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -420,7 +420,6 @@ static AssuanError
lookup_status_cb (void *opaque, const char *line)
{
struct lookup_parm_s *parm = opaque;
- int i;
if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
{
diff --git a/sm/certchain.c b/sm/certchain.c
index 0b2d8b4fc..01696fc27 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -308,7 +308,7 @@ gpgsm_is_root_cert (KsbaCert cert)
/* Validate a path and optionally return the nearest expiration time
in R_EXPTIME */
int
-gpgsm_validate_path (KsbaCert cert, time_t *r_exptime)
+gpgsm_validate_path (CTRL ctrl, KsbaCert cert, time_t *r_exptime)
{
int rc = 0, depth = 0, maxdepth;
char *issuer = NULL;
@@ -551,6 +551,14 @@ gpgsm_validate_path (KsbaCert cert, time_t *r_exptime)
}
}
+ rc = gpgsm_cert_use_cert_p (issuer_cert);
+ if (rc)
+ {
+ gpgsm_status2 (ctrl, STATUS_ERROR, "certpath.issuer.keyusage",
+ gnupg_error_token (rc), NULL);
+ rc = 0;
+ }
+
if (opt.verbose)
log_info ("certificate is good\n");
diff --git a/sm/certlist.c b/sm/certlist.c
index 177f86725..ca61eb0d2 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -60,8 +60,18 @@ cert_usage_p (KsbaCert cert, int mode)
return map_ksba_err (err);
}
- if ((use & ((mode&1)? KSBA_KEYUSAGE_DIGITAL_SIGNATURE
- : KSBA_KEYUSAGE_KEY_ENCIPHERMENT)))
+ if (mode == 4)
+ {
+ if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
+ return 0;
+ log_info ( _("certificate should have not been used certification\n"));
+ return GNUPG_Wrong_Key_Usage;
+ }
+
+ if ((use & ((mode&1)?
+ (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT):
+ (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
+ )
return 0;
log_info (mode==3? _("certificate should have not been used for encryption\n"):
mode==2? _("certificate should have not been used for signing\n"):
@@ -98,10 +108,35 @@ gpgsm_cert_use_decrypt_p (KsbaCert cert)
return cert_usage_p (cert, 3);
}
+int
+gpgsm_cert_use_cert_p (KsbaCert cert)
+{
+ return cert_usage_p (cert, 4);
+}
+
+
+static int
+same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert)
+{
+ char *subject2 = ksba_cert_get_subject (cert, 0);
+ char *issuer2 = ksba_cert_get_subject (cert, 0);
+ int tmp;
+
+ tmp = (subject && subject2
+ && !strcmp (subject, subject2)
+ && issuer && issuer2
+ && !strcmp (issuer, issuer2));
+ xfree (subject2);
+ xfree (issuer2);
+ return tmp;
+}
+
+
+
/* 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)
+gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
{
int rc;
KEYDB_SEARCH_DESC desc;
@@ -117,6 +152,9 @@ gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
else
{
int wrong_usage = 0;
+ char *subject = NULL;
+ char *issuer = NULL;
+
get_next:
rc = keydb_search (kh, &desc, 1);
if (!rc)
@@ -127,32 +165,61 @@ gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
if (rc == GNUPG_Wrong_Key_Usage)
{
/* There might be another certificate with the
- correct usage, so we better try again */
- wrong_usage = rc;
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
+ correct usage, so we try again */
+ if (!wrong_usage)
+ { /* save the first match */
+ wrong_usage = rc;
+ subject = ksba_cert_get_subject (cert, 0);
+ issuer = ksba_cert_get_subject (cert, 0);
+ ksba_cert_release (cert);
+ cert = NULL;
+ goto get_next;
+ }
+ else if (same_subject_issuer (subject, issuer, cert))
+ {
+ wrong_usage = rc;
+ ksba_cert_release (cert);
+ cert = NULL;
+ goto get_next;
+ }
+ else
+ wrong_usage = rc;
+
}
}
/* we want the error code from the first match in this case */
- if (wrong_usage)
+ if (rc && wrong_usage)
rc = wrong_usage;
-
+
if (!rc)
{
- /* Fixme: If we ever have two certifciates differing
- only in the key usage, we should only bail out here
- if the certificate differes just in the key usage.
- However we need to find some criteria to match the
- identities */
+ next_ambigious:
rc = keydb_search (kh, &desc, 1);
if (rc == -1)
rc = 0;
else if (!rc)
- rc = GNUPG_Ambiguous_Name;
+ {
+ KsbaCert cert2 = NULL;
+
+ /* We have to ignore ambigious names as long as
+ there only fault is a bad key usage */
+ if (!keydb_get_cert (kh, &cert2))
+ {
+ int tmp = (same_subject_issuer (subject, issuer, cert2)
+ && (gpgsm_cert_use_encrypt_p (cert2)
+ == GNUPG_Wrong_Key_Usage));
+ ksba_cert_release (cert2);
+ if (tmp)
+ goto next_ambigious;
+ }
+ rc = GNUPG_Ambiguous_Name;
+ }
}
+ xfree (subject);
+ xfree (issuer);
+
if (!rc)
- rc = gpgsm_validate_path (cert, NULL);
+ rc = gpgsm_validate_path (ctrl, cert, NULL);
if (!rc)
{
CERTLIST cl = xtrycalloc (1, sizeof *cl);
diff --git a/sm/certpath.c b/sm/certpath.c
index 0b2d8b4fc..01696fc27 100644
--- a/sm/certpath.c
+++ b/sm/certpath.c
@@ -308,7 +308,7 @@ gpgsm_is_root_cert (KsbaCert cert)
/* Validate a path and optionally return the nearest expiration time
in R_EXPTIME */
int
-gpgsm_validate_path (KsbaCert cert, time_t *r_exptime)
+gpgsm_validate_path (CTRL ctrl, KsbaCert cert, time_t *r_exptime)
{
int rc = 0, depth = 0, maxdepth;
char *issuer = NULL;
@@ -551,6 +551,14 @@ gpgsm_validate_path (KsbaCert cert, time_t *r_exptime)
}
}
+ rc = gpgsm_cert_use_cert_p (issuer_cert);
+ if (rc)
+ {
+ gpgsm_status2 (ctrl, STATUS_ERROR, "certpath.issuer.keyusage",
+ gnupg_error_token (rc), NULL);
+ rc = 0;
+ }
+
if (opt.verbose)
log_info ("certificate is good\n");
diff --git a/sm/decrypt.c b/sm/decrypt.c
index e3566fd13..ccbcae2a6 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -381,7 +381,13 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
/* Just in case there is a problem with the own
certificate we print this message - should never
happen of course */
- gpgsm_cert_use_decrypt_p (cert);
+ rc = gpgsm_cert_use_decrypt_p (cert);
+ if (rc)
+ {
+ gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
+ gnupg_error_token (rc), NULL);
+ rc = 0;
+ }
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 06a3a9c60..385648cb4 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -1054,7 +1054,7 @@ main ( int argc, char **argv)
for (sl = remusr; sl; sl = sl->next)
{
- int rc = gpgsm_add_to_certlist (sl->d, &recplist);
+ int rc = gpgsm_add_to_certlist (&ctrl, sl->d, &recplist);
if (rc)
{
log_error (_("can't encrypt to `%s': %s\n"),
@@ -1164,7 +1164,7 @@ main ( int argc, char **argv)
{
FILE *fp = NULL;
- if (argc == 2 && *opt.outfile)
+ if (argc == 2 && opt.outfile)
log_info ("option --output ignored for a detached signature\n");
else if (opt.outfile)
fp = open_fwrite (opt.outfile);
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 43c154364..a3cf903d3 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -186,7 +186,7 @@ int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo,
/*-- certpath.c --*/
int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next);
int gpgsm_is_root_cert (KsbaCert cert);
-int gpgsm_validate_path (KsbaCert cert, time_t *r_exptime);
+int gpgsm_validate_path (CTRL ctrl, KsbaCert cert, time_t *r_exptime);
int gpgsm_basic_cert_check (KsbaCert cert);
/*-- certlist.c --*/
@@ -194,7 +194,8 @@ int gpgsm_cert_use_sign_p (KsbaCert cert);
int gpgsm_cert_use_encrypt_p (KsbaCert cert);
int gpgsm_cert_use_verify_p (KsbaCert cert);
int gpgsm_cert_use_decrypt_p (KsbaCert cert);
-int gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr);
+int gpgsm_cert_use_cert_p (KsbaCert cert);
+int gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr);
void gpgsm_release_certlist (CERTLIST list);
int gpgsm_find_cert (const char *name, KsbaCert *r_cert);
diff --git a/sm/keydb.c b/sm/keydb.c
index 50c9e54bd..bc4721418 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -1137,10 +1137,31 @@ classify_user_id (const char *name,
mode = KEYDB_SEARCH_MODE_FPR20;
}
else if (!hexprefix)
- { /* default is substring search */
- *force_exact = 0;
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_SUBSTR;
+ {
+ /* The fingerprint in an X.509 listing is often delimited by
+ colons, so we try to single this case out. */
+ mode = 0;
+ hexlength = strspn (s, ":0123456789abcdefABCDEF");
+ if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
+ {
+ int i;
+
+ for (i=0; i < 20; i++, s += 3)
+ {
+ int c = hextobyte(s);
+ if (c == -1 || (i < 19 && s[2] != ':'))
+ break;
+ desc->u.fpr[i] = c;
+ }
+ if (i == 20)
+ mode = KEYDB_SEARCH_MODE_FPR20;
+ }
+ if (!mode) /* default is substring search */
+ {
+ *force_exact = 0;
+ desc->u.name = s;
+ mode = KEYDB_SEARCH_MODE_SUBSTR;
+ }
}
else
{ /* hex number with a prefix but a wrong length */
diff --git a/sm/keylist.c b/sm/keylist.c
index a8d9c5411..c17fb7052 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -84,15 +84,15 @@ print_capabilities (KsbaCert cert, FILE *fp)
return;
}
- if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+ if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
putc ('e', fp);
- if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+ if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
putc ('s', fp);
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
putc ('c', fp);
- if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+ if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
putc ('E', fp);
- if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+ if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
putc ('S', fp);
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
putc ('C', fp);
diff --git a/sm/server.c b/sm/server.c
index 69abe7adb..a7ae98d56 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -239,7 +239,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
- rc = gpgsm_add_to_certlist (line, &ctrl->server_local->recplist);
+ rc = gpgsm_add_to_certlist (ctrl, line, &ctrl->server_local->recplist);
if (rc)
gpgsm_status2 (ctrl, STATUS_INV_RECP,
rc == -1? "1":
diff --git a/sm/verify.c b/sm/verify.c
index 286dc68bb..d5f8629b7 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -389,10 +389,17 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
gpgsm_status (ctrl, STATUS_BADSIG, NULL);
goto next_signer;
}
- gpgsm_cert_use_verify_p (cert); /* this displays an info message */
+ rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
+ if (rc)
+ {
+ gpgsm_status2 (ctrl, STATUS_ERROR, "verify.keyusage",
+ gnupg_error_token (rc), NULL);
+ rc = 0;
+ }
+
if (DBG_X509)
log_debug ("signature okay - checking certs\n");
- rc = gpgsm_validate_path (cert, &keyexptime);
+ rc = gpgsm_validate_path (ctrl, cert, &keyexptime);
if (rc == GNUPG_Certificate_Expired)
{
gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);