aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2022-06-13 15:46:40 +0000
committerWerner Koch <[email protected]>2022-08-19 08:49:20 +0000
commit77b6896f7a85a4b1c9cdd731e1d68d59a0e09950 (patch)
tree8aefa75ef816faae6a4bcc81118d657e83d2950b
parentgpgconf: Make --auto-key-import and --include-key-block visible again. (diff)
downloadgnupg-77b6896f7a85a4b1c9cdd731e1d68d59a0e09950.tar.gz
gnupg-77b6896f7a85a4b1c9cdd731e1d68d59a0e09950.zip
gpgsm: New option --compatibility-flags.
* sm/gpgsm.c (oCompatibilityFlags): New option. (compatibility_flags): new. (main): Parse and print them in verbose mode. * sm/gpgsm.h (opt): Add field compat_glags.: (COMPAT_ALLOW_KA_TO_ENCR): New. * sm/keylist.c (print_capabilities): Take care of the new flag. * sm/certlist.c (cert_usage_p): Ditto. * common/miscellaneous.c (parse_compatibility_flags): New. * common/util.h (struct compatibility_flags_s): New. -- Backported-from-master: f0b373cec93bb01f02b9c0a3ab1f3e242b381c3f Backported-from-master: ce63eaa4f8f3f41aafcaddd8d658dacd522334a8
-rw-r--r--common/miscellaneous.c80
-rw-r--r--common/util.h9
-rw-r--r--doc/gpgsm.texi8
-rw-r--r--sm/certlist.c13
-rw-r--r--sm/gpgsm.c21
-rw-r--r--sm/gpgsm.h14
-rw-r--r--sm/keylist.c28
7 files changed, 164 insertions, 9 deletions
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
index e40dcd55f..c3775547b 100644
--- a/common/miscellaneous.c
+++ b/common/miscellaneous.c
@@ -760,3 +760,83 @@ parse_debug_flag (const char *string, unsigned int *debugvar,
*debugvar |= result;
return 0;
}
+
+
+
+/* Parse an --comaptibility_flags style argument consisting of comma
+ * separated strings.
+ *
+ * Returns: 0 on success or -1 and ERRNO set on error. On success the
+ * supplied variable is updated by the parsed flags.
+ *
+ * If STRING is NULL the enabled flags are printed.
+ */
+int
+parse_compatibility_flags (const char *string, unsigned int *flagvar,
+ const struct compatibility_flags_s *flags)
+
+{
+ unsigned long result = 0;
+ int i, j;
+
+ if (!string)
+ {
+ if (flagvar)
+ {
+ log_info ("enabled compatibility flags:");
+ for (i=0; flags[i].name; i++)
+ if ((*flagvar & flags[i].flag))
+ log_printf (" %s", flags[i].name);
+ log_printf ("\n");
+ }
+ return 0;
+ }
+
+ while (spacep (string))
+ string++;
+
+ if (!strcmp (string, "?") || !strcmp (string, "help"))
+ {
+ log_info ("available compatibility flags:\n");
+ for (i=0; flags[i].name; i++)
+ log_info (" %s\n", flags[i].name);
+ if (flags[i].flag != 77)
+ exit (0);
+ }
+ else
+ {
+ char **words;
+ words = strtokenize (string, ",");
+ if (!words)
+ return -1;
+ for (i=0; words[i]; i++)
+ {
+ if (*words[i])
+ {
+ for (j=0; flags[j].name; j++)
+ if (!strcmp (words[i], flags[j].name))
+ {
+ result |= flags[j].flag;
+ break;
+ }
+ if (!flags[j].name)
+ {
+ if (!strcmp (words[i], "none"))
+ {
+ *flagvar = 0;
+ result = 0;
+ }
+ else if (!strcmp (words[i], "all"))
+ result = ~0;
+ else
+ log_info ("unknown compatibility flag '%s' ignored\n",
+ words[i]);
+ }
+ }
+ }
+ xfree (words);
+ }
+
+ *flagvar |= result;
+ return 0;
+}
diff --git a/common/util.h b/common/util.h
index 9f46457ba..82b3a34af 100644
--- a/common/util.h
+++ b/common/util.h
@@ -358,6 +358,15 @@ struct debug_flags_s
int parse_debug_flag (const char *string, unsigned int *debugvar,
const struct debug_flags_s *flags);
+struct compatibility_flags_s
+{
+ unsigned int flag;
+ const char *name;
+ const char *desc;
+};
+int parse_compatibility_flags (const char *string, unsigned int *flagvar,
+ const struct compatibility_flags_s *flags);
+
/*-- Simple replacement functions. */
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index 06a85b1ed..ba91aed92 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -710,6 +710,14 @@ Include ephemeral flagged keys in the output of key listings. Note
that they are included anyway if the key specification for a listing
is given as fingerprint or keygrip.
+@item --compatibility-flags @var{flags}
+@opindex compatibility-flags
+Set compatibility flags to work around problems due to non-compliant
+certificates or data. The @var{flags} are given as a comma separated
+list of flag names and are OR-ed together. The special flag "none"
+clears the list and allows to start over with an empty list. To get a
+list of available flags the sole word "help" can be used.
+
@item --debug-level @var{level}
@opindex debug-level
Select the debug level for investigating problems. @var{level} may be
diff --git a/sm/certlist.c b/sm/certlist.c
index c3e4e821b..b1ae58c52 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -52,9 +52,11 @@ cert_usage_p (ksba_cert_t cert, int mode, int silent)
{
gpg_error_t err;
unsigned int use;
+ unsigned int encr_bits, sign_bits;
char *extkeyusages;
int have_ocsp_signing = 0;
+
err = ksba_cert_get_ext_key_usages (cert, &extkeyusages);
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
err = 0; /* no policy given */
@@ -158,10 +160,13 @@ cert_usage_p (ksba_cert_t cert, int mode, int silent)
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
- if ((use & ((mode&1)?
- (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT):
- (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- )
+ encr_bits = (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT);
+ if ((opt.compat_flags & COMPAT_ALLOW_KA_TO_ENCR))
+ encr_bits |= KSBA_KEYUSAGE_KEY_AGREEMENT;
+
+ sign_bits = (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION);
+
+ if ((use & ((mode&1)? encr_bits : sign_bits)))
return 0;
if (!silent)
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 87067cf31..27168904c 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -200,6 +200,7 @@ enum cmd_and_opt_values {
oIgnoreCertExtension,
oIgnoreCertWithOID,
oRequireCompliance,
+ oCompatibilityFlags,
oNoAutostart
};
@@ -422,6 +423,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oLCctype, "lc-ctype", "@"),
ARGPARSE_s_s (oLCmessages, "lc-messages", "@"),
ARGPARSE_s_s (oXauthority, "xauthority", "@"),
+ ARGPARSE_s_s (oCompatibilityFlags, "compatibility-flags", "@"),
ARGPARSE_header (NULL, ""), /* Stop the header group. */
@@ -457,6 +459,14 @@ static struct debug_flags_s debug_flags [] =
};
+/* The list of compatibility flags. */
+static struct compatibility_flags_s compatibility_flags [] =
+ {
+ { COMPAT_ALLOW_KA_TO_ENCR, "allow-ka-to-encr" },
+ { 0, NULL }
+ };
+
+
/* Global variable to keep an error count. */
int gpgsm_errors_seen = 0;
@@ -1233,6 +1243,15 @@ main ( int argc, char **argv)
case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
+ case oCompatibilityFlags:
+ if (parse_compatibility_flags (pargs.r.ret_str, &opt.compat_flags,
+ compatibility_flags))
+ {
+ pargs.r_opt = ARGPARSE_INVALID_ARG;
+ pargs.err = ARGPARSE_PRINT_ERROR;
+ }
+ break;
+
case oStatusFD:
ctrl.status_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 1);
break;
@@ -1509,6 +1528,8 @@ main ( int argc, char **argv)
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
set_debug ();
+ if (opt.verbose) /* Print the compatibility flags. */
+ parse_compatibility_flags (NULL, &opt.compat_flags, compatibility_flags);
gnupg_set_compliance_extra_info (opt.min_rsa_length);
/* Although we always use gpgsm_exit, we better install a regualr
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 5e7db4bec..53ef165a1 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -150,6 +150,8 @@ struct
* mode. */
int require_compliance;
+ /* Compatibility flags (COMPAT_FLAG_xxxx). */
+ unsigned int compat_flags;
} opt;
/* Debug values and macros. */
@@ -169,6 +171,18 @@ struct
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_IPC (opt.debug & DBG_IPC_VALUE)
+
+/* Compatibility flags */
+/* Telesec RSA cards produced for NRW in 2022 came with only the
+ * keyAgreement bit set. This flag allows there use for encryption
+ * anyway. Example cert:
+ * Issuer: /CN=DOI CA 10a/OU=DOI/O=PKI-1-Verwaltung/C=DE
+ * key usage: digitalSignature nonRepudiation keyAgreement
+ * policies: 1.3.6.1.4.1.7924.1.1:N:
+ */
+#define COMPAT_ALLOW_KA_TO_ENCR 1
+
+
/* Forward declaration for an object defined in server.c */
struct server_local_s;
diff --git a/sm/keylist.c b/sm/keylist.c
index 4f2d009fd..2d51aa74d 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -251,9 +251,11 @@ print_capabilities (ksba_cert_t cert, estream_t fp)
{
gpg_error_t err;
unsigned int use;
+ unsigned int is_encr, is_sign, is_cert;
size_t buflen;
char buffer[1];
+
err = ksba_cert_get_user_data (cert, "is_qualified",
&buffer, sizeof (buffer), &buflen);
if (!err && buflen)
@@ -285,17 +287,33 @@ print_capabilities (ksba_cert_t cert, estream_t fp)
return;
}
+ is_encr = is_sign = is_cert = 0;
+
if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
- es_putc ('e', fp);
+ is_encr = 1;
if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- es_putc ('s', fp);
+ is_sign = 1;
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
+ is_cert = 1;
+
+ /* We need to returned the faked key usage to frontends so that they
+ * can select the right key. Note that we don't do this for the
+ * human readable keyUsage. */
+ if ((opt.compat_flags & COMPAT_ALLOW_KA_TO_ENCR)
+ && (use & KSBA_KEYUSAGE_KEY_AGREEMENT))
+ is_encr = 1;
+
+ if (is_encr)
+ es_putc ('e', fp);
+ if (is_sign)
+ es_putc ('s', fp);
+ if (is_cert)
es_putc ('c', fp);
- if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
+ if (is_encr)
es_putc ('E', fp);
- if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
+ if (is_sign)
es_putc ('S', fp);
- if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
+ if (is_cert)
es_putc ('C', fp);
}