if (plaintext.size != TLS_MASTER_SIZE) { /* WOW */
RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc);
} else {
- if (_gnutls_get_adv_version_major( state) != plaintext.data[0] || _gnutls_get_adv_version_minor( state) != plaintext.data[1]) {
+ if (_gnutls_get_adv_version_major( state) != plaintext.data[0]
+ || _gnutls_get_adv_version_minor( state) != plaintext.data[1]) {
gnutls_assert();
ret = GNUTLS_E_DECRYPTION_FAILED;
}
GNUTLS_Version _gnutls_version_lowest(GNUTLS_STATE state)
{ /* returns the lowest version supported */
+ int i, min = 0xff;
+
if (state->gnutls_internals.ProtocolPriority.algorithm_priority==NULL) {
return GNUTLS_VERSION_UNKNOWN;
} else
- return state->gnutls_internals.ProtocolPriority.
- algorithm_priority[state->gnutls_internals.ProtocolPriority.algorithms-1];
+ for (i=0;i<state->gnutls_internals.ProtocolPriority.algorithms;i++) {
+ if (state->gnutls_internals.ProtocolPriority.algorithm_priority[i] < min)
+ min = state->gnutls_internals.ProtocolPriority.algorithm_priority[i];
+ }
+
+ if (min==0xff) return GNUTLS_VERSION_UNKNOWN; /* unknown version */
+
+ return min;
}
GNUTLS_Version _gnutls_version_max(GNUTLS_STATE state)
{ /* returns the maximum version supported */
+ int i, max=0x00;
+
if (state->gnutls_internals.ProtocolPriority.algorithm_priority==NULL) {
return GNUTLS_VERSION_UNKNOWN;
} else
- return state->gnutls_internals.ProtocolPriority.
- algorithm_priority[0];
+ for (i=0;i<state->gnutls_internals.ProtocolPriority.algorithms;i++) {
+ if (state->gnutls_internals.ProtocolPriority.algorithm_priority[i] > max)
+ max = state->gnutls_internals.ProtocolPriority.algorithm_priority[i];
+ }
+
+ if (max==0x00) return GNUTLS_VERSION_UNKNOWN; /* unknown version */
+
+ return max;
}
-#define READ_DEBUG
+#define IO_DEBUG 5
/*
* Copyright (C) 2000,2001 Nikos Mavroyanopoulos
*
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-#define IO_DEBUG 5
+
#include <gnutls_int.h>
#include <gnutls_errors.h>
#include <gnutls_num.h>
ptr = iptr;
left = sizeOfPtr;
+ if (sizeOfPtr == 0 || iptr == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_PARAMETERS;
+ }
+
if (state->gnutls_internals.handshake_recv_buffer.size > 0) {
/* if we have already received some data */
- fprintf(stderr, "C1: BUFFER_SIZE: %d\n", state->gnutls_internals.handshake_recv_buffer.size);
if (sizeOfPtr <= state->gnutls_internals.handshake_recv_buffer.size) {
/* if requested less data then return it.
*/
memmove( state->gnutls_internals.handshake_recv_buffer.data,
&state->gnutls_internals.handshake_recv_buffer.data[sizeOfPtr],
state->gnutls_internals.handshake_recv_buffer.size);
- fprintf(stderr, "C2: BUFFER_SIZE: %d\n", state->gnutls_internals.handshake_recv_buffer.size);
return sizeOfPtr;
}
state->gnutls_internals.handshake_recv_buffer.size = 0;
gnutls_assert();
- fprintf(stderr, "C3: BUFFER_SIZE: %d\n", state->gnutls_internals.handshake_recv_buffer.size);
return i;
} else {
state->gnutls_internals.handshake_recv_buffer.size = 0;
-{int x,j,sum=0;
- fprintf(stderr, "HREAD: read %d bytes from %d\n", (sizeOfPtr-left), fd);
- for (x=0;x<((sizeOfPtr-left)/16)+1;x++) {
- fprintf(stderr, "%.4x - ",x);
- for (j=0;j<16;j++) {
- if (sum<(sizeOfPtr-left)) {
- fprintf(stderr, "%.2x ", ((unsigned char*)ptr)[sum++]);
- }
- }
- fprintf(stderr, "\n");
-
- }
-}
- return (sizeOfPtr - left);
+ return sizeOfPtr - left;
}
/* Buffer for handshake packets. Keeps the packets in order
_gnutls_cipher_get_block_size(state->security_parameters.
write_bulk_cipher_algorithm);
- minor = _gnutls_version_get_minor(state->connection_state.version);
- major = _gnutls_version_get_major(state->connection_state.version);
+ minor = _gnutls_version_get_minor(state->security_parameters.version);
+ major = _gnutls_version_get_major(state->security_parameters.version);
- if ( state->connection_state.version == GNUTLS_SSL3) { /* SSL 3.0 */
+ if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3.0 */
td =
gnutls_mac_init_ssl3(state->security_parameters.
write_mac_algorithm,
gnutls_hmac(td, UINT64DATA(seq_num), 8);
gnutls_hmac(td, &type, 1);
- if ( state->connection_state.version != GNUTLS_SSL3) { /* TLS 1.0 only */
+ if ( state->security_parameters.version != GNUTLS_SSL3) { /* TLS 1.0 only */
gnutls_hmac(td, &major, 1);
gnutls_hmac(td, &minor, 1);
}
gnutls_hmac(td, &c_length, 2);
gnutls_hmac(td, compressed.data, compressed.size);
- if ( state->connection_state.version == GNUTLS_SSL3) { /* SSL 3.0 */
+ if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3.0 */
gnutls_mac_deinit_ssl3(td, MAC);
} else {
gnutls_hmac_deinit(td, MAC);
}
/* make rand a multiple of blocksize */
- if ( state->connection_state.version == GNUTLS_SSL3) {
+ if ( state->security_parameters.version == GNUTLS_SSL3) {
rand = 0;
} else {
rand = (rand / blocksize) * blocksize;
uint8 major, minor;
int hash_size = _gnutls_mac_get_digest_size(state->security_parameters.read_mac_algorithm);
- minor = _gnutls_version_get_minor(state->connection_state.version);
- major = _gnutls_version_get_major(state->connection_state.version);
+ minor = _gnutls_version_get_minor(state->security_parameters.version);
+ major = _gnutls_version_get_major(state->security_parameters.version);
blocksize = _gnutls_cipher_get_block_size(state->security_parameters.
read_bulk_cipher_algorithm);
- if ( state->connection_state.version == GNUTLS_SSL3) {
+ if ( state->security_parameters.version == GNUTLS_SSL3) {
td =
gnutls_mac_init_ssl3(state->security_parameters.
read_mac_algorithm,
gnutls_hmac(td, UINT64DATA(seq_num), 8);
gnutls_hmac(td, &type, 1);
- if ( state->connection_state.version != GNUTLS_SSL3) { /* TLS 1.0 only */
+ if ( state->security_parameters.version != GNUTLS_SSL3) { /* TLS 1.0 only */
gnutls_hmac(td, &major, 1);
gnutls_hmac(td, &minor, 1);
}
gnutls_hmac(td, &c_length, 2);
gnutls_hmac(td, data, compress->size);
- if ( state->connection_state.version == GNUTLS_SSL3) { /* SSL 3.0 */
+ if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3.0 */
gnutls_mac_deinit_ssl3(td, MAC);
} else {
gnutls_hmac_deinit(td, MAC);
memcpy(random, state->security_parameters.server_random, TLS_RANDOM_SIZE);
memcpy(&random[TLS_RANDOM_SIZE], state->security_parameters.client_random, TLS_RANDOM_SIZE);
- if ( state->connection_state.version == GNUTLS_SSL3) { /* SSL 3 */
+ if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */
key_block = gnutls_ssl3_generate_random( state->security_parameters.master_secret, TLS_MASTER_SIZE, random, 2*TLS_RANDOM_SIZE,
block_size);
} else { /* TLS 1.0 */
dst->session_id_size = src->session_id_size; \
dst->timestamp = src->timestamp; \
dst->max_record_size = src->max_record_size; \
+ dst->version = src->version; \
memcpy( &dst->extensions, &src->extensions, sizeof(TLSExtensions));
static void _gnutls_cpy_read_security_parameters( SecurityParameters * dst, SecurityParameters* src) {
state->security_parameters.entity =
state->gnutls_internals.resumed_security_parameters.entity;
+ state->security_parameters.version =
+ state->gnutls_internals.resumed_security_parameters.version;
+
memcpy(state->security_parameters.session_id,
state->gnutls_internals.resumed_security_parameters.
session_id, sizeof(state->security_parameters.session_id));
DECR_LEN(len, 1);
memcpy(&session_id_len, &data[pos++], 1);
- /* RESUME SESSION */
+ /* RESUME SESSION
+ */
if (session_id_len > TLS_MAX_SESSION_ID_SIZE) {
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
int data_size=0;
if (again==0) {
- if (state->connection_state.version == GNUTLS_SSL3) {
+ if (state->security_parameters.version == GNUTLS_SSL3) {
data =
_gnutls_ssl3_finished(state,
state->security_parameters.
gnutls_assert();
return ret;
}
- if (state->connection_state.version == GNUTLS_SSL3) {
+ if (state->security_parameters.version == GNUTLS_SSL3) {
data_size = 36;
} else {
data_size = 12;
gnutls_assert();
return GNUTLS_E_ERROR_IN_FINISHED_PACKET;
}
- if (state->connection_state.version == GNUTLS_SSL3) {
+ if (state->security_parameters.version == GNUTLS_SSL3) {
/* skip the bytes from the last message */
data =
_gnutls_ssl3_finished(state,
uint8 *dataptr = NULL; /* for realloc */
int handshake_header_size = HANDSHAKE_HEADER_SIZE;
- /* if we have data into the buffer then return them, do not read the next packet
+ /* if we have data into the buffer then return them, do not read the next packet.
+ * In order to return we need a full TLS handshake header, or in case of a version 2
+ * packet, then we return the first byte.
*/
- if (state->gnutls_internals.handshake_header_buffer.header_size ==
- handshake_header_size) {
+ if ((state->gnutls_internals.handshake_header_buffer.header_size == handshake_header_size ||
+ (state->gnutls_internals.v2_hello!=0 && type==GNUTLS_CLIENT_HELLO)) &&
+ state->gnutls_internals.handshake_header_buffer.packet_length > 0) {
+
*recv_type =
- state->gnutls_internals.handshake_header_buffer.
- recv_type;
+ state->gnutls_internals.handshake_header_buffer.recv_type;
- state->gnutls_internals.handshake_header_buffer.header_size = 0; /* reset buffering */
- return state->gnutls_internals.handshake_header_buffer.
- packet_length;
+ return state->gnutls_internals.handshake_header_buffer.packet_length;
}
/* Note: SSL2_HEADERS == 1 */
_gnutls_handshake_recv_int(cd, state, GNUTLS_HANDSHAKE, type,
dataptr, SSL2_HEADERS);
- if (ret <= 0) {
+ if (ret < 0) {
gnutls_assert();
return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
- state->gnutls_internals.handshake_header_buffer.header_size += SSL2_HEADERS;
+ state->gnutls_internals.handshake_header_buffer.header_size += ret;
}
if (state->gnutls_internals.v2_hello == 0 || type != GNUTLS_CLIENT_HELLO) {
length32 = READuint24(&dataptr[1]);
handshake_header_size = HANDSHAKE_HEADER_SIZE;
+
+ state->gnutls_internals.handshake_header_buffer.header_size += ret;
+
#ifdef HANDSHAKE_DEBUG
_gnutls_log("Handshake: %s was received [%ld bytes]\n",
_gnutls_handshake2str(dataptr[0]),
}
}
+ /* put the packet into the buffer */
+ state->gnutls_internals.handshake_header_buffer.header_size = handshake_header_size;
+ state->gnutls_internals.handshake_header_buffer.packet_length = length32;
+ state->gnutls_internals.handshake_header_buffer.recv_type = *recv_type;
+
+ if (*recv_type != type) {
+ gnutls_assert();
+ return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
+ }
+
if (*recv_type != GNUTLS_HELLO_REQUEST) {
if ((ret =
gnutls_insert_to_handshake_buffer(state, dataptr,
}
}
- if (*recv_type != type) {
- gnutls_assert();
-
- /* put the packet into the buffer */
- state->gnutls_internals.handshake_header_buffer.
- header_size = handshake_header_size;
- state->gnutls_internals.handshake_header_buffer.
- packet_length = length32;
- state->gnutls_internals.handshake_header_buffer.recv_type =
- *recv_type;
- return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
- }
-
- state->gnutls_internals.handshake_header_buffer.header_size = 0; /* no buffering */
-
return length32;
}
+#define _gnutls_clear_handshake_header_buffer( state) state->gnutls_internals.handshake_header_buffer.header_size = 0
+
+
/* This function will receive handshake messages of the given types,
* and will pass the message to the right place in order to be processed.
* Eg. for the SERVER_HELLO message (if it is expected), it will be
ret;
}
}
+
+ /* If we fail before this then we will reuse the handshake header
+ * have have received above. if we get here the we clear the handshake
+ * header we received.
+ */
+ _gnutls_clear_handshake_header_buffer( state);
+
ret = GNUTLS_E_UNKNOWN_ERROR;
if (data != NULL && length32 > 0)
return ret;
}
}
+
switch (recv_type) {
case GNUTLS_CLIENT_HELLO:
case GNUTLS_SERVER_HELLO:
} else {
_gnutls_set_current_version(state, version);
}
+
pos += 2;
DECR_LEN(len, TLS_RANDOM_SIZE);
state->gnutls_internals.resumed_security_parameters.
session_id_size;
- if (SessionID == NULL)
+ if (SessionID == NULL || session_id_len == 0) {
session_id_len = 0;
+ SessionID = NULL;
+ }
data = NULL;
datalen = 0;
*/
if (SessionID==NULL)
hver = _gnutls_version_max(state);
- else
- hver = gnutls_get_current_version(state);
+ else { /* we are resuming a session */
+ hver = state->gnutls_internals.resumed_security_parameters.version;
+ _gnutls_set_current_version( state, hver);
+ }
+ if (hver <= 0) {
+ if (hver==0) hver = GNUTLS_E_UNKNOWN_ERROR;
+ gnutls_assert();
+ return hver;
+ }
+
data[pos++] = _gnutls_version_get_major(hver);
data[pos++] = _gnutls_version_get_minor(hver);
-
+
_gnutls_create_random(random);
_gnutls_set_client_random(state, random);
}
data[pos++] =
- _gnutls_version_get_major(state->connection_state.version);
+ _gnutls_version_get_major(state->security_parameters.version);
data[pos++] =
- _gnutls_version_get_minor(state->connection_state.version);
+ _gnutls_version_get_minor(state->security_parameters.version);
memcpy(&data[pos],
state->security_parameters.server_random, TLS_RANDOM_SIZE);
void gnutls_set_max_handshake_data_buffer_size( GNUTLS_STATE state, int max);
#define set_adv_version( state, major, minor) \
- state->gnutls_internals.adv_version_major = data[pos]; \
- state->gnutls_internals.adv_version_minor = data[pos+1]
+ state->gnutls_internals.adv_version_major = major; \
+ state->gnutls_internals.adv_version_minor = minor
#define STATE state->gnutls_internals.handshake_state
uint8 CipherSuite[2];
} GNUTLS_CipherSuite;
+/* Versions should be in order of the oldest
+ * (eg. SSL3 is before TLS1)
+ */
+typedef enum GNUTLS_Version { GNUTLS_SSL3=1, GNUTLS_TLS1, GNUTLS_VERSION_UNKNOWN=0xff } GNUTLS_Version;
+
/* This structure holds parameters got from TLS extension
* mechanism. (some extensions may hold parameters in AUTH_INFO
* structures instead - see SRP).
time_t timestamp;
TLSExtensions extensions;
uint16 max_record_size;
+ GNUTLS_Version version; /* moved here */
} SecurityParameters;
/* This structure holds the generated keys
*/
} CipherSpecs;
-/* Versions should be in order of the oldest
- * (eg. SSL3 is before TLS1)
- */
-typedef enum GNUTLS_Version { GNUTLS_SSL3=1, GNUTLS_TLS1, GNUTLS_VERSION_UNKNOWN=0xff } GNUTLS_Version;
typedef struct {
- GNUTLS_Version version;
GNUTLS_CIPHER_HANDLE write_cipher_state;
GNUTLS_CIPHER_HANDLE read_cipher_state;
gnutls_datum read_mac_secret;
char* db_name;
int expire_time;
struct MOD_AUTH_STRUCT_INT* auth_struct; /* used in handshake packets and KX algorithms */
- int v2_hello; /* set 0 normally - 1 if v2 hello was received - server side only */
+ int v2_hello; /* 0 if the client hello is v3+.
+ * non-zero if we got a v2 hello.
+ */
#ifdef HAVE_LIBGDBM
GDBM_FILE db_reader;
#endif
_gnutls_log( "SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.server_random,32));
#endif
- if ( state->connection_state.version == GNUTLS_SSL3) {
+ if ( state->security_parameters.version == GNUTLS_SSL3) {
master =
gnutls_ssl3_generate_random( premaster, premaster_size,
random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE);
if (state->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority!=NULL)
gnutls_free(state->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority);
- state->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int*)*num);
+
+ state->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int)*num);
if (state->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority == NULL)
return GNUTLS_E_MEMORY_ERROR;
if (state->gnutls_internals.KXAlgorithmPriority.algorithm_priority!=NULL)
gnutls_free(state->gnutls_internals.KXAlgorithmPriority.algorithm_priority);
- state->gnutls_internals.KXAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int*)*num);
+ state->gnutls_internals.KXAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int)*num);
if (state->gnutls_internals.KXAlgorithmPriority.algorithm_priority==NULL)
return GNUTLS_E_MEMORY_ERROR;
state->gnutls_internals.KXAlgorithmPriority.algorithms = num;
if (state->gnutls_internals.MACAlgorithmPriority.algorithm_priority!=NULL)
gnutls_free(state->gnutls_internals.MACAlgorithmPriority.algorithm_priority);
- state->gnutls_internals.MACAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int*)*num);
+ state->gnutls_internals.MACAlgorithmPriority.algorithm_priority = gnutls_malloc(sizeof(int)*num);
if (state->gnutls_internals.MACAlgorithmPriority.algorithm_priority ==NULL)
return GNUTLS_E_MEMORY_ERROR;
state->gnutls_internals.MACAlgorithmPriority.algorithms = num;
if (state->gnutls_internals.CompressionMethodPriority.algorithm_priority!=NULL)
gnutls_free(state->gnutls_internals.CompressionMethodPriority.algorithm_priority);
- state->gnutls_internals.CompressionMethodPriority.algorithm_priority = gnutls_malloc(sizeof(int*)*num);
+ state->gnutls_internals.CompressionMethodPriority.algorithm_priority = gnutls_malloc(sizeof(int)*num);
if (state->gnutls_internals.CompressionMethodPriority.algorithm_priority == NULL)
return GNUTLS_E_MEMORY_ERROR;
if (state->gnutls_internals.ProtocolPriority.algorithm_priority!=NULL)
gnutls_free(state->gnutls_internals.ProtocolPriority.algorithm_priority);
- state->gnutls_internals.ProtocolPriority.algorithm_priority = gnutls_malloc(sizeof(int*)*num);
+ state->gnutls_internals.ProtocolPriority.algorithm_priority = gnutls_malloc(sizeof(int)*num);
if (state->gnutls_internals.ProtocolPriority.algorithm_priority == NULL) {
gnutls_assert();
state->gnutls_internals.ProtocolPriority.algorithms = num;
for (i=0;i<num;i++) {
- state->gnutls_internals.ProtocolPriority.algorithm_priority[i] = va_arg( _ap, int);
+ state->gnutls_internals.ProtocolPriority.algorithm_priority[i] = va_arg( _ap, GNUTLS_Version);
}
va_end(ap);
GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state) {
GNUTLS_Version ver;
- ver = state->connection_state.version;
+ ver = state->security_parameters.version;
return ver;
}
void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) {
- state->connection_state.version = version;
+ state->security_parameters.version = version;
}
/**
(int) uint64touint32(&state->connection_state.write_sequence_number), _gnutls_packet2str(type), type, sizeofdata);
#endif
- if ( sizeofdata > 128) //MAX_RECORD_SIZE)
- data2send = 128; //MAX_RECORD_SIZE;
+ if ( sizeofdata > MAX_RECORD_SIZE)
+ data2send = MAX_RECORD_SIZE;
else
data2send = sizeofdata;
return send (fd, buf, len, flags);
}
-//#define send send_debug
+#define send send_debug
#endif
#define HTTP_END "</BODY></HTML>\n\n"
-#define RENEGOTIATE
+//#define RENEGOTIATE
/* These are global */
SRP_SERVER_CREDENTIALS srp_cred;
}
i++;
#ifdef RENEGOTIATE
- if (i == 10) {
+ if (i == 20) {
do {
ret = gnutls_rehandshake(sd, state);
} while( ret==GNUTLS_E_INTERRUPTED || ret==GNUTLS_E_AGAIN);