diff options
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 12 | ||||
-rw-r--r-- | lib/gnutls_int.h | 6 | ||||
-rw-r--r-- | lib/gnutls_record.c | 75 | ||||
-rw-r--r-- | lib/gnutls_state.c | 9 | ||||
-rw-r--r-- | lib/gnutls_state.h | 2 | ||||
-rw-r--r-- | lib/minitasn1/coding.c | 18 | ||||
-rw-r--r-- | lib/minitasn1/element.c | 16 | ||||
-rw-r--r-- | lib/minitasn1/int.h | 2 | ||||
-rw-r--r-- | lib/minitasn1/libtasn1.h | 2 | ||||
-rw-r--r-- | lib/minitasn1/parser_aux.c | 67 | ||||
-rw-r--r-- | lib/pkix.asn | 2 | ||||
-rw-r--r-- | src/tests.c | 27 | ||||
-rw-r--r-- | src/tests.h | 1 | ||||
-rw-r--r-- | src/tls_test.c | 3 |
15 files changed, 181 insertions, 63 deletions
diff --git a/configure.in b/configure.in index 57f58694b2..e47c72b610 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os", [OS name]) dnl Gnutls Version GNUTLS_MAJOR_VERSION=0 GNUTLS_MINOR_VERSION=9 -GNUTLS_MICRO_VERSION=3 +GNUTLS_MICRO_VERSION=4 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION", [version of gnutls]) diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 0f8a95497d..863d961805 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -575,8 +575,7 @@ int _gnutls_server_select_suite(gnutls_session session, opaque *data, int datale for (i = 0; i < x; i++) { if (memcmp(ciphers[i].CipherSuite, &data[j], 2) == 0) { - _gnutls_handshake_log("HSK: Selected cipher suite: "); - _gnutls_handshake_log("%s\n", + _gnutls_handshake_log("HSK: Selected cipher suite: %s\n", _gnutls_cipher_suite_get_name(* ((GNUTLS_CipherSuite *) & data[j]))); memcpy(session->security_parameters.current_cipher_suite.CipherSuite, ciphers[i].CipherSuite, 2); @@ -1482,18 +1481,15 @@ static int _gnutls_send_client_hello(gnutls_session session, int again) */ _gnutls_set_adv_version( session, hver); - /* Some implementations do not interoperate if we send a + /* Some old implementations do not interoperate if we send a * different version in the record layer. * It seems they prefer to read the record's version * as the one we actually requested. - * The proper behaviour is to use the one in the client hello + * The proper behaviour is to use the one in the client hello * handshake packet and ignore the one in the packet's record * header. */ - if (session->internals.default_record_version==0) - _gnutls_set_current_version(session, hver); - else _gnutls_set_current_version(session, - session->internals.default_record_version); + _gnutls_set_current_version(session, hver); /* In order to know when this session was initiated. */ diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 21e15ec431..94b83f0f79 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos + * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos * - * This file is part of GNUTLS. + * This file is part of GNUTLS. * * The GNUTLS library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -578,7 +578,7 @@ typedef struct { /* This holds the default version that our first * record packet will have. */ - gnutls_protocol_version default_record_version; + opaque default_record_version[2]; int cbc_protection_hack; diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 92fd6e4801..0625b95d45 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -105,7 +105,8 @@ void gnutls_transport_set_ptr(gnutls_session session, gnutls_transport_ptr ptr) * **/ void gnutls_transport_set_ptr2(gnutls_session session, gnutls_transport_ptr recv_ptr, - gnutls_transport_ptr send_ptr) { + gnutls_transport_ptr send_ptr) +{ session->internals.transport_send_ptr = send_ptr; session->internals.transport_recv_ptr = recv_ptr; } @@ -118,7 +119,8 @@ void gnutls_transport_set_ptr2(gnutls_session session, gnutls_transport_ptr recv * PULL). This must have been set using gnutls_transport_set_ptr(). * **/ -gnutls_transport_ptr gnutls_transport_get_ptr(gnutls_session session) { +gnutls_transport_ptr gnutls_transport_get_ptr(gnutls_session session) +{ return session->internals.transport_recv_ptr; } @@ -222,6 +224,25 @@ static int _gnutls_session_is_valid( gnutls_session session) { return 0; } +/* Copies the record version into the headers. The + * version, must have 2 bytes at least. + */ +inline static void copy_record_version( gnutls_session session, HandshakeType htype, + opaque version[2]) +{ +gnutls_protocol_version lver; + + if (htype != GNUTLS_CLIENT_HELLO || session->internals.default_record_version[0] == 0) { + lver = gnutls_protocol_get_version( session); + + version[0] = _gnutls_version_get_major( lver); + version[1] = _gnutls_version_get_minor( lver); + } else { + version[0] = session->internals.default_record_version[0]; + version[1] = session->internals.default_record_version[1]; + } +} + static ssize_t _gnutls_create_empty_record( gnutls_session session, ContentType type, opaque* erecord, unsigned int erecord_size) @@ -230,7 +251,6 @@ ssize_t _gnutls_create_empty_record( gnutls_session session, ContentType type, int retval; int data2send; uint8 headers[5]; - gnutls_protocol_version lver; if (type!=GNUTLS_APPLICATION_DATA || _gnutls_cipher_is_block( gnutls_cipher_get(session))!=CIPHER_BLOCK) @@ -239,16 +259,9 @@ ssize_t _gnutls_create_empty_record( gnutls_session session, ContentType type, */ return 0; - headers[0]=type; + headers[0] = type; - lver = gnutls_protocol_get_version(session); - if (lver==GNUTLS_VERSION_UNKNOWN) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } - - headers[1]=_gnutls_version_get_major( lver); - headers[2]=_gnutls_version_get_minor( lver); + copy_record_version( session, (HandshakeType)(-1), &headers[1]); data2send = 0; @@ -294,7 +307,6 @@ ssize_t _gnutls_send_int( gnutls_session session, ContentType type, HandshakeTyp int data2send_size; uint8 headers[5]; const uint8 *data=_data; - gnutls_protocol_version lver; int erecord_size = 0; opaque* erecord = NULL; @@ -316,16 +328,13 @@ ssize_t _gnutls_send_int( gnutls_session session, ContentType type, HandshakeTyp - headers[0]=type; + headers[0] = type; - lver = gnutls_protocol_get_version(session); - if (lver==GNUTLS_VERSION_UNKNOWN) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + /* Use the default record version, if it is + * set. + */ + copy_record_version( session, htype, &headers[1]); - headers[1]=_gnutls_version_get_major( lver); - headers[2]=_gnutls_version_get_minor( lver); _gnutls_record_log( "REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session, (int) _gnutls_uint64touint32(&session->connection_state.write_sequence_number), _gnutls_packet2str(type), type, sizeofdata); @@ -498,7 +507,7 @@ static int _gnutls_check_buffers( gnutls_session session, ContentType type, opaq * content type. */ static int _gnutls_check_record_headers( gnutls_session session, uint8 headers[RECORD_HEADER_SIZE], ContentType type, - HandshakeType htype, /*output*/ ContentType *recv_type, gnutls_protocol_version *version, uint16 *length, uint16* header_size) { + HandshakeType htype, /*output*/ ContentType *recv_type, opaque version[2], uint16 *length, uint16* header_size) { /* Read the first two bytes to determine if this is a * version 2 message @@ -509,7 +518,9 @@ static int _gnutls_check_record_headers( gnutls_session session, uint8 headers[R /* if msb set and expecting handshake message * it should be SSL 2 hello */ - *version = GNUTLS_VERSION_UNKNOWN; /* assume unknown version */ + version[0] = 3; /* assume SSL 3.0 */ + version[1] = 0; + *length = (((headers[0] & 0x7f) << 8)) | headers[1]; /* SSL 2.0 headers */ @@ -528,9 +539,8 @@ static int _gnutls_check_record_headers( gnutls_session session, uint8 headers[R /* version 3.x */ *recv_type = headers[0]; -#ifdef CHECK_RECORD_VERSION - *version = _gnutls_version_get( headers[1], headers[2]); -#endif + version[0] = headers[1]; + version[1] = headers[2]; /* No DECR_LEN, since headers has enough size. */ @@ -544,14 +554,15 @@ static int _gnutls_check_record_headers( gnutls_session session, uint8 headers[R * negotiated in the handshake. */ inline -static int _gnutls_check_record_version( gnutls_session session, HandshakeType htype, gnutls_protocol_version version) +static int _gnutls_check_record_version( gnutls_session session, HandshakeType htype, opaque version[2]) { #ifdef CHECK_RECORD_VERSION - if ( (htype!=GNUTLS_CLIENT_HELLO && htype!=GNUTLS_SERVER_HELLO) && gnutls_protocol_get_version(session) != version) { - gnutls_assert(); + if ( (htype!=GNUTLS_CLIENT_HELLO && htype!=GNUTLS_SERVER_HELLO) && + gnutls_protocol_get_version(session) != _gnutls_version_get( version[0], version[1])) { + gnutls_assert(); _gnutls_record_log( "REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n", - session, htype, _gnutls_version_get_major(version), _gnutls_version_get_minor(version)); + session, htype, version[0], version[1]); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } @@ -674,7 +685,7 @@ ssize_t _gnutls_recv_int( gnutls_session session, ContentType type, HandshakeTyp { uint8 *tmpdata; int tmplen; - gnutls_protocol_version version; + opaque version[2]; uint8 *headers; ContentType recv_type; uint16 length; @@ -726,7 +737,7 @@ ssize_t _gnutls_recv_int( gnutls_session session, ContentType type, HandshakeTyp return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if ( (ret=_gnutls_check_record_headers( session, headers, type, htype, &recv_type, &version, &length, &header_size)) < 0) { + if ( (ret=_gnutls_check_record_headers( session, headers, type, htype, &recv_type, version, &length, &header_size)) < 0) { gnutls_assert(); return ret; } diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 624bdde8a0..a8120e4326 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -481,16 +481,19 @@ int _gnutls_openpgp_send_fingerprint(gnutls_session session) { /*- * _gnutls_record_set_default_version - Used to set the default version for the first record packet * @session: is a &gnutls_session structure. - * @version: is a tls version + * @major: is a tls major version + * @minor: is a tls minor version * * This function sets the default version that we will use in the first * record packet (client hello). This function is only useful to people * that know TLS internals and want to debug other implementations. * -*/ -void _gnutls_record_set_default_version(gnutls_session session, gnutls_protocol_version version) +void _gnutls_record_set_default_version(gnutls_session session, + unsigned char major, unsigned char minor) { - session->internals.default_record_version = version; + session->internals.default_record_version[0] = major; + session->internals.default_record_version[1] = minor; } /** diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h index ae34e02bec..caf3b1f1b5 100644 --- a/lib/gnutls_state.h +++ b/lib/gnutls_state.h @@ -3,8 +3,6 @@ #include <gnutls_int.h> -void _gnutls_record_set_default_version(gnutls_session session, gnutls_protocol_version version); - void _gnutls_session_cert_type_set( gnutls_session session, gnutls_certificate_type); gnutls_kx_algorithm gnutls_kx_get( gnutls_session session); gnutls_cipher_algorithm gnutls_cipher_get( gnutls_session session); diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c index 8add4692cc..ed38411a0b 100644 --- a/lib/minitasn1/coding.c +++ b/lib/minitasn1/coding.c @@ -807,15 +807,21 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, move=RIGHT; break; case TYPE_OBJECT_ID: - if(p->value==NULL){ + if((p->type&CONST_DEFAULT) && (p->value==NULL)){ + counter=counter_old; + max_len=max_len_old; + } + else{ + if(p->value==NULL){ _asn1_error_description_value_not_found(p,ErrorDescription); return ASN1_VALUE_NOT_FOUND; + } + len2=max_len; + ris=_asn1_objectid_der(p->value,der+counter,&len2); + if(ris==ASN1_MEM_ALLOC_ERROR) return ris; + max_len-=len2; + counter+=len2; } - len2=max_len; - ris=_asn1_objectid_der(p->value,der+counter,&len2); - if(ris==ASN1_MEM_ALLOC_ERROR) return ris; - max_len-=len2; - counter+=len2; move=RIGHT; break; case TYPE_TIME: diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c index ff1ac0f122..207ff67b4a 100644 --- a/lib/minitasn1/element.c +++ b/lib/minitasn1/element.c @@ -389,6 +389,14 @@ asn1_write_value(node_asn *node_root,const char *name, for(k=0;k<strlen(value);k++) if((!isdigit(value[k])) && (value[k]!='.') && (value[k]!='+')) return ASN1_VALUE_NOT_VALID; + if(node->type&CONST_DEFAULT){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + if(!strcmp(value,p->value)){ + _asn1_set_value(node,NULL,0); + break; + } + } _asn1_set_value(node,value,strlen(value)+1); break; case TYPE_TIME: @@ -665,7 +673,13 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) p=p->right; } *len = strlen(value) + 1; - } else { + } + else if((node->type&CONST_DEFAULT) && (node->value==NULL)){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + PUT_STR_VALUE(value, value_size, p->value); + } + else { PUT_STR_VALUE(value, value_size, node->value); } break; diff --git a/lib/minitasn1/int.h b/lib/minitasn1/int.h index cd2220414f..0daed1d397 100644 --- a/lib/minitasn1/int.h +++ b/lib/minitasn1/int.h @@ -32,7 +32,7 @@ #include <mem.h> -#define LIBTASN1_VERSION "0.2.3" +#define LIBTASN1_VERSION "0.2.4" #define MAX32 4294967295 #define MAX24 16777215 diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h index bcbb84f440..89f73e14f7 100644 --- a/lib/minitasn1/libtasn1.h +++ b/lib/minitasn1/libtasn1.h @@ -28,7 +28,7 @@ extern "C" { #endif -#define LIBTASN1_VERSION "0.2.3" +#define LIBTASN1_VERSION "0.2.4" #include <sys/types.h> #include <time.h> diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c index 2444f3d9a4..6f33563fae 100644 --- a/lib/minitasn1/parser_aux.c +++ b/lib/minitasn1/parser_aux.c @@ -518,7 +518,7 @@ asn1_retCode _asn1_expand_object_id(ASN1_TYPE node) { node_asn *p,*p2,*p3,*p4,*p5; - char name_root[129],name2[129]; + char name_root[MAX_NAME_SIZE],name2[2*MAX_NAME_SIZE+1]; int move; if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; @@ -584,6 +584,55 @@ _asn1_expand_object_id(ASN1_TYPE node) if(move==UP) p=_asn1_find_up(p); } + + /*******************************/ + /* expand DEFAULT */ + /*******************************/ + p=node; + move=DOWN; + + while(!((p==node) && (move==UP))){ + if(move!=UP){ + if((type_field(p->type)==TYPE_OBJECT_ID) && + (p->type&CONST_DEFAULT)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){ + _asn1_str_cpy(name2, sizeof(name2), name_root); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + p3=_asn1_find_node(node,name2); + if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) || + !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND; + p4=p3->down; + name2[0]=0; + while(p4){ + if(type_field(p4->type)==TYPE_CONSTANT){ + if(name2[0]) _asn1_str_cat(name2,sizeof(name2),"."); + _asn1_str_cat(name2,sizeof(name2),p4->value); + } + p4=p4->right; + } + _asn1_set_value(p2,name2,strlen(name2)+1); + } + } + move=DOWN; + } + else move=RIGHT; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + + if(p==node) {move=UP; continue;} + + if(move==RIGHT){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + return ASN1_SUCCESS; } @@ -675,6 +724,22 @@ _asn1_check_identifier(ASN1_TYPE node) } } else if((type_field(p->type)==TYPE_OBJECT_ID) && + (p->type&CONST_DEFAULT)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){ + _asn1_str_cpy(name2, sizeof(name2), node->name); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + strcpy(_asn1_identifierMissing,p2->value); + p2=_asn1_find_node(node,name2); + if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) || + !(p2->type&CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0]=0; + } + } + else if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){ p2=p->down; if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ diff --git a/lib/pkix.asn b/lib/pkix.asn index a175d1c794..f278026ce7 100644 --- a/lib/pkix.asn +++ b/lib/pkix.asn @@ -1070,7 +1070,7 @@ pkcs-5-PBKDF2-params ::= SEQUENCE { }, iterationCount INTEGER (1..MAX), keyLength INTEGER (1..MAX) OPTIONAL, - prf AlgorithmIdentifier OPTIONAL -- DEFAULT pkcs-5-algid-hmacWithSHA1 + prf AlgorithmIdentifier OPTIONAL -- DEFAULT pkcs-5-id-hmacWithSHA1 } END diff --git a/src/tests.c b/src/tests.c index ae3ba1f54e..153b8c7282 100644 --- a/src/tests.c +++ b/src/tests.c @@ -489,7 +489,8 @@ int ret; return ret; } -void _gnutls_record_set_default_version(gnutls_session session, gnutls_protocol_version version); +void _gnutls_record_set_default_version(gnutls_session session, unsigned char major, + unsigned char minor); int test_version_rollback( gnutls_session session) { int ret; @@ -509,7 +510,7 @@ int ret; ADD_ALL_MACS(session); ADD_ALL_KX(session); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); - _gnutls_record_set_default_version( session, GNUTLS_SSL3); + _gnutls_record_set_default_version( session, 3, 0); ret = do_handshake( session); if (ret!=SUCCEED) return ret; @@ -520,6 +521,28 @@ int ret; return SUCCEED; } +/* See if the server tolerates out of bounds + * record layer versions in the first client hello + * message. + */ +int test_version_oob( gnutls_session session) { +int ret; + /* here we enable both SSL 3.0 and TLS 1.0 + * and we connect using a 5.5 record version. + */ + ADD_ALL_CIPHERS(session); + ADD_ALL_COMP(session); + ADD_ALL_CERTTYPES(session); + ADD_ALL_PROTOCOLS(session); + ADD_ALL_MACS(session); + ADD_ALL_KX(session); + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); + _gnutls_record_set_default_version( session, 5, 5); + + ret = do_handshake( session); + return ret; +} + void _gnutls_rsa_pms_set_version(gnutls_session session, unsigned char major, unsigned char minor); diff --git a/src/tests.h b/src/tests.h index 52eed9e1dc..b30b2cb5ed 100644 --- a/src/tests.h +++ b/src/tests.h @@ -28,6 +28,7 @@ int test_certificate( gnutls_session state); int test_server_cas( gnutls_session state); int test_session_resume2( gnutls_session state); int test_rsa_pms_version_check( gnutls_session session); +int test_version_oob( gnutls_session session); #define GERR(ret) fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret)) diff --git a/src/tls_test.c b/src/tls_test.c index ac54d61012..a61f74d12c 100644 --- a/src/tls_test.c +++ b/src/tls_test.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos + * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos * * This file is part of GNUTLS. * @@ -89,6 +89,7 @@ static const TLS_TEST tls_tests[] = { { "whether the server ignores the RSA PMS version", test_rsa_pms_version_check, "yes", "no", "dunno"}, { "whether the server can accept Hello Extensions", test_hello_extension, "yes", "no", "dunno"}, { "whether the server can accept cipher suites not in SSL 3.0 spec", test_unknown_ciphersuites, "yes", "no", "dunno"}, + { "whether the server can accept a bogus TLS record version in the client hello", test_version_oob, "yes", "no", "dunno"}, { "for certificate information", test_certificate, "", "", "" }, { "for trusted CAs", test_server_cas, "", "", "" }, { "whether the server understands TLS closure alerts", test_bye, "yes", "no", "partially"}, |