If OCSP revocation data are invalid or too old set appropriate verification flags.
[gnutls.git] / lib / gnutls_buffers.c
blobf73682ccb8eae62fd6e1aa875f9a82e10845322a
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 <gnutls_handshake.h> /* remaining_time() */
53 #include <errno.h>
54 #include <system.h>
55 #include "debug.h"
57 #ifndef EAGAIN
58 #define EAGAIN EWOULDBLOCK
59 #endif
61 /* this is the maximum number of messages allowed to queue.
63 #define MAX_QUEUE 32
65 /* Buffers received packets of type APPLICATION DATA,
66 * HANDSHAKE DATA and HEARTBEAT.
68 int
69 _gnutls_record_buffer_put (gnutls_session_t session,
70 content_type_t type, uint64* seq, mbuffer_st* bufel)
73 bufel->type = type;
74 memcpy(&bufel->record_sequence, seq, sizeof(*seq));
76 _mbuffer_enqueue(&session->internals.record_buffer, bufel);
77 _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
78 (int) bufel->msg.size, (int) type);
80 return 0;
83 /**
84 * gnutls_record_check_pending:
85 * @session: is a #gnutls_session_t structure.
87 * This function checks if there are unread data
88 * in the gnutls buffers. If the return value is
89 * non-zero the next call to gnutls_record_recv()
90 * is guarranteed not to block.
92 * Returns: Returns the size of the data or zero.
93 **/
94 size_t
95 gnutls_record_check_pending (gnutls_session_t session)
97 return _gnutls_record_buffer_get_size (session);
101 _gnutls_record_buffer_get (content_type_t type,
102 gnutls_session_t session, uint8_t * data,
103 size_t length, uint8_t seq[8])
105 gnutls_datum_t msg;
106 mbuffer_st* bufel;
108 if (length == 0 || data == NULL)
110 gnutls_assert ();
111 return GNUTLS_E_INVALID_REQUEST;
114 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
115 if (bufel == NULL)
116 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
118 if (type != bufel->type)
120 if (IS_DTLS(session))
121 _gnutls_audit_log(session, "Discarded unexpected %s (%d) packet (expecting: %s (%d))\n",
122 _gnutls_packet2str(bufel->type), (int)bufel->type,
123 _gnutls_packet2str(type), (int)type);
124 _mbuffer_head_remove_bytes(&session->internals.record_buffer, msg.size);
125 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
128 if (msg.size <= length)
129 length = msg.size;
131 if (seq)
132 memcpy(seq, bufel->record_sequence.i, 8);
134 memcpy(data, msg.data, length);
135 _mbuffer_head_remove_bytes(&session->internals.record_buffer, length);
137 return length;
140 inline static void
141 reset_errno (gnutls_session_t session)
143 session->internals.errnum = 0;
146 inline static int
147 get_errno (gnutls_session_t session)
149 int ret;
151 if (session->internals.errnum != 0)
152 ret = session->internals.errnum;
153 else
154 ret = session->internals.errno_func (session->
155 internals.transport_recv_ptr);
156 return ret;
159 inline static
160 int errno_to_gerr(int err)
162 switch(err)
164 case EAGAIN:
165 return GNUTLS_E_AGAIN;
166 case EINTR:
167 return GNUTLS_E_INTERRUPTED;
168 case EMSGSIZE:
169 return GNUTLS_E_LARGE_PACKET;
170 default:
171 gnutls_assert ();
172 return GNUTLS_E_PUSH_ERROR;
176 static ssize_t
177 _gnutls_dgram_read (gnutls_session_t session, mbuffer_st **bufel,
178 gnutls_pull_func pull_func, unsigned int *ms)
180 ssize_t i, ret;
181 uint8_t *ptr;
182 struct timespec t1, t2;
183 size_t max_size = _gnutls_get_max_decrypted_data(session);
184 size_t recv_size = MAX_RECV_SIZE(session);
185 gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
186 unsigned int diff;
188 if (recv_size > max_size)
189 recv_size = max_size;
191 session->internals.direction = 0;
193 if (ms && *ms > 0)
195 ret = _gnutls_io_check_recv(session, *ms);
196 if (ret < 0)
197 return gnutls_assert_val(ret);
198 gettime(&t1);
201 *bufel = _mbuffer_alloc (0, max_size);
202 if (*bufel == NULL)
203 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
205 ptr = (*bufel)->msg.data;
207 reset_errno (session);
208 i = pull_func (fd, ptr, recv_size);
210 if (i < 0)
212 int err = get_errno (session);
214 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
215 (int) i, fd, errno, session->internals.errnum);
217 ret = errno_to_gerr(err);
218 goto cleanup;
220 else
222 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
223 if (i == 0)
225 /* If we get here, we likely have a stream socket.
226 * FIXME: this probably breaks DCCP. */
227 gnutls_assert ();
228 ret = 0;
229 goto cleanup;
232 _mbuffer_set_udata_size (*bufel, i);
235 if (ms && *ms > 0)
237 gettime(&t2);
238 diff = _dtls_timespec_sub_ms(&t2, &t1);
239 if (diff < *ms)
240 *ms -= diff;
241 else
242 return gnutls_assert_val(GNUTLS_E_TIMEDOUT);
245 _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i, fd);
247 return i;
249 cleanup:
250 _mbuffer_xfree(bufel);
251 return ret;
254 static ssize_t
255 _gnutls_stream_read (gnutls_session_t session, mbuffer_st **bufel,
256 size_t size, gnutls_pull_func pull_func, unsigned int *ms)
258 size_t left;
259 ssize_t i = 0;
260 size_t max_size = _gnutls_get_max_decrypted_data(session);
261 uint8_t *ptr;
262 gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
263 int ret;
264 struct timespec t1, t2;
265 unsigned int diff;
267 session->internals.direction = 0;
269 *bufel = _mbuffer_alloc (0, MAX(max_size, size));
270 if (!*bufel)
272 gnutls_assert ();
273 return GNUTLS_E_MEMORY_ERROR;
275 ptr = (*bufel)->msg.data;
277 left = size;
278 while (left > 0)
280 if (ms && *ms > 0)
282 ret = _gnutls_io_check_recv(session, *ms);
283 if (ret < 0)
284 return gnutls_assert_val(ret);
286 gettime(&t1);
289 reset_errno (session);
291 i = pull_func (fd, &ptr[size - left], left);
293 if (i < 0)
295 int err = get_errno (session);
297 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
298 (int) i, fd, errno, session->internals.errnum);
300 if (err == EAGAIN || err == EINTR)
302 if (size - left > 0)
305 _gnutls_read_log ("READ: returning %d bytes from %p\n",
306 (int) (size - left), fd);
308 goto finish;
311 return errno_to_gerr(err);
313 else
315 gnutls_assert ();
316 return GNUTLS_E_PULL_ERROR;
319 else
322 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
324 if (i == 0)
325 break; /* EOF */
328 left -= i;
329 (*bufel)->msg.size += i;
331 if (ms && *ms > 0)
333 gettime(&t2);
334 diff = _dtls_timespec_sub_ms(&t2, &t1);
335 if (diff < *ms)
336 *ms -= diff;
337 else
338 return gnutls_assert_val(GNUTLS_E_TIMEDOUT);
342 finish:
344 _gnutls_read_log ("READ: read %d bytes from %p\n",
345 (int) (size - left), fd);
347 return (size - left);
351 /* This function is like read. But it does not return -1 on error.
352 * It does return gnutls_errno instead.
354 * Flags are only used if the default recv() function is being used.
356 static ssize_t
357 _gnutls_read (gnutls_session_t session, mbuffer_st **bufel,
358 size_t size, gnutls_pull_func pull_func, unsigned int *ms)
360 if (IS_DTLS (session))
361 /* Size is not passed, since a whole datagram will be read. */
362 return _gnutls_dgram_read (session, bufel, pull_func, ms);
363 else
364 return _gnutls_stream_read (session, bufel, size, pull_func, ms);
367 static ssize_t
368 _gnutls_writev_emu (gnutls_session_t session, gnutls_transport_ptr_t fd, const giovec_t * giovec,
369 unsigned int giovec_cnt)
371 unsigned int j = 0;
372 size_t total = 0;
373 ssize_t ret = 0;
375 for (j = 0; j < giovec_cnt; j++)
377 ret = session->internals.push_func (fd, giovec[j].iov_base, giovec[j].iov_len);
379 if (ret == -1)
380 break;
382 total += ret;
384 if ((size_t)ret != giovec[j].iov_len)
385 break;
388 if (total > 0)
389 return total;
391 return ret;
395 static ssize_t
396 _gnutls_writev (gnutls_session_t session, const giovec_t * giovec,
397 int giovec_cnt)
399 int i;
400 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
402 reset_errno (session);
404 if (session->internals.push_func != NULL)
405 i = _gnutls_writev_emu (session, fd, giovec, giovec_cnt);
406 else
407 i = session->internals.vec_push_func (fd, giovec, giovec_cnt);
409 if (i == -1)
411 int err = get_errno (session);
412 _gnutls_debug_log ("errno: %d\n", err);
414 return errno_to_gerr(err);
416 return i;
420 * @ms: a pointer to the number of milliseconds to wait for data. Use zero or NULL for indefinite.
422 * This function is like recv(with MSG_PEEK). But it does not return -1 on error.
423 * It does return gnutls_errno instead.
424 * This function reads data from the socket and keeps them in a buffer, of up to
425 * MAX_RECV_SIZE.
427 * This is not a general purpose function. It returns EXACTLY the data requested,
428 * which are stored in a local (in the session) buffer.
430 * If the @ms parameter is non zero then this function will return before
431 * the given amount of milliseconds or return GNUTLS_E_TIMEDOUT.
434 ssize_t
435 _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
436 content_type_t recv_type, unsigned int *ms)
438 ssize_t ret = 0;
439 size_t min;
440 mbuffer_st *bufel = NULL;
441 size_t recvdata, readsize;
443 if (total > MAX_RECV_SIZE(session) || total == 0)
445 gnutls_assert (); /* internal error */
446 return GNUTLS_E_INVALID_REQUEST;
449 /* calculate the actual size, ie. get the minimum of the
450 * buffered data and the requested data.
452 min = MIN (session->internals.record_recv_buffer.byte_length, total);
453 if (min > 0)
455 /* if we have enough buffered data
456 * then just return them.
458 if (min == total)
460 return min;
464 /* min is over zero. recvdata is the data we must
465 * receive in order to return the requested data.
467 recvdata = total - min;
468 readsize = recvdata;
470 /* Check if the previously read data plus the new data to
471 * receive are longer than the maximum receive buffer size.
473 if ((session->internals.record_recv_buffer.byte_length + recvdata) >
474 MAX_RECV_SIZE(session))
476 gnutls_assert (); /* internal error */
477 return GNUTLS_E_INVALID_REQUEST;
480 /* READ DATA
482 if (readsize > 0)
484 ret =
485 _gnutls_read (session, &bufel, readsize,
486 session->internals.pull_func, ms);
488 /* return immediately if we got an interrupt or eagain
489 * error.
491 if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
493 _mbuffer_xfree (&bufel);
494 return ret;
498 /* copy fresh data to our buffer.
500 if (ret > 0)
502 _gnutls_read_log
503 ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
504 (int) session->internals.record_recv_buffer.byte_length, (int) ret);
505 _gnutls_read_log ("RB: Requested %d bytes\n", (int) total);
507 _mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
509 else
510 _mbuffer_xfree (&bufel);
512 if (ret < 0)
514 gnutls_assert ();
515 return ret;
518 if (ret == 0)
519 { /* EOF */
520 gnutls_assert ();
521 return 0;
524 if(IS_DTLS(session))
525 ret = MIN(total, session->internals.record_recv_buffer.byte_length);
526 else
527 ret = session->internals.record_recv_buffer.byte_length;
529 if ((ret > 0) && ((size_t) ret < total))
531 /* Short Read */
532 return gnutls_assert_val(GNUTLS_E_AGAIN);
534 else
536 return ret;
540 /* This function is like write. But it does not return -1 on error.
541 * It does return gnutls_errno instead.
543 * This function takes full responsibility of freeing msg->data.
545 * In case of E_AGAIN and E_INTERRUPTED errors, you must call
546 * gnutls_write_flush(), until it returns ok (0).
548 * We need to push exactly the data in msg->size, since we cannot send
549 * less data. In TLS the peer must receive the whole packet in order
550 * to decrypt and verify the integrity.
553 ssize_t
554 _gnutls_io_write_buffered (gnutls_session_t session,
555 mbuffer_st * bufel, unsigned int mflag)
557 mbuffer_head_st *const send_buffer = &session->internals.record_send_buffer;
559 /* to know where the procedure was interrupted.
561 session->internals.direction = 1;
563 _mbuffer_enqueue (send_buffer, bufel);
565 _gnutls_write_log
566 ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n",
567 (int) bufel->msg.size, session->internals.transport_recv_ptr,
568 (int) send_buffer->byte_length);
570 if (mflag == MBUFFER_FLUSH)
571 return _gnutls_io_write_flush (session);
572 else
573 return bufel->msg.size;
576 typedef ssize_t (*send_func) (gnutls_session_t, const giovec_t *, int);
578 /* This function writes the data that are left in the
579 * TLS write buffer (ie. because the previous write was
580 * interrupted.
582 ssize_t
583 _gnutls_io_write_flush (gnutls_session_t session)
585 gnutls_datum_t msg;
586 mbuffer_head_st *send_buffer = &session->internals.record_send_buffer;
587 int ret;
588 ssize_t sent = 0, tosend = 0;
589 giovec_t iovec[MAX_QUEUE];
590 int i = 0;
591 mbuffer_st *cur;
593 _gnutls_write_log ("WRITE FLUSH: %d bytes in buffer.\n",
594 (int) send_buffer->byte_length);
596 for (cur = _mbuffer_head_get_first (send_buffer, &msg);
597 cur != NULL; cur = _mbuffer_head_get_next (cur, &msg))
599 iovec[i].iov_base = msg.data;
600 iovec[i++].iov_len = msg.size;
601 tosend += msg.size;
603 /* we buffer up to MAX_QUEUE messages */
604 if (i >= MAX_QUEUE)
606 gnutls_assert ();
607 return GNUTLS_E_INTERNAL_ERROR;
611 if (tosend == 0)
613 gnutls_assert();
614 return 0;
617 ret = _gnutls_writev (session, iovec, i);
618 if (ret >= 0)
620 _mbuffer_head_remove_bytes (send_buffer, ret);
621 _gnutls_write_log ("WRITE: wrote %d bytes, %d bytes left.\n",
622 ret, (int) send_buffer->byte_length);
624 sent += ret;
626 else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)
628 _gnutls_write_log ("WRITE interrupted: %d bytes left.\n",
629 (int) send_buffer->byte_length);
630 return ret;
632 else if (ret == GNUTLS_E_LARGE_PACKET)
634 _mbuffer_head_remove_bytes (send_buffer, tosend);
635 _gnutls_write_log ("WRITE cannot send large packet (%u bytes).\n",
636 (unsigned int) tosend);
637 return ret;
639 else
641 _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n",
642 ret, (int) send_buffer->byte_length);
644 gnutls_assert ();
645 return ret;
648 if (sent < tosend)
650 return gnutls_assert_val(GNUTLS_E_AGAIN);
653 return sent;
656 /* Checks whether there are received data within
657 * a timeframe.
659 * Returns 0 if data were received, GNUTLS_E_TIMEDOUT
660 * on timeout and a negative error code on error.
663 _gnutls_io_check_recv (gnutls_session_t session, unsigned int ms)
665 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
666 int ret = 0, err;
668 if (session->internals.pull_timeout_func == system_recv_timeout &&
669 session->internals.pull_func != system_read)
670 return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
672 reset_errno (session);
674 ret = session->internals.pull_timeout_func(fd, ms);
675 if (ret == -1)
677 err = get_errno (session);
678 _gnutls_read_log ("READ_TIMEOUT: %d returned from %p, errno=%d (timeout: %u)\n",
679 (int) ret, fd, err, ms);
680 return errno_to_gerr(err);
683 if (ret > 0)
684 return 0;
685 else return GNUTLS_E_TIMEDOUT;
688 /* HANDSHAKE buffers part
691 /* This function writes the data that are left in the
692 * Handshake write buffer (ie. because the previous write was
693 * interrupted.
696 ssize_t
697 _gnutls_handshake_io_write_flush (gnutls_session_t session)
699 mbuffer_head_st *const send_buffer =
700 &session->internals.handshake_send_buffer;
701 gnutls_datum_t msg;
702 int ret;
703 uint16_t epoch;
704 ssize_t total = 0;
705 mbuffer_st *cur;
707 _gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n",
708 (int) send_buffer->byte_length);
710 if (IS_DTLS(session))
711 return _dtls_transmit(session);
713 for (cur = _mbuffer_head_get_first (send_buffer, &msg);
714 cur != NULL; cur = _mbuffer_head_get_first (send_buffer, &msg))
716 epoch = cur->epoch;
718 ret = _gnutls_send_int (session, cur->type,
719 cur->htype,
720 epoch,
721 msg.data, msg.size, 0);
723 if (ret >= 0)
725 total += ret;
727 ret = _mbuffer_head_remove_bytes (send_buffer, ret);
728 if (ret == 1)
729 _gnutls_epoch_refcount_dec(session, epoch);
731 _gnutls_write_log ("HWRITE: wrote %d bytes, %d bytes left.\n",
732 ret, (int) send_buffer->byte_length);
735 else
737 _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n",
738 ret, (int) send_buffer->byte_length);
740 gnutls_assert ();
741 return ret;
745 return _gnutls_io_write_flush (session);
749 /* This is a send function for the gnutls handshake
750 * protocol. Just makes sure that all data have been sent.
754 _gnutls_handshake_io_cache_int (gnutls_session_t session,
755 gnutls_handshake_description_t htype,
756 mbuffer_st * bufel)
758 mbuffer_head_st * send_buffer;
760 if (IS_DTLS(session))
762 bufel->handshake_sequence = session->internals.dtls.hsk_write_seq-1;
765 send_buffer =
766 &session->internals.handshake_send_buffer;
768 bufel->epoch = (uint16_t)_gnutls_epoch_refcount_inc(session, EPOCH_WRITE_CURRENT);
769 bufel->htype = htype;
770 if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
771 bufel->type = GNUTLS_CHANGE_CIPHER_SPEC;
772 else
773 bufel->type = GNUTLS_HANDSHAKE;
775 _mbuffer_enqueue (send_buffer, bufel);
777 _gnutls_write_log
778 ("HWRITE: enqueued [%s] %d. Total %d bytes.\n",
779 _gnutls_handshake2str (bufel->htype), (int) bufel->msg.size, (int) send_buffer->byte_length);
781 return 0;
784 static int handshake_compare(const void* _e1, const void* _e2)
786 const handshake_buffer_st* e1 = _e1;
787 const handshake_buffer_st* e2 = _e2;
789 if (e1->sequence <= e2->sequence)
790 return 1;
791 else
792 return -1;
795 #define SSL2_HEADERS 1
796 static int
797 parse_handshake_header (gnutls_session_t session, mbuffer_st* bufel,
798 handshake_buffer_st* hsk)
800 uint8_t *dataptr = NULL; /* for realloc */
801 size_t handshake_header_size = HANDSHAKE_HEADER_SIZE(session), data_size;
803 /* Note: SSL2_HEADERS == 1 */
804 if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
805 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
807 dataptr = _mbuffer_get_udata_ptr(bufel);
809 /* if reading a client hello of SSLv2 */
810 if (unlikely(!IS_DTLS(session) && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2))
812 handshake_header_size = SSL2_HEADERS; /* we've already read one byte */
814 hsk->length = _mbuffer_get_udata_size(bufel) - handshake_header_size; /* we've read the first byte */
816 if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO)
817 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
819 hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
821 hsk->sequence = 0;
822 hsk->start_offset = 0;
823 hsk->end_offset = hsk->length;
825 else /* TLS or DTLS handshake headers */
828 hsk->htype = dataptr[0];
830 /* we do not use DECR_LEN because we know
831 * that the packet has enough data.
833 hsk->length = _gnutls_read_uint24 (&dataptr[1]);
834 handshake_header_size = HANDSHAKE_HEADER_SIZE(session);
836 if (IS_DTLS(session))
838 hsk->sequence = _gnutls_read_uint16 (&dataptr[4]);
839 hsk->start_offset = _gnutls_read_uint24 (&dataptr[6]);
840 hsk->end_offset = hsk->start_offset + _gnutls_read_uint24 (&dataptr[9]);
842 else
844 hsk->sequence = 0;
845 hsk->start_offset = 0;
846 hsk->end_offset = MIN((_mbuffer_get_udata_size(bufel) - handshake_header_size), hsk->length);
849 data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
851 /* make the length offset */
852 if (hsk->end_offset > 0) hsk->end_offset--;
854 _gnutls_handshake_log ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
855 session, _gnutls_handshake2str (hsk->htype), (unsigned)hsk->htype,
856 (int) hsk->length, (int)data_size, hsk->start_offset, hsk->end_offset-hsk->start_offset+1, (int)hsk->sequence);
858 hsk->header_size = handshake_header_size;
859 memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel), handshake_header_size);
861 if (hsk->length > 0 &&
862 (hsk->end_offset-hsk->start_offset >= data_size))
863 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
865 if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset ||
866 hsk->end_offset-hsk->start_offset >= data_size ||
867 hsk->end_offset >= hsk->length))
868 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
869 else if (hsk->length == 0 && hsk->end_offset != 0 && hsk->start_offset != 0)
870 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
872 return handshake_header_size;
875 static void _gnutls_handshake_buffer_move(handshake_buffer_st* dst, handshake_buffer_st* src)
877 memcpy(dst, src, sizeof(*dst));
878 memset(src, 0, sizeof(*src));
879 src->htype = -1;
882 /* will merge the given handshake_buffer_st to the handshake_recv_buffer
883 * list. The given hsk packet will be released in any case (success or failure).
884 * Only used in DTLS.
886 static int merge_handshake_packet(gnutls_session_t session, handshake_buffer_st* hsk)
888 int exists = 0, i, pos = 0;
889 int ret;
891 for (i=0;i<session->internals.handshake_recv_buffer_size;i++)
893 if (session->internals.handshake_recv_buffer[i].htype == hsk->htype)
895 exists = 1;
896 pos = i;
897 break;
901 if (exists == 0)
902 pos = session->internals.handshake_recv_buffer_size;
904 if (pos > MAX_HANDSHAKE_MSGS)
905 return gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
907 if (exists == 0)
909 if (hsk->length > 0 && hsk->end_offset > 0 && hsk->end_offset-hsk->start_offset+1 != hsk->length)
911 ret = _gnutls_buffer_resize(&hsk->data, hsk->length);
912 if (ret < 0)
913 return gnutls_assert_val(ret);
915 hsk->data.length = hsk->length;
917 memmove(&hsk->data.data[hsk->start_offset], hsk->data.data, hsk->end_offset-hsk->start_offset+1);
920 session->internals.handshake_recv_buffer_size++;
922 /* rewrite headers to make them look as each packet came as a single fragment */
923 _gnutls_write_uint24(hsk->length, &hsk->header[1]);
924 _gnutls_write_uint24(0, &hsk->header[6]);
925 _gnutls_write_uint24(hsk->length, &hsk->header[9]);
927 _gnutls_handshake_buffer_move(&session->internals.handshake_recv_buffer[pos], hsk);
930 else
932 if (hsk->start_offset < session->internals.handshake_recv_buffer[pos].start_offset &&
933 hsk->end_offset >= session->internals.handshake_recv_buffer[pos].start_offset)
935 memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset],
936 hsk->data.data, hsk->data.length);
937 session->internals.handshake_recv_buffer[pos].start_offset = hsk->start_offset;
938 session->internals.handshake_recv_buffer[pos].end_offset =
939 MIN(hsk->end_offset, session->internals.handshake_recv_buffer[pos].end_offset);
941 else if (hsk->end_offset > session->internals.handshake_recv_buffer[pos].end_offset &&
942 hsk->start_offset <= session->internals.handshake_recv_buffer[pos].end_offset+1)
944 memcpy(&session->internals.handshake_recv_buffer[pos].data.data[hsk->start_offset],
945 hsk->data.data, hsk->data.length);
947 session->internals.handshake_recv_buffer[pos].end_offset = hsk->end_offset;
948 session->internals.handshake_recv_buffer[pos].start_offset =
949 MIN(hsk->start_offset, session->internals.handshake_recv_buffer[pos].start_offset);
951 _gnutls_handshake_buffer_clear(hsk);
954 return 0;
957 /* returns non-zero on match and zero on mismatch
959 inline static int cmp_hsk_types(gnutls_handshake_description_t expected, gnutls_handshake_description_t recvd)
961 if ((expected != GNUTLS_HANDSHAKE_CLIENT_HELLO || recvd != GNUTLS_HANDSHAKE_CLIENT_HELLO_V2) &&
962 (expected != recvd))
963 return 0;
965 return 1;
968 #define LAST_ELEMENT (session->internals.handshake_recv_buffer_size-1)
970 /* returns the last stored handshake packet.
972 static int get_last_packet(gnutls_session_t session, gnutls_handshake_description_t htype,
973 handshake_buffer_st * hsk, unsigned int optional)
975 handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;
977 if (IS_DTLS(session))
979 if (session->internals.handshake_recv_buffer_size == 0 ||
980 (session->internals.dtls.hsk_read_seq != recv_buf[LAST_ELEMENT].sequence))
981 goto timeout;
983 if (htype != recv_buf[LAST_ELEMENT].htype)
985 if (optional == 0)
986 _gnutls_audit_log(session, "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n",
987 _gnutls_handshake2str(recv_buf[0].htype), (int)recv_buf[0].htype, _gnutls_handshake2str(htype), (int)htype);
989 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
992 else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
993 recv_buf[LAST_ELEMENT].end_offset == recv_buf[LAST_ELEMENT].length -1) ||
994 recv_buf[LAST_ELEMENT].length == 0)
996 session->internals.dtls.hsk_read_seq++;
997 _gnutls_handshake_buffer_move(hsk, &recv_buf[LAST_ELEMENT]);
998 session->internals.handshake_recv_buffer_size--;
999 return 0;
1001 else
1002 goto timeout;
1004 else /* TLS */
1006 if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length == recv_buf[0].data.length)
1008 if (cmp_hsk_types(htype, recv_buf[0].htype) == 0)
1010 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
1013 _gnutls_handshake_buffer_move(hsk, &recv_buf[0]);
1014 session->internals.handshake_recv_buffer_size--;
1015 return 0;
1017 else
1018 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1021 timeout:
1022 RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0);
1025 /* This is a receive function for the gnutls handshake
1026 * protocol. Makes sure that we have received all data.
1028 * htype is the next handshake packet expected.
1031 _gnutls_parse_record_buffered_msgs (gnutls_session_t session)
1033 gnutls_datum_t msg;
1034 mbuffer_st* bufel = NULL, *prev = NULL;
1035 int ret;
1036 size_t data_size;
1037 handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;
1039 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
1040 if (bufel == NULL)
1041 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1043 if (!IS_DTLS(session))
1045 ssize_t remain, append, header_size;
1049 if (bufel->type != GNUTLS_HANDSHAKE)
1050 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
1052 /* if we have a half received message the complete it.
1054 remain = recv_buf[0].length -
1055 recv_buf[0].data.length;
1057 /* this is the rest of a previous message */
1058 if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length > 0 && remain > 0)
1060 if ((ssize_t)msg.size <= remain)
1061 append = msg.size;
1062 else
1063 append = remain;
1065 ret = _gnutls_buffer_append_data(&recv_buf[0].data, msg.data, append);
1066 if (ret < 0)
1067 return gnutls_assert_val(ret);
1069 _mbuffer_head_remove_bytes(&session->internals.record_buffer, append);
1071 else /* received new message */
1073 ret = parse_handshake_header(session, bufel, &recv_buf[0]);
1074 if (ret < 0)
1075 return gnutls_assert_val(ret);
1077 header_size = ret;
1078 session->internals.handshake_recv_buffer_size = 1;
1080 _mbuffer_set_uhead_size(bufel, header_size);
1082 data_size = MIN(recv_buf[0].length, _mbuffer_get_udata_size(bufel));
1083 ret = _gnutls_buffer_append_data(&recv_buf[0].data, _mbuffer_get_udata_ptr(bufel), data_size);
1084 if (ret < 0)
1085 return gnutls_assert_val(ret);
1086 _mbuffer_set_uhead_size(bufel, 0);
1087 _mbuffer_head_remove_bytes(&session->internals.record_buffer, data_size+header_size);
1090 /* if packet is complete then return it
1092 if (recv_buf[0].length ==
1093 recv_buf[0].data.length)
1095 return 0;
1097 bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
1099 while(bufel != NULL);
1101 /* if we are here it means that the received packets were not
1102 * enough to complete the handshake packet.
1104 return gnutls_assert_val(GNUTLS_E_AGAIN);
1106 else /* DTLS */
1108 handshake_buffer_st tmp;
1112 /* we now
1113 * 0. parse headers
1114 * 1. insert to handshake_recv_buffer
1115 * 2. sort handshake_recv_buffer on sequence numbers
1116 * 3. return first packet if completed or GNUTLS_E_AGAIN.
1120 if (bufel->type != GNUTLS_HANDSHAKE)
1122 gnutls_assert();
1123 goto next; /* ignore packet */
1126 _gnutls_handshake_buffer_init(&tmp);
1128 ret = parse_handshake_header(session, bufel, &tmp);
1129 if (ret < 0)
1131 gnutls_assert();
1132 _gnutls_audit_log(session, "Invalid handshake packet headers. Discarding.\n");
1133 break;
1136 _mbuffer_consume(&session->internals.record_buffer, bufel, ret);
1138 data_size = MIN(tmp.length, tmp.end_offset-tmp.start_offset+1);
1140 ret = _gnutls_buffer_append_data(&tmp.data, _mbuffer_get_udata_ptr(bufel), data_size);
1141 if (ret < 0)
1142 return gnutls_assert_val(ret);
1144 _mbuffer_consume(&session->internals.record_buffer, bufel, data_size);
1146 ret = merge_handshake_packet(session, &tmp);
1147 if (ret < 0)
1148 return gnutls_assert_val(ret);
1151 while(_mbuffer_get_udata_size(bufel) > 0);
1153 prev = bufel;
1154 bufel = _mbuffer_dequeue(&session->internals.record_buffer, bufel);
1156 _mbuffer_xfree(&prev);
1157 continue;
1159 next:
1160 bufel = _mbuffer_head_get_next(bufel, NULL);
1162 while(bufel != NULL);
1164 /* sort in descending order */
1165 if (session->internals.handshake_recv_buffer_size > 1)
1166 qsort(recv_buf, session->internals.handshake_recv_buffer_size,
1167 sizeof(recv_buf[0]), handshake_compare);
1169 while(session->internals.handshake_recv_buffer_size > 0 &&
1170 recv_buf[LAST_ELEMENT].sequence < session->internals.dtls.hsk_read_seq)
1172 _gnutls_audit_log(session, "Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence);
1173 _gnutls_handshake_buffer_clear(&recv_buf[LAST_ELEMENT]);
1174 session->internals.handshake_recv_buffer_size--;
1177 return 0;
1181 /* This is a receive function for the gnutls handshake
1182 * protocol. Makes sure that we have received all data.
1184 ssize_t
1185 _gnutls_handshake_io_recv_int (gnutls_session_t session,
1186 gnutls_handshake_description_t htype,
1187 handshake_buffer_st * hsk, unsigned int optional)
1189 int ret;
1190 unsigned int tleft = 0;
1192 ret = get_last_packet(session, htype, hsk, optional);
1193 if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1195 return gnutls_assert_val(ret);
1198 /* try using the already existing records before
1199 * trying to receive.
1201 ret = _gnutls_parse_record_buffered_msgs(session);
1203 if (ret == 0) ret = get_last_packet(session, htype, hsk, optional);
1205 if (IS_DTLS(session))
1207 if (ret >= 0)
1208 return ret;
1210 else
1212 if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE && ret < 0) || ret >= 0)
1213 return gnutls_assert_val(ret);
1216 if (htype != (unsigned)-1)
1218 ret = handshake_remaining_time(session);
1219 if (ret < 0)
1220 return gnutls_assert_val(ret);
1221 tleft = ret;
1224 /* if we don't have a complete message waiting for us, try
1225 * receiving more */
1226 ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype, tleft);
1227 if (ret < 0)
1228 return gnutls_assert_val_fatal(ret);
1230 ret = _gnutls_parse_record_buffered_msgs(session);
1231 if (ret == 0) ret = get_last_packet(session, htype, hsk, optional);
1233 return ret;