aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2004-02-20 13:46:21 +0000
committerWerner Koch <[email protected]>2004-02-20 13:46:21 +0000
commitaa0e38982a2d220ecafb6f82b169c1e4897f9e29 (patch)
treed4afe59e3bace3e8949c95069d32091f4c1c706b
parent* protect-tool.c: New options --have-cert and --prompt. (diff)
downloadgnupg-aa0e38982a2d220ecafb6f82b169c1e4897f9e29.tar.gz
gnupg-aa0e38982a2d220ecafb6f82b169c1e4897f9e29.zip
* gpgsm.c (main): New option --debug-ignore-expiration.
* certchain.c (gpgsm_validate_chain): Use it here. * certlist.c (cert_usage_p): Apply extKeyUsage.
Diffstat (limited to '')
-rw-r--r--TODO24
-rw-r--r--doc/gpgsm.texi6
-rw-r--r--sm/ChangeLog7
-rw-r--r--sm/certchain.c14
-rw-r--r--sm/certlist.c82
-rw-r--r--sm/gpgsm.c5
-rw-r--r--sm/gpgsm.h1
-rw-r--r--sm/keylist.c56
8 files changed, 159 insertions, 36 deletions
diff --git a/TODO b/TODO
index 7f06e546b..496babfdc 100644
--- a/TODO
+++ b/TODO
@@ -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.
** figure out how to auto retrieve a key by serialno+issuer.
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
** 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
** Add an source_of_key field
** We need an error code GPG_ERR_NOT_LOCKED
+ It is already libgpg-error.
* agent/gpg-agent.c
** A SIGHUP should also restart the scdaemon
But do this only after all connections terminated.
+ As of now we only send a RESET.
* agent/command.c
** 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
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.
* 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
** 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 ?
* 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
keyID.
-* Store the revocation status directly in the Keybox
-
* tests
** Makefile.am
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
matter for now, because we use some GNU/*BSDish features anyway.
+** Add a test to check the extkeyusage.
+
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index 53624558d..24503a10b 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -411,6 +411,12 @@ Same as @code{--debug=0xffffffff}
This is actually not a debugging option but only useful as such. It
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
All the long options may also be given in the configuration file after
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 922773ecb..a8a8f3f44 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,10 @@
+2004-02-20 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* export.c (export_p12, popen_protect_tool)
diff --git a/sm/certchain.c b/sm/certchain.c
index bf5582503..2a59c559d 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -66,7 +66,6 @@ do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
}
-
static int
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.19", /* basic Constraints */
"2.5.29.32", /* certificatePolicies */
+ "2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
NULL
};
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);
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)
{
- log_error ("(expired at ");
+ log_info ("(expired at ");
gpgsm_dump_time (not_after);
log_printf (")\n");
}
- any_expired = 1;
+ if (opt.ignore_expiration)
+ log_info ("WARNING: ignoring expiration\n");
+ else
+ any_expired = 1;
}
}
diff --git a/sm/certlist.c b/sm/certlist.c
index 66fb46326..8ee3c2caf 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -1,5 +1,5 @@
/* 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.
*
@@ -33,7 +33,14 @@
#include "keydb.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
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
@@ -43,20 +50,78 @@ cert_usage_p (ksba_cert_t cert, int mode)
{
gpg_error_t err;
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)
+ err = 0; /* no policy given */
+ if (!err)
{
- if (opt.verbose && mode < 2)
- log_info (mode?
- _("no key usage specified - accepted for encryption\n"):
- _("no key usage specified - accepted for signing\n"));
- return 0;
+ unsigned int extusemask = ~0; /* Allow all. */
+
+ if (extkeyusages)
+ {
+ 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)
{
log_error (_("error getting key usage information: %s\n"),
gpg_strerror (err));
+ xfree (extkeyusages);
return err;
}
@@ -73,6 +138,7 @@ cert_usage_p (ksba_cert_t cert, int mode)
(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"):
mode==1? _("certificate is not usable for encryption\n"):
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index ede432b1b..68214a6d8 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -89,6 +89,7 @@ enum cmd_and_opt_values {
oDebugAll,
oDebugWait,
oDebugNoChainValidation,
+ oDebugIgnoreExpiration,
oLogFile,
oEnableSpecialFilenames,
@@ -323,7 +324,8 @@ static ARGPARSE_OPTS opts[] = {
{ oDebugLevel, "debug-level" ,2, "@"},
{ oDebugAll, "debug-all" ,0, "@"},
{ 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") },
{ aDummy, "no-comment", 0, "@"},
{ aDummy, "completes-needed", 1, "@"},
@@ -991,6 +993,7 @@ main ( int argc, char **argv)
case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: debug_wait = pargs.r.ret_int; 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 oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index a1711a72e..6cf3ed094 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -94,6 +94,7 @@ struct {
char *policy_file; /* full pathname of policy file */
int no_policy_check; /* ignore certificate policies */
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. */
} opt;
diff --git a/sm/keylist.c b/sm/keylist.c
index e6daec681..a73d18e92 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -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
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;
char *dn;
ksba_isotime_t t;
- int idx;
+ int idx, i;
int is_ca, chainlen;
unsigned int kusage;
- char *string, *p;
+ char *string, *p, *pend;
sexp = ksba_cert_get_serial (cert);
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);
}
+ 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);
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
{