diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2004-04-03 11:16:40 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2004-04-03 11:16:40 +0000 |
commit | 73832ea02923f5b00ac71a8f0febd90c76daef3d (patch) | |
tree | 1ec959119e00a31a4f9458e89d3de29336ba90ec | |
parent | 77b159387bc8e6ee9e62d92a712110a2acca3e44 (diff) | |
download | gnutls-73832ea02923f5b00ac71a8f0febd90c76daef3d.tar.gz |
- Corrected bug in SSL 3.0 authentication.
(backported changes from the development branch)
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | lib/auth_cert.c | 44 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 43 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 2 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 41 | ||||
-rw-r--r-- | lib/gnutls_extensions.h | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 66 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 20 |
8 files changed, 106 insertions, 113 deletions
@@ -1,6 +1,7 @@ Version 1.0.10 - Corrected bug in RSA parameters handling which could cause unexpected crashes. +- Corrected bug in SSL 3.0 authentication. Version 1.0.9 (29/03/2004) - Added gnutls_certificate_set_params_function() and diff --git a/lib/auth_cert.c b/lib/auth_cert.c index f35bfaeeef..8b6392d125 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -122,6 +122,48 @@ static int _gnutls_check_pk_algo_in_list(const gnutls_pk_algorithm *pk_algos, return -1; } +/* Returns the issuer's Distinguished name in odn, of the certificate + * specified in cert. + */ +static int _gnutls_cert_get_issuer_dn(gnutls_cert * cert, gnutls_datum * odn ) +{ + ASN1_TYPE dn; + int len, result; + int start, end; + + if ((result=asn1_create_element + (_gnutls_get_pkix(), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = asn1_der_decoding(&dn, cert->raw.data, cert->raw.size, NULL); + if (result != ASN1_SUCCESS) { + /* couldn't decode DER */ + gnutls_assert(); + asn1_delete_structure(&dn); + return _gnutls_asn2err(result); + } + + result = asn1_der_decoding_startEnd(dn, cert->raw.data, cert->raw.size, + "tbsCertificate.issuer", &start, + &end); + + if (result != ASN1_SUCCESS) { + /* couldn't decode DER */ + gnutls_assert(); + asn1_delete_structure(&dn); + return _gnutls_asn2err(result); + } + asn1_delete_structure(&dn); + + len = end - start + 1; + + odn->size = len; + odn->data = &cert->raw.data[start]; + + return 0; +} /* Locates the most appropriate x509 certificate using the @@ -151,7 +193,7 @@ static int _find_x509_cert(const gnutls_certificate_credentials cred, for (i = 0; i < cred->ncerts; i++) { for (j = 0; j < cred->cert_list_length[i]; j++) { if ((result = - _gnutls_cert_get_dn(&cred-> + _gnutls_cert_get_issuer_dn(&cred-> cert_list[i][j], &odn)) < 0) { gnutls_assert(); diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 67d1520da2..4fcc0312d2 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -775,46 +775,3 @@ void _gnutls_gcert_deinit(gnutls_cert *cert) _gnutls_free_datum(&cert->raw); } - -/* Returns the issuer's Distinguished name in odn, of the certificate - * specified in cert. - */ -int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn ) -{ - ASN1_TYPE dn; - int len, result; - int start, end; - - if ((result=asn1_create_element - (_gnutls_get_pkix(), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS) { - gnutls_assert(); - return _gnutls_asn2err(result); - } - - result = asn1_der_decoding(&dn, cert->raw.data, cert->raw.size, NULL); - if (result != ASN1_SUCCESS) { - /* couldn't decode DER */ - gnutls_assert(); - asn1_delete_structure(&dn); - return _gnutls_asn2err(result); - } - - result = asn1_der_decoding_startEnd(dn, cert->raw.data, cert->raw.size, - "tbsCertificate.issuer", &start, - &end); - - if (result != ASN1_SUCCESS) { - /* couldn't decode DER */ - gnutls_assert(); - asn1_delete_structure(&dn); - return _gnutls_asn2err(result); - } - asn1_delete_structure(&dn); - - len = end - start + 1; - - odn->size = len; - odn->data = &cert->raw.data[start]; - - return 0; -} diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index c1384f17b3..803eca5033 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -86,8 +86,6 @@ int _gnutls_x509_raw_cert_to_gcert(gnutls_cert * gcert, const gnutls_datum *derC int _gnutls_x509_crt_to_gcert(gnutls_cert * gcert, gnutls_x509_crt cert, unsigned int flags); -int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn); - void _gnutls_gkey_deinit(gnutls_privkey *key); void _gnutls_gcert_deinit(gnutls_cert *cert); diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index d13e89cd86..515ecb7032 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -174,20 +174,29 @@ static void _gnutls_extension_list_add( gnutls_session session, uint16 type) { } } -int _gnutls_gen_extensions( gnutls_session session, opaque** data) { +int _gnutls_gen_extensions( gnutls_session session, opaque* data, size_t data_size) +{ int next, size; uint16 pos=0; -opaque sdata[1024]; -int sdata_size = sizeof(sdata); +opaque *sdata; +int sdata_size; ext_send_func ext_send; - (*data) = gnutls_malloc(2); /* allocate size for size */ - if ((*data)==NULL) { + if (data_size < 2) { gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; + return GNUTLS_E_INTERNAL_ERROR; } + /* allocate enough data for each extension. + */ + sdata_size = data_size; + sdata = gnutls_malloc( sdata_size); + if (sdata == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + pos+=2; next = MAX_EXT_TYPES; /* maximum supported extensions */ do { @@ -196,21 +205,21 @@ ext_send_func ext_send; if (ext_send == NULL) continue; size = ext_send( session, sdata, sdata_size); if (size > 0) { - (*data) = gnutls_realloc_fast( (*data), pos+size+4); - if ((*data)==NULL) { + if (data_size < pos+(size_t)size+4) { gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; + gnutls_free(sdata); + return GNUTLS_E_INTERNAL_ERROR; } /* write extension type */ - _gnutls_write_uint16( next, &(*data)[pos]); + _gnutls_write_uint16( next, &data[pos]); pos+=2; /* write size */ - _gnutls_write_uint16( size, &(*data)[pos]); + _gnutls_write_uint16( size, &data[pos]); pos+=2; - memcpy( &(*data)[pos], sdata, size); + memcpy( &data[pos], sdata, size); pos+=size; /* add this extension to the extension list @@ -221,7 +230,7 @@ ext_send_func ext_send; _gnutls_extension_get_name(next)); } else if (size < 0) { gnutls_assert(); - gnutls_free(*data); *data = NULL; + gnutls_free(sdata); return size; } @@ -230,13 +239,13 @@ ext_send_func ext_send; size = pos; pos-=2; /* remove the size of the size header! */ - _gnutls_write_uint16( pos, (*data)); + _gnutls_write_uint16( pos, data); if (size==2) { /* empty */ size = 0; - gnutls_free(*data); - (*data) = NULL; } + + gnutls_free( sdata); return size; } diff --git a/lib/gnutls_extensions.h b/lib/gnutls_extensions.h index 3ea42a7739..f87bc80cbd 100644 --- a/lib/gnutls_extensions.h +++ b/lib/gnutls_extensions.h @@ -22,7 +22,7 @@ const char *_gnutls_extension_get_name(uint16 type); int _gnutls_parse_extensions( gnutls_session, const opaque*, int); -int _gnutls_gen_extensions( gnutls_session session, opaque** data); +int _gnutls_gen_extensions( gnutls_session session, opaque* data, size_t data_size); typedef int (*ext_recv_func)( gnutls_session, const opaque*, size_t); /* recv data */ typedef int (*ext_send_func)( gnutls_session, opaque*, size_t); /* send data */ diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 937f1af337..74d90419ad 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1339,7 +1339,7 @@ static int _gnutls_read_server_hello(gnutls_session session, opaque *data, * Needed in client hello messages. Returns the new data length. */ static int _gnutls_copy_ciphersuites(gnutls_session session, - opaque ** ret_data) + opaque * ret_data, size_t ret_data_size) { int ret, i; GNUTLS_CipherSuite *cipher_suites; @@ -1381,21 +1381,18 @@ static int _gnutls_copy_ciphersuites(gnutls_session session, datalen += sizeof(uint16) + cipher_num; - *ret_data = gnutls_malloc(datalen); - if (*ret_data == NULL) { + if ((size_t)datalen > ret_data_size) { gnutls_assert(); - gnutls_free(cipher_suites); - return GNUTLS_E_MEMORY_ERROR; + return GNUTLS_E_INTERNAL_ERROR; } - - _gnutls_write_uint16(cipher_num, *ret_data); + + _gnutls_write_uint16(cipher_num, ret_data); pos += 2; for (i = 0; i < (cipher_num / 2); i++) { - memcpy( &(*ret_data)[pos], cipher_suites[i].CipherSuite, 2); + memcpy( &ret_data[pos], cipher_suites[i].CipherSuite, 2); pos += 2; } - gnutls_free(cipher_suites); return datalen; @@ -1406,7 +1403,7 @@ static int _gnutls_copy_ciphersuites(gnutls_session session, * Needed in hello messages. Returns the new data length. */ static int _gnutls_copy_comp_methods(gnutls_session session, - opaque ** ret_data) + opaque * ret_data, size_t ret_data_size) { int ret, i; uint8 *compression_methods, comp_num; @@ -1425,17 +1422,15 @@ static int _gnutls_copy_comp_methods(gnutls_session session, datalen = pos = 0; datalen += comp_num + 1; - *ret_data = gnutls_malloc(datalen); - if (*ret_data == NULL) { + if ((size_t)datalen > ret_data_size) { gnutls_assert(); - gnutls_free(compression_methods); - return GNUTLS_E_MEMORY_ERROR; + return GNUTLS_E_INTERNAL_ERROR; } - (*ret_data)[pos++] = comp_num; /* put the number of compression methods */ + ret_data[pos++] = comp_num; /* put the number of compression methods */ for (i = 0; i < comp_num; i++) { - (*ret_data)[pos++] = compression_methods[i]; + ret_data[pos++] = compression_methods[i]; } gnutls_free(compression_methods); @@ -1443,17 +1438,22 @@ static int _gnutls_copy_comp_methods(gnutls_session session, return datalen; } +/* This should be sufficient by now. It should hold all the extensions + * plus the headers in a hello message. + */ +#define MAX_EXT_DATA_LENGTH 1024 + /* This function sends the client hello handshake message. */ static int _gnutls_send_client_hello(gnutls_session session, int again) { opaque *data = NULL; - opaque *extdata = NULL; int extdatalen; int pos = 0; int datalen = 0, ret = 0; opaque random[TLS_RANDOM_SIZE]; gnutls_protocol_version hver; + opaque extdata[MAX_EXT_DATA_LENGTH]; opaque *SessionID = session->internals.resumed_security_parameters.session_id; @@ -1535,18 +1535,16 @@ static int _gnutls_send_client_hello(gnutls_session session, int again) /* Copy the ciphersuites. */ - extdatalen = _gnutls_copy_ciphersuites(session, &extdata); + extdatalen = _gnutls_copy_ciphersuites(session, extdata, sizeof(extdata)); if (extdatalen > 0) { datalen += extdatalen; data = gnutls_realloc_fast(data, datalen); if (data == NULL) { gnutls_assert(); - gnutls_free(extdata); return GNUTLS_E_MEMORY_ERROR; } memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); pos += extdatalen; } else { @@ -1560,18 +1558,16 @@ static int _gnutls_send_client_hello(gnutls_session session, int again) /* Copy the compression methods. */ - extdatalen = _gnutls_copy_comp_methods(session, &extdata); + extdatalen = _gnutls_copy_comp_methods(session, extdata, sizeof(extdata)); if (extdatalen > 0) { datalen += extdatalen; data = gnutls_realloc_fast(data, datalen); if (data == NULL) { gnutls_assert(); - gnutls_free(extdata); return GNUTLS_E_MEMORY_ERROR; } memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); pos += extdatalen; } else { @@ -1585,19 +1581,17 @@ static int _gnutls_send_client_hello(gnutls_session session, int again) /* Generate and copy TLS extensions. */ if (hver >= GNUTLS_TLS1) { - extdatalen = _gnutls_gen_extensions(session, &extdata); + extdatalen = _gnutls_gen_extensions(session, extdata, sizeof(extdata)); if (extdatalen > 0) { datalen += extdatalen; data = gnutls_realloc_fast(data, datalen); if (data == NULL) { gnutls_assert(); - gnutls_free(extdata); return GNUTLS_E_MEMORY_ERROR; } memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); } else if (extdatalen < 0) { gnutls_assert(); gnutls_free(data); @@ -1617,7 +1611,7 @@ static int _gnutls_send_client_hello(gnutls_session session, int again) static int _gnutls_send_server_hello(gnutls_session session, int again) { opaque *data = NULL; - opaque *extdata = NULL; + opaque extdata[MAX_EXT_DATA_LENGTH]; int extdatalen; int pos = 0; int datalen, ret = 0; @@ -1654,7 +1648,7 @@ static int _gnutls_send_server_hello(gnutls_session session, int again) if (again == 0) { datalen = 2 + session_id_len + 1 + TLS_RANDOM_SIZE + 3; - extdatalen = _gnutls_gen_extensions(session, &extdata); + extdatalen = _gnutls_gen_extensions(session, extdata, sizeof(extdata)); if (extdatalen < 0) { gnutls_assert(); @@ -1664,7 +1658,6 @@ static int _gnutls_send_server_hello(gnutls_session session, int again) data = gnutls_alloca(datalen + extdatalen); if (data == NULL) { gnutls_assert(); - gnutls_free(extdata); return GNUTLS_E_MEMORY_ERROR; } @@ -1705,7 +1698,6 @@ static int _gnutls_send_server_hello(gnutls_session session, int again) datalen += extdatalen; memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); } } @@ -1823,7 +1815,9 @@ int gnutls_rehandshake(gnutls_session session) return 0; } -static int _gnutls_abort_handshake( gnutls_session session, int ret) { +inline +static int _gnutls_abort_handshake( gnutls_session session, int ret) +{ if ( ((ret==GNUTLS_E_WARNING_ALERT_RECEIVED) && ( gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION)) || ret==GNUTLS_E_GOT_APPLICATION_DATA) @@ -1900,10 +1894,11 @@ int gnutls_handshake(gnutls_session session) } if (ret < 0) { /* In the case of a rehandshake abort - * we should reset the handshake's session + * we should reset the handshake's internal state. */ if (_gnutls_abort_handshake( session, ret) == 0) STATE = STATE0; + return ret; } @@ -1912,6 +1907,7 @@ int gnutls_handshake(gnutls_session session) if (ret < 0) { if (_gnutls_abort_handshake( session, ret) == 0) STATE = STATE0; + return ret; } @@ -2359,8 +2355,8 @@ inline static int check_server_params( gnutls_session session, gnutls_kx_algorit _gnutls_get_cred(session->key, cred_type, NULL); if (x509_cred != NULL) { - dh_params = x509_cred->dh_params; - rsa_params = x509_cred->rsa_params; + dh_params = _gnutls_certificate_get_dh_params(x509_cred, session); + rsa_params = _gnutls_certificate_get_rsa_params(x509_cred, session); } /* Check also if the certificate supports the @@ -2382,7 +2378,7 @@ inline static int check_server_params( gnutls_session session, gnutls_kx_algorit _gnutls_get_cred(session->key, cred_type, NULL); if (anon_cred != NULL) { - dh_params = anon_cred->dh_params; + dh_params = _gnutls_anon_get_dh_params(anon_cred, session); } } else return 0; /* no need for params */ diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index ab362df3b8..8f1b26728e 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -33,6 +33,7 @@ #include <debug.h> #include <gnutls_buffers.h> #include <gnutls_sig.h> +#include <gnutls_kx.h> static int _gnutls_tls_sign( gnutls_cert* cert, gnutls_privkey* pkey, const gnutls_datum* hash_concat, gnutls_datum *signature); @@ -105,16 +106,14 @@ gnutls_protocol_version ver = gnutls_protocol_get_version( session); /* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ -int _gnutls_tls_sign_params( gnutls_session session, - gnutls_cert* cert, gnutls_privkey* pkey, - gnutls_datum* params, gnutls_datum *signature) +int _gnutls_tls_sign_params( gnutls_session session, gnutls_cert* cert, gnutls_privkey* pkey, gnutls_datum* params, gnutls_datum *signature) { gnutls_datum dconcat; int ret; GNUTLS_MAC_HANDLE td_md5; GNUTLS_MAC_HANDLE td_sha; opaque concat[36]; -gnutls_protocol_version ver = gnutls_protocol_get_version( session); + td_sha = _gnutls_hash_init( GNUTLS_MAC_SHA); if (td_sha == NULL) { @@ -126,16 +125,7 @@ gnutls_protocol_version ver = gnutls_protocol_get_version( session); _gnutls_hash( td_sha, session->security_parameters.server_random, TLS_RANDOM_SIZE); _gnutls_hash( td_sha, params->data, params->size); - if (ver == GNUTLS_SSL3) { - ret = _gnutls_generate_master( session, 1); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - _gnutls_mac_deinit_ssl3_handshake( td_sha, &concat[16], session->security_parameters.master_secret, TLS_MASTER_SIZE); - } else - _gnutls_hash_deinit(td_sha, &concat[16]); + _gnutls_hash_deinit(td_sha, &concat[16]); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: @@ -344,8 +334,8 @@ gnutls_protocol_version ver = gnutls_protocol_get_version( session); } return ret; -} +} /* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. |