summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-03-14 22:57:55 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-03-14 22:57:55 +0100
commit897cbce62c0263a498088ac3e465aa5f05f8719c (patch)
treea4ef11e2a99a1a18f8a700ffded7528bc28b5d08
parente9724276a47562bac049b1c98d3c9e31f639dd41 (diff)
downloadgnutls-897cbce62c0263a498088ac3e465aa5f05f8719c.tar.gz
Extended time verification to trusted certificate list as well. Introduced
the flag GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS that will prevent the trusted certificate list verification.
-rw-r--r--NEWS3
-rw-r--r--lib/includes/gnutls/x509.h5
-rw-r--r--lib/x509/verify.c83
3 files changed, 70 insertions, 21 deletions
diff --git a/NEWS b/NEWS
index b81277aeb8..c214963fa7 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,9 @@ See the end for copying conditions.
* Version 2.9.10 (unreleased)
+** libgnutls: Time verification extended to trusted certificate list,
+unless GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS flag is specified.
+
** libgnutls: Added Steve Dispensa's patch for safe renegotiation (RFC 5746)
Solves the issue discussed in:
<http://www.ietf.org/mail-archive/web/tls/current/msg03928.html> and
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 0645e9b1d7..6ea5f5d6ab 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -500,6 +500,8 @@ extern "C"
* @GNUTLS_VERIFY_DISABLE_CA_SIGN: If set a signer does not have to be
* a certificate authority. This flag should normaly be disabled,
* unless you know what this means.
+ * @GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS: If set a signer in the trusted
+ * list is never checked for expiration or activation.
* @GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT: Allow only trusted CA
* certificates that have version 1. This is safer than
* %GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT, and should be used
@@ -531,7 +533,8 @@ extern "C"
GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT = 8,
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 = 16,
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32,
- GNUTLS_VERIFY_DISABLE_TIME_CHECKS = 64
+ GNUTLS_VERIFY_DISABLE_TIME_CHECKS = 64,
+ GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS = 128,
} gnutls_certificate_verify_flags;
int gnutls_x509_crt_check_issuer (gnutls_x509_crt_t cert,
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index a464596ac6..5bb20bc95c 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -42,7 +42,7 @@
static int _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
const gnutls_x509_crt_t * trusted_cas,
int tcas_size, unsigned int flags,
- unsigned int *output);
+ unsigned int *output, gnutls_x509_crt_t* issuer);
static int is_crl_issuer (gnutls_x509_crl_t crl,
gnutls_x509_crt_t issuer_cert);
@@ -261,17 +261,17 @@ find_issuer (gnutls_x509_crt_t cert,
* 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
*
* Output will hold some extra information about the verification
- * procedure.
+ * procedure. Issuer will hold the actual issuer from the trusted list.
*/
static int
_gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
const gnutls_x509_crt_t * trusted_cas,
int tcas_size, unsigned int flags,
- unsigned int *output)
+ unsigned int *output, gnutls_x509_crt_t *_issuer)
{
gnutls_datum_t cert_signed_data = { NULL, 0 };
gnutls_datum_t cert_signature = { NULL, 0 };
- gnutls_x509_crt_t issuer;
+ gnutls_x509_crt_t issuer = NULL;
int ret, issuer_version, result;
if (output)
@@ -298,6 +298,8 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
return 0;
}
+ if (_issuer != NULL) *_issuer = issuer;
+
issuer_version = gnutls_x509_crt_get_version (issuer);
if (issuer_version < 0)
{
@@ -399,6 +401,29 @@ gnutls_x509_crt_check_issuer (gnutls_x509_crt_t cert,
return is_issuer (cert, issuer);
}
+static unsigned int check_time(gnutls_x509_crt_t crt, time_t now)
+{
+int status = 0;
+time_t t;
+
+ t = gnutls_x509_crt_get_activation_time (crt);
+ if (t == (time_t) - 1 || now < t)
+ {
+ status |= GNUTLS_CERT_NOT_ACTIVATED;
+ status |= GNUTLS_CERT_INVALID;
+ return status;
+ }
+
+ t = gnutls_x509_crt_get_expiration_time (crt);
+ if (t == (time_t) - 1 || now > t)
+ {
+ status |= GNUTLS_CERT_EXPIRED;
+ status |= GNUTLS_CERT_INVALID;
+ return status;
+ }
+
+ return 0;
+}
/* Verify X.509 certificate chain.
*
@@ -417,6 +442,8 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
{
int i = 0, ret;
unsigned int status = 0, output;
+ time_t now = time (0);
+ gnutls_x509_crt_t issuer = NULL;
if (clist_size > 1)
{
@@ -452,6 +479,17 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
if (check_if_same_cert (certificate_list[i],
trusted_cas[j]) == 0)
{
+ /* explicity time check for trusted CA that we remove from
+ * list. GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS
+ */
+ if (!(flags&GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS) && !(flags&GNUTLS_VERIFY_DISABLE_TIME_CHECKS))
+ {
+ status |= check_time(trusted_cas[j], now);
+ if (status != 0)
+ {
+ return status;
+ }
+ }
clist_size = i;
break;
}
@@ -472,7 +510,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
* in self signed etc certificates.
*/
ret = _gnutls_verify_certificate2 (certificate_list[clist_size - 1],
- trusted_cas, tcas_size, flags, &output);
+ trusted_cas, tcas_size, flags, &output, &issuer);
if (ret == 0)
{
/* if the last certificate in the certificate
@@ -501,27 +539,32 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
}
#endif
+
/* Check activation/expiration times
*/
if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS))
{
- time_t t, now = time (0);
+ /* check the time of the issuer first */
+ if (!(flags&GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS))
+ {
+ if (issuer == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ status |= check_time(issuer, now);
+ if (status != 0)
+ {
+ return status;
+ }
+ }
for (i = 0; i < clist_size; i++)
{
- t = gnutls_x509_crt_get_activation_time (certificate_list[i]);
- if (t == (time_t) - 1 || now < t)
- {
- status |= GNUTLS_CERT_NOT_ACTIVATED;
- status |= GNUTLS_CERT_INVALID;
- return status;
- }
-
- t = gnutls_x509_crt_get_expiration_time (certificate_list[i]);
- if (t == (time_t) - 1 || now > t)
+ status |= check_time(certificate_list[i], now);
+ if (status != 0)
{
- status |= GNUTLS_CERT_EXPIRED;
- status |= GNUTLS_CERT_INVALID;
return status;
}
}
@@ -542,7 +585,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
if ((ret =
_gnutls_verify_certificate2 (certificate_list[i - 1],
&certificate_list[i], 1, flags,
- NULL)) == 0)
+ NULL, NULL)) == 0)
{
status |= GNUTLS_CERT_INVALID;
return status;
@@ -1009,7 +1052,7 @@ gnutls_x509_crt_verify (gnutls_x509_crt_t cert,
*/
ret =
_gnutls_verify_certificate2 (cert, CA_list, CA_list_length, flags,
- verify);
+ verify, NULL);
if (ret < 0)
{
gnutls_assert ();