gnutls_record_check_pending functionality was divided to gnutls_record_check_pending...
[gnutls.git] / lib / gnutls_buffers.c
bloba7c00cad9223897223b7a38f512f0292856b72f1
1 /*
2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /*
24 * This file holds all the buffering code used in gnutls.
25 * The buffering code works as:
27 * RECORD LAYER:
28 * 1. uses a buffer to hold data (application/handshake),
29 * we got but they were not requested, yet.
30 * (see gnutls_record_buffer_put(), gnutls_record_buffer_get_size() etc.)
32 * 2. uses a buffer to hold data that were incomplete (ie the read/write
33 * was interrupted)
34 * (see _gnutls_io_read_buffered(), _gnutls_io_write_buffered() etc.)
36 * HANDSHAKE LAYER:
37 * 1. Uses buffer to hold the last received handshake message.
38 * (see _gnutls_handshake_hash_buffer_put() etc.)
42 #include <gnutls_int.h>
43 #include <gnutls_errors.h>
44 #include <gnutls_num.h>
45 #include <gnutls_record.h>
46 #include <gnutls_buffers.h>
47 #include <gnutls_mbuffers.h>
48 #include <gnutls_state.h>
49 #include <gnutls_dtls.h>
50 #include <system.h>
51 #include <gnutls_constate.h> /* gnutls_epoch_get */
52 #include <errno.h>
53 #include <system.h>
54 #include "debug.h"
56 #ifndef EAGAIN
57 #define EAGAIN EWOULDBLOCK
58 #endif
60 /* this is the maximum number of messages allowed to queue.
62 #define MAX_QUEUE 32
64 /* Buffers received packets of type APPLICATION DATA and
65 * HANDSHAKE DATA.
67 int
68 _gnutls_record_buffer_put (gnutls_session_t session,
69 content_type_t type, uint64* seq, mbuffer_st* bufel)
72 bufel->type = type;
73 memcpy(&bufel->record_sequence, seq, sizeof(*seq));
75 _mbuffer_enqueue(&session->internals.record_buffer, bufel);
76 _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
77 (int) bufel->msg.size, (int) type);
79 return 0;
82 /**
83 * gnutls_record_check_pending:
84 * @session: is a #gnutls_session_t structure.
86 * This function checks if there are unread data
87 * in the gnutls buffers. If the return value is
88 * non-zero the next call to gnutls_record_recv()
89 * is guarranteed not to block.
91 * Returns: Returns the size of the data or zero.
92 **/
93 size_t
94 gnutls_record_check_pending (gnutls_session_t session)
96 return _gnutls_record_buffer_get_size (session);
99 /**
100 * gnutls_record_check_unprocessed:
101 * @session: is a #gnutls_session_t structure.
103 * This function checks if there are unprocessed data
104 * in the gnutls record buffers. Those data might not
105 * be complete records.
107 * Returns: Returns the size of the data or zero.
109 size_t
110 gnutls_record_check_unprocessed (gnutls_session_t session)
112 return session->internals.record_recv_buffer.byte_length;
116 _gnutls_record_buffer_get (content_type_t type,
117 gnutls_session_t session, uint8_t * data,
118 size_t length, uint8_t seq[8])
120 gnutls_datum_t msg;
121 mbuffer_st* bufel;
123 if (length == 0 || data == NULL)
125 gnutls_assert ();
126 return GNUTLS_E_INVALID_REQUEST;
129 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
130 if (bufel == NULL)
131 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
133 if (type != bufel->type)
135 if (IS_DTLS(session))
136 _gnutls_audit_log(session, "Discarded unexpected %s (%d) packet (expecting: %s (%d))\n",
137 _gnutls_packet2str(bufel->type), (int)bufel->type,
138 _gnutls_packet2str(type), (int)type);
139 _mbuffer_head_remove_bytes(&session->internals.record_buffer, msg.size);
140 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
143 if (msg.size <= length)
144 length = msg.size;
146 if (seq)
147 memcpy(seq, bufel->record_sequence.i, 8);
149 memcpy(data, msg.data, length);
150 _mbuffer_head_remove_bytes(&session->internals.record_buffer, length);
152 return length;
155 inline static void
156 reset_errno (gnutls_session_t session)
158 session->internals.errnum = 0;
161 inline static int
162 get_errno (gnutls_session_t session)
164 int ret;
166 if (session->internals.errnum != 0)
167 ret = session->internals.errnum;
168 else
169 ret = session->internals.errno_func (session->
170 internals.transport_recv_ptr);
171 return ret;
174 static ssize_t
175 _gnutls_dgram_read (gnutls_session_t session, mbuffer_st **bufel,
176 gnutls_pull_func pull_func)
178 ssize_t i, ret;
179 uint8_t *ptr;
180 size_t max_size = _gnutls_get_max_decrypted_data(session);
181 size_t recv_size = MAX_RECV_SIZE(session);
182 gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
184 if (recv_size > max_size)
185 recv_size = max_size;
187 *bufel = _mbuffer_alloc (0, max_size);
188 if (*bufel == NULL)
189 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
191 ptr = (*bufel)->msg.data;
193 session->internals.direction = 0;
195 reset_errno (session);
196 i = pull_func (fd, ptr, recv_size);
198 if (i < 0)
200 int err = get_errno (session);
202 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
203 (int) i, fd, errno, session->internals.errnum);
205 if (err == EAGAIN)
207 ret = GNUTLS_E_AGAIN;
208 goto cleanup;
210 else if (err == EINTR)
212 ret = GNUTLS_E_INTERRUPTED;
213 goto cleanup;
215 else
217 gnutls_assert ();
218 ret = GNUTLS_E_PULL_ERROR;
219 goto cleanup;
222 else
224 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
225 if (i == 0)
227 /* If we get here, we likely have a stream socket.
228 * FIXME: this probably breaks DCCP. */
229 gnutls_assert ();
230 ret = 0;
231 goto cleanup;
234 _mbuffer_set_udata_size (*bufel, i);
237 _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i, fd);
239 return i;
241 cleanup:
242 _mbuffer_xfree(bufel);
243 return ret;
246 static ssize_t
247 _gnutls_stream_read (gnutls_session_t session, mbuffer_st **bufel,
248 size_t size, gnutls_pull_func pull_func)
250 size_t left;
251 ssize_t i = 0;
252 size_t max_size = _gnutls_get_max_decrypted_data(session);
253 uint8_t *ptr;
254 gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
256 *bufel = _mbuffer_alloc (0, MAX(max_size, size));
257 if (!*bufel)
259 gnutls_assert ();
260 return GNUTLS_E_MEMORY_ERROR;
262 ptr = (*bufel)->msg.data;
264 session->internals.direction = 0;
266 left = size;
267 while (left > 0)
269 reset_errno (session);
271 i = pull_func (fd, &ptr[size - left], left);
273 if (i < 0)
275 int err = get_errno (session);
277 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
278 (int) i, fd, errno, session->internals.errnum);
280 if (err == EAGAIN || err == EINTR)
282 if (size - left > 0)
285 _gnutls_read_log ("READ: returning %d bytes from %p\n",
286 (int) (size - left), fd);
288 goto finish;
291 if (err == EAGAIN)
292 return GNUTLS_E_AGAIN;
293 return GNUTLS_E_INTERRUPTED;
295 else
297 gnutls_assert ();
298 return GNUTLS_E_PULL_ERROR;
301 else
304 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
306 if (i == 0)
307 break; /* EOF */
310 left -= i;
311 (*bufel)->msg.size += i;
314 finish:
316 _gnutls_read_log ("READ: read %d bytes from %p\n",
317 (int) (size - left), fd);
319 return (size - left);
323 /* This function is like read. But it does not return -1 on error.
324 * It does return gnutls_errno instead.
326 * Flags are only used if the default recv() function is being used.
328 static ssize_t
329 _gnutls_read (gnutls_session_t session, mbuffer_st **bufel,
330 size_t size, gnutls_pull_func pull_func)
332 if (IS_DTLS (session))
333 /* Size is not passed, since a whole datagram will be read. */
334 return _gnutls_dgram_read (session, bufel, pull_func);
335 else
336 return _gnutls_stream_read (session, bufel, size, pull_func);
339 static ssize_t
340 _gnutls_writev_emu (gnutls_session_t session, gnutls_transport_ptr_t fd, const giovec_t * giovec,
341 unsigned int giovec_cnt)
343 unsigned int j = 0;
344 size_t total = 0;
345 ssize_t ret = 0;
347 for (j = 0; j < giovec_cnt; j++)
349 ret = session->internals.push_func (fd, giovec[j].iov_base, giovec[j].iov_len);
351 if (ret == -1)
352 break;
354 total += ret;
356 if ((size_t)ret != giovec[j].iov_len)
357 break;
360 if (total > 0)
361 return total;
363 return ret;
366 static ssize_t
367 _gnutls_writev (gnutls_session_t session, const giovec_t * giovec,
368 int giovec_cnt)
370 int i;
371 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
373 reset_errno (session);
375 if (session->internals.push_func != NULL)
376 i = _gnutls_writev_emu (session, fd, giovec, giovec_cnt);
377 else
378 i = session->internals.vec_push_func (fd, giovec, giovec_cnt);
380 if (i == -1)
382 int err = get_errno (session);
383 _gnutls_debug_log ("errno: %d\n", err);
384 if (err == EAGAIN)
385 return GNUTLS_E_AGAIN;
386 else if (err == EINTR)
387 return GNUTLS_E_INTERRUPTED;
388 else
390 gnutls_assert ();
391 return GNUTLS_E_PUSH_ERROR;
394 return i;
397 /* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
398 * It does return gnutls_errno instead.
399 * This function reads data from the socket and keeps them in a buffer, of up to
400 * MAX_RECV_SIZE.
402 * This is not a general purpose function. It returns EXACTLY the data requested,
403 * which are stored in a local (in the session) buffer.
406 ssize_t
407 _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
408 content_type_t recv_type)
410 ssize_t ret = 0;
411 size_t min;
412 mbuffer_st *bufel = NULL;
413 size_t recvdata, readsize;
415 if (total > MAX_RECV_SIZE(session) || total == 0)
417 gnutls_assert (); /* internal error */
418 return GNUTLS_E_INVALID_REQUEST;
421 /* calculate the actual size, ie. get the minimum of the
422 * buffered data and the requested data.
424 min = MIN (session->internals.record_recv_buffer.byte_length, total);
425 if (min > 0)
427 /* if we have enough buffered data
428 * then just return them.
430 if (min == total)
432 return min;
436 /* min is over zero. recvdata is the data we must
437 * receive in order to return the requested data.
439 recvdata = total - min;
440 readsize = recvdata;
442 /* Check if the previously read data plus the new data to
443 * receive are longer than the maximum receive buffer size.
445 if ((session->internals.record_recv_buffer.byte_length + recvdata) >
446 MAX_RECV_SIZE(session))
448 gnutls_assert (); /* internal error */
449 return GNUTLS_E_INVALID_REQUEST;
452 if (ret < 0)
454 gnutls_assert ();
455 return ret;
458 /* READ DATA
460 if (readsize > 0)
462 ret =
463 _gnutls_read (session, &bufel, readsize,
464 session->internals.pull_func);
466 /* return immediately if we got an interrupt or eagain
467 * error.
469 if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
471 _mbuffer_xfree (&bufel);
472 return ret;
476 /* copy fresh data to our buffer.
478 if (ret > 0)
480 _gnutls_read_log
481 ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
482 (int) session->internals.record_recv_buffer.byte_length, (int) ret);
483 _gnutls_read_log ("RB: Requested %d bytes\n", (int) total);
485 _mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
487 else
488 _mbuffer_xfree (&bufel);
490 if (ret < 0)
492 gnutls_assert ();
493 return ret;
496 if (ret == 0)
497 { /* EOF */
498 gnutls_assert ();
499 return 0;
502 if(IS_DTLS(session))
503 ret = MIN(total, session->internals.record_recv_buffer.byte_length);
504 else
505 ret = session->internals.record_recv_buffer.byte_length;
507 if ((ret > 0) && ((size_t) ret < total))
509 /* Short Read */
510 return gnutls_assert_val(GNUTLS_E_AGAIN);
512 else
514 return ret;
518 /* This function is like write. But it does not return -1 on error.
519 * It does return gnutls_errno instead.
521 * This function takes full responsibility of freeing msg->data.
523 * In case of E_AGAIN and E_INTERRUPTED errors, you must call
524 * gnutls_write_flush(), until it returns ok (0).
526 * We need to push exactly the data in msg->size, since we cannot send
527 * less data. In TLS the peer must receive the whole packet in order
528 * to decrypt and verify the integrity.
531 ssize_t
532 _gnutls_io_write_buffered (gnutls_session_t session,
533 mbuffer_st * bufel, unsigned int mflag)
535 mbuffer_head_st *const send_buffer = &session->internals.record_send_buffer;
537 /* to know where the procedure was interrupted.
539 session->internals.direction = 1;
541 _mbuffer_enqueue (send_buffer, bufel);
543 _gnutls_write_log
544 ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n",
545 (int) bufel->msg.size, session->internals.transport_recv_ptr,
546 (int) send_buffer->byte_length);
548 if (mflag == MBUFFER_FLUSH)
549 return _gnutls_io_write_flush (session);
550 else
551 return bufel->msg.size;
554 typedef ssize_t (*send_func) (gnutls_session_t, const giovec_t *, int);
556 /* This function writes the data that are left in the
557 * TLS write buffer (ie. because the previous write was
558 * interrupted.
560 ssize_t
561 _gnutls_io_write_flush (gnutls_session_t session)
563 gnutls_datum_t msg;
564 mbuffer_head_st *send_buffer = &session->internals.record_send_buffer;
565 int ret;
566 ssize_t sent = 0, tosend = 0;
567 giovec_t iovec[MAX_QUEUE];
568 int i = 0;
569 mbuffer_st *cur;
571 _gnutls_write_log ("WRITE FLUSH: %d bytes in buffer.\n",
572 (int) send_buffer->byte_length);
574 for (cur = _mbuffer_head_get_first (send_buffer, &msg);
575 cur != NULL; cur = _mbuffer_head_get_next (cur, &msg))
577 iovec[i].iov_base = msg.data;
578 iovec[i++].iov_len = msg.size;
579 tosend += msg.size;
581 /* we buffer up to MAX_QUEUE messages */
582 if (i >= MAX_QUEUE)
584 gnutls_assert ();
585 return GNUTLS_E_INTERNAL_ERROR;
589 if (tosend == 0)
591 gnutls_assert();
592 return 0;
595 ret = _gnutls_writev (session, iovec, i);
596 if (ret >= 0)
598 _mbuffer_head_remove_bytes (send_buffer, ret);
599 _gnutls_write_log ("WRITE: wrote %d bytes, %d bytes left.\n",
600 ret, (int) send_buffer->byte_length);
602 sent += ret;
604 else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)
606 _gnutls_write_log ("WRITE interrupted: %d bytes left.\n",
607 (int) send_buffer->byte_length);
608 return ret;
610 else
612 _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n",
613 ret, (int) send_buffer->byte_length);
615 gnutls_assert ();
616 return ret;
619 if (sent < tosend)
621 return gnutls_assert_val(GNUTLS_E_AGAIN);
624 return sent;
627 /* Checks whether there are received data within
628 * a timeframe.
630 * Returns 0 if data were received, GNUTLS_E_TIMEDOUT
631 * on timeout and a negative error code on error.
634 _gnutls_io_check_recv (gnutls_session_t session, unsigned int ms)
636 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
637 int ret = 0, err;
639 if (session->internals.pull_timeout_func == system_recv_timeout &&
640 session->internals.pull_func != system_read)
641 return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
643 reset_errno (session);
645 ret = session->internals.pull_timeout_func(fd, ms);
647 err = get_errno (session);
648 if (ret == -1 && err == EINTR)
649 return GNUTLS_E_INTERRUPTED;
650 else if (ret == -1 && err == EAGAIN)
651 return GNUTLS_E_AGAIN;
652 else if (ret == -1)
653 return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
655 if (ret > 0)
656 return 0;
657 else return GNUTLS_E_TIMEDOUT;
660 /* HANDSHAKE buffers part
663 /* This function writes the data that are left in the
664 * Handshake write buffer (ie. because the previous write was
665 * interrupted.
668 ssize_t
669 _gnutls_handshake_io_write_flush (gnutls_session_t session)
671 mbuffer_head_st *const send_buffer =
672 &session->internals.handshake_send_buffer;
673 gnutls_datum_t msg;
674 int ret;
675 uint16_t epoch;
676 ssize_t total = 0;
677 mbuffer_st *cur;
679 _gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n",
680 (int) send_buffer->byte_length);
682 if (IS_DTLS(session))
683 return _dtls_transmit(session);
685 for (cur = _mbuffer_head_get_first (send_buffer, &msg);
686 cur != NULL; cur = _mbuffer_head_get_first (send_buffer, &msg))
688 epoch = cur->epoch;
690 ret = _gnutls_send_int (session, cur->type,
691 cur->htype,
692 epoch,
693 msg.data, msg.size, 0);
695 if (ret >= 0)
697 total += ret;
699 ret = _mbuffer_head_remove_bytes (send_buffer, ret);
700 if (ret == 1)
701 _gnutls_epoch_refcount_dec(session, epoch);
703 _gnutls_write_log ("HWRITE: wrote %d bytes, %d bytes left.\n",
704 ret, (int) send_buffer->byte_length);
707 else
709 _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n",
710 ret, (int) send_buffer->byte_length);
712 gnutls_assert ();
713 return ret;
717 return _gnutls_io_write_flush (session);
721 /* This is a send function for the gnutls handshake
722 * protocol. Just makes sure that all data have been sent.
726 _gnutls_handshake_io_cache_int (gnutls_session_t session,
727 gnutls_handshake_description_t htype,
728 mbuffer_st * bufel)
730 mbuffer_head_st * send_buffer;
732 if (IS_DTLS(session))
734 bufel->handshake_sequence = session->internals.dtls.hsk_write_seq-1;
737 send_buffer =
738 &session->internals.handshake_send_buffer;
740 bufel->epoch = (uint16_t)_gnutls_epoch_refcount_inc(session, EPOCH_WRITE_CURRENT);
741 bufel->htype = htype;
742 if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
743 bufel->type = GNUTLS_CHANGE_CIPHER_SPEC;
744 else
745 bufel->type = GNUTLS_HANDSHAKE;
747 _mbuffer_enqueue (send_buffer, bufel);
749 _gnutls_write_log
750 ("HWRITE: enqueued [%s] %d. Total %d bytes.\n",
751 _gnutls_handshake2str (bufel->htype), (int) bufel->msg.size, (int) send_buffer->byte_length);
753 return 0;
756 static int handshake_compare(const void* _e1, const void* _e2)
758 const handshake_buffer_st* e1 = _e1;
759 const handshake_buffer_st* e2 = _e2;
761 if (e1->sequence <= e2->sequence)
762 return 1;
763 else
764 return -1;
767 #define SSL2_HEADERS 1
768 static int
769 parse_handshake_header (gnutls_session_t session, mbuffer_st* bufel,
770 handshake_buffer_st* hsk)
772 uint8_t *dataptr = NULL; /* for realloc */
773 size_t handshake_header_size = HANDSHAKE_HEADER_SIZE(session), data_size;
775 /* Note: SSL2_HEADERS == 1 */
776 if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
777 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
779 dataptr = _mbuffer_get_udata_ptr(bufel);
781 /* if reading a client hello of SSLv2 */
782 if (!IS_DTLS(session) && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)
784 handshake_header_size = SSL2_HEADERS; /* we've already read one byte */
786 hsk->length = _mbuffer_get_udata_size(bufel) - handshake_header_size; /* we've read the first byte */
788 if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO)
789 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
791 hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
793 hsk->sequence = 0;
794 hsk->start_offset = 0;
795 hsk->end_offset = hsk->length;
797 else /* TLS handshake headers */
800 hsk->htype = dataptr[0];
802 /* we do not use DECR_LEN because we know
803 * that the packet has enough data.
805 hsk->length = _gnutls_read_uint24 (&dataptr[1]);
806 handshake_header_size = HANDSHAKE_HEADER_SIZE(session);
808 if (IS_DTLS(session))
810 hsk->sequence = _gnutls_read_uint16 (&dataptr[4]);
811 hsk->start_offset = _gnutls_read_uint24 (&dataptr[6]);
812 hsk->end_offset = hsk->start_offset + _gnutls_read_uint24 (&dataptr[9]);
814 else
816 hsk->sequence = 0;
817 hsk->start_offset = 0;
818 hsk->end_offset = hsk->length;
821 data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
823 /* make the length offset */
824 if (hsk->end_offset > 0) hsk->end_offset--;
826 _gnutls_handshake_log ("HSK[%p]: %s was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
827 session, _gnutls_handshake2str (hsk->htype),
828 (int) hsk->length, (int)data_size, hsk->start_offset, hsk->end_offset-hsk->start_offset+1, (int)hsk->sequence);
830 hsk->header_size = handshake_header_size;
831 memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel), handshake_header_size);
833 if (hsk->length > 0 &&
834 (hsk->end_offset-hsk->start_offset >= data_size))
835 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
837 if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset ||
838 hsk->end_offset-hsk->start_offset >= data_size ||
839 hsk->end_offset >= hsk->length))
840 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
841 else if (hsk->length == 0 && hsk->end_offset != 0 && hsk->start_offset != 0)
842 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
844 return handshake_header_size;
847 static void _gnutls_handshake_buffer_move(handshake_buffer_st* dst, handshake_buffer_st* src)
849 memcpy(dst, src, sizeof(*dst));
850 memset(src, 0, sizeof(*src));
851 src->htype = -1;
854 /* will merge the given handshake_buffer_st to the handshake_recv_buffer
855 * list. The given hsk packet will be released in any case (success or failure).
856 * Only used in DTLS.
858 static int merge_handshake_packet(gnutls_session_t session, handshake_buffer_st* hsk)
860 int exists = 0, i, pos = 0;
861 int ret;
863 for (i=0;i<session->internals.handshake_recv_buffer_size;i++)
865 if (session->internals.handshake_recv_buffer[i].htype == hsk->htype)
867 exists = 1;
868 pos = i;
869 break;
873 if (exists == 0)
874 pos = session->internals.handshake_recv_buffer_size;
876 if (pos > MAX_HANDSHAKE_MSGS)
877 return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
879 if (exists == 0)
881 if (hsk->length > 0 && hsk->end_offset > 0 && hsk->end_offset-hsk->start_offset+1 != hsk->length)
883 ret = _gnutls_buffer_resize(&hsk->data, hsk->length);
884 if (ret < 0)
885 return gnutls_assert_val(ret);
887 hsk->data.length = hsk->length;
889 memmove(&hsk->data.data[hsk->start_offset], hsk->data.data, hsk->end_offset-hsk->start_offset+1);
892 session->internals.handshake_recv_buffer_size++;
894 /* rewrite headers to make them look as each packet came as a single fragment */
895 _gnutls_write_uint24(hsk->length, &hsk->header[1]);
896 _gnutls_write_uint24(0, &hsk->header[6]);
897 _gnutls_write_uint24(hsk->length, &hsk->header[9]);
899 _gnutls_handshake_buffer_move(&session->internals.handshake_recv_buffer[pos], hsk);
902 else
904 if (hsk->start_offset < session->internals.handshake_recv_buffer[pos].start_offset &&
905 hsk->end_offset >= session->internals.handshake_recv_buffer[pos].start_offset)
907 memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset],
908 hsk->data.data, hsk->data.length);
909 session->internals.handshake_recv_buffer[pos].start_offset = hsk->start_offset;
910 session->internals.handshake_recv_buffer[pos].end_offset =
911 MIN(hsk->end_offset, session->internals.handshake_recv_buffer[pos].end_offset);
913 else if (hsk->end_offset > session->internals.handshake_recv_buffer[pos].end_offset &&
914 hsk->start_offset <= session->internals.handshake_recv_buffer[pos].end_offset+1)
916 memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset],
917 hsk->data.data, hsk->data.length);
919 session->internals.handshake_recv_buffer[pos].end_offset = hsk->end_offset;
920 session->internals.handshake_recv_buffer[pos].start_offset =
921 MIN(hsk->start_offset, session->internals.handshake_recv_buffer[pos].start_offset);
923 _gnutls_handshake_buffer_clear(hsk);
926 return 0;
929 /* returns non-zero on match and zero on mismatch
931 inline static int cmp_hsk_types(gnutls_handshake_description_t expected, gnutls_handshake_description_t recvd)
933 if ((expected != GNUTLS_HANDSHAKE_CLIENT_HELLO || recvd != GNUTLS_HANDSHAKE_CLIENT_HELLO_V2) &&
934 (expected != recvd))
935 return 0;
937 return 1;
940 #define LAST_ELEMENT (session->internals.handshake_recv_buffer_size-1)
942 /* returns the last stored handshake packet.
944 static int get_last_packet(gnutls_session_t session, gnutls_handshake_description_t htype,
945 handshake_buffer_st * hsk, unsigned int optional)
947 handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;
949 if (IS_DTLS(session))
951 if (session->internals.handshake_recv_buffer_size == 0 ||
952 (session->internals.dtls.hsk_read_seq != recv_buf[LAST_ELEMENT].sequence))
953 goto timeout;
955 if (htype != recv_buf[LAST_ELEMENT].htype)
957 if (optional == 0)
958 _gnutls_audit_log(session, "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n",
959 _gnutls_handshake2str(recv_buf[0].htype), (int)recv_buf[0].htype, _gnutls_handshake2str(htype), (int)htype);
961 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
964 else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
965 recv_buf[LAST_ELEMENT].end_offset == recv_buf[LAST_ELEMENT].length -1) ||
966 recv_buf[LAST_ELEMENT].length == 0)
968 session->internals.dtls.hsk_read_seq++;
969 _gnutls_handshake_buffer_move(hsk, &recv_buf[LAST_ELEMENT]);
970 session->internals.handshake_recv_buffer_size--;
971 return 0;
973 else
974 goto timeout;
976 else /* TLS */
978 if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length == recv_buf[0].data.length)
980 if (cmp_hsk_types(htype, recv_buf[0].htype) == 0)
982 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
985 _gnutls_handshake_buffer_move(hsk, &recv_buf[0]);
986 session->internals.handshake_recv_buffer_size--;
987 return 0;
989 else
990 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
993 timeout:
994 RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0);
997 /* This is a receive function for the gnutls handshake
998 * protocol. Makes sure that we have received all data.
1000 * htype is the next handshake packet expected.
1003 _gnutls_parse_record_buffered_msgs (gnutls_session_t session)
1005 gnutls_datum_t msg;
1006 mbuffer_st* bufel = NULL, *prev = NULL;
1007 int ret;
1008 size_t data_size;
1009 handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;
1011 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
1012 if (bufel == NULL)
1013 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1015 if (!IS_DTLS(session))
1017 ssize_t remain, append, header_size;
1021 if (bufel->type != GNUTLS_HANDSHAKE)
1022 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
1024 /* if we have a half received message the complete it.
1026 remain = recv_buf[0].length -
1027 recv_buf[0].data.length;
1029 /* this is the rest of a previous message */
1030 if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length > 0 && remain > 0)
1032 if (msg.size <= remain)
1033 append = msg.size;
1034 else
1035 append = remain;
1037 ret = _gnutls_buffer_append_data(&recv_buf[0].data, msg.data, append);
1038 if (ret < 0)
1039 return gnutls_assert_val(ret);
1041 _mbuffer_head_remove_bytes(&session->internals.record_buffer, append);
1043 else /* received new message */
1045 ret = parse_handshake_header(session, bufel, &recv_buf[0]);
1046 if (ret < 0)
1047 return gnutls_assert_val(ret);
1049 header_size = ret;
1050 session->internals.handshake_recv_buffer_size = 1;
1052 _mbuffer_set_uhead_size(bufel, header_size);
1054 data_size = MIN(recv_buf[0].length, _mbuffer_get_udata_size(bufel));
1055 ret = _gnutls_buffer_append_data(&recv_buf[0].data, _mbuffer_get_udata_ptr(bufel), data_size);
1056 if (ret < 0)
1057 return gnutls_assert_val(ret);
1058 _mbuffer_set_uhead_size(bufel, 0);
1059 _mbuffer_head_remove_bytes(&session->internals.record_buffer, data_size+header_size);
1062 /* if packet is complete then return it
1064 if (recv_buf[0].length ==
1065 recv_buf[0].data.length)
1067 return 0;
1069 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
1071 while(bufel != NULL);
1073 /* if we are here it means that the received packets were not
1074 * enough to complete the handshake packet.
1076 return gnutls_assert_val(GNUTLS_E_AGAIN);
1078 else /* DTLS */
1080 handshake_buffer_st tmp;
1084 /* we now
1085 * 0. parse headers
1086 * 1. insert to handshake_recv_buffer
1087 * 2. sort handshake_recv_buffer on sequence numbers
1088 * 3. return first packet if completed or GNUTLS_E_AGAIN.
1092 if (bufel->type != GNUTLS_HANDSHAKE)
1094 gnutls_assert();
1095 goto next; /* ignore packet */
1098 _gnutls_handshake_buffer_init(&tmp);
1100 ret = parse_handshake_header(session, bufel, &tmp);
1101 if (ret < 0)
1103 gnutls_assert();
1104 _gnutls_audit_log(session, "Invalid handshake packet headers. Discarding.\n");
1105 break;
1108 _mbuffer_consume(&session->internals.record_buffer, bufel, ret);
1110 data_size = MIN(tmp.length, tmp.end_offset-tmp.start_offset+1);
1112 ret = _gnutls_buffer_append_data(&tmp.data, _mbuffer_get_udata_ptr(bufel), data_size);
1113 if (ret < 0)
1114 return gnutls_assert_val(ret);
1116 _mbuffer_consume(&session->internals.record_buffer, bufel, data_size);
1118 ret = merge_handshake_packet(session, &tmp);
1119 if (ret < 0)
1120 return gnutls_assert_val(ret);
1123 while(_mbuffer_get_udata_size(bufel) > 0);
1125 prev = bufel;
1126 bufel = _mbuffer_dequeue(&session->internals.record_buffer, bufel);
1128 _mbuffer_xfree(&prev);
1129 continue;
1131 next:
1132 bufel = _mbuffer_head_get_next(bufel, NULL);
1134 while(bufel != NULL);
1136 /* sort in descending order */
1137 if (session->internals.handshake_recv_buffer_size > 1)
1138 qsort(recv_buf, session->internals.handshake_recv_buffer_size,
1139 sizeof(recv_buf[0]), handshake_compare);
1141 while(session->internals.handshake_recv_buffer_size > 0 &&
1142 recv_buf[LAST_ELEMENT].sequence < session->internals.dtls.hsk_read_seq)
1144 _gnutls_audit_log(session, "Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence);
1145 _gnutls_handshake_buffer_clear(&recv_buf[LAST_ELEMENT]);
1146 session->internals.handshake_recv_buffer_size--;
1149 return 0;
1153 /* This is a receive function for the gnutls handshake
1154 * protocol. Makes sure that we have received all data.
1156 ssize_t
1157 _gnutls_handshake_io_recv_int (gnutls_session_t session,
1158 gnutls_handshake_description_t htype,
1159 handshake_buffer_st * hsk, unsigned int optional)
1161 int ret;
1163 ret = get_last_packet(session, htype, hsk, optional);
1164 if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1166 return gnutls_assert_val(ret);
1169 /* try using the already existing records before
1170 * trying to receive.
1172 ret = _gnutls_parse_record_buffered_msgs(session);
1174 if (ret == 0) ret = get_last_packet(session, htype, hsk, optional);
1176 if (IS_DTLS(session))
1178 if (ret >= 0)
1179 return ret;
1181 else
1183 if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE && ret < 0) || ret >= 0)
1184 return gnutls_assert_val(ret);
1187 /* if we don't have a complete message waiting for us, try
1188 * receiving more */
1189 ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype);
1190 if (ret < 0)
1191 return gnutls_assert_val_fatal(ret);
1193 ret = _gnutls_parse_record_buffered_msgs(session);
1194 if (ret == 0) ret = get_last_packet(session, htype, hsk, optional);
1196 return ret;