* gpgsm.c (main): New option --debug-ignore-expiration.

* certchain.c (gpgsm_validate_chain): Use it here.

* certlist.c (cert_usage_p): Apply extKeyUsage.
This commit is contained in:
Werner Koch 2004-02-20 13:46:21 +00:00
parent a1b487a17a
commit aa0e38982a
8 changed files with 159 additions and 36 deletions

24
TODO
View File

@ -21,14 +21,6 @@ might want to have an agent context for each service request
** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent. ** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent.
** figure out how to auto retrieve a key by serialno+issuer. ** figure out how to auto retrieve a key by serialno+issuer.
Dirmngr is currently not able to parse more than the CN. Dirmngr is currently not able to parse more than the CN.
** Try all available root certs in case we have several of them in our keybox.
For example TC TrustCenter Class 1 CA certs are ambiguous becuase
user certs don't come with a authorityKeyIdentifier.
** Support extKeyUsage
The only value which makes sense for us is emailProtection (I have
not yet found a test cetificate with that). We might want to allow
other usages depending on special options (e.g. an option used for code
signing).
* sm/decrypt.c * sm/decrypt.c
** replace leading zero in integer hack by a cleaner solution ** replace leading zero in integer hack by a cleaner solution
@ -49,10 +41,12 @@ might want to have an agent context for each service request
** Remove the inter-module dependencies between gpgsm and keybox ** Remove the inter-module dependencies between gpgsm and keybox
** Add an source_of_key field ** Add an source_of_key field
** We need an error code GPG_ERR_NOT_LOCKED ** We need an error code GPG_ERR_NOT_LOCKED
It is already libgpg-error.
* agent/gpg-agent.c * agent/gpg-agent.c
** A SIGHUP should also restart the scdaemon ** A SIGHUP should also restart the scdaemon
But do this only after all connections terminated. But do this only after all connections terminated.
As of now we only send a RESET.
* agent/command.c * agent/command.c
** Make sure that secure memory is used where appropriate ** Make sure that secure memory is used where appropriate
@ -63,10 +57,6 @@ might want to have an agent context for each service request
* agent/divert-scd.c * agent/divert-scd.c
Remove the agent_reset_scd kludge. Remove the agent_reset_scd kludge.
* agent/protect-tool.c
** Export certificates along with the secret key.
** BUG? --p12-export seems to work only with unprotected keys
* Move pkcs-1 encoding into libgcrypt. * Move pkcs-1 encoding into libgcrypt.
* Use a MAC to protect some files. * Use a MAC to protect some files.
@ -74,12 +64,6 @@ might want to have an agent context for each service request
* sm/export.c * sm/export.c
** Return an error code or a status info per user ID. ** Return an error code or a status info per user ID.
* scd/apdu.c
** We need close_reader functionality
* ALL
** Return IMPORT_OK status.
* Where is http.c, regcomp.c, srv.c, w32reg.c ? * Where is http.c, regcomp.c, srv.c, w32reg.c ?
* scd/sc-investigate * scd/sc-investigate
@ -90,12 +74,12 @@ might want to have an agent context for each service request
authentication key. Old GnuPG versions seem to encode the wrong authentication key. Old GnuPG versions seem to encode the wrong
keyID. keyID.
* Store the revocation status directly in the Keybox
* tests * tests
** Makefile.am ** Makefile.am
We use printf(1) to setup the library path, this is not portable. We use printf(1) to setup the library path, this is not portable.
Furthermore LD_LIBRARY_PATH is not used on all systems. It doesn't Furthermore LD_LIBRARY_PATH is not used on all systems. It doesn't
matter for now, because we use some GNU/*BSDish features anyway. matter for now, because we use some GNU/*BSDish features anyway.
** Add a test to check the extkeyusage.

View File

@ -411,6 +411,12 @@ Same as @code{--debug=0xffffffff}
This is actually not a debugging option but only useful as such. It This is actually not a debugging option but only useful as such. It
lets gpgsm bypass all certificate chain validation checks. lets gpgsm bypass all certificate chain validation checks.
@item --debug-ignore-expiration
@opindex debug-ignore-expiration
This is actually not a debugging option but only useful as such. It
lets gpgsm ignore all notAfter dates, this is used by the regresssion
tests.
@end table @end table
All the long options may also be given in the configuration file after All the long options may also be given in the configuration file after

View File

@ -1,3 +1,10 @@
2004-02-20 Werner Koch <wk@gnupg.org>
* gpgsm.c (main): New option --debug-ignore-expiration.
* certchain.c (gpgsm_validate_chain): Use it here.
* certlist.c (cert_usage_p): Apply extKeyUsage.
2004-02-19 Werner Koch <wk@gnupg.org> 2004-02-19 Werner Koch <wk@gnupg.org>
* export.c (export_p12, popen_protect_tool) * export.c (export_p12, popen_protect_tool)

View File

@ -66,7 +66,6 @@ do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
} }
static int static int
unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
{ {
@ -74,6 +73,7 @@ unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
"2.5.29.15", /* keyUsage */ "2.5.29.15", /* keyUsage */
"2.5.29.19", /* basic Constraints */ "2.5.29.19", /* basic Constraints */
"2.5.29.32", /* certificatePolicies */ "2.5.29.32", /* certificatePolicies */
"2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
NULL NULL
}; };
int rc = 0, i, idx, crit; int rc = 0, i, idx, crit;
@ -548,16 +548,20 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG); rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
goto leave; goto leave;
} }
if (not_after && strcmp (current_time, not_after) > 0 ) if (*not_after && strcmp (current_time, not_after) > 0 )
{ {
do_list (1, lm, fp, _("certificate has expired")); do_list (opt.ignore_expiration?0:1, lm, fp,
_("certificate has expired"));
if (!lm) if (!lm)
{ {
log_error ("(expired at "); log_info ("(expired at ");
gpgsm_dump_time (not_after); gpgsm_dump_time (not_after);
log_printf (")\n"); log_printf (")\n");
} }
any_expired = 1; if (opt.ignore_expiration)
log_info ("WARNING: ignoring expiration\n");
else
any_expired = 1;
} }
} }

View File

@ -1,5 +1,5 @@
/* certlist.c - build list of certificates /* certlist.c - build list of certificates
* Copyright (C) 2001, 2003 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -33,7 +33,14 @@
#include "keydb.h" #include "keydb.h"
#include "i18n.h" #include "i18n.h"
static const char oid_kp_serverAuth[] = "1.3.6.1.5.5.7.3.1";
static const char oid_kp_clientAuth[] = "1.3.6.1.5.5.7.3.2";
static const char oid_kp_codeSigning[] = "1.3.6.1.5.5.7.3.3";
static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4";
static const char oid_kp_timeStamping[] = "1.3.6.1.5.5.7.3.8";
/* Return 0 if the cert is usable for encryption. A MODE of 0 checks /* Return 0 if the cert is usable for encryption. A MODE of 0 checks
for signing a MODE of 1 checks for encryption, a MODE of 2 checks for signing a MODE of 1 checks for encryption, a MODE of 2 checks
for verification and a MODE of 3 for decryption (just for for verification and a MODE of 3 for decryption (just for
@ -43,20 +50,78 @@ cert_usage_p (ksba_cert_t cert, int mode)
{ {
gpg_error_t err; gpg_error_t err;
unsigned int use; unsigned int use;
char *extkeyusages;
err = ksba_cert_get_key_usage (cert, &use); err = ksba_cert_get_ext_key_usages (cert, &extkeyusages);
if (gpg_err_code (err) == GPG_ERR_NO_DATA) if (gpg_err_code (err) == GPG_ERR_NO_DATA)
err = 0; /* no policy given */
if (!err)
{ {
if (opt.verbose && mode < 2) unsigned int extusemask = ~0; /* Allow all. */
log_info (mode?
_("no key usage specified - accepted for encryption\n"): if (extkeyusages)
_("no key usage specified - accepted for signing\n")); {
return 0; char *p, *pend;
int any_critical = 0;
extusemask = 0;
p = extkeyusages;
while (p && (pend=strchr (p, ':')))
{
*pend++ = 0;
/* Only care about critical flagged usages. */
if ( *pend == 'C' )
{
any_critical = 1;
if ( !strcmp (p, oid_kp_serverAuth))
extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
| KSBA_KEYUSAGE_KEY_ENCIPHERMENT
| KSBA_KEYUSAGE_KEY_AGREEMENT);
else if ( !strcmp (p, oid_kp_clientAuth))
extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
| KSBA_KEYUSAGE_KEY_AGREEMENT);
else if ( !strcmp (p, oid_kp_codeSigning))
extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE);
else if ( !strcmp (p, oid_kp_emailProtection))
extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
| KSBA_KEYUSAGE_NON_REPUDIATION
| KSBA_KEYUSAGE_KEY_ENCIPHERMENT
| KSBA_KEYUSAGE_KEY_AGREEMENT);
else if ( !strcmp (p, oid_kp_timeStamping))
extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE
| KSBA_KEYUSAGE_NON_REPUDIATION);
}
if ((p = strchr (pend, '\n')))
p++;
}
xfree (extkeyusages);
extkeyusages = NULL;
if (!any_critical)
extusemask = ~0; /* Reset to the don't care mask. */
}
err = ksba_cert_get_key_usage (cert, &use);
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
{
err = 0;
if (opt.verbose && mode < 2)
log_info (_("no key usage specified - assuming all usages\n"));
use = ~0;
}
/* Apply extKeyUsage. */
use &= extusemask;
} }
if (err) if (err)
{ {
log_error (_("error getting key usage information: %s\n"), log_error (_("error getting key usage information: %s\n"),
gpg_strerror (err)); gpg_strerror (err));
xfree (extkeyusages);
return err; return err;
} }
@ -73,6 +138,7 @@ cert_usage_p (ksba_cert_t cert, int mode)
(KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
) )
return 0; return 0;
log_info (mode==3? _("certificate should have not been used for encryption\n"): log_info (mode==3? _("certificate should have not been used for encryption\n"):
mode==2? _("certificate should have not been used for signing\n"): mode==2? _("certificate should have not been used for signing\n"):
mode==1? _("certificate is not usable for encryption\n"): mode==1? _("certificate is not usable for encryption\n"):

View File

@ -89,6 +89,7 @@ enum cmd_and_opt_values {
oDebugAll, oDebugAll,
oDebugWait, oDebugWait,
oDebugNoChainValidation, oDebugNoChainValidation,
oDebugIgnoreExpiration,
oLogFile, oLogFile,
oEnableSpecialFilenames, oEnableSpecialFilenames,
@ -323,7 +324,8 @@ static ARGPARSE_OPTS opts[] = {
{ oDebugLevel, "debug-level" ,2, "@"}, { oDebugLevel, "debug-level" ,2, "@"},
{ oDebugAll, "debug-all" ,0, "@"}, { oDebugAll, "debug-all" ,0, "@"},
{ oDebugWait, "debug-wait" ,1, "@"}, { oDebugWait, "debug-wait" ,1, "@"},
{ oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"}, { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"},
{ oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"},
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
{ aDummy, "no-comment", 0, "@"}, { aDummy, "no-comment", 0, "@"},
{ aDummy, "completes-needed", 1, "@"}, { aDummy, "completes-needed", 1, "@"},
@ -991,6 +993,7 @@ main ( int argc, char **argv)
case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oDebugNoChainValidation: opt.no_chain_validation = 1; break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;

View File

@ -94,6 +94,7 @@ struct {
char *policy_file; /* full pathname of policy file */ char *policy_file; /* full pathname of policy file */
int no_policy_check; /* ignore certificate policies */ int no_policy_check; /* ignore certificate policies */
int no_chain_validation; /* Bypass all cert chain validity tests */ int no_chain_validation; /* Bypass all cert chain validity tests */
int ignore_expiration; /* Ignore the notAfter validity checks. */
int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */
} opt; } opt;

View File

@ -46,6 +46,28 @@ struct list_external_parm_s {
}; };
/* This table is to map Extended Key Usage OIDs to human readable
names. */
struct {
const char *oid;
const char *name;
} key_purpose_map[] = {
{ "1.3.6.1.5.5.7.3.1", "serverAuth" },
{ "1.3.6.1.5.5.7.3.2", "clientAuth" },
{ "1.3.6.1.5.5.7.3.3", "codeSigning" },
{ "1.3.6.1.5.5.7.3.4", "emailProtection" },
{ "1.3.6.1.5.5.7.3.5", "ipsecEndSystem" },
{ "1.3.6.1.5.5.7.3.6", "ipsecTunnel" },
{ "1.3.6.1.5.5.7.3.7", "ipsecUser" },
{ "1.3.6.1.5.5.7.3.8", "timeStamping" },
{ "1.3.6.1.5.5.7.3.9", "ocspSigning" },
{ "1.3.6.1.5.5.7.3.10", "dvcs" },
{ "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
{ "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
{ "1.3.6.1.5.5.7.3.14", "wlanSSID" },
{ NULL, NULL }
};
static void static void
print_key_data (ksba_cert_t cert, FILE *fp) print_key_data (ksba_cert_t cert, FILE *fp)
@ -292,10 +314,10 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
ksba_sexp_t sexp; ksba_sexp_t sexp;
char *dn; char *dn;
ksba_isotime_t t; ksba_isotime_t t;
int idx; int idx, i;
int is_ca, chainlen; int is_ca, chainlen;
unsigned int kusage; unsigned int kusage;
char *string, *p; char *string, *p, *pend;
sexp = ksba_cert_get_serial (cert); sexp = ksba_cert_get_serial (cert);
fputs ("Serial number: ", fp); fputs ("Serial number: ", fp);
@ -367,6 +389,36 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
putc ('\n', fp); putc ('\n', fp);
} }
err = ksba_cert_get_ext_key_usages (cert, &string);
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
{
fputs ("ext key usage: ", fp);
if (err)
fprintf (fp, "[error: %s]", gpg_strerror (err));
else
{
p = string;
while (p && (pend=strchr (p, ':')))
{
*pend++ = 0;
for (i=0; key_purpose_map[i].oid; i++)
if ( !strcmp (key_purpose_map[i].oid, p) )
break;
fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
p = pend;
if (*p != 'C')
fputs (" (suggested)", fp);
if ((p = strchr (p, '\n')))
{
p++;
fputs (", ", fp);
}
}
xfree (string);
}
putc ('\n', fp);
}
err = ksba_cert_get_cert_policies (cert, &string); err = ksba_cert_get_cert_policies (cert, &string);
if (gpg_err_code (err) != GPG_ERR_NO_DATA) if (gpg_err_code (err) != GPG_ERR_NO_DATA)
{ {