* 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.
This commit is contained in:
Werner Koch 2002-06-20 10:43:02 +00:00
parent 52146943d1
commit 42cf865350
12 changed files with 176 additions and 36 deletions

View File

@ -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

View File

@ -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]))
{

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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":

View File

@ -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);