mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Add Kludge for RegTP sillyness.
This commit is contained in:
parent
89824e5d59
commit
6b19366e4e
3
NEWS
3
NEWS
@ -8,6 +8,9 @@ Noteworthy changes in version 1.9.21
|
|||||||
|
|
||||||
* Cards are not anymore reseted at the end of a connection.
|
* 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)
|
Noteworthy changes in version 1.9.20 (2005-12-20)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
4
TODO
4
TODO
@ -18,7 +18,9 @@ might want to have an agent context for each service request
|
|||||||
|
|
||||||
* sm/certchain.c
|
* sm/certchain.c
|
||||||
** 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.
|
||||||
|
** 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
|
* sm/decrypt.c
|
||||||
** replace leading zero in integer hack by a cleaner solution
|
** replace leading zero in integer hack by a cleaner solution
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2006-03-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* certchain.c (get_regtp_ca_info): New.
|
||||||
|
(allowed_ca): Use it.
|
||||||
|
|
||||||
|
2006-03-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* qualified.c (gpgsm_is_in_qualified_list): New optional arg COUNTRY.
|
||||||
|
|
||||||
2006-02-17 Werner Koch <wk@g10code.com>
|
2006-02-17 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* call-dirmngr.c (start_dirmngr): Print name of dirmngr to be started.
|
* call-dirmngr.c (start_dirmngr): Print name of dirmngr to be started.
|
||||||
|
127
sm/certchain.c
127
sm/certchain.c
@ -1,5 +1,6 @@
|
|||||||
/* certchain.c - certificate chain validation
|
/* 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.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -39,6 +40,10 @@
|
|||||||
#include "i18n.h"
|
#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
|
/* If LISTMODE is true, print FORMAT using LISTMODE to FP. If
|
||||||
LISTMODE is false, use the string to print an log_info or, if
|
LISTMODE is false, use the string to print an log_info or, if
|
||||||
IS_ERROR is true, and log_error. */
|
IS_ERROR is true, and log_error. */
|
||||||
@ -128,6 +133,11 @@ allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp)
|
|||||||
return err;
|
return err;
|
||||||
if (!flag)
|
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"));
|
do_list (1, listmode, fp,_("issuer certificate is not marked as a CA"));
|
||||||
return gpg_error (GPG_ERR_BAD_CA_CERT);
|
return gpg_error (GPG_ERR_BAD_CA_CERT);
|
||||||
}
|
}
|
||||||
@ -267,7 +277,7 @@ check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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
|
for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns
|
||||||
0 obn success or -1 when not found. */
|
0 obn success or -1 when not found. */
|
||||||
static int
|
static int
|
||||||
@ -796,7 +806,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
{
|
{
|
||||||
/* Need to consult the list of root certificates for
|
/* Need to consult the list of root certificates for
|
||||||
qualified signatures. */
|
qualified signatures. */
|
||||||
err = gpgsm_is_in_qualified_list (ctrl, subject_cert);
|
err = gpgsm_is_in_qualified_list (ctrl, subject_cert, NULL);
|
||||||
if (!err)
|
if (!err)
|
||||||
is_qualified = 1;
|
is_qualified = 1;
|
||||||
else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
||||||
@ -807,8 +817,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
if ( is_qualified != -1 )
|
if ( is_qualified != -1 )
|
||||||
{
|
{
|
||||||
/* Cache the result but don't care toomuch about
|
/* Cache the result but don't care too much
|
||||||
an error. */
|
about an error. */
|
||||||
buf[0] = !!is_qualified;
|
buf[0] = !!is_qualified;
|
||||||
err = ksba_cert_set_user_data (subject_cert,
|
err = ksba_cert_set_user_data (subject_cert,
|
||||||
"is_qualified", buf, 1);
|
"is_qualified", buf, 1);
|
||||||
@ -1181,3 +1191,110 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
|
|||||||
return rc;
|
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;
|
||||||
|
}
|
||||||
|
@ -296,7 +296,8 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
|||||||
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
||||||
|
|
||||||
/*-- qualified.c --*/
|
/*-- 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_qualified_consent (ctrl_t ctrl, ksba_cert_t cert);
|
||||||
gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert);
|
gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert);
|
||||||
|
|
||||||
|
@ -145,24 +145,29 @@ read_list (char *key, char *country, int *lnr)
|
|||||||
per user because it is not a decision of the user.
|
per user because it is not a decision of the user.
|
||||||
|
|
||||||
Returns: 0 if the certificate is included. GPG_ERR_NOT_FOUND if it
|
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
|
is not in the list or any other error (e.g. if no list of
|
||||||
qualified signatures is available. */
|
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
|
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;
|
gpg_error_t err;
|
||||||
char *fpr;
|
char *fpr;
|
||||||
char key[41];
|
char key[41];
|
||||||
char country[2];
|
char mycountry[3];
|
||||||
int lnr = 0;
|
int lnr = 0;
|
||||||
|
|
||||||
|
if (country)
|
||||||
|
*country = 0;
|
||||||
|
|
||||||
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
||||||
if (!fpr)
|
if (!fpr)
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
if (listfp)
|
if (listfp)
|
||||||
rewind (listfp);
|
rewind (listfp);
|
||||||
while (!(err = read_list (key, country, &lnr)))
|
while (!(err = read_list (key, mycountry, &lnr)))
|
||||||
{
|
{
|
||||||
if (!strcmp (key, fpr))
|
if (!strcmp (key, fpr))
|
||||||
break;
|
break;
|
||||||
@ -170,6 +175,9 @@ gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert)
|
|||||||
if (gpg_err_code (err) == GPG_ERR_EOF)
|
if (gpg_err_code (err) == GPG_ERR_EOF)
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
|
||||||
|
if (!err && country)
|
||||||
|
strcpy (country, mycountry);
|
||||||
|
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user