mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
* certpath.c (unknown_criticals): New.
(allowed_ca): New. (gpgsm_validate_path): Check validity, CA attribute, path length and unknown critical extensions.
This commit is contained in:
parent
1146232890
commit
4f39f92eff
@ -77,6 +77,10 @@ enum {
|
|||||||
GNUPG_Line_Too_Long = 48,
|
GNUPG_Line_Too_Long = 48,
|
||||||
GNUPG_Not_Trusted = 49,
|
GNUPG_Not_Trusted = 49,
|
||||||
GNUPG_Canceled = 50,
|
GNUPG_Canceled = 50,
|
||||||
|
GNUPG_Bad_CA_Certificate = 51,
|
||||||
|
GNUPG_Certificate_Expired = 52,
|
||||||
|
GNUPG_Certificate_Too_Young = 53,
|
||||||
|
GNUPG_Unsupported_Certificate = 54,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Status codes - fixme: should go into another file */
|
/* Status codes - fixme: should go into another file */
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2002-01-22 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* certpath.c (unknown_criticals): New.
|
||||||
|
(allowed_ca): New.
|
||||||
|
(gpgsm_validate_path): Check validity, CA attribute, path length
|
||||||
|
and unknown critical extensions.
|
||||||
|
|
||||||
2002-01-21 Werner Koch <wk@gnupg.org>
|
2002-01-21 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* gpgsm.c: Add option --enable-crl-checks.
|
* gpgsm.c: Add option --enable-crl-checks.
|
||||||
|
121
sm/certchain.c
121
sm/certchain.c
@ -34,14 +34,64 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
unknown_criticals (KsbaCert cert)
|
||||||
|
{
|
||||||
|
static const char *known[] = {
|
||||||
|
"2.5.29.19", /* basic Constraints */
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int rc = 0, i, idx, crit;
|
||||||
|
const char *oid;
|
||||||
|
KsbaError err;
|
||||||
|
|
||||||
|
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
|
||||||
|
&oid, &crit, NULL, NULL));idx++)
|
||||||
|
{
|
||||||
|
if (!crit)
|
||||||
|
continue;
|
||||||
|
for (i=0; known[i] && strcmp (known[i],oid); i++)
|
||||||
|
;
|
||||||
|
if (!known[i])
|
||||||
|
{
|
||||||
|
log_error (_("critical certificate extension %s is not supported\n"),
|
||||||
|
oid);
|
||||||
|
rc = GNUPG_Unsupported_Certificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err && err != -1)
|
||||||
|
rc = map_ksba_err (err);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
allowed_ca (KsbaCert cert, int *pathlen)
|
||||||
|
{
|
||||||
|
KsbaError err;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
err = ksba_cert_is_ca (cert, &flag, pathlen);
|
||||||
|
if (err)
|
||||||
|
return map_ksba_err (err);
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
log_error (_("issuer certificate is not marked as a CA\n"));
|
||||||
|
return GNUPG_Bad_CA_Certificate;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gpgsm_validate_path (KsbaCert cert)
|
gpgsm_validate_path (KsbaCert cert)
|
||||||
{
|
{
|
||||||
int rc = 0, depth = 0;
|
int rc = 0, depth = 0, maxdepth;
|
||||||
char *issuer = NULL;
|
char *issuer = NULL;
|
||||||
char *subject = NULL;
|
char *subject = NULL;
|
||||||
KEYDB_HANDLE kh = keydb_new (0);
|
KEYDB_HANDLE kh = keydb_new (0);
|
||||||
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
||||||
|
time_t current_time = time (NULL);
|
||||||
|
|
||||||
if (!kh)
|
if (!kh)
|
||||||
{
|
{
|
||||||
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
gpgsm_dump_cert ("subject", cert);
|
gpgsm_dump_cert ("subject", cert);
|
||||||
|
|
||||||
subject_cert = cert;
|
subject_cert = cert;
|
||||||
|
maxdepth = 50;
|
||||||
/* FIXME: We need to check that none of the certs didexpire */
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
|
|
||||||
if (!issuer)
|
if (!issuer)
|
||||||
{
|
{
|
||||||
if (DBG_X509)
|
log_error ("no issuer found in certificate\n");
|
||||||
log_debug ("ERROR: issuer missing\n");
|
|
||||||
rc = GNUPG_Bad_Certificate;
|
rc = GNUPG_Bad_Certificate;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time_t not_before, not_after;
|
||||||
|
|
||||||
|
not_before = ksba_cert_get_validity (subject_cert, 0);
|
||||||
|
not_after = ksba_cert_get_validity (subject_cert, 1);
|
||||||
|
if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
|
||||||
|
{
|
||||||
|
log_error ("certificate with invalid validity\n");
|
||||||
|
rc = GNUPG_Bad_Certificate;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_time < not_before)
|
||||||
|
{
|
||||||
|
log_error ("certificate to young; valid from ");
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_printf ("\n");
|
||||||
|
rc = GNUPG_Certificate_Too_Young;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (current_time > not_after)
|
||||||
|
{
|
||||||
|
log_error ("certificate has expired at ");
|
||||||
|
gpgsm_dump_time (not_after);
|
||||||
|
log_printf ("\n");
|
||||||
|
rc = GNUPG_Certificate_Expired;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = unknown_criticals (subject_cert);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
if (!opt.no_crl_check)
|
if (!opt.no_crl_check)
|
||||||
{
|
{
|
||||||
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
||||||
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
rc = allowed_ca (subject_cert, NULL);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
rc = gpgsm_agent_istrusted (subject_cert);
|
rc = gpgsm_agent_istrusted (subject_cert);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
;
|
;
|
||||||
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
/* fixme: print a note while we have not yet the code to
|
/* fixme: print a note while we have not yet the code to
|
||||||
ask whether the cert should be netered into the trust
|
ask whether the cert should be entered into the trust
|
||||||
list */
|
list */
|
||||||
gpgsm_dump_cert ("issuer", subject_cert);
|
gpgsm_dump_cert ("issuer", subject_cert);
|
||||||
log_info ("after checking the fingerprint, you may want "
|
log_info ("after checking the fingerprint, you may want "
|
||||||
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
depth++;
|
depth++;
|
||||||
/* fixme: check against a maximum path length */
|
if (depth > maxdepth)
|
||||||
|
{
|
||||||
|
log_error (_("certificate path too long\n"));
|
||||||
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* find the next cert up the tree */
|
/* find the next cert up the tree */
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
rc = GNUPG_Bad_Certificate_Path;
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (opt.verbose)
|
|
||||||
|
{
|
||||||
|
int pathlen;
|
||||||
|
rc = allowed_ca (issuer_cert, &pathlen);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
if (pathlen >= 0 && (depth - 1) > pathlen)
|
||||||
|
{
|
||||||
|
log_error (_("certificate path longer than allowed by CA (%d)\n"),
|
||||||
|
pathlen);
|
||||||
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log_info ("certificate is good\n");
|
log_info ("certificate is good\n");
|
||||||
|
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
|
121
sm/certpath.c
121
sm/certpath.c
@ -34,14 +34,64 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
unknown_criticals (KsbaCert cert)
|
||||||
|
{
|
||||||
|
static const char *known[] = {
|
||||||
|
"2.5.29.19", /* basic Constraints */
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int rc = 0, i, idx, crit;
|
||||||
|
const char *oid;
|
||||||
|
KsbaError err;
|
||||||
|
|
||||||
|
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
|
||||||
|
&oid, &crit, NULL, NULL));idx++)
|
||||||
|
{
|
||||||
|
if (!crit)
|
||||||
|
continue;
|
||||||
|
for (i=0; known[i] && strcmp (known[i],oid); i++)
|
||||||
|
;
|
||||||
|
if (!known[i])
|
||||||
|
{
|
||||||
|
log_error (_("critical certificate extension %s is not supported\n"),
|
||||||
|
oid);
|
||||||
|
rc = GNUPG_Unsupported_Certificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err && err != -1)
|
||||||
|
rc = map_ksba_err (err);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
allowed_ca (KsbaCert cert, int *pathlen)
|
||||||
|
{
|
||||||
|
KsbaError err;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
err = ksba_cert_is_ca (cert, &flag, pathlen);
|
||||||
|
if (err)
|
||||||
|
return map_ksba_err (err);
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
log_error (_("issuer certificate is not marked as a CA\n"));
|
||||||
|
return GNUPG_Bad_CA_Certificate;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gpgsm_validate_path (KsbaCert cert)
|
gpgsm_validate_path (KsbaCert cert)
|
||||||
{
|
{
|
||||||
int rc = 0, depth = 0;
|
int rc = 0, depth = 0, maxdepth;
|
||||||
char *issuer = NULL;
|
char *issuer = NULL;
|
||||||
char *subject = NULL;
|
char *subject = NULL;
|
||||||
KEYDB_HANDLE kh = keydb_new (0);
|
KEYDB_HANDLE kh = keydb_new (0);
|
||||||
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
KsbaCert subject_cert = NULL, issuer_cert = NULL;
|
||||||
|
time_t current_time = time (NULL);
|
||||||
|
|
||||||
if (!kh)
|
if (!kh)
|
||||||
{
|
{
|
||||||
@ -54,8 +104,7 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
gpgsm_dump_cert ("subject", cert);
|
gpgsm_dump_cert ("subject", cert);
|
||||||
|
|
||||||
subject_cert = cert;
|
subject_cert = cert;
|
||||||
|
maxdepth = 50;
|
||||||
/* FIXME: We need to check that none of the certs didexpire */
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -66,12 +115,45 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
|
|
||||||
if (!issuer)
|
if (!issuer)
|
||||||
{
|
{
|
||||||
if (DBG_X509)
|
log_error ("no issuer found in certificate\n");
|
||||||
log_debug ("ERROR: issuer missing\n");
|
|
||||||
rc = GNUPG_Bad_Certificate;
|
rc = GNUPG_Bad_Certificate;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time_t not_before, not_after;
|
||||||
|
|
||||||
|
not_before = ksba_cert_get_validity (subject_cert, 0);
|
||||||
|
not_after = ksba_cert_get_validity (subject_cert, 1);
|
||||||
|
if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
|
||||||
|
{
|
||||||
|
log_error ("certificate with invalid validity\n");
|
||||||
|
rc = GNUPG_Bad_Certificate;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_time < not_before)
|
||||||
|
{
|
||||||
|
log_error ("certificate to young; valid from ");
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_printf ("\n");
|
||||||
|
rc = GNUPG_Certificate_Too_Young;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (current_time > not_after)
|
||||||
|
{
|
||||||
|
log_error ("certificate has expired at ");
|
||||||
|
gpgsm_dump_time (not_after);
|
||||||
|
log_printf ("\n");
|
||||||
|
rc = GNUPG_Certificate_Expired;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = unknown_criticals (subject_cert);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
if (!opt.no_crl_check)
|
if (!opt.no_crl_check)
|
||||||
{
|
{
|
||||||
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
rc = gpgsm_dirmngr_isvalid (subject_cert);
|
||||||
@ -107,6 +189,10 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
rc = depth? GNUPG_Bad_Certificate_Path : GNUPG_Bad_Certificate;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
rc = allowed_ca (subject_cert, NULL);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
rc = gpgsm_agent_istrusted (subject_cert);
|
rc = gpgsm_agent_istrusted (subject_cert);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
;
|
;
|
||||||
@ -118,7 +204,7 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
/* fixme: print a note while we have not yet the code to
|
/* fixme: print a note while we have not yet the code to
|
||||||
ask whether the cert should be netered into the trust
|
ask whether the cert should be entered into the trust
|
||||||
list */
|
list */
|
||||||
gpgsm_dump_cert ("issuer", subject_cert);
|
gpgsm_dump_cert ("issuer", subject_cert);
|
||||||
log_info ("after checking the fingerprint, you may want "
|
log_info ("after checking the fingerprint, you may want "
|
||||||
@ -134,7 +220,12 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
depth++;
|
depth++;
|
||||||
/* fixme: check against a maximum path length */
|
if (depth > maxdepth)
|
||||||
|
{
|
||||||
|
log_error (_("certificate path too long\n"));
|
||||||
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* find the next cert up the tree */
|
/* find the next cert up the tree */
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
@ -167,7 +258,21 @@ gpgsm_validate_path (KsbaCert cert)
|
|||||||
rc = GNUPG_Bad_Certificate_Path;
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (opt.verbose)
|
|
||||||
|
{
|
||||||
|
int pathlen;
|
||||||
|
rc = allowed_ca (issuer_cert, &pathlen);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
if (pathlen >= 0 && (depth - 1) > pathlen)
|
||||||
|
{
|
||||||
|
log_error (_("certificate path longer than allowed by CA (%d)\n"),
|
||||||
|
pathlen);
|
||||||
|
rc = GNUPG_Bad_Certificate_Path;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log_info ("certificate is good\n");
|
log_info ("certificate is good\n");
|
||||||
|
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user