diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-11-08 22:14:07 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-11-08 22:17:10 +0100 |
commit | 76c93d23c073ef8b885503b7d28a31ffe2add6d8 (patch) | |
tree | 1dd2d22a197bc40c5330e516969a7cb1ae9bc96f /lib/gnutls_buffers.c | |
parent | 559a144f6bbcbb611453f82e655dd7438c14d1a7 (diff) | |
download | gnutls-76c93d23c073ef8b885503b7d28a31ffe2add6d8.tar.gz |
reindented code
Diffstat (limited to 'lib/gnutls_buffers.c')
-rw-r--r-- | lib/gnutls_buffers.c | 2029 |
1 files changed, 1054 insertions, 975 deletions
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c index a327bbd981..50d0f52ca1 100644 --- a/lib/gnutls_buffers.c +++ b/lib/gnutls_buffers.c @@ -48,8 +48,8 @@ #include <gnutls_state.h> #include <gnutls_dtls.h> #include <system.h> -#include <gnutls_constate.h> /* gnutls_epoch_get */ -#include <gnutls_handshake.h> /* remaining_time() */ +#include <gnutls_constate.h> /* gnutls_epoch_get */ +#include <gnutls_handshake.h> /* remaining_time() */ #include <errno.h> #include <system.h> #include "debug.h" @@ -66,18 +66,19 @@ * HANDSHAKE DATA and HEARTBEAT. */ int -_gnutls_record_buffer_put (gnutls_session_t session, - content_type_t type, uint64* seq, mbuffer_st* bufel) +_gnutls_record_buffer_put(gnutls_session_t session, + content_type_t type, uint64 * seq, + mbuffer_st * bufel) { - bufel->type = type; - memcpy(&bufel->record_sequence, seq, sizeof(*seq)); + bufel->type = type; + memcpy(&bufel->record_sequence, seq, sizeof(*seq)); - _mbuffer_enqueue(&session->internals.record_buffer, bufel); - _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n", - (int) bufel->msg.size, (int) type); + _mbuffer_enqueue(&session->internals.record_buffer, bufel); + _gnutls_buffers_log("BUF[REC]: Inserted %d bytes of Data(%d)\n", + (int) bufel->msg.size, (int) type); - return 0; + return 0; } /** @@ -91,278 +92,269 @@ _gnutls_record_buffer_put (gnutls_session_t session, * * Returns: Returns the size of the data or zero. **/ -size_t -gnutls_record_check_pending (gnutls_session_t session) +size_t gnutls_record_check_pending(gnutls_session_t session) { - return _gnutls_record_buffer_get_size (session); + return _gnutls_record_buffer_get_size(session); } int -_gnutls_record_buffer_get (content_type_t type, - gnutls_session_t session, uint8_t * data, - size_t length, uint8_t seq[8]) +_gnutls_record_buffer_get(content_type_t type, + gnutls_session_t session, uint8_t * data, + size_t length, uint8_t seq[8]) { -gnutls_datum_t msg; -mbuffer_st* bufel; - - if (length == 0 || data == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg); - if (bufel == NULL) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - if (type != bufel->type) - { - if (IS_DTLS(session)) - _gnutls_audit_log(session, "Discarded unexpected %s (%d) packet (expecting: %s (%d))\n", - _gnutls_packet2str(bufel->type), (int)bufel->type, - _gnutls_packet2str(type), (int)type); - _mbuffer_head_remove_bytes(&session->internals.record_buffer, msg.size); - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); - } - - if (msg.size <= length) - length = msg.size; - - if (seq) - memcpy(seq, bufel->record_sequence.i, 8); - - memcpy(data, msg.data, length); - _mbuffer_head_remove_bytes(&session->internals.record_buffer, length); - - return length; + gnutls_datum_t msg; + mbuffer_st *bufel; + + if (length == 0 || data == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + bufel = + _mbuffer_head_get_first(&session->internals.record_buffer, + &msg); + if (bufel == NULL) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + if (type != bufel->type) { + if (IS_DTLS(session)) + _gnutls_audit_log(session, + "Discarded unexpected %s (%d) packet (expecting: %s (%d))\n", + _gnutls_packet2str(bufel->type), + (int) bufel->type, + _gnutls_packet2str(type), + (int) type); + _mbuffer_head_remove_bytes(&session->internals. + record_buffer, msg.size); + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + } + + if (msg.size <= length) + length = msg.size; + + if (seq) + memcpy(seq, bufel->record_sequence.i, 8); + + memcpy(data, msg.data, length); + _mbuffer_head_remove_bytes(&session->internals.record_buffer, + length); + + return length; } -inline static void -reset_errno (gnutls_session_t session) +inline static void reset_errno(gnutls_session_t session) { - session->internals.errnum = 0; + session->internals.errnum = 0; } -inline static int -get_errno (gnutls_session_t session) +inline static int get_errno(gnutls_session_t session) { -int ret; - - if (session->internals.errnum != 0) - ret = session->internals.errnum; - else - ret = session->internals.errno_func (session-> - internals.transport_recv_ptr); - return ret; + int ret; + + if (session->internals.errnum != 0) + ret = session->internals.errnum; + else + ret = + session->internals.errno_func(session->internals. + transport_recv_ptr); + return ret; } -inline static +inline static int errno_to_gerr(int err) { - switch(err) - { - case EAGAIN: - return GNUTLS_E_AGAIN; - case EINTR: - return GNUTLS_E_INTERRUPTED; - case EMSGSIZE: - return GNUTLS_E_LARGE_PACKET; - default: - gnutls_assert (); - return GNUTLS_E_PUSH_ERROR; - } + switch (err) { + case EAGAIN: + return GNUTLS_E_AGAIN; + case EINTR: + return GNUTLS_E_INTERRUPTED; + case EMSGSIZE: + return GNUTLS_E_LARGE_PACKET; + default: + gnutls_assert(); + return GNUTLS_E_PUSH_ERROR; + } } static ssize_t -_gnutls_dgram_read (gnutls_session_t session, mbuffer_st **bufel, - gnutls_pull_func pull_func, unsigned int *ms) +_gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel, + gnutls_pull_func pull_func, unsigned int *ms) { - ssize_t i, ret; - uint8_t *ptr; - struct timespec t1, t2; - size_t max_size = get_max_decrypted_data(session); - size_t recv_size = MAX_RECV_SIZE(session); - gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; - unsigned int diff; - - if (recv_size > max_size) - recv_size = max_size; - - session->internals.direction = 0; - - if (ms && *ms > 0) - { - ret = _gnutls_io_check_recv(session, *ms); - if (ret < 0) - return gnutls_assert_val(ret); - gettime(&t1); - } - - *bufel = _mbuffer_alloc (0, max_size); - if (*bufel == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - ptr = (*bufel)->msg.data; - - reset_errno (session); - i = pull_func (fd, ptr, recv_size); - - if (i < 0) - { - int err = get_errno (session); - - _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n", - (int) i, fd, errno, session->internals.errnum); - - ret = errno_to_gerr(err); - goto cleanup; - } - else - { - _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd); - if (i == 0) - { - /* If we get here, we likely have a stream socket. - * FIXME: this probably breaks DCCP. */ - gnutls_assert (); - ret = 0; - goto cleanup; - } - - _mbuffer_set_udata_size (*bufel, i); - } - - if (ms && *ms > 0) - { - gettime(&t2); - diff = timespec_sub_ms(&t2, &t1); - if (diff < *ms) - *ms -= diff; - else - { - ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT); - goto cleanup; - } - } - - _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i, fd); - - return i; - -cleanup: - _mbuffer_xfree(bufel); - return ret; + ssize_t i, ret; + uint8_t *ptr; + struct timespec t1, t2; + size_t max_size = get_max_decrypted_data(session); + size_t recv_size = MAX_RECV_SIZE(session); + gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; + unsigned int diff; + + if (recv_size > max_size) + recv_size = max_size; + + session->internals.direction = 0; + + if (ms && *ms > 0) { + ret = _gnutls_io_check_recv(session, *ms); + if (ret < 0) + return gnutls_assert_val(ret); + gettime(&t1); + } + + *bufel = _mbuffer_alloc(0, max_size); + if (*bufel == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + ptr = (*bufel)->msg.data; + + reset_errno(session); + i = pull_func(fd, ptr, recv_size); + + if (i < 0) { + int err = get_errno(session); + + _gnutls_read_log + ("READ: %d returned from %p, errno=%d gerrno=%d\n", + (int) i, fd, errno, session->internals.errnum); + + ret = errno_to_gerr(err); + goto cleanup; + } else { + _gnutls_read_log("READ: Got %d bytes from %p\n", (int) i, + fd); + if (i == 0) { + /* If we get here, we likely have a stream socket. + * FIXME: this probably breaks DCCP. */ + gnutls_assert(); + ret = 0; + goto cleanup; + } + + _mbuffer_set_udata_size(*bufel, i); + } + + if (ms && *ms > 0) { + gettime(&t2); + diff = timespec_sub_ms(&t2, &t1); + if (diff < *ms) + *ms -= diff; + else { + ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT); + goto cleanup; + } + } + + _gnutls_read_log("READ: read %d bytes from %p\n", (int) i, fd); + + return i; + + cleanup: + _mbuffer_xfree(bufel); + return ret; } static ssize_t -_gnutls_stream_read (gnutls_session_t session, mbuffer_st **bufel, - size_t size, gnutls_pull_func pull_func, unsigned int *ms) +_gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel, + size_t size, gnutls_pull_func pull_func, + unsigned int *ms) { - size_t left; - ssize_t i = 0; - size_t max_size = get_max_decrypted_data(session); - uint8_t *ptr; - gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; - int ret; - struct timespec t1, t2; - unsigned int diff; - - session->internals.direction = 0; - - *bufel = _mbuffer_alloc (0, MAX(max_size, size)); - if (!*bufel) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - ptr = (*bufel)->msg.data; - - left = size; - while (left > 0) - { - if (ms && *ms > 0) - { - ret = _gnutls_io_check_recv(session, *ms); - if (ret < 0) - { - gnutls_assert(); - goto cleanup; - } - - gettime(&t1); - } - - reset_errno (session); - - i = pull_func (fd, &ptr[size - left], left); - - if (i < 0) - { - int err = get_errno (session); - - _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n", - (int) i, fd, errno, session->internals.errnum); - - if (err == EAGAIN || err == EINTR) - { - if (size - left > 0) - { - - _gnutls_read_log ("READ: returning %d bytes from %p\n", - (int) (size - left), fd); - - goto finish; - } - - ret = errno_to_gerr(err); - goto cleanup; - } - else - { - gnutls_assert (); - ret = GNUTLS_E_PULL_ERROR; - goto cleanup; - } - } - else - { - - _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd); - - if (i == 0) - break; /* EOF */ - } - - left -= i; - (*bufel)->msg.size += i; - - if (ms && *ms > 0) - { - gettime(&t2); - diff = timespec_sub_ms(&t2, &t1); - if (diff < *ms) - *ms -= diff; - else - { - ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT); - goto cleanup; - } - } - } - -finish: - - _gnutls_read_log ("READ: read %d bytes from %p\n", - (int) (size - left), fd); - - if (size - left == 0) - _mbuffer_xfree(bufel); - - return (size - left); - -cleanup: - _mbuffer_xfree(bufel); - return ret; + size_t left; + ssize_t i = 0; + size_t max_size = get_max_decrypted_data(session); + uint8_t *ptr; + gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; + int ret; + struct timespec t1, t2; + unsigned int diff; + + session->internals.direction = 0; + + *bufel = _mbuffer_alloc(0, MAX(max_size, size)); + if (!*bufel) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + ptr = (*bufel)->msg.data; + + left = size; + while (left > 0) { + if (ms && *ms > 0) { + ret = _gnutls_io_check_recv(session, *ms); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + gettime(&t1); + } + + reset_errno(session); + + i = pull_func(fd, &ptr[size - left], left); + + if (i < 0) { + int err = get_errno(session); + + _gnutls_read_log + ("READ: %d returned from %p, errno=%d gerrno=%d\n", + (int) i, fd, errno, + session->internals.errnum); + + if (err == EAGAIN || err == EINTR) { + if (size - left > 0) { + + _gnutls_read_log + ("READ: returning %d bytes from %p\n", + (int) (size - left), fd); + + goto finish; + } + + ret = errno_to_gerr(err); + goto cleanup; + } else { + gnutls_assert(); + ret = GNUTLS_E_PULL_ERROR; + goto cleanup; + } + } else { + + _gnutls_read_log("READ: Got %d bytes from %p\n", + (int) i, fd); + + if (i == 0) + break; /* EOF */ + } + + left -= i; + (*bufel)->msg.size += i; + + if (ms && *ms > 0) { + gettime(&t2); + diff = timespec_sub_ms(&t2, &t1); + if (diff < *ms) + *ms -= diff; + else { + ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT); + goto cleanup; + } + } + } + + finish: + + _gnutls_read_log("READ: read %d bytes from %p\n", + (int) (size - left), fd); + + if (size - left == 0) + _mbuffer_xfree(bufel); + + return (size - left); + + cleanup: + _mbuffer_xfree(bufel); + return ret; } @@ -372,66 +364,68 @@ cleanup: * Flags are only used if the default recv() function is being used. */ static ssize_t -_gnutls_read (gnutls_session_t session, mbuffer_st **bufel, - size_t size, gnutls_pull_func pull_func, unsigned int *ms) +_gnutls_read(gnutls_session_t session, mbuffer_st ** bufel, + size_t size, gnutls_pull_func pull_func, unsigned int *ms) { - if (IS_DTLS (session)) - /* Size is not passed, since a whole datagram will be read. */ - return _gnutls_dgram_read (session, bufel, pull_func, ms); - else - return _gnutls_stream_read (session, bufel, size, pull_func, ms); + if (IS_DTLS(session)) + /* Size is not passed, since a whole datagram will be read. */ + return _gnutls_dgram_read(session, bufel, pull_func, ms); + else + return _gnutls_stream_read(session, bufel, size, pull_func, + ms); } static ssize_t -_gnutls_writev_emu (gnutls_session_t session, gnutls_transport_ptr_t fd, const giovec_t * giovec, - unsigned int giovec_cnt) +_gnutls_writev_emu(gnutls_session_t session, gnutls_transport_ptr_t fd, + const giovec_t * giovec, unsigned int giovec_cnt) { - unsigned int j = 0; - size_t total = 0; - ssize_t ret = 0; + unsigned int j = 0; + size_t total = 0; + ssize_t ret = 0; - for (j = 0; j < giovec_cnt; j++) - { - ret = session->internals.push_func (fd, giovec[j].iov_base, giovec[j].iov_len); + for (j = 0; j < giovec_cnt; j++) { + ret = + session->internals.push_func(fd, giovec[j].iov_base, + giovec[j].iov_len); - if (ret == -1) - break; + if (ret == -1) + break; - total += ret; + total += ret; - if ((size_t)ret != giovec[j].iov_len) - break; - } + if ((size_t) ret != giovec[j].iov_len) + break; + } - if (total > 0) - return total; + if (total > 0) + return total; - return ret; + return ret; } static ssize_t -_gnutls_writev (gnutls_session_t session, const giovec_t * giovec, - int giovec_cnt) +_gnutls_writev(gnutls_session_t session, const giovec_t * giovec, + int giovec_cnt) { - int i; - gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; + int i; + gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; - reset_errno (session); + reset_errno(session); - if (session->internals.push_func != NULL) - i = _gnutls_writev_emu (session, fd, giovec, giovec_cnt); - else - i = session->internals.vec_push_func (fd, giovec, giovec_cnt); + if (session->internals.push_func != NULL) + i = _gnutls_writev_emu(session, fd, giovec, giovec_cnt); + else + i = session->internals.vec_push_func(fd, giovec, + giovec_cnt); - if (i == -1) - { - int err = get_errno (session); - _gnutls_debug_log ("errno: %d\n", err); + if (i == -1) { + int err = get_errno(session); + _gnutls_debug_log("errno: %d\n", err); - return errno_to_gerr(err); - } - return i; + return errno_to_gerr(err); + } + return i; } /* @@ -450,91 +444,92 @@ _gnutls_writev (gnutls_session_t session, const giovec_t * giovec, * */ ssize_t -_gnutls_io_read_buffered (gnutls_session_t session, size_t total, - content_type_t recv_type, unsigned int *ms) +_gnutls_io_read_buffered(gnutls_session_t session, size_t total, + content_type_t recv_type, unsigned int *ms) { - ssize_t ret; - size_t min; - mbuffer_st *bufel = NULL; - size_t recvdata, readsize; - - if (total > MAX_RECV_SIZE(session) || total == 0) - { - gnutls_assert (); /* internal error */ - return GNUTLS_E_INVALID_REQUEST; - } - - /* calculate the actual size, ie. get the minimum of the - * buffered data and the requested data. - */ - min = MIN (session->internals.record_recv_buffer.byte_length, total); - if (min > 0) - { - /* if we have enough buffered data - * then just return them. - */ - if (min == total) - { - return min; - } - } - - /* min is over zero. recvdata is the data we must - * receive in order to return the requested data. - */ - recvdata = total - min; - readsize = recvdata; - - /* Check if the previously read data plus the new data to - * receive are longer than the maximum receive buffer size. - */ - if ((session->internals.record_recv_buffer.byte_length + recvdata) > - MAX_RECV_SIZE(session)) - { - gnutls_assert (); /* internal error */ - return GNUTLS_E_INVALID_REQUEST; - } - - /* READ DATA - */ - if (readsize > 0) - { - ret = - _gnutls_read (session, &bufel, readsize, - session->internals.pull_func, ms); - - /* return immediately if we got an interrupt or eagain - * error. - */ - if (ret < 0) - { - return gnutls_assert_val(ret); - } - - if (ret == 0) /* EOF */ - return gnutls_assert_val(0); - - /* copy fresh data to our buffer. - */ - _gnutls_read_log - ("RB: Have %d bytes into buffer. Adding %d bytes.\n", - (int) session->internals.record_recv_buffer.byte_length, (int) ret); - _gnutls_read_log ("RB: Requested %d bytes\n", (int) total); - - _mbuffer_enqueue (&session->internals.record_recv_buffer, bufel); - - if(IS_DTLS(session)) - ret = MIN(total, session->internals.record_recv_buffer.byte_length); - else - ret = session->internals.record_recv_buffer.byte_length; - - if ((ret > 0) && ((size_t) ret < total)) /* Short Read */ - return gnutls_assert_val(GNUTLS_E_AGAIN); - else - return ret; - } - else - return gnutls_assert_val(0); + ssize_t ret; + size_t min; + mbuffer_st *bufel = NULL; + size_t recvdata, readsize; + + if (total > MAX_RECV_SIZE(session) || total == 0) { + gnutls_assert(); /* internal error */ + return GNUTLS_E_INVALID_REQUEST; + } + + /* calculate the actual size, ie. get the minimum of the + * buffered data and the requested data. + */ + min = + MIN(session->internals.record_recv_buffer.byte_length, total); + if (min > 0) { + /* if we have enough buffered data + * then just return them. + */ + if (min == total) { + return min; + } + } + + /* min is over zero. recvdata is the data we must + * receive in order to return the requested data. + */ + recvdata = total - min; + readsize = recvdata; + + /* Check if the previously read data plus the new data to + * receive are longer than the maximum receive buffer size. + */ + if ((session->internals.record_recv_buffer.byte_length + + recvdata) > MAX_RECV_SIZE(session)) { + gnutls_assert(); /* internal error */ + return GNUTLS_E_INVALID_REQUEST; + } + + /* READ DATA + */ + if (readsize > 0) { + ret = + _gnutls_read(session, &bufel, readsize, + session->internals.pull_func, ms); + + /* return immediately if we got an interrupt or eagain + * error. + */ + if (ret < 0) { + return gnutls_assert_val(ret); + } + + if (ret == 0) /* EOF */ + return gnutls_assert_val(0); + + /* copy fresh data to our buffer. + */ + _gnutls_read_log + ("RB: Have %d bytes into buffer. Adding %d bytes.\n", + (int) session->internals.record_recv_buffer. + byte_length, (int) ret); + _gnutls_read_log("RB: Requested %d bytes\n", (int) total); + + _mbuffer_enqueue(&session->internals.record_recv_buffer, + bufel); + + if (IS_DTLS(session)) + ret = + MIN(total, + session->internals.record_recv_buffer. + byte_length); + else + ret = + session->internals.record_recv_buffer. + byte_length; + + if ((ret > 0) && ((size_t) ret < total)) /* Short Read */ + return gnutls_assert_val(GNUTLS_E_AGAIN); + else + return ret; + } else + return gnutls_assert_val(0); } /* This function is like write. But it does not return -1 on error. @@ -551,106 +546,98 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total, * */ ssize_t -_gnutls_io_write_buffered (gnutls_session_t session, - mbuffer_st * bufel, unsigned int mflag) +_gnutls_io_write_buffered(gnutls_session_t session, + mbuffer_st * bufel, unsigned int mflag) { - mbuffer_head_st *const send_buffer = &session->internals.record_send_buffer; + mbuffer_head_st *const send_buffer = + &session->internals.record_send_buffer; - /* to know where the procedure was interrupted. - */ - session->internals.direction = 1; + /* to know where the procedure was interrupted. + */ + session->internals.direction = 1; - _mbuffer_enqueue (send_buffer, bufel); + _mbuffer_enqueue(send_buffer, bufel); - _gnutls_write_log - ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n", - (int) bufel->msg.size, session->internals.transport_recv_ptr, - (int) send_buffer->byte_length); + _gnutls_write_log + ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n", + (int) bufel->msg.size, session->internals.transport_recv_ptr, + (int) send_buffer->byte_length); - if (mflag == MBUFFER_FLUSH) - return _gnutls_io_write_flush (session); - else - return bufel->msg.size; + if (mflag == MBUFFER_FLUSH) + return _gnutls_io_write_flush(session); + else + return bufel->msg.size; } -typedef ssize_t (*send_func) (gnutls_session_t, const giovec_t *, int); +typedef ssize_t(*send_func) (gnutls_session_t, const giovec_t *, int); /* This function writes the data that are left in the * TLS write buffer (ie. because the previous write was * interrupted. */ -ssize_t -_gnutls_io_write_flush (gnutls_session_t session) +ssize_t _gnutls_io_write_flush(gnutls_session_t session) { - gnutls_datum_t msg; - mbuffer_head_st *send_buffer = &session->internals.record_send_buffer; - int ret; - ssize_t sent = 0, tosend = 0; - giovec_t iovec[MAX_QUEUE]; - int i = 0; - mbuffer_st *cur; - - _gnutls_write_log ("WRITE FLUSH: %d bytes in buffer.\n", - (int) send_buffer->byte_length); - - for (cur = _mbuffer_head_get_first (send_buffer, &msg); - cur != NULL; cur = _mbuffer_head_get_next (cur, &msg)) - { - iovec[i].iov_base = msg.data; - iovec[i++].iov_len = msg.size; - tosend += msg.size; - - /* we buffer up to MAX_QUEUE messages */ - if (i >= MAX_QUEUE) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - } - - if (tosend == 0) - { - gnutls_assert(); - return 0; - } - - ret = _gnutls_writev (session, iovec, i); - if (ret >= 0) - { - _mbuffer_head_remove_bytes (send_buffer, ret); - _gnutls_write_log ("WRITE: wrote %d bytes, %d bytes left.\n", - ret, (int) send_buffer->byte_length); - - sent += ret; - } - else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) - { - _gnutls_write_log ("WRITE interrupted: %d bytes left.\n", - (int) send_buffer->byte_length); - return ret; - } - else if (ret == GNUTLS_E_LARGE_PACKET) - { - _mbuffer_head_remove_bytes (send_buffer, tosend); - _gnutls_write_log ("WRITE cannot send large packet (%u bytes).\n", - (unsigned int) tosend); - return ret; - } - else - { - _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n", - ret, (int) send_buffer->byte_length); - - gnutls_assert (); - return ret; - } - - if (sent < tosend) - { - return gnutls_assert_val(GNUTLS_E_AGAIN); - } - - return sent; + gnutls_datum_t msg; + mbuffer_head_st *send_buffer = + &session->internals.record_send_buffer; + int ret; + ssize_t sent = 0, tosend = 0; + giovec_t iovec[MAX_QUEUE]; + int i = 0; + mbuffer_st *cur; + + _gnutls_write_log("WRITE FLUSH: %d bytes in buffer.\n", + (int) send_buffer->byte_length); + + for (cur = _mbuffer_head_get_first(send_buffer, &msg); + cur != NULL; cur = _mbuffer_head_get_next(cur, &msg)) { + iovec[i].iov_base = msg.data; + iovec[i++].iov_len = msg.size; + tosend += msg.size; + + /* we buffer up to MAX_QUEUE messages */ + if (i >= MAX_QUEUE) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + } + + if (tosend == 0) { + gnutls_assert(); + return 0; + } + + ret = _gnutls_writev(session, iovec, i); + if (ret >= 0) { + _mbuffer_head_remove_bytes(send_buffer, ret); + _gnutls_write_log + ("WRITE: wrote %d bytes, %d bytes left.\n", ret, + (int) send_buffer->byte_length); + + sent += ret; + } else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + _gnutls_write_log("WRITE interrupted: %d bytes left.\n", + (int) send_buffer->byte_length); + return ret; + } else if (ret == GNUTLS_E_LARGE_PACKET) { + _mbuffer_head_remove_bytes(send_buffer, tosend); + _gnutls_write_log + ("WRITE cannot send large packet (%u bytes).\n", + (unsigned int) tosend); + return ret; + } else { + _gnutls_write_log("WRITE error: code %d, %d bytes left.\n", + ret, (int) send_buffer->byte_length); + + gnutls_assert(); + return ret; + } + + if (sent < tosend) { + return gnutls_assert_val(GNUTLS_E_AGAIN); + } + + return sent; } /* Checks whether there are received data within @@ -659,30 +646,31 @@ _gnutls_io_write_flush (gnutls_session_t session) * Returns 0 if data were received, GNUTLS_E_TIMEDOUT * on timeout and a negative error code on error. */ -int -_gnutls_io_check_recv (gnutls_session_t session, unsigned int ms) +int _gnutls_io_check_recv(gnutls_session_t session, unsigned int ms) { - gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; - int ret = 0, err; - - if (unlikely(session->internals.pull_timeout_func == system_recv_timeout && - session->internals.pull_func != system_read)) - return gnutls_assert_val(GNUTLS_E_PULL_ERROR); - - reset_errno (session); - - ret = session->internals.pull_timeout_func(fd, ms); - if (ret == -1) - { - err = get_errno (session); - _gnutls_read_log ("READ_TIMEOUT: %d returned from %p, errno=%d (timeout: %u)\n", - (int) ret, fd, err, ms); - return errno_to_gerr(err); - } - - if (ret > 0) - return 0; - else return GNUTLS_E_TIMEDOUT; + gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; + int ret = 0, err; + + if (unlikely + (session->internals.pull_timeout_func == system_recv_timeout + && session->internals.pull_func != system_read)) + return gnutls_assert_val(GNUTLS_E_PULL_ERROR); + + reset_errno(session); + + ret = session->internals.pull_timeout_func(fd, ms); + if (ret == -1) { + err = get_errno(session); + _gnutls_read_log + ("READ_TIMEOUT: %d returned from %p, errno=%d (timeout: %u)\n", + (int) ret, fd, err, ms); + return errno_to_gerr(err); + } + + if (ret > 0) + return 0; + else + return GNUTLS_E_TIMEDOUT; } /* HANDSHAKE buffers part @@ -693,56 +681,53 @@ _gnutls_io_check_recv (gnutls_session_t session, unsigned int ms) * interrupted. * */ -ssize_t -_gnutls_handshake_io_write_flush (gnutls_session_t session) +ssize_t _gnutls_handshake_io_write_flush(gnutls_session_t session) { - mbuffer_head_st *const send_buffer = - &session->internals.handshake_send_buffer; - gnutls_datum_t msg; - int ret; - uint16_t epoch; - ssize_t total = 0; - mbuffer_st *cur; - - _gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n", - (int) send_buffer->byte_length); - - if (IS_DTLS(session)) - return _dtls_transmit(session); - - for (cur = _mbuffer_head_get_first (send_buffer, &msg); - cur != NULL; cur = _mbuffer_head_get_first (send_buffer, &msg)) - { - epoch = cur->epoch; - - ret = _gnutls_send_int (session, cur->type, - cur->htype, - epoch, - msg.data, msg.size, 0); - - if (ret >= 0) - { - total += ret; - - ret = _mbuffer_head_remove_bytes (send_buffer, ret); - if (ret == 1) - _gnutls_epoch_refcount_dec(session, epoch); - - _gnutls_write_log ("HWRITE: wrote %d bytes, %d bytes left.\n", - ret, (int) send_buffer->byte_length); - - } - else - { - _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n", - ret, (int) send_buffer->byte_length); - - gnutls_assert (); - return ret; - } - } - - return _gnutls_io_write_flush (session); + mbuffer_head_st *const send_buffer = + &session->internals.handshake_send_buffer; + gnutls_datum_t msg; + int ret; + uint16_t epoch; + ssize_t total = 0; + mbuffer_st *cur; + + _gnutls_write_log("HWRITE FLUSH: %d bytes in buffer.\n", + (int) send_buffer->byte_length); + + if (IS_DTLS(session)) + return _dtls_transmit(session); + + for (cur = _mbuffer_head_get_first(send_buffer, &msg); + cur != NULL; cur = _mbuffer_head_get_first(send_buffer, &msg)) + { + epoch = cur->epoch; + + ret = _gnutls_send_int(session, cur->type, + cur->htype, + epoch, msg.data, msg.size, 0); + + if (ret >= 0) { + total += ret; + + ret = _mbuffer_head_remove_bytes(send_buffer, ret); + if (ret == 1) + _gnutls_epoch_refcount_dec(session, epoch); + + _gnutls_write_log + ("HWRITE: wrote %d bytes, %d bytes left.\n", + ret, (int) send_buffer->byte_length); + + } else { + _gnutls_write_log + ("HWRITE error: code %d, %d bytes left.\n", + ret, (int) send_buffer->byte_length); + + gnutls_assert(); + return ret; + } + } + + return _gnutls_io_write_flush(session); } @@ -751,275 +736,327 @@ _gnutls_handshake_io_write_flush (gnutls_session_t session) * */ int -_gnutls_handshake_io_cache_int (gnutls_session_t session, - gnutls_handshake_description_t htype, - mbuffer_st * bufel) +_gnutls_handshake_io_cache_int(gnutls_session_t session, + gnutls_handshake_description_t htype, + mbuffer_st * bufel) { - mbuffer_head_st * send_buffer; - - if (IS_DTLS(session)) - { - bufel->handshake_sequence = session->internals.dtls.hsk_write_seq-1; - } - - send_buffer = - &session->internals.handshake_send_buffer; - - bufel->epoch = (uint16_t)_gnutls_epoch_refcount_inc(session, EPOCH_WRITE_CURRENT); - bufel->htype = htype; - if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC) - bufel->type = GNUTLS_CHANGE_CIPHER_SPEC; - else - bufel->type = GNUTLS_HANDSHAKE; - - _mbuffer_enqueue (send_buffer, bufel); - - _gnutls_write_log - ("HWRITE: enqueued [%s] %d. Total %d bytes.\n", - _gnutls_handshake2str (bufel->htype), (int) bufel->msg.size, (int) send_buffer->byte_length); - - return 0; + mbuffer_head_st *send_buffer; + + if (IS_DTLS(session)) { + bufel->handshake_sequence = + session->internals.dtls.hsk_write_seq - 1; + } + + send_buffer = &session->internals.handshake_send_buffer; + + bufel->epoch = + (uint16_t) _gnutls_epoch_refcount_inc(session, + EPOCH_WRITE_CURRENT); + bufel->htype = htype; + if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC) + bufel->type = GNUTLS_CHANGE_CIPHER_SPEC; + else + bufel->type = GNUTLS_HANDSHAKE; + + _mbuffer_enqueue(send_buffer, bufel); + + _gnutls_write_log + ("HWRITE: enqueued [%s] %d. Total %d bytes.\n", + _gnutls_handshake2str(bufel->htype), (int) bufel->msg.size, + (int) send_buffer->byte_length); + + return 0; } -static int handshake_compare(const void* _e1, const void* _e2) +static int handshake_compare(const void *_e1, const void *_e2) { -const handshake_buffer_st* e1 = _e1; -const handshake_buffer_st* e2 = _e2; + const handshake_buffer_st *e1 = _e1; + const handshake_buffer_st *e2 = _e2; - if (e1->sequence <= e2->sequence) - return 1; - else - return -1; + if (e1->sequence <= e2->sequence) + return 1; + else + return -1; } #define SSL2_HEADERS 1 static int -parse_handshake_header (gnutls_session_t session, mbuffer_st* bufel, - handshake_buffer_st* hsk) +parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel, + handshake_buffer_st * hsk) { - uint8_t *dataptr = NULL; /* for realloc */ - size_t handshake_header_size = HANDSHAKE_HEADER_SIZE(session), data_size; - - /* Note: SSL2_HEADERS == 1 */ - if (_mbuffer_get_udata_size(bufel) < handshake_header_size) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - - dataptr = _mbuffer_get_udata_ptr(bufel); - - /* if reading a client hello of SSLv2 */ - if (unlikely(!IS_DTLS(session) && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)) - { - handshake_header_size = SSL2_HEADERS; /* we've already read one byte */ - - hsk->length = _mbuffer_get_udata_size(bufel) - handshake_header_size; /* we've read the first byte */ - - if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); - - hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2; - - hsk->sequence = 0; - hsk->start_offset = 0; - hsk->end_offset = hsk->length; - } - else /* TLS or DTLS handshake headers */ - { - - hsk->htype = dataptr[0]; - - /* we do not use DECR_LEN because we know - * that the packet has enough data. - */ - hsk->length = _gnutls_read_uint24 (&dataptr[1]); - handshake_header_size = HANDSHAKE_HEADER_SIZE(session); - - if (IS_DTLS(session)) - { - hsk->sequence = _gnutls_read_uint16 (&dataptr[4]); - hsk->start_offset = _gnutls_read_uint24 (&dataptr[6]); - hsk->end_offset = hsk->start_offset + _gnutls_read_uint24 (&dataptr[9]); - } - else - { - hsk->sequence = 0; - hsk->start_offset = 0; - hsk->end_offset = MIN((_mbuffer_get_udata_size(bufel) - handshake_header_size), hsk->length); - } - } - data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size; - - /* make the length offset */ - if (hsk->end_offset > 0) hsk->end_offset--; - - _gnutls_handshake_log ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n", - session, _gnutls_handshake2str (hsk->htype), (unsigned)hsk->htype, - (int) hsk->length, (int)data_size, hsk->start_offset, hsk->end_offset-hsk->start_offset+1, (int)hsk->sequence); - - hsk->header_size = handshake_header_size; - memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel), handshake_header_size); - - if (hsk->length > 0 && - (hsk->end_offset-hsk->start_offset >= data_size)) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - - if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset || - hsk->end_offset-hsk->start_offset >= data_size || - hsk->end_offset >= hsk->length)) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - else if (hsk->length == 0 && hsk->end_offset != 0 && hsk->start_offset != 0) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - - return handshake_header_size; + uint8_t *dataptr = NULL; /* for realloc */ + size_t handshake_header_size = + HANDSHAKE_HEADER_SIZE(session), data_size; + + /* Note: SSL2_HEADERS == 1 */ + if (_mbuffer_get_udata_size(bufel) < handshake_header_size) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + dataptr = _mbuffer_get_udata_ptr(bufel); + + /* if reading a client hello of SSLv2 */ + if (unlikely + (!IS_DTLS(session) + && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)) { + handshake_header_size = SSL2_HEADERS; /* we've already read one byte */ + + hsk->length = _mbuffer_get_udata_size(bufel) - handshake_header_size; /* we've read the first byte */ + + if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + + hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2; + + hsk->sequence = 0; + hsk->start_offset = 0; + hsk->end_offset = hsk->length; + } else { /* TLS or DTLS handshake headers */ + + + hsk->htype = dataptr[0]; + + /* we do not use DECR_LEN because we know + * that the packet has enough data. + */ + hsk->length = _gnutls_read_uint24(&dataptr[1]); + handshake_header_size = HANDSHAKE_HEADER_SIZE(session); + + if (IS_DTLS(session)) { + hsk->sequence = _gnutls_read_uint16(&dataptr[4]); + hsk->start_offset = + _gnutls_read_uint24(&dataptr[6]); + hsk->end_offset = + hsk->start_offset + + _gnutls_read_uint24(&dataptr[9]); + } else { + hsk->sequence = 0; + hsk->start_offset = 0; + hsk->end_offset = + MIN((_mbuffer_get_udata_size(bufel) - + handshake_header_size), hsk->length); + } + } + data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size; + + /* make the length offset */ + if (hsk->end_offset > 0) + hsk->end_offset--; + + _gnutls_handshake_log + ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n", + session, _gnutls_handshake2str(hsk->htype), + (unsigned) hsk->htype, (int) hsk->length, (int) data_size, + hsk->start_offset, hsk->end_offset - hsk->start_offset + 1, + (int) hsk->sequence); + + hsk->header_size = handshake_header_size; + memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel), + handshake_header_size); + + if (hsk->length > 0 && + (hsk->end_offset - hsk->start_offset >= data_size)) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset || + hsk->end_offset - hsk->start_offset >= + data_size + || hsk->end_offset >= hsk->length)) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + else if (hsk->length == 0 && hsk->end_offset != 0 + && hsk->start_offset != 0) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + return handshake_header_size; } -static void _gnutls_handshake_buffer_move(handshake_buffer_st* dst, handshake_buffer_st* src) +static void _gnutls_handshake_buffer_move(handshake_buffer_st * dst, + handshake_buffer_st * src) { - memcpy(dst, src, sizeof(*dst)); - memset(src, 0, sizeof(*src)); - src->htype = -1; + memcpy(dst, src, sizeof(*dst)); + memset(src, 0, sizeof(*src)); + src->htype = -1; } /* will merge the given handshake_buffer_st to the handshake_recv_buffer * list. The given hsk packet will be released in any case (success or failure). * Only used in DTLS. */ -static int merge_handshake_packet(gnutls_session_t session, handshake_buffer_st* hsk) +static int merge_handshake_packet(gnutls_session_t session, + handshake_buffer_st * hsk) { -int exists = 0, i, pos = 0; -int ret; - - for (i=0;i<session->internals.handshake_recv_buffer_size;i++) - { - if (session->internals.handshake_recv_buffer[i].htype == hsk->htype) - { - exists = 1; - pos = i; - break; - } - } - - if (exists == 0) - pos = session->internals.handshake_recv_buffer_size; - - if (pos > MAX_HANDSHAKE_MSGS) - return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS); - - if (exists == 0) - { - if (hsk->length > 0 && hsk->end_offset > 0 && hsk->end_offset-hsk->start_offset+1 != hsk->length) - { - ret = _gnutls_buffer_resize(&hsk->data, hsk->length); - if (ret < 0) - return gnutls_assert_val(ret); - - hsk->data.length = hsk->length; - - memmove(&hsk->data.data[hsk->start_offset], hsk->data.data, hsk->end_offset-hsk->start_offset+1); - } - - session->internals.handshake_recv_buffer_size++; - - /* rewrite headers to make them look as each packet came as a single fragment */ - _gnutls_write_uint24(hsk->length, &hsk->header[1]); - _gnutls_write_uint24(0, &hsk->header[6]); - _gnutls_write_uint24(hsk->length, &hsk->header[9]); - - _gnutls_handshake_buffer_move(&session->internals.handshake_recv_buffer[pos], hsk); - - } - else - { - if (hsk->start_offset < session->internals.handshake_recv_buffer[pos].start_offset && - hsk->end_offset >= session->internals.handshake_recv_buffer[pos].start_offset) - { - memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset], - hsk->data.data, hsk->data.length); - session->internals.handshake_recv_buffer[pos].start_offset = hsk->start_offset; - session->internals.handshake_recv_buffer[pos].end_offset = - MIN(hsk->end_offset, session->internals.handshake_recv_buffer[pos].end_offset); - } - else if (hsk->end_offset > session->internals.handshake_recv_buffer[pos].end_offset && - hsk->start_offset <= session->internals.handshake_recv_buffer[pos].end_offset+1) - { - memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset], - hsk->data.data, hsk->data.length); - - session->internals.handshake_recv_buffer[pos].end_offset = hsk->end_offset; - session->internals.handshake_recv_buffer[pos].start_offset = - MIN(hsk->start_offset, session->internals.handshake_recv_buffer[pos].start_offset); - } - _gnutls_handshake_buffer_clear(hsk); - } - - return 0; + int exists = 0, i, pos = 0; + int ret; + + for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) { + if (session->internals.handshake_recv_buffer[i].htype == + hsk->htype) { + exists = 1; + pos = i; + break; + } + } + + if (exists == 0) + pos = session->internals.handshake_recv_buffer_size; + + if (pos > MAX_HANDSHAKE_MSGS) + return + gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS); + + if (exists == 0) { + if (hsk->length > 0 && hsk->end_offset > 0 + && hsk->end_offset - hsk->start_offset + 1 != + hsk->length) { + ret = + _gnutls_buffer_resize(&hsk->data, hsk->length); + if (ret < 0) + return gnutls_assert_val(ret); + + hsk->data.length = hsk->length; + + memmove(&hsk->data.data[hsk->start_offset], + hsk->data.data, + hsk->end_offset - hsk->start_offset + 1); + } + + session->internals.handshake_recv_buffer_size++; + + /* rewrite headers to make them look as each packet came as a single fragment */ + _gnutls_write_uint24(hsk->length, &hsk->header[1]); + _gnutls_write_uint24(0, &hsk->header[6]); + _gnutls_write_uint24(hsk->length, &hsk->header[9]); + + _gnutls_handshake_buffer_move(&session->internals. + handshake_recv_buffer[pos], + hsk); + + } else { + if (hsk->start_offset < + session->internals.handshake_recv_buffer[pos]. + start_offset + && hsk->end_offset >= + session->internals.handshake_recv_buffer[pos]. + start_offset) { + memcpy(&session->internals. + handshake_recv_buffer[pos].data.data[hsk-> + start_offset], + hsk->data.data, hsk->data.length); + session->internals.handshake_recv_buffer[pos]. + start_offset = hsk->start_offset; + session->internals.handshake_recv_buffer[pos]. + end_offset = + MIN(hsk->end_offset, + session->internals. + handshake_recv_buffer[pos].end_offset); + } else if (hsk->end_offset > + session->internals.handshake_recv_buffer[pos]. + end_offset + && hsk->start_offset <= + session->internals.handshake_recv_buffer[pos]. + end_offset + 1) { + memcpy(&session->internals. + handshake_recv_buffer[pos].data.data[hsk-> + start_offset], + hsk->data.data, hsk->data.length); + + session->internals.handshake_recv_buffer[pos]. + end_offset = hsk->end_offset; + session->internals.handshake_recv_buffer[pos]. + start_offset = + MIN(hsk->start_offset, + session->internals. + handshake_recv_buffer[pos].start_offset); + } + _gnutls_handshake_buffer_clear(hsk); + } + + return 0; } /* returns non-zero on match and zero on mismatch */ -inline static int cmp_hsk_types(gnutls_handshake_description_t expected, gnutls_handshake_description_t recvd) +inline static int cmp_hsk_types(gnutls_handshake_description_t expected, + gnutls_handshake_description_t recvd) { - if ((expected != GNUTLS_HANDSHAKE_CLIENT_HELLO || recvd != GNUTLS_HANDSHAKE_CLIENT_HELLO_V2) && - (expected != recvd)) - return 0; - - return 1; + if ((expected != GNUTLS_HANDSHAKE_CLIENT_HELLO + || recvd != GNUTLS_HANDSHAKE_CLIENT_HELLO_V2) + && (expected != recvd)) + return 0; + + return 1; } #define LAST_ELEMENT (session->internals.handshake_recv_buffer_size-1) /* returns the last stored handshake packet. */ -static int get_last_packet(gnutls_session_t session, gnutls_handshake_description_t htype, - handshake_buffer_st * hsk, unsigned int optional) +static int get_last_packet(gnutls_session_t session, + gnutls_handshake_description_t htype, + handshake_buffer_st * hsk, + unsigned int optional) { -handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer; - - if (IS_DTLS(session)) - { - if (session->internals.handshake_recv_buffer_size == 0 || - (session->internals.dtls.hsk_read_seq != recv_buf[LAST_ELEMENT].sequence)) - goto timeout; - - if (htype != recv_buf[LAST_ELEMENT].htype) - { - if (optional == 0) - _gnutls_audit_log(session, "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n", - _gnutls_handshake2str(recv_buf[0].htype), (int)recv_buf[0].htype, _gnutls_handshake2str(htype), (int)htype); - - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET); - } - - else if ((recv_buf[LAST_ELEMENT].start_offset == 0 && - recv_buf[LAST_ELEMENT].end_offset == recv_buf[LAST_ELEMENT].length -1) || - recv_buf[LAST_ELEMENT].length == 0) - { - session->internals.dtls.hsk_read_seq++; - _gnutls_handshake_buffer_move(hsk, &recv_buf[LAST_ELEMENT]); - session->internals.handshake_recv_buffer_size--; - return 0; - } - else - goto timeout; - } - else /* TLS */ - { - if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length == recv_buf[0].data.length) - { - if (cmp_hsk_types(htype, recv_buf[0].htype) == 0) - { - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET); - } - - _gnutls_handshake_buffer_move(hsk, &recv_buf[0]); - session->internals.handshake_recv_buffer_size--; - return 0; - } - else - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - } - -timeout: - RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0); + handshake_buffer_st *recv_buf = + session->internals.handshake_recv_buffer; + + if (IS_DTLS(session)) { + if (session->internals.handshake_recv_buffer_size == 0 || + (session->internals.dtls.hsk_read_seq != + recv_buf[LAST_ELEMENT].sequence)) + goto timeout; + + if (htype != recv_buf[LAST_ELEMENT].htype) { + if (optional == 0) + _gnutls_audit_log(session, + "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n", + _gnutls_handshake2str + (recv_buf[0].htype), + (int) recv_buf[0].htype, + _gnutls_handshake2str + (htype), (int) htype); + + return + gnutls_assert_val + (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET); + } + + else if ((recv_buf[LAST_ELEMENT].start_offset == 0 && + recv_buf[LAST_ELEMENT].end_offset == + recv_buf[LAST_ELEMENT].length - 1) + || recv_buf[LAST_ELEMENT].length == 0) { + session->internals.dtls.hsk_read_seq++; + _gnutls_handshake_buffer_move(hsk, + &recv_buf + [LAST_ELEMENT]); + session->internals.handshake_recv_buffer_size--; + return 0; + } else + goto timeout; + } else { /* TLS */ + + if (session->internals.handshake_recv_buffer_size > 0 + && recv_buf[0].length == recv_buf[0].data.length) { + if (cmp_hsk_types(htype, recv_buf[0].htype) == 0) { + return + gnutls_assert_val + (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET); + } + + _gnutls_handshake_buffer_move(hsk, &recv_buf[0]); + session->internals.handshake_recv_buffer_size--; + return 0; + } else + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + } + + timeout: + RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0); } /* This is a receive function for the gnutls handshake @@ -1027,208 +1064,250 @@ timeout: * * htype is the next handshake packet expected. */ -int -_gnutls_parse_record_buffered_msgs (gnutls_session_t session) +int _gnutls_parse_record_buffered_msgs(gnutls_session_t session) { - gnutls_datum_t msg; - mbuffer_st* bufel = NULL, *prev = NULL; - int ret; - size_t data_size; - handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer; - - bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg); - if (bufel == NULL) - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - - if (!IS_DTLS(session)) - { - ssize_t remain, append, header_size; - - do - { - if (bufel->type != GNUTLS_HANDSHAKE) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); - - /* if we have a half received message the complete it. - */ - remain = recv_buf[0].length - - recv_buf[0].data.length; - - /* this is the rest of a previous message */ - if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length > 0 && remain > 0) - { - if ((ssize_t)msg.size <= remain) - append = msg.size; - else - append = remain; - - ret = _gnutls_buffer_append_data(&recv_buf[0].data, msg.data, append); - if (ret < 0) - return gnutls_assert_val(ret); - - _mbuffer_head_remove_bytes(&session->internals.record_buffer, append); - } - else /* received new message */ - { - ret = parse_handshake_header(session, bufel, &recv_buf[0]); - if (ret < 0) - return gnutls_assert_val(ret); - - header_size = ret; - session->internals.handshake_recv_buffer_size = 1; - - _mbuffer_set_uhead_size(bufel, header_size); - - data_size = MIN(recv_buf[0].length, _mbuffer_get_udata_size(bufel)); - ret = _gnutls_buffer_append_data(&recv_buf[0].data, _mbuffer_get_udata_ptr(bufel), data_size); - if (ret < 0) - return gnutls_assert_val(ret); - _mbuffer_set_uhead_size(bufel, 0); - _mbuffer_head_remove_bytes(&session->internals.record_buffer, data_size+header_size); - } - - /* if packet is complete then return it - */ - if (recv_buf[0].length == - recv_buf[0].data.length) - { - return 0; - } - bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg); - } - while(bufel != NULL); - - /* if we are here it means that the received packets were not - * enough to complete the handshake packet. - */ - return gnutls_assert_val(GNUTLS_E_AGAIN); - } - else /* DTLS */ - { - handshake_buffer_st tmp; - - do - { - /* we now - * 0. parse headers - * 1. insert to handshake_recv_buffer - * 2. sort handshake_recv_buffer on sequence numbers - * 3. return first packet if completed or GNUTLS_E_AGAIN. - */ - do - { - if (bufel->type != GNUTLS_HANDSHAKE) - { - gnutls_assert(); - goto next; /* ignore packet */ - } - - _gnutls_handshake_buffer_init(&tmp); - - ret = parse_handshake_header(session, bufel, &tmp); - if (ret < 0) - { - gnutls_assert(); - _gnutls_audit_log(session, "Invalid handshake packet headers. Discarding.\n"); - break; - } - - _mbuffer_consume(&session->internals.record_buffer, bufel, ret); - - data_size = MIN(tmp.length, tmp.end_offset-tmp.start_offset+1); - - ret = _gnutls_buffer_append_data(&tmp.data, _mbuffer_get_udata_ptr(bufel), data_size); - if (ret < 0) - return gnutls_assert_val(ret); - - _mbuffer_consume(&session->internals.record_buffer, bufel, data_size); - - ret = merge_handshake_packet(session, &tmp); - if (ret < 0) - return gnutls_assert_val(ret); - - } - while(_mbuffer_get_udata_size(bufel) > 0); - - prev = bufel; - bufel = _mbuffer_dequeue(&session->internals.record_buffer, bufel); - - _mbuffer_xfree(&prev); - continue; - -next: - bufel = _mbuffer_head_get_next(bufel, NULL); - } - while(bufel != NULL); - - /* sort in descending order */ - if (session->internals.handshake_recv_buffer_size > 1) - qsort(recv_buf, session->internals.handshake_recv_buffer_size, - sizeof(recv_buf[0]), handshake_compare); - - while(session->internals.handshake_recv_buffer_size > 0 && - recv_buf[LAST_ELEMENT].sequence < session->internals.dtls.hsk_read_seq) - { - _gnutls_audit_log(session, "Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence); - _gnutls_handshake_buffer_clear(&recv_buf[LAST_ELEMENT]); - session->internals.handshake_recv_buffer_size--; - } - - return 0; - } + gnutls_datum_t msg; + mbuffer_st *bufel = NULL, *prev = NULL; + int ret; + size_t data_size; + handshake_buffer_st *recv_buf = + session->internals.handshake_recv_buffer; + + bufel = + _mbuffer_head_get_first(&session->internals.record_buffer, + &msg); + if (bufel == NULL) + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + if (!IS_DTLS(session)) { + ssize_t remain, append, header_size; + + do { + if (bufel->type != GNUTLS_HANDSHAKE) + return + gnutls_assert_val + (GNUTLS_E_UNEXPECTED_PACKET); + + /* if we have a half received message the complete it. + */ + remain = recv_buf[0].length - + recv_buf[0].data.length; + + /* this is the rest of a previous message */ + if (session->internals.handshake_recv_buffer_size > + 0 && recv_buf[0].length > 0 && remain > 0) { + if ((ssize_t) msg.size <= remain) + append = msg.size; + else + append = remain; + + ret = + _gnutls_buffer_append_data(&recv_buf + [0].data, + msg.data, + append); + if (ret < 0) + return gnutls_assert_val(ret); + + _mbuffer_head_remove_bytes(&session-> + internals. + record_buffer, + append); + } else { /* received new message */ + + ret = + parse_handshake_header(session, bufel, + &recv_buf[0]); + if (ret < 0) + return gnutls_assert_val(ret); + + header_size = ret; + session->internals. + handshake_recv_buffer_size = 1; + + _mbuffer_set_uhead_size(bufel, + header_size); + + data_size = + MIN(recv_buf[0].length, + _mbuffer_get_udata_size(bufel)); + ret = + _gnutls_buffer_append_data(&recv_buf + [0].data, + _mbuffer_get_udata_ptr + (bufel), + data_size); + if (ret < 0) + return gnutls_assert_val(ret); + _mbuffer_set_uhead_size(bufel, 0); + _mbuffer_head_remove_bytes(&session-> + internals. + record_buffer, + data_size + + header_size); + } + + /* if packet is complete then return it + */ + if (recv_buf[0].length == recv_buf[0].data.length) { + return 0; + } + bufel = + _mbuffer_head_get_first(&session->internals. + record_buffer, &msg); + } + while (bufel != NULL); + + /* if we are here it means that the received packets were not + * enough to complete the handshake packet. + */ + return gnutls_assert_val(GNUTLS_E_AGAIN); + } else { /* DTLS */ + + handshake_buffer_st tmp; + + do { + /* we now + * 0. parse headers + * 1. insert to handshake_recv_buffer + * 2. sort handshake_recv_buffer on sequence numbers + * 3. return first packet if completed or GNUTLS_E_AGAIN. + */ + do { + if (bufel->type != GNUTLS_HANDSHAKE) { + gnutls_assert(); + goto next; /* ignore packet */ + } + + _gnutls_handshake_buffer_init(&tmp); + + ret = + parse_handshake_header(session, bufel, + &tmp); + if (ret < 0) { + gnutls_assert(); + _gnutls_audit_log(session, + "Invalid handshake packet headers. Discarding.\n"); + break; + } + + _mbuffer_consume(&session->internals. + record_buffer, bufel, + ret); + + data_size = + MIN(tmp.length, + tmp.end_offset - tmp.start_offset + + 1); + + ret = + _gnutls_buffer_append_data(&tmp.data, + _mbuffer_get_udata_ptr + (bufel), + data_size); + if (ret < 0) + return gnutls_assert_val(ret); + + _mbuffer_consume(&session->internals. + record_buffer, bufel, + data_size); + + ret = + merge_handshake_packet(session, &tmp); + if (ret < 0) + return gnutls_assert_val(ret); + + } + while (_mbuffer_get_udata_size(bufel) > 0); + + prev = bufel; + bufel = + _mbuffer_dequeue(&session->internals. + record_buffer, bufel); + + _mbuffer_xfree(&prev); + continue; + + next: + bufel = _mbuffer_head_get_next(bufel, NULL); + } + while (bufel != NULL); + + /* sort in descending order */ + if (session->internals.handshake_recv_buffer_size > 1) + qsort(recv_buf, + session->internals. + handshake_recv_buffer_size, + sizeof(recv_buf[0]), handshake_compare); + + while (session->internals.handshake_recv_buffer_size > 0 && + recv_buf[LAST_ELEMENT].sequence < + session->internals.dtls.hsk_read_seq) { + _gnutls_audit_log(session, + "Discarded replayed handshake packet with sequence %d\n", + recv_buf[LAST_ELEMENT].sequence); + _gnutls_handshake_buffer_clear(&recv_buf + [LAST_ELEMENT]); + session->internals.handshake_recv_buffer_size--; + } + + return 0; + } } /* This is a receive function for the gnutls handshake * protocol. Makes sure that we have received all data. */ ssize_t -_gnutls_handshake_io_recv_int (gnutls_session_t session, - gnutls_handshake_description_t htype, - handshake_buffer_st * hsk, unsigned int optional) +_gnutls_handshake_io_recv_int(gnutls_session_t session, + gnutls_handshake_description_t htype, + handshake_buffer_st * hsk, + unsigned int optional) { - int ret; - unsigned int tleft = 0; - - ret = get_last_packet(session, htype, hsk, optional); - if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) - { - return gnutls_assert_val(ret); - } - - /* try using the already existing records before - * trying to receive. - */ - ret = _gnutls_parse_record_buffered_msgs(session); - - if (ret == 0) ret = get_last_packet(session, htype, hsk, optional); - - if (IS_DTLS(session)) - { - if (ret >= 0) - return ret; - } - else - { - if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE && ret < 0) || ret >= 0) - return gnutls_assert_val(ret); - } - - if (htype != (unsigned)-1) - { - ret = handshake_remaining_time(session); - if (ret < 0) - return gnutls_assert_val(ret); - tleft = ret; - } - - /* if we don't have a complete message waiting for us, try - * receiving more */ - ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype, tleft); - if (ret < 0) - return gnutls_assert_val_fatal(ret); - - ret = _gnutls_parse_record_buffered_msgs(session); - if (ret == 0) ret = get_last_packet(session, htype, hsk, optional); - - return ret; + int ret; + unsigned int tleft = 0; + + ret = get_last_packet(session, htype, hsk, optional); + if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED + && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + return gnutls_assert_val(ret); + } + + /* try using the already existing records before + * trying to receive. + */ + ret = _gnutls_parse_record_buffered_msgs(session); + + if (ret == 0) + ret = get_last_packet(session, htype, hsk, optional); + + if (IS_DTLS(session)) { + if (ret >= 0) + return ret; + } else { + if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE + && ret < 0) || ret >= 0) + return gnutls_assert_val(ret); + } + + if (htype != (unsigned) -1) { + ret = handshake_remaining_time(session); + if (ret < 0) + return gnutls_assert_val(ret); + tleft = ret; + } + + /* if we don't have a complete message waiting for us, try + * receiving more */ + ret = + _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype, + tleft); + if (ret < 0) + return gnutls_assert_val_fatal(ret); + + ret = _gnutls_parse_record_buffered_msgs(session); + if (ret == 0) + ret = get_last_packet(session, htype, hsk, optional); + + return ret; } |