versions.
- Reentracy fixes in ASN.1 Parsing.
- Optimizations in hash/hmac functions
- (Error) message handling has changed
+- Better Protocol Version handling
Version 0.1.4 (22/06/2001)
- Corrected (srp) base64 encoding.
/* decodes data and puts the result into result (localy alocated)
* The result_size is the return value
- * FIXME: This function is a mess
*/
#define ENDSTR "-----\n"
int _gnutls_fbase64_decode( uint8 * data, int data_size,
uint8 ** result)
{
- int i, ret;
- char top[80];
- char bottom[80];
+ int ret;
+ char top[] = "-----BEGIN ";
+ char bottom[] = "\n-----END ";
uint8 *rdata;
int rdata_size;
uint8 *kdata;
int kdata_size;
- strcpy(top, "-----BEGIN ");
-
- strcpy(bottom, "\n-----END ");
-
- i = 0;
- do {
- rdata = &data[i];
- data_size --;
- i++;
- } while (data_size > 0 && strncmp(rdata, top, strlen(top)) != 0);
+ rdata = strstr( data, top);
+ if (rdata==NULL) {
+ gnutls_assert();
+ return -1;
+ }
+ data_size -= (int)rdata-(int)data;
if (data_size < 4 + strlen(bottom)) {
gnutls_assert();
return -1;
}
-
- do {
- data_size--;
- rdata++;
- } while( ( strncmp( rdata, ENDSTR, strlen(ENDSTR)) != 0) && data_size > 0) ;
+ kdata = strstr( rdata, ENDSTR);
+ if (kdata==NULL) {
+ gnutls_assert();
+ return -1;
+ }
data_size -= strlen(ENDSTR);
- rdata += strlen(ENDSTR);
+ data_size -= (int)kdata-(int)rdata;
+
+ rdata = kdata + strlen(ENDSTR);
+
+ /* position is now after the ---BEGIN--- headers */
- rdata_size = 0;
- do {
- rdata_size++;
- } while (rdata_size < data_size
- && strncmp(&rdata[rdata_size], bottom, strlen(bottom)) != 0);
+ kdata = strstr( rdata, bottom);
+ if (kdata==NULL) {
+ gnutls_assert();
+ return -1;
+ }
+ /* position of kdata is before the ----END--- footer
+ */
+ rdata_size = (int)kdata-(int)rdata;
if (rdata_size < 4) {
gnutls_assert();
GNUTLS_NO_RENEGOTIATION=100
} AlertDescription;
-typedef enum GNUTLS_Version { GNUTLS_TLS1, GNUTLS_SSL3 } GNUTLS_Version;
+typedef enum GNUTLS_Version { GNUTLS_SSL3=1, GNUTLS_TLS1 } GNUTLS_Version;
#define SOCKET int
#define LIST ...
ssize_t gnutls_read(SOCKET cd, GNUTLS_STATE state, void *data, size_t sizeofdata);
/* functions to set priority of cipher suites */
-void gnutls_set_cipher_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_mac_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_compression_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_kx_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_cipher_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_mac_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_compression_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_kx_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_protocol_priority( GNUTLS_STATE state, LIST);
/* set our version - 0 for TLS 1.0 and 1 for SSL3 */
-void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version);
GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state);
const char *gnutls_version_get_name(GNUTLS_Version version);
#define MAX_KX 256
#define MAX_CIPHERSUITE 256
#define MAX_COMPRESSION 256
+#define MAX_VERSION 256
/* Cred type mappings to KX algorithms */
static const gnutls_version_entry sup_versions[] = {
{"SSL 3.0", GNUTLS_SSL3, 3, 0, 1},
{"TLS 1.0", GNUTLS_TLS1, 3, 1, 1},
+ {"UNKNOWN", GNUTLS_VERSION_UNKNOWN, 0, 0, 1},
{0}
};
return ret;
}
+/* Version */
+int _gnutls_version_priority(GNUTLS_STATE state,
+ GNUTLS_Version version)
+{ /* actually returns the priority */
+ int i;
+
+ if (state->gnutls_internals.ProtocolPriority.algorithm_priority==NULL) {
+ gnutls_assert();
+ return -1;
+ }
+
+ for (i = 0;
+ i <
+ state->gnutls_internals.ProtocolPriority.algorithms;
+ i++) {
+ if (state->gnutls_internals.
+ ProtocolPriority.algorithm_priority[i] ==
+ version)
+ return i;
+ }
+ return -1;
+}
+
+GNUTLS_Version _gnutls_version_lowest(GNUTLS_STATE state)
+{ /* returns the lowest version supported */
+ 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];
+}
+
+GNUTLS_Version _gnutls_version_max(GNUTLS_STATE state)
+{ /* returns the maximum version supported */
+ if (state->gnutls_internals.ProtocolPriority.algorithm_priority==NULL) {
+ return GNUTLS_VERSION_UNKNOWN;
+ } else
+ return state->gnutls_internals.ProtocolPriority.
+ algorithm_priority[0];
+}
+
+
/**
* gnutls_version_get_name - Returns a string with the name of the specified SSL/TLS version
* @version: is a (gnutls) version number
_gnutls_version_is_supported(GNUTLS_STATE state,
const GNUTLS_Version version)
{
- size_t ret = 0;
- /* FIXME: make it to read it from the state */
+int ret;
+
GNUTLS_VERSION_ALG_LOOP(ret = p->supported);
- return ret;
+ if (ret == 0) return 0;
+
+ if (_gnutls_version_priority( state, version) < 0)
+ return 0; /* disabled by the user */
+ else
+ return 1;
}
/* Type to KX mappings */
#include "gnutls_auth.h"
/* functions for version */
+
+GNUTLS_Version _gnutls_version_lowest( GNUTLS_STATE state);
+GNUTLS_Version _gnutls_version_max( GNUTLS_STATE state);
+int _gnutls_version_priority(GNUTLS_STATE state, GNUTLS_Version version);
int _gnutls_version_is_supported(GNUTLS_STATE state, const GNUTLS_Version version);
int _gnutls_version_get_major( GNUTLS_Version ver);
int _gnutls_version_get_minor( GNUTLS_Version ver);
return n;
}
-ssize_t _gnutls_Send_int(int fd, GNUTLS_STATE state, ContentType type, void *iptr, size_t n)
+ssize_t _gnutls_Send_int(int fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, void *iptr, size_t n)
{
size_t left;
ssize_t i = 0;
left = n;
while (left > 0) {
- i = gnutls_send_int(fd, state, type, &ptr[i], left, 0);
+ i = gnutls_send_int(fd, state, type, htype, &ptr[i], left, 0);
if (i <= 0) {
return i;
}
}
-ssize_t _gnutls_Recv_int(int fd, GNUTLS_STATE state, ContentType type, void *iptr, size_t sizeOfPtr)
+ssize_t _gnutls_Recv_int(int fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, void *iptr, size_t sizeOfPtr)
{
size_t left;
ssize_t i=0;
left = sizeOfPtr;
while (left > 0) {
- i = gnutls_recv_int(fd, state, type, &ptr[i], left, 0);
+ i = gnutls_recv_int(fd, state, type, htype, &ptr[i], left, 0);
if (i < 0) {
return i;
} else {
int gnutls_insertHashDataBuffer( GNUTLS_STATE state, char *data, int length);
int gnutls_clearHashDataBuffer( GNUTLS_STATE state);
-ssize_t _gnutls_Recv_int(int fd, GNUTLS_STATE state, ContentType type, void *iptr, size_t sizeOfPtr);
-ssize_t _gnutls_Send_int(int fd, GNUTLS_STATE state, ContentType type, void *iptr, size_t n);
+ssize_t _gnutls_Recv_int(int fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
+ssize_t _gnutls_Send_int(int fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
res->ca_list = NULL;
+{FILE* fd;
+fd = fopen("/tmp/aaa1", "w");
+fwrite( ptr, siz, 1, fd);
+fclose(fd);
+
+}
+
+
do {
siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
siz-=siz2; /* FIXME: this is not enough
*/
+{FILE* fd;
+fd = fopen("/tmp/test1", "w");
+fwrite( b64, siz2, 1, fd);
+fclose(fd);
+
+}
+
if (siz2 < 0) {
gnutls_assert();
gnutls_free(b64);
{
int ret;
-/* FIXME: This function fails (DER parsing) if it is called
- * after gnutls_set_x509_key(). why?
- */
if ( (ret=read_ca_file( res, CAFILE)) < 0)
return ret;
_gnutls_set_read_keys(state);
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "Cipher Suite: %s\n",
_gnutls_cipher_suite_get_name(state->
security_parameters.current_cipher_suite));
_gnutls_set_write_keys(state);
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "Cipher Suite: %s\n",
_gnutls_cipher_suite_get_name(state->
security_parameters.current_cipher_suite));
#include "gnutls_cert.h"
#include "gnutls_constate.h"
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
#define ERR(x, y) fprintf(stderr, "GNUTLS Error: %s (%d)\n", x,y)
#else
#define ERR(x, y)
int len = datalen;
int err;
opaque random[TLS_RANDOM_SIZE];
+ GNUTLS_Version ver;
if (state->gnutls_internals.v2_hello != 0) { /* version 2.0 */
return _gnutls_read_client_hello_v2(state, data, datalen);
DECR_LEN(len, 2);
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "Client's version: %d.%d\n", data[pos],
data[pos + 1]);
#endif
/* if we do not support that version */
if (_gnutls_version_is_supported(state, version) == 0) {
+ /* If he requested something we do not support
+ * then we send him the lowest we support.
+ */
+ ver = _gnutls_version_lowest( state);
+ } else {
+ ver = version;
+ }
+
+ /* he should have send us the highest version
+ * he supports.
+ */
+ if (ver==GNUTLS_VERSION_UNKNOWN || ver > version) {
gnutls_assert();
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
- } else {
- gnutls_set_current_version(state, version);
}
+ _gnutls_set_current_version(state, ver);
+
pos += 2;
DECR_LEN(len, TLS_RANDOM_SIZE);
(state->security_parameters.
current_cipher_suite));
if (state->gnutls_internals.auth_struct == NULL) {
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr,
"Cannot find the appropriate handler for the KX algorithm\n");
#endif
gnutls_insertHashDataBuffer(state, data, i_datasize);
ret =
- _gnutls_Send_int(cd, state, GNUTLS_HANDSHAKE, data,
+ _gnutls_Send_int(cd, state, GNUTLS_HANDSHAKE, type, data,
i_datasize);
gnutls_free(data);
dataptr = gnutls_malloc(HANDSHAKE_HEADERS_SIZE);
ret =
- _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, dataptr,
+ _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, type, dataptr,
SSL2_HEADERS);
if (ret < 0) {
gnutls_assert();
|| type != GNUTLS_CLIENT_HELLO) {
ret =
- _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE,
+ _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, type,
&dataptr[SSL2_HEADERS],
HANDSHAKE_HEADERS_SIZE -
SSL2_HEADERS);
sum = handshake_headers;
do {
ret =
- _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE,
+ _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, type,
&dataptr[sum], length32);
sum += ret;
} while (((sum - handshake_headers) < length32) && (ret > 0));
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "Server's version: %d.%d\n", data[pos],
data[pos + 1]);
#endif
gnutls_assert();
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
} else {
- gnutls_set_current_version(state, version);
+ _gnutls_set_current_version(state, version);
}
pos += 2;
_gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo
(cipher_suite));
if (state->gnutls_internals.auth_struct == NULL) {
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr,
"Cannot find the appropriate handler for the KX algorithm\n");
#endif
int i, datalen, ret = 0;
uint16 x;
opaque random[TLS_RANDOM_SIZE];
+ GNUTLS_Version hver;
opaque *SessionID =
state->gnutls_internals.resumed_security_parameters.session_id;
*/
data = gnutls_malloc(datalen);
+ hver = _gnutls_version_max(state);
data[pos++] =
- _gnutls_version_get_major(state->connection_state.version);
+ _gnutls_version_get_major( hver);
data[pos++] =
- _gnutls_version_get_minor(state->connection_state.version);
+ _gnutls_version_get_minor( hver);
_gnutls_create_random(random);
_gnutls_set_client_random(state, random);
int ret = 0;
ret =
- gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC,
+ gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC, -1,
NULL, 0, 0);
if (ret < 0) {
ERR("recv ChangeCipherSpec", ret);
#define HARD_DEBUG
#define BUFFERS_DEBUG
#define RECORD_DEBUG
-#define HANDSHAKE_DEBUG*/
+#define HANDSHAKE_DEBUG
#define DEBUG
-
+*/
#define SOCKET int
#define LIST ...
*/
} CipherSpecs;
-typedef enum GNUTLS_Version { GNUTLS_TLS1, GNUTLS_SSL3, GNUTLS_VERSION_UNKNOWN=0xff } GNUTLS_Version;
+/* 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;
#define MACAlgorithm_Priority GNUTLS_Priority
#define KXAlgorithm_Priority GNUTLS_Priority
#define CompressionMethod_Priority GNUTLS_Priority
+#define Protocol_Priority GNUTLS_Priority
typedef struct {
gnutls_datum buffer;
MACAlgorithm_Priority MACAlgorithmPriority;
KXAlgorithm_Priority KXAlgorithmPriority;
CompressionMethod_Priority CompressionMethodPriority;
+ Protocol_Priority ProtocolPriority;
+
/* resumed session */
ResumableSession resumed; /* TRUE or FALSE - if we are resuming a session */
SecurityParameters resumed_security_parameters;
svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label,
int label_size, opaque * seed, int seed_size,
int total_bytes);
-void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version);
+void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version);
GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state);
-ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, const void* data, size_t sizeofdata, int flags);
-ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata, int flags);
+ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType htype, const void* data, size_t sizeofdata, int flags);
+ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType, char* data, size_t sizeofdata, int flags);
int _gnutls_send_change_cipher_spec(SOCKET cd, GNUTLS_STATE state);
int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2);
#define _gnutls_version_ssl3(x) _gnutls_version_cmp(x, GNUTLS_SSL3)
va_end(ap);
return 0;
}
+
+/**
+ * gnutls_set_protocol_priority - Sets the priority on the protocol versions supported by gnutls.
+ * @state: is a &GNUTLS_STATE structure.
+ * @LIST: is a 0 terminated list of GNUTLS_Version elements.
+ *
+ * Sets the priority on the protocol versions supported by gnutls.
+ * Priority is higher for protocols specified before others.
+ * After specifying the protocols you want, you should add 0.
+ * Note that the priority is set on the client. The server does
+ * not use the protocols's priority except for disabling
+ * protocols that were not specified.
+ **/
+int gnutls_set_protocol_priority( GNUTLS_STATE state, LIST) {
+
+ va_list ap;
+ int i,num=0;
+ va_list _ap;
+
+ va_start( ap, state);
+ _ap = ap;
+
+ while( va_arg( ap, int) != 0) {
+ num++;
+ }
+
+ 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);
+
+ if (state->gnutls_internals.ProtocolPriority.algorithm_priority == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ state->gnutls_internals.ProtocolPriority.algorithms = num;
+ for (i=0;i<num;i++) {
+ state->gnutls_internals.ProtocolPriority.algorithm_priority[i] = va_arg( _ap, int);
+ }
+ va_end(ap);
+
+ /* set the current version to the lowest
+ */
+ _gnutls_set_current_version( state, state->gnutls_internals.ProtocolPriority.algorithm_priority[num-1]);
+ return 0;
+}
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-void gnutls_set_cipher_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_kx_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_mac_priority( GNUTLS_STATE state, LIST);
-void gnutls_set_compression_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_cipher_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_kx_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_mac_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_compression_priority( GNUTLS_STATE state, LIST);
+int gnutls_set_protocol_priority( GNUTLS_STATE state, LIST);
return ver;
}
-void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) {
+void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) {
state->connection_state.version = version;
if (state->gnutls_key!=NULL) {
state->gnutls_key->version.major = _gnutls_version_get_major(version);
(*state)->gnutls_internals.resumable = RESUME_TRUE;
- gnutls_set_current_version ( (*state), GNUTLS_TLS1); /* default */
+ gnutls_set_protocol_priority( *state, GNUTLS_TLS1, 0); /* default */
(*state)->gnutls_key = gnutls_calloc(1, sizeof(GNUTLS_KEY_A));
memcpy(&data[0], &level, 1);
memcpy(&data[1], &desc, 1);
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Sending Alert[%d|%d] - %s\n", data[0], data[1], _gnutls_alert2str((int)data[1]));
#endif
- return gnutls_send_int(cd, state, GNUTLS_ALERT, data, 2, 0);
+ return gnutls_send_int(cd, state, GNUTLS_ALERT, -1, data, 2, 0);
}
/**
ret = _gnutls_send_alert(cd, state, GNUTLS_WARNING, GNUTLS_CLOSE_NOTIFY);
/* receive the closure alert */
- if (wait==0) gnutls_recv_int(cd, state, GNUTLS_ALERT, NULL, 0, 0);
+ if (wait==0) gnutls_recv_int(cd, state, GNUTLS_ALERT, -1, NULL, 0, 0);
state->gnutls_internals.valid_connection = VALID_FALSE;
* send (if called by the user the Content is specific)
* It is intended to transfer data, under the current state.
*/
-ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, const void *_data, size_t sizeofdata, int flags)
+ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType htype, const void *_data, size_t sizeofdata, int flags)
{
uint8 *cipher;
int i, cipher_size;
int Size;
uint8 headers[5];
const uint8 *data=_data;
+ GNUTLS_Version lver;
if (sizeofdata == 0)
return 0;
}
headers[0]=type;
- headers[1]=_gnutls_version_get_major(state->connection_state.version);
- headers[2]=_gnutls_version_get_minor(state->connection_state.version);
+
+ if (htype==GNUTLS_CLIENT_HELLO) { /* then send the lowest
+ * protocol we support
+ */
+ lver = _gnutls_version_lowest(state);
+ if (lver==GNUTLS_VERSION_UNKNOWN) {
+ gnutls_assert();
+ return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+ }
+ } else { /* send the current */
+ lver = gnutls_get_current_version( state);
+ }
+ headers[1]=_gnutls_version_get_major( lver);
+ headers[2]=_gnutls_version_get_minor( lver);
+
+
#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Sending Packet[%d] %s(%d) with length: %d\n",
(int) uint64touint32(&state->connection_state.write_sequence_number), _gnutls_packet2str(type), type, sizeofdata);
fprintf(stderr, "Record: Sending ChangeCipherSpec\n");
#endif
- return gnutls_send_int( cd, state, GNUTLS_CHANGE_CIPHER_SPEC, data, 1, 0);
+ return gnutls_send_int( cd, state, GNUTLS_CHANGE_CIPHER_SPEC, -1, data, 1, 0);
}
return 0;
}
+#define CHECK_RECORD_VERSION
+
/* This function behave exactly like read(). The only difference is
* that it accepts, the gnutls_state and the ContentType of data to
* send (if called by the user the Content is Userdata only)
* flags is the sockets flags to use. Currently only MSG_DONTWAIT is
* supported.
*/
-ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, char *data, size_t sizeofdata, int flags)
+ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType htype, char *data, size_t sizeofdata, int flags)
{
uint8 *tmpdata;
int tmplen;
/* Read the first two bytes to determine if this is a
* version 2 message
*/
- if ( headers[0] > 127 && type==GNUTLS_HANDSHAKE) {
+ if ( headers[0] > 127 && type==GNUTLS_HANDSHAKE && htype == GNUTLS_CLIENT_HELLO) {
/* if msb set and expecting handshake message
* it should be SSL 2 hello
recv_type = GNUTLS_HANDSHAKE; /* we accept only v2 client hello
*/
state->gnutls_internals.v2_hello = length;
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: V2 packet received. Length: %d\n", length);
#endif
/* version 3.x
*/
recv_type = headers[0];
+#ifdef CHECK_RECORD_VERSION
version = _gnutls_version_get( headers[1], headers[2]);
+#endif
length = READuint16( &headers[3]);
}
-
- if ( gnutls_get_current_version(state) != version && recv_type != GNUTLS_HANDSHAKE) {
-#ifdef DEBUG
+
+#ifdef CHECK_RECORD_VERSION
+ if ( htype!=GNUTLS_CLIENT_HELLO && gnutls_get_current_version(state) != version) {
+# ifdef RECORD_DEBUG
fprintf(stderr, "Record: INVALID VERSION PACKET: (%d) %d.%d\n", headers[0], headers[1], headers[2]);
-#endif
+# endif
if (type!=GNUTLS_ALERT) {
/* some browsers return garbage, when
* we send them a close notify.
gnutls_assert();
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
}
-
+#endif
#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Expected Packet[%d] %s(%d) with length: %d\n",
#endif
if (length > MAX_RECV_SIZE) {
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: FATAL ERROR: Received packet with length: %d\n", length);
#endif
_gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_RECORD_OVERFLOW);
* received that data.
*/
if (ret != length) {
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Received packet with length: %d\nExpected %d\n", ret, length);
#endif
gnutls_free(ciphertext);
} else {
switch (recv_type) {
case GNUTLS_ALERT:
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Alert[%d|%d] - %s - was received\n", tmpdata[0], tmpdata[1], _gnutls_alert2str((int)tmpdata[1]));
#endif
state->gnutls_internals.last_alert = tmpdata[1];
break;
default:
-#ifdef DEBUG
+#ifdef RECORD_DEBUG
fprintf(stderr, "Record: Received Unknown packet %d expecting %d\n", recv_type, type);
#endif
gnutls_assert();
* be anything except 0.
**/
ssize_t gnutls_send(SOCKET cd, GNUTLS_STATE state, const void *data, size_t sizeofdata, int flags) {
- return gnutls_send_int( cd, state, GNUTLS_APPLICATION_DATA, data, sizeofdata, flags);
+ return gnutls_send_int( cd, state, GNUTLS_APPLICATION_DATA, -1, data, sizeofdata, flags);
}
/**
* if there are no data in the socket.
**/
ssize_t gnutls_recv(SOCKET cd, GNUTLS_STATE state, void *data, size_t sizeofdata, int flags) {
- return gnutls_recv_int( cd, state, GNUTLS_APPLICATION_DATA, data, sizeofdata, flags);
+ return gnutls_recv_int( cd, state, GNUTLS_APPLICATION_DATA, -1, data, sizeofdata, flags);
}
/**
* difference is that is accepts a GNUTLS state.
**/
ssize_t gnutls_write(SOCKET cd, GNUTLS_STATE state, const void *data, size_t sizeofdata) {
- return gnutls_send_int( cd, state, GNUTLS_APPLICATION_DATA, data, sizeofdata, 0);
+ return gnutls_send_int( cd, state, GNUTLS_APPLICATION_DATA, -1, data, sizeofdata, 0);
}
/**
* difference is that is accepts a GNUTLS state.
**/
ssize_t gnutls_read(SOCKET cd, GNUTLS_STATE state, void *data, size_t sizeofdata) {
- return gnutls_recv_int( cd, state, GNUTLS_APPLICATION_DATA, data, sizeofdata, 0);
+ return gnutls_recv_int( cd, state, GNUTLS_APPLICATION_DATA, -1, data, sizeofdata, 0);
}
int err;
uint16 challenge;
opaque session_id[TLS_MAX_SESSION_ID_SIZE];
+ GNUTLS_Version ver;
/* we only want to get here once - only in client hello */
state->gnutls_internals.v2_hello = 0;
DECR_LEN(len, 2);
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "V2 Handshake: Client's version: %d.%d\n", data[pos],
data[pos + 1]);
#endif
/* if we do not support that version */
if (_gnutls_version_is_supported(state, version) == 0) {
+ ver = _gnutls_version_lowest( state);
+ } else {
+ ver = version;
+ }
+
+ if (ver==GNUTLS_VERSION_UNKNOWN || ver > version) {
gnutls_assert();
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
- } else {
- gnutls_set_current_version(state, version);
}
+ _gnutls_set_current_version(state, ver);
+
pos += 2;
(state->security_parameters.
current_cipher_suite));
if (state->gnutls_internals.auth_struct == NULL) {
-#ifdef DEBUG
+#ifdef HANDSHAKE_DEBUG
fprintf(stderr,
"V2 Handshake: Cannot find the appropriate handler for the KX algorithm\n");
#endif
gnutls_set_compression_priority(state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0);
gnutls_set_kx_priority(state, GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_SRP,
GNUTLS_KX_DH_ANON, 0);
+ gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
+
gnutls_set_cred(state, GNUTLS_ANON, dh_cred);
gnutls_set_cred(state, GNUTLS_SRP, srp_cred);
gnutls_set_cred(state, GNUTLS_X509PKI, x509_cred);
-
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
ERR(listen_sd, "socket");