summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in2
-rw-r--r--lib/gnutls_handshake.c12
-rw-r--r--lib/gnutls_int.h6
-rw-r--r--lib/gnutls_record.c75
-rw-r--r--lib/gnutls_state.c9
-rw-r--r--lib/gnutls_state.h2
-rw-r--r--lib/minitasn1/coding.c18
-rw-r--r--lib/minitasn1/element.c16
-rw-r--r--lib/minitasn1/int.h2
-rw-r--r--lib/minitasn1/libtasn1.h2
-rw-r--r--lib/minitasn1/parser_aux.c67
-rw-r--r--lib/pkix.asn2
-rw-r--r--src/tests.c27
-rw-r--r--src/tests.h1
-rw-r--r--src/tls_test.c3
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"},