summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-11-10 21:37:13 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-11-10 21:37:13 +0000
commit7d28c069875e58a0a6640684a379fe6d2aaf69b6 (patch)
treea2a01fdffbf4495fccd17a16f442d128e0bfe0cf
parentd4b8f2c7eea4246a6e2d1dee4118f0bd8ebd20e6 (diff)
downloadgnutls-7d28c069875e58a0a6640684a379fe6d2aaf69b6.tar.gz
several fixes.
Including: - max_record_header extension. - resume handshake sending wrong ssl version - Non blocking IO (not ready yet)
-rw-r--r--NEWS1
-rw-r--r--configure.in29
-rw-r--r--lib/ext_max_record.c23
-rw-r--r--lib/gnutls.h.in1
-rw-r--r--lib/gnutls_buffers.c256
-rw-r--r--lib/gnutls_buffers.h1
-rw-r--r--lib/gnutls_cert.c44
-rw-r--r--lib/gnutls_cert.h5
-rw-r--r--lib/gnutls_compress_int.c2
-rw-r--r--lib/gnutls_global.c68
-rw-r--r--lib/gnutls_handshake.c44
-rw-r--r--lib/gnutls_int.h51
-rw-r--r--lib/gnutls_mem.c5
-rw-r--r--lib/gnutls_mem.h1
-rw-r--r--lib/gnutls_privkey.c12
-rw-r--r--lib/gnutls_record.c73
-rw-r--r--lib/io_debug.h10
-rw-r--r--src/cli.c7
-rw-r--r--src/serv.c7
19 files changed, 417 insertions, 223 deletions
diff --git a/NEWS b/NEWS
index 07022afd1b..3f59bcd0bc 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Version 0.2.11
it occupies less space.
- Added max_record_size extension
- Bugfixes in session handling
+- Improved non blocking IO support in the Handshake Protocol
Version 0.2.10 (5/11/2001)
- Corrected bugs and improved non blocking IO
diff --git a/configure.in b/configure.in
index 682ef32ad1..c445a563cd 100644
--- a/configure.in
+++ b/configure.in
@@ -104,7 +104,7 @@ LIBS="${LIBS} -lmhash")])
if test $ac_cv_c_compiler_gnu != no; then
CFLAGS=""
- if test $opt_profiler_mode = yes; then
+ if test x$opt_profiler_mode = xyes; then
CFLAGS="${CFLAGS} -O0 -fprofile-arcs -finstrument-functions -ftest-coverage"
AC_CHECK_LIB(fnccheck, main,
LIBS="$LIBS -lfnccheck",
@@ -112,14 +112,14 @@ if test $ac_cv_c_compiler_gnu != no; then
)
fi
- if test $opt_maintainer_mode = yes; then
+ if test x$opt_maintainer_mode = xyes; then
CFLAGS="${CFLAGS} -O0 -ggdb3 -Wall -Wpointer-arith"
else
CFLAGS="${CFLAGS} -O2"
fi
- if test $opt_dmalloc_mode = yes; then
+ if test x$opt_dmalloc_mode = xyes; then
AC_CHECK_LIB( dmalloc, main)
AC_DEFINE(USE_DMALLOC)
fi
@@ -128,8 +128,7 @@ fi
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h pwd.h locale.h strings.h stdarg.h)
AC_CHECK_HEADERS(sys/stat.h sys/types.h sys/socket.h)
-AC_CHECK_HEADERS(utime.h zlib.h errno.h signal.h)
-AC_CHECK_FUNCS(signal sigaction,AC_DEFINE(USE_SIGNALS),)
+AC_CHECK_HEADERS(utime.h errno.h)
AC_CHECK_FUNCS(bzero memset lstat stat umask utime memmove bcopy getpwuid,,)
dnl Defines USE_VA_COPY
@@ -176,10 +175,26 @@ dnl **** CROSS COMPILING
AC_MSG_RESULT(none)
)
+AC_MSG_CHECKING([whether to check for external libraries])
+
+dnl if used --with-ext-libraries then we will not check
+dnl for any library (libz, libgdbm)
+
+AC_ARG_WITH( ext-libraries, [ --without-ext-libraries disable external libraries support],
+ ac_ext_libraries=$withval
+)
+
+if test x$ac_ext_libraries != xno; then
+ AC_MSG_RESULT(yes)
+ AC_CHECK_LIB(gdbm, gdbm_open,, AC_MSG_WARN("GDBM was not found. You will not be able to use Server side session resuming."))
+ AC_CHECK_LIB(z, compress,,AC_MSG_WARN("ZLIB was not found. You will not be able to use ZLIB compression."))
+else
+ AC_MSG_RESULT()
+
+
+fi
-AC_CHECK_LIB(gdbm, gdbm_open,, AC_MSG_WARN("GDBM was not found. You will not be able to use Server side session resuming."))
-AC_CHECK_LIB(z, compress,,AC_MSG_WARN("ZLIB was not found. You will not be able to use ZLIB compression."))
dnl Checks for libraries.
AC_C_BIGENDIAN
diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c
index 09f269df5d..b33adf809e 100644
--- a/lib/ext_max_record.c
+++ b/lib/ext_max_record.c
@@ -38,6 +38,7 @@ int _gnutls_max_record_recv_params( GNUTLS_STATE state, const opaque* data, int
if (state->security_parameters.entity == GNUTLS_SERVER) {
if (data_size > 0) {
+ gnutls_assert();
if ( data_size != 1) {
gnutls_assert();
@@ -61,15 +62,14 @@ int _gnutls_max_record_recv_params( GNUTLS_STATE state, const opaque* data, int
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
-
- new_size = _gnutls_mre_num2record(data[0]);
-fprintf(stderr, "RECEIVING IT %d\n", new_size);
+ new_size = _gnutls_mre_num2record(data[0]);
- if (new_size < 0 || new_size != state->security_parameters.max_record_size) {
+ if (new_size < 0 || new_size != state->gnutls_internals.proposed_record_size) {
gnutls_assert();
return GNUTLS_E_ILLEGAL_PARAMETER;
- }
+ } else
+ state->security_parameters.max_record_size = state->gnutls_internals.proposed_record_size;
}
@@ -87,12 +87,14 @@ int _gnutls_max_record_send_params( GNUTLS_STATE state, opaque** data) {
/* this function sends the client extension data (dnsname) */
if (state->security_parameters.entity == GNUTLS_CLIENT) {
- if (state->security_parameters.max_record_size != DEFAULT_MAX_RECORD_SIZE) {
+ if (state->gnutls_internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE) {
+ gnutls_assert();
+
len = 1;
(*data) = gnutls_malloc(len); /* hold the size and the type also */
if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
- (*data)[0] = _gnutls_mre_record2num( state->security_parameters.max_record_size);
+ (*data)[0] = _gnutls_mre_record2num( state->gnutls_internals.proposed_record_size);
return len;
}
@@ -100,7 +102,7 @@ int _gnutls_max_record_send_params( GNUTLS_STATE state, opaque** data) {
if (state->security_parameters.max_record_size != DEFAULT_MAX_RECORD_SIZE) {
len = 1;
- (*data) = gnutls_malloc(len+2); /* hold the size and the type also */
+ (*data) = gnutls_malloc(len);
if (*data==NULL) return GNUTLS_E_MEMORY_ERROR;
(*data)[0] = _gnutls_mre_record2num( state->security_parameters.max_record_size);
@@ -114,7 +116,7 @@ int _gnutls_max_record_send_params( GNUTLS_STATE state, opaque** data) {
return 0;
}
-/* Maps record size to numbers according to the
+/* Maps numbers to record sizes according to the
* extensions draft.
*/
int _gnutls_mre_num2record( int num) {
@@ -132,6 +134,9 @@ int _gnutls_mre_num2record( int num) {
}
}
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
int _gnutls_mre_record2num( int record_size) {
switch(record_size) {
case 512:
diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in
index f7a9d9464e..87b6cf684b 100644
--- a/lib/gnutls.h.in
+++ b/lib/gnutls.h.in
@@ -94,6 +94,7 @@ int gnutls_rehandshake(SOCKET cd, GNUTLS_STATE state);
AlertDescription gnutls_get_last_alert( GNUTLS_STATE state);
int gnutls_send_alert(SOCKET, GNUTLS_STATE, AlertLevel, AlertDescription);
+int gnutls_send_appropriate_alert( SOCKET cd, GNUTLS_STATE state, int err);
/* get information on the current state */
BulkCipherAlgorithm gnutls_get_current_cipher( GNUTLS_STATE state);
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 364cbfb832..e1ae16bce2 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -1,3 +1,4 @@
+#define READ_DEBUG
/*
* Copyright (C) 2000,2001 Nikos Mavroyanopoulos
*
@@ -17,13 +18,16 @@
* 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>
#include <gnutls_record.h>
+#include <gnutls_buffers.h>
/* This is the only file that uses the berkeley sockets API.
+ *
+ * Also holds all the buffering code used in gnutls.
*/
#ifdef HAVE_ERRNO_H
@@ -113,6 +117,11 @@ int gnutls_check_pending(GNUTLS_STATE state) {
int gnutls_get_data_buffer(ContentType type, GNUTLS_STATE state, char *data, int length)
{
+ if (length < 0 || data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_PARAMETERS;
+ }
+
switch(type) {
case GNUTLS_APPLICATION_DATA:
@@ -304,7 +313,7 @@ ssize_t _gnutls_read_buffered( int fd, GNUTLS_STATE state, opaque **iptr, size_t
int recvlowat = RCVLOWAT;
int recvdata;
- *iptr = NULL;
+ *iptr = state->gnutls_internals.recv_buffer.data;
if ( sizeOfPtr > MAX_RECV_SIZE || sizeOfPtr == 0
|| (state->gnutls_internals.recv_buffer.size+sizeOfPtr) > MAX_RECV_SIZE) {
@@ -431,13 +440,11 @@ ssize_t _gnutls_read_buffered( int fd, GNUTLS_STATE state, opaque **iptr, size_t
}
}
-
-
/* This function is like write. But it does not return -1 on error.
* It does return gnutls_errno instead.
*
- * This function may not cope right with interrupted system calls
- * and EAGAIN error. Ideas?
+ * In case of E_AGAIN and E_INTERRUPTED errors, you must call gnutls_write_flush(),
+ * until it returns ok (0).
*
* We need to push exactly the data in n, since we cannot send less
* data. In TLS the peer must receive the whole packet in order
@@ -452,6 +459,7 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
#endif
ssize_t retval, i;
const opaque * ptr;
+ int ptrcopy; /* indicates whether to copy from the ptr */
ptr = iptr;
@@ -466,12 +474,14 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
/* If data in the buffer exist
*/
+ ptrcopy = 1;
if (iptr == NULL) {
/* checking is handled above */
ptr = state->gnutls_internals.send_buffer.data;
n = state->gnutls_internals.send_buffer.size;
+ ptrcopy = 0;
#ifdef WRITE_DEBUG
- _gnutls_log( "WRITE: Restoring old write. (%d data to send)\n", n);
+ _gnutls_log( "WRITE: Restoring old write. (%d bytes to send)\n", n);
#endif
}
@@ -492,19 +502,23 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
if (errno == EAGAIN || errno == EINTR) {
state->gnutls_internals.send_buffer_prev_size += n - left;
- state->gnutls_internals.send_buffer.data = gnutls_realloc_fast( state->gnutls_internals.send_buffer.data, left);
+ state->gnutls_internals.send_buffer.data = gnutls_realloc_fast(
+ state->gnutls_internals.send_buffer.data, left);
+
if (state->gnutls_internals.send_buffer.data == NULL) {
gnutls_assert();
return GNUTLS_E_MEMORY_ERROR;
}
state->gnutls_internals.send_buffer.size = left;
- /* use memmove since they may overlap
- */
- memmove( state->gnutls_internals.send_buffer.data, &ptr[n-left], left);
+
+ if (ptrcopy != 0)
+ memcpy( state->gnutls_internals.send_buffer.data, &ptr[n-left], left);
+ else
+ memmove( state->gnutls_internals.send_buffer.data, &state->gnutls_internals.send_buffer.data[n-left], left);
+
#ifdef WRITE_DEBUG
- _gnutls_log( "WRITE: Interrupted.\n");
+ _gnutls_log( "WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n", left, n-left);
#endif
- gnutls_assert();
if (errno==EAGAIN) retval = GNUTLS_E_AGAIN;
else retval = GNUTLS_E_INTERRUPTED;
@@ -517,16 +531,20 @@ ssize_t _gnutls_write_buffered(SOCKET fd, GNUTLS_STATE state, const void *iptr,
left -= i;
#ifdef WRITE_DEBUG
- _gnutls_log( "WRITE: wrote %d bytes to %d. Left %d bytes\n", i, fd, left);
- for (x=0;x<((n-left)/16)+1;x++) {
+ _gnutls_log( "WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n", i, fd, left, n);
+ for (x=0;x<((i)/16)+1;x++) {
+ if (sum>n-left)
+ break;
+
_gnutls_log( "%.4x - ",x);
for (j=0;j<16;j++) {
if (sum<n-left) {
_gnutls_log( "%.2x ", ((unsigned char*)ptr)[sum++]);
- }
+ } else break;
}
_gnutls_log( "\n");
}
+ _gnutls_log( "\n");
#endif
}
@@ -553,8 +571,37 @@ ssize_t _gnutls_write_flush(SOCKET fd, GNUTLS_STATE state)
ret = _gnutls_write_buffered(fd, state, NULL, 0);
#ifdef WRITE_DEBUG
- _gnutls_log("WRITE FLUSH: %d\n", ret);
+ _gnutls_log("WRITE FLUSH: %d [buffer: %d]\n", ret, state->gnutls_internals.send_buffer.size);
+#endif
+
+ return ret;
+}
+
+/* This function writes the data that are left in the
+ * Handshake write buffer (ie. because the previous write was
+ * interrupted.
+ */
+ssize_t _gnutls_handshake_write_flush(SOCKET fd, GNUTLS_STATE state)
+{
+ ssize_t ret;
+
+ ret = _gnutls_handshake_send_int(fd, state, 0, 0, NULL, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+#ifdef WRITE_DEBUG
+ _gnutls_log("HANDSHAKE_FLUSH: written[1] %d bytes\n", ret);
#endif
+
+ if (state->gnutls_internals.handshake_send_buffer.size == 0) {
+ ret = state->gnutls_internals.handshake_send_buffer_prev_size; /* done */
+ state->gnutls_internals.handshake_send_buffer_prev_size = 0;
+ state->gnutls_internals.handshake_send_buffer.size = 0;
+
+ return ret;
+ }
+
return ret;
}
@@ -565,35 +612,90 @@ ssize_t _gnutls_write_flush(SOCKET fd, GNUTLS_STATE state)
ssize_t _gnutls_handshake_send_int( SOCKET fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, void *iptr, size_t n)
{
size_t left;
- ssize_t i = 0;
- char *ptr = iptr;
-
- if (iptr==NULL && n == 0) {
- /* resuming interrupted write.
+ ssize_t i = 0, ret=0;
+ opaque *ptr;
+ int ptrcopy;
+ ssize_t retval = 0;
+
+ ptrcopy = 1;
+ if (state->gnutls_internals.handshake_send_buffer.size > 0 && iptr==NULL && n == 0) {
+ /* resuming previously interrupted write
*/
- return _gnutls_write_flush( fd, state);
+ gnutls_assert();
+ n = state->gnutls_internals.handshake_send_buffer.size;
+ iptr = state->gnutls_internals.handshake_send_buffer.data;
+
+ type = state->gnutls_internals.handshake_send_buffer_type;
+ htype = state->gnutls_internals.handshake_send_buffer_htype;
+ ptrcopy = 0;
+
+ } else if (state->gnutls_internals.handshake_send_buffer.size > 0) {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_ERROR;
}
- /* FIXME: Potential problem here. If ie one message has been
- * sent, and the next send_int() gets an interrupt (or e_again).
- * This might be more dangerous, since a non blocking server may
- * block here. Should a buffer be used here?
- */
+ if (n==0) { /* if we have no data to send */
+ gnutls_assert();
+ return 0;
+ } else if (iptr==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
+
+ ptr = iptr;
left = n;
while (left > 0) {
- i = gnutls_send_int(fd, state, type, htype, &ptr[i], left);
- if (i <= 0) {
- gnutls_assert();
- if (n-left > 0) {
+ ret = gnutls_send_int(fd, state, type, htype, &ptr[n-left], left);
+
+ if (ret <= 0) {
+ if (ret==0) {
gnutls_assert();
- return n-left;
+ ret = GNUTLS_E_UNKNOWN_ERROR;
}
- return i;
+
+ if ( left > 0 && (ret==GNUTLS_E_INTERRUPTED || ret==GNUTLS_E_AGAIN)) {
+ gnutls_assert();
+
+ state->gnutls_internals.handshake_send_buffer.data = gnutls_realloc_fast(
+ state->gnutls_internals.handshake_send_buffer.data, left);
+
+ if (state->gnutls_internals.handshake_send_buffer.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (ptrcopy!=0)
+ memcpy( state->gnutls_internals.handshake_send_buffer.data, &ptr[n-left], left);
+ else
+ if (n-left > 0)
+ memmove( state->gnutls_internals.handshake_send_buffer.data,
+ &state->gnutls_internals.handshake_send_buffer.data[n-left], left);
+
+ state->gnutls_internals.handshake_send_buffer.size = left;
+ state->gnutls_internals.handshake_send_buffer_prev_size += n-left;
+
+ state->gnutls_internals.handshake_send_buffer_type = type;
+ state->gnutls_internals.handshake_send_buffer_htype = htype;
+
+ } else {
+ state->gnutls_internals.handshake_send_buffer_prev_size = 0;
+ state->gnutls_internals.handshake_send_buffer.size = 0;
+ }
+
+ gnutls_assert();
+ return ret;
}
+ i = ret;
left -= i;
}
- return n;
+ retval = n + state->gnutls_internals.handshake_send_buffer_prev_size;
+
+ state->gnutls_internals.handshake_send_buffer.size = 0;
+ state->gnutls_internals.handshake_send_buffer_prev_size = 0;
+
+ return retval;
}
@@ -603,18 +705,69 @@ ssize_t _gnutls_handshake_send_int( SOCKET fd, GNUTLS_STATE state, ContentType t
ssize_t _gnutls_handshake_recv_int(int fd, GNUTLS_STATE state, ContentType type, HandshakeType htype, void *iptr, size_t sizeOfPtr)
{
size_t left;
- ssize_t i=0;
- char *ptr = iptr;
-
+ ssize_t i;
+ char *ptr;
+ size_t dsize;
+
+ ptr = iptr;
left = sizeOfPtr;
+
+ 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.
+ */
+ gnutls_assert();
+ memcpy( iptr, state->gnutls_internals.handshake_recv_buffer.data, sizeOfPtr);
+
+ state->gnutls_internals.handshake_recv_buffer.size -= sizeOfPtr;
+
+ 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;
+ }
+ gnutls_assert();
+ memcpy( iptr, state->gnutls_internals.handshake_recv_buffer.data, state->gnutls_internals.handshake_recv_buffer.size);
+
+ htype = state->gnutls_internals.handshake_recv_buffer_htype;
+ type = state->gnutls_internals.handshake_recv_buffer_type;
+
+ left -= state->gnutls_internals.handshake_recv_buffer.size;
+
+ state->gnutls_internals.handshake_recv_buffer.size = 0;
+ }
+
while (left > 0) {
- i = gnutls_recv_int(fd, state, type, htype, &ptr[i], left);
+ dsize = sizeOfPtr - left;
+ i = gnutls_recv_int(fd, state, type, htype, &ptr[dsize], left);
if (i < 0) {
- if (sizeOfPtr - left > 0) {
+
+ if (dsize > 0 && (i==GNUTLS_E_INTERRUPTED || i==GNUTLS_E_AGAIN)) {
gnutls_assert();
- goto finish;
- }
+
+ state->gnutls_internals.handshake_recv_buffer.data = gnutls_realloc_fast(
+ state->gnutls_internals.handshake_recv_buffer.data, dsize);
+ if (state->gnutls_internals.handshake_recv_buffer.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy( state->gnutls_internals.handshake_recv_buffer.data, iptr, dsize);
+
+ state->gnutls_internals.handshake_recv_buffer_htype = htype;
+ state->gnutls_internals.handshake_recv_buffer_type = type;
+
+ state->gnutls_internals.handshake_recv_buffer.size = dsize;
+ } else
+ 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 {
if (i == 0)
@@ -625,12 +778,27 @@ ssize_t _gnutls_handshake_recv_int(int fd, GNUTLS_STATE state, ContentType type,
}
- finish:
+ 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);
}
/* Buffer for handshake packets. Keeps the packets in order
- * for finished messages to use them.
+ * for finished messages to use them. Used in HMAC calculation
+ * and finished messages.
*/
int gnutls_insert_to_handshake_buffer( GNUTLS_STATE state, char *data, int length)
{
diff --git a/lib/gnutls_buffers.h b/lib/gnutls_buffers.h
index 430282a2ae..63b17e0ef5 100644
--- a/lib/gnutls_buffers.h
+++ b/lib/gnutls_buffers.h
@@ -37,3 +37,4 @@ int gnutls_clear_handshake_buffer( GNUTLS_STATE state);
ssize_t _gnutls_handshake_recv_int(SOCKET fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
ssize_t _gnutls_handshake_send_int(SOCKET fd, GNUTLS_STATE, ContentType, HandshakeType, void *, size_t);
ssize_t _gnutls_write_flush(SOCKET fd, GNUTLS_STATE state);
+ssize_t _gnutls_handshake_write_flush(SOCKET fd, GNUTLS_STATE state);
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 0830152bd8..c5156bdab0 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -34,6 +34,10 @@
#include <gnutls_algorithms.h>
#include <gnutls_dh.h>
+#ifdef DEBUG
+# warning MAX ALGORITHM PARAMS == 2, ok for RSA
+#endif
+
/* KX mappings to PK algorithms */
typedef struct {
KXAlgorithm kx_algorithm;
@@ -70,7 +74,6 @@ PKAlgorithm _gnutls_map_pk_get_pk(KXAlgorithm kx_algorithm)
return ret;
}
-#define GNUTLS_FREE(x) if(x!=NULL) gnutls_free(x)
void gnutls_free_cert(gnutls_cert cert)
{
int n, i;
@@ -86,9 +89,7 @@ void gnutls_free_cert(gnutls_cert cert)
for (i = 0; i < n; i++) {
_gnutls_mpi_release(&cert.params[i]);
}
- if (cert.params != NULL)
- gnutls_free(cert.params);
-
+
gnutls_free_datum(&cert.raw);
return;
@@ -448,7 +449,7 @@ int gnutls_set_x509_dh_bits(X509PKI_CREDENTIALS res, int bits)
}
-static int _read_rsa_params(opaque * der, int dersize, MPI ** params)
+static int _read_rsa_params(opaque * der, int dersize, MPI * params)
{
opaque str[MAX_X509_CERT_SIZE];
int len, result;
@@ -477,16 +478,8 @@ static int _read_rsa_params(opaque * der, int dersize, MPI ** params)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- /* allocate size for the parameters (2) */
- *params = gnutls_calloc(1, 2 * sizeof(MPI));
- if (*params==NULL) {
+ if (_gnutls_mpi_scan(&params[0], GCRYMPI_FMT_USG, str, &len) != 0) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- if (_gnutls_mpi_scan(&(*params)[0], GCRYMPI_FMT_USG, str, &len) != 0) {
- gnutls_assert();
- gnutls_free((*params));
asn1_delete_structure(spk);
return GNUTLS_E_MPI_SCAN_FAILED;
}
@@ -497,17 +490,14 @@ static int _read_rsa_params(opaque * der, int dersize, MPI ** params)
&len);
if (result != ASN_OK) {
gnutls_assert();
- _gnutls_mpi_release(&(*params)[0]);
- gnutls_free((*params));
+ _gnutls_mpi_release(&params[0]);
asn1_delete_structure(spk);
return GNUTLS_E_ASN1_PARSING_ERROR;
}
-
- if (_gnutls_mpi_scan(&(*params)[1], GCRYMPI_FMT_USG, str, &len) != 0) {
+ if (_gnutls_mpi_scan(&params[1], GCRYMPI_FMT_USG, str, &len) != 0) {
gnutls_assert();
- _gnutls_mpi_release(&(*params)[0]);
- gnutls_free((*params));
+ _gnutls_mpi_release(&params[0]);
asn1_delete_structure(spk);
return GNUTLS_E_MPI_SCAN_FAILED;
}
@@ -807,6 +797,7 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert)
_gnutls_log("Decoding error %d\n", result);
#endif
gnutls_assert();
+ asn1_delete_structure(c2);
return GNUTLS_E_ASN1_PARSING_ERROR;
}
@@ -838,12 +829,21 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert)
if (result != ASN_OK) {
gnutls_assert();
+ asn1_delete_structure(c2);
return GNUTLS_E_ASN1_PARSING_ERROR;
}
+ if ((sizeof( gCert->params)/sizeof(MPI)) < 2) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ asn1_delete_structure(c2);
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
if ((result =
- _read_rsa_params(str, len / 8, &gCert->params)) < 0) {
+ _read_rsa_params(str, len / 8, gCert->params)) < 0) {
gnutls_assert();
+ asn1_delete_structure(c2);
return result;
}
@@ -854,10 +854,10 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert)
gnutls_assert();
#ifdef DEBUG
_gnutls_log("ALGORITHM: %s\n", str);
+ asn1_delete_structure(c2);
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
#endif
gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN;
- gCert->params = NULL;
}
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index 06e416c70a..b9743ad9fc 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -5,8 +5,9 @@
#include <x509_asn1.h>
#include <gnutls_ui.h>
+#define MAX_PARAMS_SIZE 2 /* ok for RSA */
typedef struct gnutls_cert {
- MPI *params; /* the size of params depends on the public
+ MPI params[MAX_PARAMS_SIZE]; /* the size of params depends on the public
* key algorithm
*/
PKAlgorithm subject_pk_algorithm;
@@ -38,7 +39,7 @@ typedef struct gnutls_cert {
} gnutls_cert;
typedef struct {
- MPI *params; /* the size of params depends on the public
+ MPI params[MAX_PARAMS_SIZE];/* the size of params depends on the public
* key algorithm
*/
PKAlgorithm pk_algorithm;
diff --git a/lib/gnutls_compress_int.c b/lib/gnutls_compress_int.c
index 9dbc4bb3f5..8eea99f6d2 100644
--- a/lib/gnutls_compress_int.c
+++ b/lib/gnutls_compress_int.c
@@ -22,7 +22,7 @@
#include "gnutls_compress.h"
#include "gnutls_errors.h"
#include "gnutls_compress_int.h"
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index 207a624e7c..4adb3081bb 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -23,22 +23,6 @@
#include <x509_asn1.h>
#include <gnutls_dh.h>
-#ifdef USE_SIGNALS
-
-# ifdef HAVE_SIGNAL_H
-# include <signal.h>
-# endif
-
-# ifndef SIGFUNC
-# define SIGFUNC
- typedef void Sigfunc(int);
-# endif
-static Sigfunc *Signal( int signo, Sigfunc *func);
-
-static Sigfunc *old_sig_handler;
-
-#endif
-
/* created by asn1c */
extern const static_asn pkcs1_asn1_tab[];
@@ -93,10 +77,6 @@ static void dlog( const char* str) {
* You must call gnutls_global_deinit() when gnutls usage is no longer needed
* Returns zero on success.
*
- * If signals are supported in your system, this function sets SIGPIPE,
- * to SIG_IGN. The old signal handler will be restored when calling
- * gnutls_global_deinit().
- *
**/
int gnutls_global_init()
{
@@ -105,11 +85,6 @@ int gnutls_global_init()
/* for gcrypt in order to be able to allocate memory */
gcry_set_allocation_handler(gnutls_malloc, secure_malloc, _gnutls_is_secure_memory, gnutls_realloc, gnutls_free);
- /* we need this */
-#ifdef USE_SIGNALS
- old_sig_handler = Signal( SIGPIPE, SIG_IGN);
-#endif
-
/* set default recv/send functions
*/
gnutls_global_set_log_func( dlog);
@@ -147,10 +122,6 @@ int gnutls_global_init()
void gnutls_global_deinit() {
- /* restore signal handler */
-#ifdef USE_SIGNALS
- Signal( SIGPIPE, old_sig_handler);
-#endif
asn1_delete_structure( PKCS1_ASN);
asn1_delete_structure( PKIX1_ASN);
@@ -158,45 +129,6 @@ void gnutls_global_deinit() {
}
-#ifdef USE_SIGNALS
-
-/* This is an emulation of the signal() function, using the
- * POSIX sigaction() (if present).
- */
-static Sigfunc *
- Signal(int signo, Sigfunc * func)
-{
-#ifdef HAVE_SIGACTION
-
- struct sigaction act, oact;
-
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- if (signo == SIGALRM) {
-#ifdef SA_INTERRUPT
- act.sa_flags |= SA_INTERRUPT; /* SunOs 4.x */
-#endif
- } else {
-#ifdef SA_RESTART
- act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
-#endif
- }
-
- if (sigaction(signo, &act, &oact) < 0)
- return (SIG_ERR);
- return (oact.sa_handler);
-
-#else /* ifdef HAVE_SIGACTION */
-#ifdef HAVE_SIGNAL
- return signal(signo, func);
-#else
- return (Sigfunc *) 0; /* Do nothing */
-#endif /* HAVE_SIGNAL */
-#endif /* HAVE_SIGACTION */
-}
-#endif /* USE_SIGNALS */
-
/* These functions should be elsewere. Kept here for
* historical reasons.
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index dc7e4f1f94..11111c47a4 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -588,7 +588,9 @@ int _gnutls_send_handshake(SOCKET cd, GNUTLS_STATE state, void *i_data,
/* we are resuming a previously interrupted
* send.
*/
- return _gnutls_write_flush( cd, state);
+ ret = _gnutls_handshake_write_flush( cd, state);
+ return ret;
+
}
if (i_data==NULL && i_datasize > 0) {
@@ -820,7 +822,6 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data,
}
ret = GNUTLS_E_UNKNOWN_ERROR;
-
if (data != NULL && length32 > 0)
*data = dataptr;
@@ -1070,10 +1071,17 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state, int again)
return GNUTLS_E_MEMORY_ERROR;
}
- hver = _gnutls_version_max(state);
+ /* if we are resuming a session then we set the
+ * version number to the previously established.
+ */
+ if (SessionID==NULL)
+ hver = _gnutls_version_max(state);
+ else
+ hver = gnutls_get_current_version(state);
+
data[pos++] = _gnutls_version_get_major(hver);
data[pos++] = _gnutls_version_get_minor(hver);
-
+
_gnutls_create_random(random);
_gnutls_set_client_random(state, random);
@@ -1166,7 +1174,7 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state, int again)
static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state, int again)
{
- char *data = NULL;
+ opaque *data;
opaque *extdata;
int extdatalen;
int pos = 0;
@@ -1270,24 +1278,6 @@ int ret;
return ret;
}
-/* Sends the appropriate alert, depending
- * on the error message.
- */
-static int _gnutls_handshake_send_appropriate_alert( SOCKET cd, GNUTLS_STATE state, int err) {
-int ret;
- switch (err) { /* send appropriate alert */
- case GNUTLS_E_ILLEGAL_PARAMETER:
- ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_ILLEGAL_PARAMETER);
- break;
- default:
- ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE);
- break;
- }
-
- return ret;
-}
-
-
/* RECEIVE A HELLO MESSAGE. This should be called from gnutls_recv_handshake_int only if a
* hello message is expected. It uses the security_parameters.current_cipher_suite
* and gnutls_internals.compression_method.
@@ -1300,7 +1290,6 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data,
if (state->security_parameters.entity == GNUTLS_CLIENT) {
ret = _gnutls_read_server_hello(state, data, datalen);
if (ret < 0) {
- _gnutls_handshake_send_appropriate_alert( cd, state, ret);
gnutls_assert();
return ret;
}
@@ -1308,7 +1297,6 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data,
ret = _gnutls_read_client_hello(state, data, datalen);
if (ret < 0) {
- _gnutls_handshake_send_appropriate_alert( cd, state, ret);
gnutls_assert();
return ret;
}
@@ -1393,7 +1381,8 @@ int gnutls_rehandshake(SOCKET cd, GNUTLS_STATE state)
* and the connection should be terminated.
*
* This function may also return the non-fatal errors GNUTLS_E_AGAIN, or
- * GNUTLS_E_INTERRUPTED, and you may resume this handshake later.
+ * GNUTLS_E_INTERRUPTED. In that case you may resume the handshake
+ * (call this function, until it returns ok)
*
**/
int gnutls_handshake(SOCKET cd, GNUTLS_STATE state)
@@ -1415,6 +1404,8 @@ int gnutls_handshake(SOCKET cd, GNUTLS_STATE state)
STATE = STATE0;
+ _gnutls_clear_handshake_buffers( state);
+
return 0;
}
@@ -1423,7 +1414,6 @@ int gnutls_handshake(SOCKET cd, GNUTLS_STATE state)
if (gnutls_is_fatal_error(ret)==0) return ret; \
gnutls_assert(); \
ERR( str, ret); \
- _gnutls_handshake_send_appropriate_alert( cd, state, ret); \
gnutls_clear_handshake_buffer(state); \
return ret; \
}
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index ac51a5dec6..8efed39c8f 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -25,16 +25,15 @@
#include <defines.h>
/*
-#define IO_DEBUG 5 // define this to check non blocking behaviour
+#define IO_DEBUG 3 // define this to check non blocking behaviour
#define BUFFERS_DEBUG
#define HARD_DEBUG
-#define READ_DEBUG
#define WRITE_DEBUG
#define READ_DEBUG
#define HANDSHAKE_DEBUG // Prints some information on handshake
-#define RECORD_DEBUG
+#define RECORD_DEBUG*/
#define DEBUG
-*/
+
/* It might be a good idea to replace int with void*
* here.
@@ -77,9 +76,9 @@
/* the maximum size of encrypted packets */
#define DEFAULT_MAX_RECORD_SIZE 16384
-#define MAX_ENC_LEN state->security_parameters.max_record_size
#define RECORD_HEADER_SIZE 5
-#define MAX_RECV_SIZE 18432+RECORD_HEADER_SIZE /* 2^14+2048+RECORD_HEADER_SIZE */
+#define MAX_RECORD_SIZE state->security_parameters.max_record_size
+#define MAX_RECV_SIZE 2048+MAX_RECORD_SIZE+RECORD_HEADER_SIZE /* 2^14+2048+RECORD_HEADER_SIZE */
#define HANDSHAKE_HEADER_SIZE 4
@@ -150,6 +149,10 @@ typedef enum CompressionMethod { GNUTLS_NULL_COMPRESSION=1, GNUTLS_ZLIB } Compre
typedef enum ValidSession { VALID_TRUE, VALID_FALSE } ValidSession;
typedef enum ResumableSession { RESUME_TRUE, RESUME_FALSE } ResumableSession;
+/* Record Protocol */
+typedef enum ContentType { GNUTLS_CHANGE_CIPHER_SPEC=20, GNUTLS_ALERT, GNUTLS_HANDSHAKE,
+ GNUTLS_APPLICATION_DATA } ContentType;
+
/* STATE (stop) */
@@ -376,6 +379,17 @@ typedef struct {
/* sockets internals */
int lowat;
+ /* These buffers are used in the handshake
+ * protocol only. freed using _gnutls_clear_handshake_buffers();
+ */
+ gnutls_datum handshake_send_buffer;
+ size_t handshake_send_buffer_prev_size;
+ ContentType handshake_send_buffer_type;
+ HandshakeType handshake_send_buffer_htype;
+ ContentType handshake_recv_buffer_type;
+ HandshakeType handshake_recv_buffer_htype;
+ gnutls_datum handshake_recv_buffer;
+
/* this buffer holds a record packet -mostly used for
* non blocking IO.
*/
@@ -384,10 +398,10 @@ typedef struct {
* for the gnutls_write_buffered()
* function.
*/
- int send_buffer_prev_size; /* holds the
+ size_t send_buffer_prev_size; /* holds the
* data written in the previous runs.
*/
- int send_buffer_user_size; /* holds the
+ size_t send_buffer_user_size; /* holds the
* size of the user specified data to
* send.
*/
@@ -433,10 +447,12 @@ typedef struct {
int (*x509_client_cert_callback)(void*,void*,int, void*, int);
gnutls_cert peer_cert;
int max_handshake_data_buffer_size;
+
/* PUSH & PULL functions.
*/
PULL_FUNC _gnutls_pull_func;
PUSH_FUNC _gnutls_push_func;
+
/* STORE & RETRIEVE functions. Only used if other
* backend than gdbm is used.
*/
@@ -444,6 +460,11 @@ typedef struct {
DB_RETR_FUNC db_retrieve_func;
DB_REMOVE_FUNC db_remove_func;
void* db_ptr;
+
+ /* Holds the record size requested by the
+ * user.
+ */
+ uint16 proposed_record_size;
} GNUTLS_INTERNALS;
struct GNUTLS_STATE_INT {
@@ -457,9 +478,6 @@ struct GNUTLS_STATE_INT {
typedef struct GNUTLS_STATE_INT *GNUTLS_STATE;
-/* Record Protocol */
-typedef enum ContentType { GNUTLS_CHANGE_CIPHER_SPEC=20, GNUTLS_ALERT, GNUTLS_HANDSHAKE,
- GNUTLS_APPLICATION_DATA } ContentType;
/* functions */
@@ -471,7 +489,7 @@ svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label,
void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version);
GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state);
-/* These macros return the advertized TLS version of
+/* These two macros return the advertized TLS version of
* the peer.
*/
#define _gnutls_get_adv_version_major( state) \
@@ -480,4 +498,13 @@ GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state);
#define _gnutls_get_adv_version_minor( state) \
state->gnutls_internals.adv_version_minor
+#define _gnutls_clear_handshake_buffers( state) \
+ gnutls_free( state->gnutls_internals.handshake_send_buffer.data); \
+ gnutls_free( state->gnutls_internals.handshake_recv_buffer.data); \
+ state->gnutls_internals.handshake_send_buffer.data = NULL; \
+ state->gnutls_internals.handshake_recv_buffer.data = NULL; \
+ state->gnutls_internals.handshake_send_buffer.size = 0; \
+ state->gnutls_internals.handshake_recv_buffer.size = 0; \
+ state->gnutls_internals.handshake_send_buffer_prev_size = 0
+
#endif /* GNUTLS_INT_H */
diff --git a/lib/gnutls_mem.c b/lib/gnutls_mem.c
index 9cde853528..6ed871a93f 100644
--- a/lib/gnutls_mem.c
+++ b/lib/gnutls_mem.c
@@ -105,6 +105,9 @@ void *gnutls_realloc(void *_ptr, size_t size)
return ret;
}
+/* This realloc only returns a new pointer if you
+ * request more data than the data into the pointer.
+ */
void *gnutls_realloc_fast(void *ptr, size_t size)
{
@@ -117,7 +120,6 @@ void *gnutls_realloc_fast(void *ptr, size_t size)
return gnutls_realloc(ptr, size);
}
-
void gnutls_free(void *_ptr)
{
opaque *ptr = _ptr;
@@ -205,3 +207,4 @@ char *gnutls_strdup(const char *s)
return ret;
}
#endif /* USE_DMALLOC */
+
diff --git a/lib/gnutls_mem.h b/lib/gnutls_mem.h
index 920a9fe5b4..fbe0375cc6 100644
--- a/lib/gnutls_mem.h
+++ b/lib/gnutls_mem.h
@@ -35,3 +35,4 @@ void gnutls_free( void* ptr);
char* gnutls_strdup( const char* s);
#endif
+
diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c
index 7a64d6b3f0..f17971ce74 100644
--- a/lib/gnutls_privkey.c
+++ b/lib/gnutls_privkey.c
@@ -41,15 +41,17 @@ int _gnutls_pkcs1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum cert) {
pkey->pk_algorithm = GNUTLS_PK_RSA;
- /* we do return 2 MPIs
- */
- pkey->params = gnutls_malloc(2*sizeof(MPI));
-
if (asn1_create_structure( _gnutls_get_pkcs(), "PKCS-1.RSAPrivateKey", &pkcs_asn, "rsakey")!=ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_ERROR;
}
+ if ((sizeof( pkey->params)/sizeof(MPI)) < 2) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
result = asn1_get_der( pkcs_asn, cert.data, cert.size);
if (result != ASN_OK) {
gnutls_assert();
@@ -117,7 +119,7 @@ int n, i;
for (i=0;i<n;i++) {
_gnutls_mpi_release( &pkey.params[i]);
}
- if (pkey.params!=NULL) gnutls_free(pkey.params);
+
gnutls_free_datum( &pkey.raw);
return;
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index fca32d02dd..dfb6f2956d 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -121,11 +121,12 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end)
/* set the default maximum record size for TLS
*/
(*state)->security_parameters.max_record_size = DEFAULT_MAX_RECORD_SIZE;
+ (*state)->gnutls_internals.proposed_record_size = DEFAULT_MAX_RECORD_SIZE;
/* everything else not initialized here is initialized
* as NULL or 0. This is why calloc is used.
*/
-
+
return 0;
}
@@ -151,6 +152,8 @@ int gnutls_deinit(GNUTLS_STATE state)
gdbm_close(state->gnutls_internals.db_reader);
#endif
+ _gnutls_clear_handshake_buffers( state);
+
gnutls_sfree_datum(&state->connection_state.read_mac_secret);
gnutls_sfree_datum(&state->connection_state.write_mac_secret);
@@ -384,8 +387,24 @@ int gnutls_send_alert(SOCKET cd, GNUTLS_STATE state, AlertLevel level, AlertDesc
/* Sends the appropriate alert, depending
* on the error message.
*/
-int _gnutls_send_appropriate_alert( SOCKET cd, GNUTLS_STATE state, int err) {
-int ret;
+/**
+ * gnutls_send_appropriate_alert - This function sends an alert to the peer depending on the error code
+ * @cd: is a connection descriptor.
+ * @state: is a &GNUTLS_STATE structure.
+ * @err: is an integer
+ *
+ * Sends an alert to the peer depending on the error code returned by a gnutls
+ * function. All alerts sent by this function are fatal, so connection should
+ * be considered terminated after calling this function.
+ *
+ * This function may also return GNUTLS_E_AGAIN, or GNUTLS_E_INTERRUPTED.
+ *
+ * If the return value is GNUTLS_E_UNIMPLEMENTED_FEATURE, then no alert has
+ * been sent to the peer.
+ *
+ **/
+int gnutls_send_appropriate_alert( SOCKET cd, GNUTLS_STATE state, int err) {
+int ret = GNUTLS_E_UNIMPLEMENTED_FEATURE;
switch (err) { /* send appropriate alert */
case GNUTLS_E_MAC_FAILED:
ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_BAD_RECORD_MAC);
@@ -396,8 +415,11 @@ int ret;
case GNUTLS_E_DECOMPRESSION_FAILED:
ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_DECOMPRESSION_FAILURE);
break;
+ case GNUTLS_E_ILLEGAL_PARAMETER:
+ ret = gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_ILLEGAL_PARAMETER);
+ break;
+
}
-
return ret;
}
@@ -461,7 +483,7 @@ int gnutls_bye(SOCKET cd, GNUTLS_STATE state, CloseRequest how)
* send (if called by the user the Content is specific)
* It is intended to transfer data, under the current state.
*
- * Oct 30 2001: Removed capability to send data more than MAX_ENC_SIZE.
+ * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
* This makes the function much easier to read, and more error resistant
* (there were cases were the old function could mess everything up).
* --nmav
@@ -510,16 +532,20 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
(int) uint64touint32(&state->connection_state.write_sequence_number), _gnutls_packet2str(type), type, sizeofdata);
#endif
- if ( sizeofdata > MAX_ENC_LEN)
- data2send = MAX_ENC_LEN;
+ if ( sizeofdata > 128) //MAX_RECORD_SIZE)
+ data2send = 128; //MAX_RECORD_SIZE;
else
data2send = sizeofdata;
/* Only encrypt if we don't have data to send
* from the previous run. - probably interrupted.
*/
- if (state->gnutls_internals.send_buffer.size != 0) {
+ if (state->gnutls_internals.send_buffer.size > 0) {
ret = _gnutls_write_flush(cd, state);
+ if (ret > 0) cipher_size = ret;
+ cipher = NULL;
+
+ retval = state->gnutls_internals.send_buffer_user_size;
} else {
cipher_size = _gnutls_encrypt( state, headers, RECORD_HEADER_SIZE, data, data2send, &cipher, type);
if (cipher_size <= 0) {
@@ -541,10 +567,9 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
return GNUTLS_E_RECORD_LIMIT_REACHED;
}
-
ret = _gnutls_write_buffered(cd, state, cipher, cipher_size);
}
-
+
if ( ret != cipher_size) {
gnutls_free( cipher);
if ( ret < 0 && gnutls_is_fatal_error(ret)==0) {
@@ -554,6 +579,12 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
gnutls_assert();
return ret;
}
+
+ if (ret > 0) {
+ gnutls_assert();
+ ret = GNUTLS_E_UNKNOWN_ERROR;
+ }
+
state->gnutls_internals.valid_connection = VALID_FALSE;
state->gnutls_internals.resumable = RESUME_FALSE;
gnutls_assert();
@@ -644,7 +675,11 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
*/
if ( (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && gnutls_get_data_buffer_size(type, state) > 0) {
ret = gnutls_get_data_buffer(type, state, data, sizeofdata);
-
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
/* if the buffer just got empty */
if (gnutls_get_data_buffer_size(type, state)==0) {
if ( (ret2=_gnutls_clear_peeked_data( cd, state)) < 0) {
@@ -770,7 +805,6 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
*/
tmplen = _gnutls_decrypt( state, ciphertext, length, &tmpdata, recv_type);
if (tmplen < 0) {
- _gnutls_send_appropriate_alert( cd, state, tmplen);
state->gnutls_internals.valid_connection = VALID_FALSE;
state->gnutls_internals.resumable = RESUME_FALSE;
gnutls_assert();
@@ -897,6 +931,10 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha
/* Get Application data from buffer */
if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && (recv_type == type)) {
ret = gnutls_get_data_buffer(type, state, data, sizeofdata);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
/* if the buffer just got empty */
if (gnutls_get_data_buffer_size(type, state)==0) {
@@ -1067,8 +1105,7 @@ AlertDescription gnutls_get_last_alert( GNUTLS_STATE state) {
* same parameters. Otherwise the write operation will be
* corrupted and the connection will be terminated.
*
- * Returns the number of bytes received, zero on EOF, or
- * a negative error code.
+ * Returns the number of bytes sent, or a negative error code.
*
**/
ssize_t gnutls_write(SOCKET cd, GNUTLS_STATE state, const void *data, size_t sizeofdata) {
@@ -1120,7 +1157,9 @@ size_t gnutls_get_max_record_size( GNUTLS_STATE state) {
* choose not to accept the requested size.
*
* Acceptable values are $2^{9}, 2^{10}, 2^{11}$ and $2^{12}$.
- * Returns the new record size.
+ * Returns 0 on success. The requested record size does not
+ * get in effect immediately. It will be used after a successful
+ * handshake.
*
**/
size_t gnutls_set_max_record_size( GNUTLS_STATE state, size_t size) {
@@ -1136,7 +1175,7 @@ size_t new_size;
return new_size;
}
- state->security_parameters.max_record_size = size;
+ state->gnutls_internals.proposed_record_size = size;
- return state->security_parameters.max_record_size;
+ return 0;
}
diff --git a/lib/io_debug.h b/lib/io_debug.h
index faa16dbe20..d79fabf7ea 100644
--- a/lib/io_debug.h
+++ b/lib/io_debug.h
@@ -17,11 +17,9 @@
*/
/* This debug file was contributed by
- * Paul Sheer <psheer@icon.co.za>
- *
- * It does return EAGAIN errors in recv() and
- * send() calls in order to check, whether
- * non blocking support is ok.
+ * Paul Sheer <psheer@icon.co.za>. Some changes were made by nmav.
+ * It's purpose it to debug non blocking behaviour of gnutls. The included
+ * send() and recv() functions return EAGAIN errors in random.
*
*/
@@ -66,6 +64,6 @@ static int send_debug (int fd, const char *buf, int len, int flags)
return send (fd, buf, len, flags);
}
-#define send send_debug
+//#define send send_debug
#endif
diff --git a/src/cli.c b/src/cli.c
index 36e6c13145..0428f78ae6 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -29,8 +29,7 @@
#include <unistd.h>
#include "../lib/gnutls.h"
#include <sys/time.h>
-
-#include <dmalloc.h>
+#include <signal.h>
#ifndef SHUT_WR
# define SHUT_WR 1
@@ -174,6 +173,8 @@ int main(int argc, char** argv)
SRP_CLIENT_CREDENTIALS cred;
X509PKI_CLIENT_CREDENTIALS xcred;
+ signal( SIGPIPE, SIG_IGN);
+
if (argc!=3) {
fprintf(stderr, "Usage: cli [IP] [PORT]\n");
exit(1);
@@ -216,6 +217,8 @@ int main(int argc, char** argv)
#ifdef RESUME
gnutls_init(&state, GNUTLS_CLIENT);
+ gnutls_set_max_record_size( state, 512);
+
gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_RIJNDAEL_CBC, 0);
gnutls_set_compression_priority( state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0);
diff --git a/src/serv.c b/src/serv.c
index 93625797f3..9ed9ff355e 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include "../lib/gnutls.h"
#include <port.h>
+#include <signal.h>
#define KEYFILE "x509/key.pem"
#define CERTFILE "x509/cert.pem"
@@ -343,6 +344,8 @@ int main(int argc, char **argv)
int http = 0;
char name[256];
+ signal(SIGPIPE, SIG_IGN);
+
if (argc != 2) {
fprintf(stderr, "Usage: serv [-e] [-h]\n");
exit(1);
@@ -435,9 +438,11 @@ int main(int argc, char **argv)
ret = read_request(sd, state, buffer, MAX_BUF, (http==0)?1:2);
if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
+ fflush(stdout);
if (ret == 0) {
printf
("\n- Peer has closed the GNUTLS connection\n");
+ fflush(stdout);
break;
} else {
fprintf(stderr,
@@ -475,10 +480,12 @@ int main(int argc, char **argv)
} while( ret==GNUTLS_E_INTERRUPTED || ret==GNUTLS_E_AGAIN);
if (gnutls_get_last_alert(state)!=GNUTLS_NO_RENEGOTIATION) {
+ printf("* Requesting rehandshake.\n");
/* continue handshake proccess */
do {
ret = gnutls_handshake(sd, state);
} while( ret==GNUTLS_E_INTERRUPTED || ret==GNUTLS_E_AGAIN);
+ printf("* Rehandshake returned %d\n", ret);
}
}
#endif