[svn] GnuPG - r4074 - in branches/GNUPG-1-9-BRANCH: . sm
svn author wk
cvs at cvs.gnupg.org
Tue Mar 21 10:56:47 CET 2006
Author: wk
Date: 2006-03-21 10:56:47 +0100 (Tue, 21 Mar 2006)
New Revision: 4074
Modified:
branches/GNUPG-1-9-BRANCH/NEWS
branches/GNUPG-1-9-BRANCH/TODO
branches/GNUPG-1-9-BRANCH/sm/ChangeLog
branches/GNUPG-1-9-BRANCH/sm/certchain.c
branches/GNUPG-1-9-BRANCH/sm/gpgsm.h
branches/GNUPG-1-9-BRANCH/sm/qualified.c
Log:
Add Kludge for RegTP sillyness.
Modified: branches/GNUPG-1-9-BRANCH/NEWS
===================================================================
--- branches/GNUPG-1-9-BRANCH/NEWS 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/NEWS 2006-03-21 09:56:47 UTC (rev 4074)
@@ -8,7 +8,10 @@
* Cards are not anymore reseted at the end of a connection.
+ * [gpgsm] Kludge to allow use of Bundesnetzagentur issued
+ certificates.
+
Noteworthy changes in version 1.9.20 (2005-12-20)
-------------------------------------------------
Modified: branches/GNUPG-1-9-BRANCH/TODO
===================================================================
--- branches/GNUPG-1-9-BRANCH/TODO 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/TODO 2006-03-21 09:56:47 UTC (rev 4074)
@@ -18,8 +18,10 @@
* sm/certchain.c
** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent.
+** Try to keep certificate references somewhere
+ This will help with some of our caching code. We also need to test
+ that cachining; in particular "regtp_ca_chainlen".
-
* sm/decrypt.c
** replace leading zero in integer hack by a cleaner solution
Modified: branches/GNUPG-1-9-BRANCH/sm/ChangeLog
===================================================================
--- branches/GNUPG-1-9-BRANCH/sm/ChangeLog 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/sm/ChangeLog 2006-03-21 09:56:47 UTC (rev 4074)
@@ -1,3 +1,12 @@
+2006-03-21 Werner Koch <wk at g10code.com>
+
+ * certchain.c (get_regtp_ca_info): New.
+ (allowed_ca): Use it.
+
+2006-03-20 Werner Koch <wk at g10code.com>
+
+ * qualified.c (gpgsm_is_in_qualified_list): New optional arg COUNTRY.
+
2006-02-17 Werner Koch <wk at g10code.com>
* call-dirmngr.c (start_dirmngr): Print name of dirmngr to be started.
Modified: branches/GNUPG-1-9-BRANCH/sm/certchain.c
===================================================================
--- branches/GNUPG-1-9-BRANCH/sm/certchain.c 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/sm/certchain.c 2006-03-21 09:56:47 UTC (rev 4074)
@@ -1,5 +1,6 @@
/* certchain.c - certificate chain validation
- * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005,
+ * 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -39,6 +40,10 @@
#include "i18n.h"
+static int get_regtp_ca_info (ksba_cert_t cert, int *chainlen);
+
+
+
/* If LISTMODE is true, print FORMAT using LISTMODE to FP. If
LISTMODE is false, use the string to print an log_info or, if
IS_ERROR is true, and log_error. */
@@ -128,6 +133,11 @@
return err;
if (!flag)
{
+ if (get_regtp_ca_info (cert, chainlen))
+ {
+ return 0; /* RegTP issued certificate. */
+ }
+
do_list (1, listmode, fp,_("issuer certificate is not marked as a CA"));
return gpg_error (GPG_ERR_BAD_CA_CERT);
}
@@ -267,7 +277,7 @@
}
-/* Helper fucntion for find_up. This resets the key handle and search
+/* Helper function for find_up. This resets the key handle and search
for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns
0 obn success or -1 when not found. */
static int
@@ -796,7 +806,7 @@
{
/* Need to consult the list of root certificates for
qualified signatures. */
- err = gpgsm_is_in_qualified_list (ctrl, subject_cert);
+ err = gpgsm_is_in_qualified_list (ctrl, subject_cert, NULL);
if (!err)
is_qualified = 1;
else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND)
@@ -807,8 +817,8 @@
gpg_strerror (err));
if ( is_qualified != -1 )
{
- /* Cache the result but don't care toomuch about
- an error. */
+ /* Cache the result but don't care too much
+ about an error. */
buf[0] = !!is_qualified;
err = ksba_cert_set_user_data (subject_cert,
"is_qualified", buf, 1);
@@ -1181,3 +1191,110 @@
return rc;
}
+
+
+/* Check whether the certificate CERT has been issued by the German
+ authority for qualified signature. They do not set the
+ basicConstraints and thus we need this workaround. It works by
+ looking up the root certificate and checking whether that one is
+ listed as a qualified certificate for Germany.
+
+ We also try to cache this data but as long as don't keep a
+ reference to the certificate this won't be used.
+
+ Returns: True if CERT is a RegTP issued CA cert (i.e. the root
+ certificate itself or one of the CAs). In that case CHAINLEN will
+ receive the length of the chain which is either 0 or 1.
+*/
+static int
+get_regtp_ca_info (ksba_cert_t cert, int *chainlen)
+{
+ gpg_error_t err;
+ ksba_cert_t next;
+ int rc = 0;
+ int i, depth;
+ char country[3];
+ ksba_cert_t array[4];
+ char buf[2];
+ size_t buflen;
+ int dummy_chainlen;
+
+ if (!chainlen)
+ chainlen = &dummy_chainlen;
+
+ *chainlen = 0;
+ err = ksba_cert_get_user_data (cert, "regtp_ca_chainlen",
+ &buf, sizeof (buf), &buflen);
+ if (!err)
+ {
+ /* Got info. */
+ if (buflen < 2 || !*buf)
+ return 0; /* Nothing found. */
+ *chainlen = buf[1];
+ return 1; /* This is a regtp CA. */
+ }
+ else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
+ {
+ log_error ("ksba_cert_get_user_data(%s) failed: %s\n",
+ "regtp_ca_chainlen", gpg_strerror (err));
+ return 0; /* Nothing found. */
+ }
+
+ /* Need to gather the info. This requires to walk up the chain
+ until we have found the root. Because we are only interested in
+ German Bundesnetzagentur (former RegTP) derived certificates 3
+ levels are enough. (The German signature law demands a 3 tier
+ hierachy; thus there is only one CA between the EE and the Root
+ CA.) */
+ memset (&array, 0, sizeof array);
+
+ depth = 0;
+ ksba_cert_ref (cert);
+ array[depth++] = cert;
+ ksba_cert_ref (cert);
+ while (depth < DIM(array) && !(rc=gpgsm_walk_cert_chain (cert, &next)))
+ {
+ ksba_cert_release (cert);
+ ksba_cert_ref (next);
+ array[depth++] = next;
+ cert = next;
+ }
+ ksba_cert_release (cert);
+ if (rc != -1 || !depth || depth == DIM(array) )
+ {
+ /* We did not reached the root. */
+ goto leave;
+ }
+
+ /* If this is a German signature law issued certificate, we store
+ additional additional information. */
+ if (!gpgsm_is_in_qualified_list (NULL, array[depth-1], country)
+ && !strcmp (country, "de"))
+ {
+ /* Setting the pathlen for the root CA and the CA flag for the
+ next one is all what we need to do. */
+ err = ksba_cert_set_user_data (array[depth-1], "regtp_ca_chainlen",
+ "\x01\x01", 2);
+ if (!err && depth > 1)
+ err = ksba_cert_set_user_data (array[depth-2], "regtp_ca_chainlen",
+ "\x01\x00", 2);
+ if (err)
+ log_error ("ksba_set_user_data(%s) failed: %s\n",
+ "regtp_ca_chainlen", gpg_strerror (err));
+ for (i=0; i < depth; i++)
+ ksba_cert_release (array[i]);
+ *chainlen = (depth>1? 0:1);
+ return 1;
+ }
+
+ leave:
+ /* Nothing special with this certificate. Mark the target
+ certificate anyway to avoid duplicate lookups. */
+ err = ksba_cert_set_user_data (cert, "regtp_ca_chainlen", "", 1);
+ if (err)
+ log_error ("ksba_set_user_data(%s) failed: %s\n",
+ "regtp_ca_chainlen", gpg_strerror (err));
+ for (i=0; i < depth; i++)
+ ksba_cert_release (array[i]);
+ return 0;
+}
Modified: branches/GNUPG-1-9-BRANCH/sm/gpgsm.h
===================================================================
--- branches/GNUPG-1-9-BRANCH/sm/gpgsm.h 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/sm/gpgsm.h 2006-03-21 09:56:47 UTC (rev 4074)
@@ -296,7 +296,8 @@
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
/*-- qualified.c --*/
-gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert);
+gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert,
+ char *country);
gpg_error_t gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert);
gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert);
Modified: branches/GNUPG-1-9-BRANCH/sm/qualified.c
===================================================================
--- branches/GNUPG-1-9-BRANCH/sm/qualified.c 2006-03-20 16:40:28 UTC (rev 4073)
+++ branches/GNUPG-1-9-BRANCH/sm/qualified.c 2006-03-21 09:56:47 UTC (rev 4074)
@@ -145,24 +145,29 @@
per user because it is not a decision of the user.
Returns: 0 if the certificate is included. GPG_ERR_NOT_FOUND if it
- is not in the liost or any other error (e.g. if no list of
- qualified signatures is available. */
+ is not in the list or any other error (e.g. if no list of
+ qualified signatures is available. If COUNTRY has not been passed
+ as NULL a string witha maximum length of 2 will be copied into it;
+ thus the caller needs to provide a buffer of length 3. */
gpg_error_t
-gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert)
+gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert, char *country)
{
gpg_error_t err;
char *fpr;
char key[41];
- char country[2];
+ char mycountry[3];
int lnr = 0;
+ if (country)
+ *country = 0;
+
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
if (!fpr)
return gpg_error (GPG_ERR_GENERAL);
if (listfp)
rewind (listfp);
- while (!(err = read_list (key, country, &lnr)))
+ while (!(err = read_list (key, mycountry, &lnr)))
{
if (!strcmp (key, fpr))
break;
@@ -170,6 +175,9 @@
if (gpg_err_code (err) == GPG_ERR_EOF)
err = gpg_error (GPG_ERR_NOT_FOUND);
+ if (!err && country)
+ strcpy (country, mycountry);
+
xfree (fpr);
return err;
}
More information about the Gnupg-commits
mailing list