summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-06-22 14:52:37 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-06-22 14:52:37 +0000
commitea5da3f8fd0b439a847f9dca9376d0ebc94fbb38 (patch)
tree350311b44136139d56e9365f87383c24a86e8903
parentf2ea2f1c95bc0fafdc51ac818cc0dd9546607cf2 (diff)
downloadgnutls-ea5da3f8fd0b439a847f9dca9376d0ebc94fbb38.tar.gz
The TLS handshake no longer fails if the X.509 extensions in the Certificate are critical and unsupported. The unsupported critical extensions are now only catched by the verification functions.
-rw-r--r--lib/auth_cert.c4
-rw-r--r--lib/auth_dhe.c2
-rw-r--r--lib/auth_rsa.c2
-rw-r--r--lib/gnutls_cert.h3
-rw-r--r--lib/gnutls_record.c5
-rw-r--r--lib/gnutls_str.h5
-rw-r--r--lib/gnutls_x509.c27
-rw-r--r--lib/gnutls_x509.h2
-rw-r--r--lib/x509_extensions.c16
-rw-r--r--lib/x509_extensions.h2
-rw-r--r--lib/x509_sig_check.c4
11 files changed, 44 insertions, 28 deletions
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index c5477373c9..d3597d9d7e 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -750,7 +750,7 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data,
if ((ret =
_gnutls_x509_cert2gnutls_cert(&peer_certificate_list
- [j], tmp)) < 0) {
+ [j], tmp, 1)) < 0) {
gnutls_assert();
CLEAR_CERTS;
gnutls_afree(peer_certificate_list);
@@ -1153,7 +1153,7 @@ int _gnutls_proc_cert_client_cert_vrfy(GNUTLS_STATE state, opaque * data,
ret =
_gnutls_x509_cert2gnutls_cert(&peer_cert,
info->
- raw_certificate_list[0]);
+ raw_certificate_list[0], 1);
break;
case GNUTLS_CRT_OPENPGP:
if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) {
diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c
index 4367e8df14..9d2df316ba 100644
--- a/lib/auth_dhe.c
+++ b/lib/auth_dhe.c
@@ -389,7 +389,7 @@ static int proc_dhe_server_kx(GNUTLS_STATE state, opaque * data,
case GNUTLS_CRT_X509:
if ((ret =
_gnutls_x509_cert2gnutls_cert( &peer_cert,
- info->raw_certificate_list[0])) < 0) {
+ info->raw_certificate_list[0], 1)) < 0) {
gnutls_assert();
return ret;
}
diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c
index 6b62f370bd..9fd20d819c 100644
--- a/lib/auth_rsa.c
+++ b/lib/auth_rsa.c
@@ -81,7 +81,7 @@ int i;
case GNUTLS_CRT_X509:
if ((ret =
_gnutls_x509_cert2gnutls_cert( &peer_cert,
- info->raw_certificate_list[0])) < 0) {
+ info->raw_certificate_list[0], 1)) < 0) {
gnutls_assert();
return ret;
}
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index 33e2a933c1..c86943d42f 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -47,9 +47,6 @@ typedef struct gnutls_cert {
uint16 keyUsage; /* bits from X509KEY_*
*/
- int valid; /* 0 if the certificate looks good.
- */
-
int CA; /* 0 if the certificate does not belong to
* a certificate authority. 1 otherwise.
*/
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index df657e2e56..e31119bb0a 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -146,7 +146,10 @@ int gnutls_bye( GNUTLS_STATE state, GNUTLS_CloseRequest how)
if (ret2 < 0)
return ret2;
-
+ break;
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
STATE = STATE0;
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index bc8f1252ed..8855180b1d 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -15,7 +15,12 @@ typedef struct {
void _gnutls_string_init( gnutls_string*, ALLOC_FUNC, REALLOC_FUNC, FREE_FUNC);
void _gnutls_string_clear( gnutls_string*);
+
+/* Beware, do not clear the string, after calling this
+ * function
+ */
gnutls_datum _gnutls_string2datum( gnutls_string* str);
+
int _gnutls_string_copy_str( gnutls_string* dest, const char* src);
int _gnutls_string_append_str( gnutls_string*, const char* str);
int _gnutls_string_append_data( gnutls_string*, const void* data, size_t data_size);
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index a2e63da7f4..3c395a178b 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -864,7 +864,7 @@ int _gnutls_x509_cert_verify_peers(GNUTLS_STATE state)
if ((ret =
_gnutls_x509_cert2gnutls_cert(&peer_certificate_list[i],
info->
- raw_certificate_list[i])) <
+ raw_certificate_list[i], 0)) <
0) {
gnutls_assert();
CLEAR_CERTS;
@@ -968,7 +968,7 @@ int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list
for (i = 0; i < peer_certificate_list_size; i++) {
if ((ret =
_gnutls_x509_cert2gnutls_cert(&peer_certificate_list[i],
- cert_list[i])) < 0) {
+ cert_list[i], 0)) < 0) {
gnutls_assert();
CLEAR_CERTS_CA;
gnutls_free( peer_certificate_list);
@@ -982,7 +982,7 @@ int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list
for (i = 0; i < ca_certificate_list_size; i++) {
if ((ret =
_gnutls_x509_cert2gnutls_cert(&ca_certificate_list[i],
- CA_list[i])) < 0) {
+ CA_list[i], 0)) < 0) {
gnutls_assert();
CLEAR_CERTS_CA;
gnutls_free( peer_certificate_list);
@@ -1107,7 +1107,7 @@ static int parse_der_cert_mem( gnutls_cert** cert_list, int* ncerts,
if ((ret =
_gnutls_x509_cert2gnutls_cert(
&cert_list[0][i - 1],
- tmp)) < 0) {
+ tmp, 0)) < 0) {
gnutls_assert();
return ret;
}
@@ -1179,7 +1179,7 @@ static int parse_pkcs7_cert_mem( gnutls_cert** cert_list, int* ncerts,
if ((ret =
_gnutls_x509_cert2gnutls_cert(
&cert_list[0][i - 1],
- tmp2)) < 0) {
+ tmp2, 0)) < 0) {
gnutls_assert();
return ret;
}
@@ -1252,7 +1252,7 @@ static int parse_pem_cert_mem( gnutls_cert** cert_list, int* ncerts,
if ((ret =
_gnutls_x509_cert2gnutls_cert(
&cert_list[0][i - 1],
- tmp)) < 0) {
+ tmp, 0)) < 0) {
gnutls_free(b64);
gnutls_assert();
return ret;
@@ -1969,8 +1969,13 @@ int len, result;
* (structure) that gnutls can understand and use. Actually the
* important thing on this function is that it extracts the
* certificate's (public key) parameters.
+ *
+ * The noext flag is used to complete the handshake even if the
+ * extensions found in the certificate are unsupported and critical.
+ * The critical extensions will be catched by the verification functions.
*/
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
+int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert,
+ int no_critical_ext /* if non zero do not parse X.509 extensions */)
{
int result;
ASN1_TYPE c2;
@@ -1980,7 +1985,6 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
memset(gCert, 0, sizeof(gnutls_cert));
- gCert->valid = 1;
gCert->cert_type = GNUTLS_CRT_X509;
if (gnutls_set_datum(&gCert->raw, derCert.data, derCert.size) < 0) {
@@ -2069,7 +2073,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
if ((result =
_gnutls_get_ext_type(c2,
"certificate2.tbsCertificate.extensions",
- gCert)) < 0) {
+ gCert, no_critical_ext)) < 0) {
gnutls_assert();
asn1_delete_structure(&c2);
gnutls_free_datum( &gCert->raw);
@@ -2078,11 +2082,6 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
asn1_delete_structure(&c2);
-
- gCert->valid = 0; /* if we got until here
- * the certificate is valid.
- */
-
return 0;
}
diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h
index 69e149846d..105bae09ce 100644
--- a/lib/gnutls_x509.h
+++ b/lib/gnutls_x509.h
@@ -1,7 +1,7 @@
#include <libtasn1.h>
int _gnutls_x509_cert_verify_peers(GNUTLS_STATE state);
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert);
+int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert, int noext);
#define MAX_INT_DIGITS 4
void _gnutls_int2str(unsigned int k, char *data);
diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c
index 181c352739..2c38827551 100644
--- a/lib/x509_extensions.c
+++ b/lib/x509_extensions.c
@@ -114,9 +114,13 @@ static int _extract_basicConstraints(int *CA, opaque * extnValue,
}
+/*
+ * If no_critical_ext is non zero, then unsupported critical extensions
+ * do not lead into a fatal error.
+ */
static int _parse_extension(gnutls_cert * cert, char *extnID,
char *critical, char *extnValue,
- int extnValueLen)
+ int extnValueLen, int no_critical_ext)
{
if (strcmp(extnID, "2 5 29 14") == 0) { /* subject Key ID */
@@ -139,7 +143,7 @@ static int _parse_extension(gnutls_cert * cert, char *extnID,
_gnutls_x509_log("X509_EXT: CERT[%s]: Unsupported Extension: %s, %s\n",
GET_CN(cert->raw), extnID, critical);
- if (strcmp(critical, "TRUE") == 0) {
+ if (strcmp(critical, "TRUE") == 0 && no_critical_ext == 0) {
gnutls_assert();
return GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION;
}
@@ -149,8 +153,12 @@ static int _parse_extension(gnutls_cert * cert, char *extnID,
/* This function will attempt to parse Extensions in
* an X509v3 certificate
+ *
+ * If no_critical_ext is non zero, then unsupported critical extensions
+ * do not lead into a fatal error.
*/
-int _gnutls_get_ext_type(ASN1_TYPE rasn, char *root, gnutls_cert * cert)
+int _gnutls_get_ext_type(ASN1_TYPE rasn, char *root, gnutls_cert * cert,
+ int no_critical_ext)
{
int k, result, len;
char name[128], name2[128], counter[MAX_INT_DIGITS];
@@ -235,7 +243,7 @@ int _gnutls_get_ext_type(ASN1_TYPE rasn, char *root, gnutls_cert * cert)
/* Handle Extension */
if ((result =
_parse_extension(cert, extnID, critical,
- extnValue, len)) < 0) {
+ extnValue, len, no_critical_ext)) < 0) {
gnutls_assert();
return result;
}
diff --git a/lib/x509_extensions.h b/lib/x509_extensions.h
index ddcb0e72d8..755f942cbb 100644
--- a/lib/x509_extensions.h
+++ b/lib/x509_extensions.h
@@ -1,2 +1,2 @@
-int _gnutls_get_ext_type( ASN1_TYPE rasn, char *root, gnutls_cert *cert);
+int _gnutls_get_ext_type( ASN1_TYPE rasn, char *root, gnutls_cert *cert, int no_critical_ext);
int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, gnutls_datum* ret);
diff --git a/lib/x509_sig_check.c b/lib/x509_sig_check.c
index 89e5f633ae..3987e7684a 100644
--- a/lib/x509_sig_check.c
+++ b/lib/x509_sig_check.c
@@ -225,6 +225,10 @@ gnutls_datum tbs;
gnutls_free_datum(&tbs);
return 0;
break;
+ default:
+ gnutls_assert();
+ gnutls_free_datum(&tbs);
+ return GNUTLS_E_INTERNAL_ERROR;
}