1 /*
2  * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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 2.1 of
11  * the License, or (at your option) any later version.
12  *
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.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 /*
24  * This file holds all the buffering code used in gnutls.
25  * The buffering code works as:
26  *
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.)
31  *
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.)
35  *
36  * HANDSHAKE LAYER:
37  *  1. Uses buffer to hold the last received handshake message.
38  *  (see _gnutls_handshake_hash_buffer_put() etc.)
39  *
40  */
41 
42 #include "gnutls_int.h"
43 #include "errors.h"
44 #include <num.h>
45 #include <record.h>
46 #include <buffers.h>
47 #include <mbuffers.h>
48 #include <state.h>
49 #include <dtls.h>
50 #include <system.h>
51 #include <constate.h>	/* gnutls_epoch_get */
52 #include <handshake.h>	/* remaining_time() */
53 #include <errno.h>
54 #include <system.h>
55 #include "debug.h"
56 
57 #ifndef EAGAIN
58 #define EAGAIN EWOULDBLOCK
59 #endif
60 
61 /* this is the maximum number of messages allowed to queue.
62  */
63 #define MAX_QUEUE 32
64 
65 /* Buffers received packets of type APPLICATION DATA,
66  * HANDSHAKE DATA and HEARTBEAT.
67  */
68 void
_gnutls_record_buffer_put(gnutls_session_t session,content_type_t type,uint64_t seq,mbuffer_st * bufel)69 _gnutls_record_buffer_put(gnutls_session_t session,
70 			  content_type_t type, uint64_t seq,
71 			  mbuffer_st * bufel)
72 {
73 
74 	bufel->type = type;
75 	bufel->record_sequence = seq;
76 
77 	_mbuffer_enqueue(&session->internals.record_buffer, bufel);
78 	_gnutls_buffers_log("BUF[REC]: Inserted %d bytes of Data(%d)\n",
79 			    (int) bufel->msg.size, (int) type);
80 
81 	return;
82 }
83 
84 /**
85  * gnutls_record_check_pending:
86  * @session: is a #gnutls_session_t type.
87  *
88  * This function checks if there are unread data
89  * in the gnutls buffers. If the return value is
90  * non-zero the next call to gnutls_record_recv()
91  * is guaranteed not to block.
92  *
93  * Returns: Returns the size of the data or zero.
94  **/
gnutls_record_check_pending(gnutls_session_t session)95 size_t gnutls_record_check_pending(gnutls_session_t session)
96 {
97 	return _gnutls_record_buffer_get_size(session);
98 }
99 
100 /**
101  * gnutls_record_check_corked:
102  * @session: is a #gnutls_session_t type.
103  *
104  * This function checks if there pending corked
105  * data in the gnutls buffers --see gnutls_record_cork().
106  *
107  * Returns: Returns the size of the corked data or zero.
108  *
109  * Since: 3.2.8
110  **/
gnutls_record_check_corked(gnutls_session_t session)111 size_t gnutls_record_check_corked(gnutls_session_t session)
112 {
113 	return session->internals.record_presend_buffer.length;
114 }
115 
116 int
_gnutls_record_buffer_get(content_type_t type,gnutls_session_t session,uint8_t * data,size_t length,uint8_t seq[8])117 _gnutls_record_buffer_get(content_type_t type,
118 			  gnutls_session_t session, uint8_t * data,
119 			  size_t length, uint8_t seq[8])
120 {
121 	gnutls_datum_t msg;
122 	mbuffer_st *bufel;
123 
124 	if (length == 0 || data == NULL) {
125 		gnutls_assert();
126 		return GNUTLS_E_INVALID_REQUEST;
127 	}
128 
129 	bufel =
130 	    _mbuffer_head_get_first(&session->internals.record_buffer,
131 				    &msg);
132 	if (bufel == NULL)
133 		return
134 		    gnutls_assert_val
135 		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
136 
137 	if (type != bufel->type) {
138 		if (IS_DTLS(session))
139 			_gnutls_audit_log(session,
140 					  "Discarded unexpected %s (%d) packet (expecting: %s (%d))\n",
141 					  _gnutls_packet2str(bufel->type),
142 					  (int) bufel->type,
143 					  _gnutls_packet2str(type),
144 					  (int) type);
145 		else
146 			_gnutls_debug_log("received unexpected packet: %s(%d)\n",
147 						_gnutls_packet2str(bufel->type), (int)bufel->type);
148 
149 		_mbuffer_head_remove_bytes(&session->internals.
150 					   record_buffer, msg.size);
151 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
152 	}
153 
154 	if (msg.size <= length)
155 		length = msg.size;
156 
157 	if (seq)
158 		_gnutls_write_uint64(bufel->record_sequence, seq);
159 
160 	memcpy(data, msg.data, length);
161 	_mbuffer_head_remove_bytes(&session->internals.record_buffer,
162 				   length);
163 
164 	return length;
165 }
166 
167 int
_gnutls_record_buffer_get_packet(content_type_t type,gnutls_session_t session,gnutls_packet_t * packet)168 _gnutls_record_buffer_get_packet(content_type_t type, gnutls_session_t session, gnutls_packet_t *packet)
169 {
170 	mbuffer_st *bufel;
171 
172 	bufel =
173 	    _mbuffer_head_pop_first(&session->internals.record_buffer);
174 	if (bufel == NULL)
175 		return
176 		    gnutls_assert_val
177 		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
178 
179 	if (type != bufel->type) {
180 		if (IS_DTLS(session))
181 			_gnutls_audit_log(session,
182 					  "Discarded unexpected %s (%d) packet (expecting: %s)\n",
183 					  _gnutls_packet2str(bufel->type),
184 					  (int) bufel->type,
185 					  _gnutls_packet2str(type));
186 		_mbuffer_head_remove_bytes(&session->internals.
187 					   record_buffer, bufel->msg.size);
188 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
189 	}
190 
191 	*packet = bufel;
192 
193 	return bufel->msg.size - bufel->mark;
194 }
195 
reset_errno(gnutls_session_t session)196 inline static void reset_errno(gnutls_session_t session)
197 {
198 	session->internals.errnum = 0;
199 }
200 
get_errno(gnutls_session_t session)201 inline static int get_errno(gnutls_session_t session)
202 {
203 	int ret;
204 
205 	if (session->internals.errnum != 0)
206 		ret = session->internals.errnum;
207 	else
208 		ret =
209 		    session->internals.errno_func(session->internals.
210 						  transport_recv_ptr);
211 	return ret;
212 }
213 
214 inline static
errno_to_gerr(int err,unsigned dtls)215 int errno_to_gerr(int err, unsigned dtls)
216 {
217 	switch (err) {
218 	case EAGAIN:
219 		return GNUTLS_E_AGAIN;
220 	case EINTR:
221 		return GNUTLS_E_INTERRUPTED;
222 	case EMSGSIZE:
223 		if (dtls != 0)
224 			return GNUTLS_E_LARGE_PACKET;
225 		else
226 			return GNUTLS_E_PUSH_ERROR;
227 	case ECONNRESET:
228 		return GNUTLS_E_PREMATURE_TERMINATION;
229 	default:
230 		gnutls_assert();
231 		return GNUTLS_E_PUSH_ERROR;
232 	}
233 }
234 
235 static ssize_t
_gnutls_dgram_read(gnutls_session_t session,mbuffer_st ** bufel,gnutls_pull_func pull_func,unsigned int * ms)236 _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel,
237 		   gnutls_pull_func pull_func, unsigned int *ms)
238 {
239 	ssize_t i, ret;
240 	uint8_t *ptr;
241 	struct timespec t1, t2;
242 	size_t max_size, recv_size;
243 	gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
244 	unsigned int diff;
245 
246 	max_size = max_record_recv_size(session);
247 	recv_size = max_size;
248 
249 	session->internals.direction = 0;
250 
251 	if (ms && *ms > 0) {
252 		ret = _gnutls_io_check_recv(session, *ms);
253 		if (ret < 0)
254 			return gnutls_assert_val(ret);
255 		gnutls_gettime(&t1);
256 	}
257 
258 	*bufel = _mbuffer_alloc_align16(max_size, get_total_headers(session));
259 	if (*bufel == NULL)
260 		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
261 
262 	ptr = (*bufel)->msg.data;
263 
264 	reset_errno(session);
265 	i = pull_func(fd, ptr, recv_size);
266 
267 	if (i < 0) {
268 		int err = get_errno(session);
269 
270 		_gnutls_read_log("READ: %d returned from %p, errno=%d\n",
271 				 (int) i, fd, err);
272 
273 		ret = errno_to_gerr(err, 1);
274 		goto cleanup;
275 	} else {
276 		_gnutls_read_log("READ: Got %d bytes from %p\n", (int) i,
277 				 fd);
278 		if (i == 0) {
279 			/* If we get here, we likely have a stream socket.
280 			 * That assumption may not work on DCCP. */
281 			gnutls_assert();
282 			ret = 0;
283 			goto cleanup;
284 		}
285 
286 		_mbuffer_set_udata_size(*bufel, i);
287 	}
288 
289 	if (ms && *ms > 0) {
290 		gnutls_gettime(&t2);
291 		diff = timespec_sub_ms(&t2, &t1);
292 		if (diff < *ms)
293 			*ms -= diff;
294 		else {
295 			ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT);
296 			goto cleanup;
297 		}
298 	}
299 
300 	_gnutls_read_log("READ: read %d bytes from %p\n", (int) i, fd);
301 
302 	return i;
303 
304       cleanup:
305 	_mbuffer_xfree(bufel);
306 	return ret;
307 }
308 
309 static ssize_t
_gnutls_stream_read(gnutls_session_t session,mbuffer_st ** bufel,size_t size,gnutls_pull_func pull_func,unsigned int * ms)310 _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel,
311 		    size_t size, gnutls_pull_func pull_func,
312 		    unsigned int *ms)
313 {
314 	size_t left;
315 	ssize_t i = 0;
316 	size_t max_size = max_record_recv_size(session);
317 	uint8_t *ptr;
318 	gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
319 	int ret;
320 	struct timespec t1, t2;
321 	unsigned int diff;
322 
323 	session->internals.direction = 0;
324 
325 	*bufel = _mbuffer_alloc_align16(MAX(max_size, size), get_total_headers(session));
326 	if (!*bufel) {
327 		gnutls_assert();
328 		return GNUTLS_E_MEMORY_ERROR;
329 	}
330 	ptr = (*bufel)->msg.data;
331 
332 	left = size;
333 	while (left > 0) {
334 		if (ms && *ms > 0) {
335 			ret = _gnutls_io_check_recv(session, *ms);
336 			if (ret < 0) {
337 				gnutls_assert();
338 				goto cleanup;
339 			}
340 
341 			gnutls_gettime(&t1);
342 		}
343 
344 		reset_errno(session);
345 
346 		i = pull_func(fd, &ptr[size - left], left);
347 
348 		if (i < 0) {
349 			int err = get_errno(session);
350 
351 			_gnutls_read_log
352 			    ("READ: %d returned from %p, errno=%d gerrno=%d\n",
353 			     (int) i, fd, errno,
354 			     session->internals.errnum);
355 
356 			if (err == EAGAIN || err == EINTR) {
357 				if (size - left > 0) {
358 
359 					_gnutls_read_log
360 					    ("READ: returning %d bytes from %p\n",
361 					     (int) (size - left), fd);
362 
363 					goto finish;
364 				}
365 
366 				ret = errno_to_gerr(err, 0);
367 				goto cleanup;
368 			} else {
369 				gnutls_assert();
370 				ret = GNUTLS_E_PULL_ERROR;
371 				goto cleanup;
372 			}
373 		} else {
374 
375 			_gnutls_read_log("READ: Got %d bytes from %p\n",
376 					 (int) i, fd);
377 
378 			if (i == 0)
379 				break;	/* EOF */
380 		}
381 
382 		left -= i;
383 		(*bufel)->msg.size += i;
384 
385 		if (ms && *ms > 0 && *ms != GNUTLS_INDEFINITE_TIMEOUT) {
386 			gnutls_gettime(&t2);
387 			diff = timespec_sub_ms(&t2, &t1);
388 			if (diff < *ms)
389 				*ms -= diff;
390 			else {
391 				ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT);
392 				goto cleanup;
393 			}
394 		}
395 	}
396 
397       finish:
398 
399 	_gnutls_read_log("READ: read %d bytes from %p\n",
400 			 (int) (size - left), fd);
401 
402 	if (size - left == 0)
403 		_mbuffer_xfree(bufel);
404 
405 	return (size - left);
406 
407       cleanup:
408 	_mbuffer_xfree(bufel);
409 	return ret;
410 }
411 
412 
413 /* This function is like read. But it does not return -1 on error.
414  * It does return gnutls_errno instead.
415  *
416  * Flags are only used if the default recv() function is being used.
417  */
418 static ssize_t
_gnutls_read(gnutls_session_t session,mbuffer_st ** bufel,size_t size,gnutls_pull_func pull_func,unsigned int * ms)419 _gnutls_read(gnutls_session_t session, mbuffer_st ** bufel,
420 	     size_t size, gnutls_pull_func pull_func, unsigned int *ms)
421 {
422 	if (IS_DTLS(session))
423 		/* Size is not passed, since a whole datagram will be read. */
424 		return _gnutls_dgram_read(session, bufel, pull_func, ms);
425 	else
426 		return _gnutls_stream_read(session, bufel, size, pull_func,
427 					   ms);
428 }
429 
430 /* @vec: if non-zero then the vector function will be used to
431  *       push the data.
432  */
433 static ssize_t
_gnutls_writev_emu(gnutls_session_t session,gnutls_transport_ptr_t fd,const giovec_t * giovec,unsigned int giovec_cnt,unsigned vec)434 _gnutls_writev_emu(gnutls_session_t session, gnutls_transport_ptr_t fd,
435 		   const giovec_t * giovec, unsigned int giovec_cnt, unsigned vec)
436 {
437 	unsigned int j = 0;
438 	size_t total = 0;
439 	ssize_t ret = 0;
440 
441 	for (j = 0; j < giovec_cnt; j++) {
442 		if (vec) {
443 			ret = session->internals.vec_push_func(fd, &giovec[j], 1);
444 		} else {
445 			size_t sent = 0;
446 			ssize_t left = giovec[j].iov_len;
447 			char *p = giovec[j].iov_base;
448 			do {
449 				ret =
450 				    session->internals.push_func(fd, p,
451 								 left);
452 				if (ret > 0) {
453 					sent += ret;
454 					left -= ret;
455 					p += ret;
456 				}
457 			} while(ret > 0 && left > 0);
458 
459 			if (sent > 0)
460 				ret = sent;
461 		}
462 
463 		if (ret == -1) {
464 			gnutls_assert();
465 			break;
466 		}
467 
468 		total += ret;
469 
470 		if ((size_t) ret != giovec[j].iov_len)
471 			break;
472 	}
473 
474 	if (total > 0)
475 		return total;
476 
477 	return ret;
478 }
479 
480 /* @total: The sum of the data in giovec
481  */
482 static ssize_t
_gnutls_writev(gnutls_session_t session,const giovec_t * giovec,unsigned giovec_cnt,unsigned total)483 _gnutls_writev(gnutls_session_t session, const giovec_t * giovec,
484 	       unsigned giovec_cnt, unsigned total)
485 {
486 	int i;
487 	bool is_dtls = IS_DTLS(session);
488 	unsigned no_writev = 0;
489 	gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
490 
491 	reset_errno(session);
492 
493 	if (session->internals.vec_push_func != NULL) {
494 		if (is_dtls && giovec_cnt > 1) {
495 			if (total > session->internals.dtls.mtu) {
496 				no_writev = 1;
497 			}
498 		}
499 
500 		if (no_writev == 0) {
501 			i = session->internals.vec_push_func(fd, giovec, giovec_cnt);
502 		} else {
503 			i = _gnutls_writev_emu(session, fd, giovec, giovec_cnt, 1);
504 		}
505 	} else if (session->internals.push_func != NULL) {
506 		i = _gnutls_writev_emu(session, fd, giovec, giovec_cnt, 0);
507 	} else
508 		return gnutls_assert_val(GNUTLS_E_PUSH_ERROR);
509 
510 	if (i == -1) {
511 		int err = get_errno(session);
512 		_gnutls_debug_log("WRITE: %d returned from %p, errno: %d\n",
513 				  i, fd, err);
514 
515 		return errno_to_gerr(err, is_dtls);
516 	}
517 	return i;
518 }
519 
520 /*
521  * @ms: a pointer to the number of milliseconds to wait for data. Use zero or NULL for indefinite.
522  *
523  * This function is like recv(with MSG_PEEK). But it does not return -1 on error.
524  * It does return gnutls_errno instead.
525  * This function reads data from the socket and keeps them in a buffer, of up to
526  * max_record_recv_size.
527  *
528  * This is not a general purpose function. It returns EXACTLY the data requested,
529  * which are stored in a local (in the session) buffer.
530  *
531  * If the @ms parameter is non zero then this function will return before
532  * the given amount of milliseconds or return GNUTLS_E_TIMEDOUT.
533  *
534  */
535 ssize_t
_gnutls_io_read_buffered(gnutls_session_t session,size_t total,content_type_t recv_type,unsigned int * ms)536 _gnutls_io_read_buffered(gnutls_session_t session, size_t total,
537 			 content_type_t recv_type, unsigned int *ms)
538 {
539 	ssize_t ret;
540 	size_t min;
541 	mbuffer_st *bufel = NULL;
542 	size_t recvdata, readsize;
543 
544 	if (total > max_record_recv_size(session) || total == 0) {
545 		gnutls_assert();
546 		return GNUTLS_E_RECORD_OVERFLOW;
547 	}
548 
549 	/* calculate the actual size, ie. get the minimum of the
550 	 * buffered data and the requested data.
551 	 */
552 	min =
553 	    MIN(session->internals.record_recv_buffer.byte_length, total);
554 	if (min > 0) {
555 		/* if we have enough buffered data
556 		 * then just return them.
557 		 */
558 		if (min == total) {
559 			return min;
560 		}
561 	}
562 
563 	/* min is over zero. recvdata is the data we must
564 	 * receive in order to return the requested data.
565 	 */
566 	recvdata = total - min;
567 	readsize = recvdata;
568 
569 	/* Check if the previously read data plus the new data to
570 	 * receive are longer than the maximum receive buffer size.
571 	 */
572 	if ((session->internals.record_recv_buffer.byte_length +
573 	     recvdata) > max_record_recv_size(session)) {
574 		gnutls_assert();	/* internal error */
575 		return GNUTLS_E_INVALID_REQUEST;
576 	}
577 
578 	/* READ DATA
579 	 */
580 	if (readsize > 0) {
581 		ret =
582 		    _gnutls_read(session, &bufel, readsize,
583 				 session->internals.pull_func, ms);
584 
585 		/* return immediately if we got an interrupt or eagain
586 		 * error.
587 		 */
588 		if (ret < 0) {
589 			return gnutls_assert_val(ret);
590 		}
591 
592 		if (ret == 0)	/* EOF */
593 			return gnutls_assert_val(0);
594 
595 		/* copy fresh data to our buffer.
596 		 */
597 		_gnutls_read_log
598 		    ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
599 		     (int) session->internals.record_recv_buffer.
600 		     byte_length, (int) ret);
601 		_gnutls_read_log("RB: Requested %d bytes\n", (int) total);
602 
603 		_mbuffer_enqueue(&session->internals.record_recv_buffer,
604 				 bufel);
605 
606 		if (IS_DTLS(session))
607 			ret =
608 			    MIN(total,
609 				session->internals.record_recv_buffer.
610 				byte_length);
611 		else
612 			ret =
613 			    session->internals.record_recv_buffer.
614 			    byte_length;
615 
616 		if ((ret > 0) && ((size_t) ret < total))	/* Short Read */
617 			return gnutls_assert_val(GNUTLS_E_AGAIN);
618 		else
619 			return ret;
620 	} else
621 		return gnutls_assert_val(0);
622 }
623 
624 /* This function is like write. But it does not return -1 on error.
625  * It does return gnutls_errno instead.
626  *
627  * This function takes full responsibility of freeing msg->data.
628  *
629  * In case of E_AGAIN and E_INTERRUPTED errors, you must call
630  * gnutls_write_flush(), until it returns ok (0).
631  *
632  * We need to push exactly the data in msg->size, since we cannot send
633  * less data. In TLS the peer must receive the whole packet in order
634  * to decrypt and verify the integrity.
635  *
636  */
637 ssize_t
_gnutls_io_write_buffered(gnutls_session_t session,mbuffer_st * bufel,unsigned int mflag)638 _gnutls_io_write_buffered(gnutls_session_t session,
639 			  mbuffer_st * bufel, unsigned int mflag)
640 {
641 	mbuffer_head_st *const send_buffer =
642 	    &session->internals.record_send_buffer;
643 
644 	/* to know where the procedure was interrupted.
645 	 */
646 	session->internals.direction = 1;
647 
648 	_mbuffer_enqueue(send_buffer, bufel);
649 
650 	_gnutls_write_log
651 	    ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n",
652 	     (int) bufel->msg.size, session->internals.transport_recv_ptr,
653 	     (int) send_buffer->byte_length);
654 
655 	if (mflag == MBUFFER_FLUSH)
656 		return _gnutls_io_write_flush(session);
657 	else
658 		return bufel->msg.size;
659 }
660 
661 typedef ssize_t(*send_func) (gnutls_session_t, const giovec_t *, int);
662 
663 /* This function writes the data that are left in the
664  * TLS write buffer (ie. because the previous write was
665  * interrupted.
666  */
_gnutls_io_write_flush(gnutls_session_t session)667 ssize_t _gnutls_io_write_flush(gnutls_session_t session)
668 {
669 	gnutls_datum_t msg;
670 	mbuffer_head_st *send_buffer =
671 	    &session->internals.record_send_buffer;
672 	int ret;
673 	ssize_t sent = 0, tosend = 0;
674 	giovec_t iovec[MAX_QUEUE];
675 	int i = 0;
676 	mbuffer_st *cur;
677 
678 	session->internals.direction = 1;
679 	_gnutls_write_log("WRITE FLUSH: %d bytes in buffer.\n",
680 			  (int) send_buffer->byte_length);
681 
682 	for (cur = _mbuffer_head_get_first(send_buffer, &msg);
683 	     cur != NULL; cur = _mbuffer_head_get_next(cur, &msg)) {
684 		iovec[i].iov_base = msg.data;
685 		iovec[i++].iov_len = msg.size;
686 		tosend += msg.size;
687 
688 		/* we buffer up to MAX_QUEUE messages */
689 		if (i >= MAX_QUEUE) {
690 			gnutls_assert();
691 			return GNUTLS_E_INTERNAL_ERROR;
692 		}
693 	}
694 
695 	if (tosend == 0) {
696 		gnutls_assert();
697 		return 0;
698 	}
699 
700 	ret = _gnutls_writev(session, iovec, i, tosend);
701 	if (ret >= 0) {
702 		_mbuffer_head_remove_bytes(send_buffer, ret);
703 		_gnutls_write_log
704 		    ("WRITE: wrote %d bytes, %d bytes left.\n", ret,
705 		     (int) send_buffer->byte_length);
706 
707 		sent += ret;
708 	} else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
709 		_gnutls_write_log("WRITE interrupted: %d bytes left.\n",
710 				  (int) send_buffer->byte_length);
711 		return ret;
712 	} else if (ret == GNUTLS_E_LARGE_PACKET) {
713 		_mbuffer_head_remove_bytes(send_buffer, tosend);
714 		_gnutls_write_log
715 		    ("WRITE cannot send large packet (%u bytes).\n",
716 		     (unsigned int) tosend);
717 		return ret;
718 	} else {
719 		_gnutls_write_log("WRITE error: code %d, %d bytes left.\n",
720 				  ret, (int) send_buffer->byte_length);
721 
722 		gnutls_assert();
723 		return ret;
724 	}
725 
726 	if (sent < tosend) {
727 		return gnutls_assert_val(GNUTLS_E_AGAIN);
728 	}
729 
730 	return sent;
731 }
732 
733 /* Checks whether there are received data within
734  * a timeframe.
735  *
736  * Returns 0 if data were received, GNUTLS_E_TIMEDOUT
737  * on timeout and a negative error code on error.
738  */
_gnutls_io_check_recv(gnutls_session_t session,unsigned int ms)739 int _gnutls_io_check_recv(gnutls_session_t session, unsigned int ms)
740 {
741 	gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
742 	int ret = 0, err;
743 
744 	if (NO_TIMEOUT_FUNC_SET(session)) {
745 		_gnutls_debug_log("The pull function has been replaced but not the pull timeout.\n");
746 		return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
747 	}
748 
749 	reset_errno(session);
750 
751 	ret = session->internals.pull_timeout_func(fd, ms);
752 	if (ret == -1) {
753 		err = get_errno(session);
754 		_gnutls_read_log
755 		    ("READ_TIMEOUT: %d returned from %p, errno=%d (timeout: %u)\n",
756 		     (int) ret, fd, err, ms);
757 		return errno_to_gerr(err, IS_DTLS(session));
758 	}
759 
760 	if (ret > 0)
761 		return 0;
762 	else
763 		return GNUTLS_E_TIMEDOUT;
764 }
765 
766 /* HANDSHAKE buffers part
767  */
768 
769 /* This function writes the data that are left in the
770  * Handshake write buffer (ie. because the previous write was
771  * interrupted.
772  *
773  */
_gnutls_handshake_io_write_flush(gnutls_session_t session)774 ssize_t _gnutls_handshake_io_write_flush(gnutls_session_t session)
775 {
776 	mbuffer_head_st *const send_buffer =
777 	    &session->internals.handshake_send_buffer;
778 	gnutls_datum_t msg;
779 	int ret;
780 	uint16_t epoch;
781 	ssize_t total = 0;
782 	mbuffer_st *cur;
783 
784 	_gnutls_write_log("HWRITE FLUSH: %d bytes in buffer.\n",
785 			  (int) send_buffer->byte_length);
786 
787 	if (IS_DTLS(session))
788 		return _dtls_transmit(session);
789 
790 	for (cur = _mbuffer_head_get_first(send_buffer, &msg);
791 	     cur != NULL; cur = _mbuffer_head_get_first(send_buffer, &msg))
792 	{
793 		epoch = cur->epoch;
794 
795 		ret = _gnutls_send_int(session, cur->type,
796 				       cur->htype,
797 				       epoch, msg.data, msg.size, 0);
798 
799 		if (ret >= 0) {
800 			total += ret;
801 
802 			ret = _mbuffer_head_remove_bytes(send_buffer, ret);
803 			/* for each queued message we send, ensure that
804 			 * we drop the epoch refcount set in _gnutls_handshake_io_cache_int(). */
805 			if (ret == 1)
806 				_gnutls_epoch_refcount_dec(session, epoch);
807 
808 			_gnutls_write_log
809 			    ("HWRITE: wrote %d bytes, %d bytes left.\n",
810 			     ret, (int) send_buffer->byte_length);
811 
812 		} else {
813 			_gnutls_write_log
814 			    ("HWRITE error: code %d, %d bytes left.\n",
815 			     ret, (int) send_buffer->byte_length);
816 
817 			gnutls_assert();
818 			return ret;
819 		}
820 	}
821 
822 	return _gnutls_io_write_flush(session);
823 }
824 
825 
826 /* This is a send function for the gnutls handshake
827  * protocol. Just makes sure that all data have been sent.
828  *
829  */
830 int
_gnutls_handshake_io_cache_int(gnutls_session_t session,gnutls_handshake_description_t htype,mbuffer_st * bufel)831 _gnutls_handshake_io_cache_int(gnutls_session_t session,
832 			       gnutls_handshake_description_t htype,
833 			       mbuffer_st * bufel)
834 {
835 	mbuffer_head_st *send_buffer;
836 
837 	if (IS_DTLS(session)) {
838 		bufel->handshake_sequence =
839 		    session->internals.dtls.hsk_write_seq - 1;
840 	}
841 
842 	send_buffer = &session->internals.handshake_send_buffer;
843 
844 	/* ensure that our epoch does not get garbage collected
845 	 * before we send all queued messages with it */
846 	bufel->epoch =
847 	    (uint16_t) _gnutls_epoch_refcount_inc(session,
848 						  EPOCH_WRITE_CURRENT);
849 	bufel->htype = htype;
850 	if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
851 		bufel->type = GNUTLS_CHANGE_CIPHER_SPEC;
852 	else
853 		bufel->type = GNUTLS_HANDSHAKE;
854 
855 	_mbuffer_enqueue(send_buffer, bufel);
856 
857 	_gnutls_write_log
858 	    ("HWRITE: enqueued [%s] %d. Total %d bytes.\n",
859 	     _gnutls_handshake2str(bufel->htype), (int) bufel->msg.size,
860 	     (int) send_buffer->byte_length);
861 
862 	return 0;
863 }
864 
handshake_compare(const void * _e1,const void * _e2)865 static int handshake_compare(const void *_e1, const void *_e2)
866 {
867 	const handshake_buffer_st *e1 = _e1;
868 	const handshake_buffer_st *e2 = _e2;
869 
870 	if (e1->sequence <= e2->sequence)
871 		return 1;
872 	else
873 		return -1;
874 }
875 
876 #define SSL2_HEADERS 1
877 static int
parse_handshake_header(gnutls_session_t session,mbuffer_st * bufel,handshake_buffer_st * hsk)878 parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel,
879 		       handshake_buffer_st * hsk)
880 {
881 	uint8_t *dataptr = NULL;	/* for realloc */
882 	size_t handshake_header_size =
883 	    HANDSHAKE_HEADER_SIZE(session), data_size, frag_size;
884 
885 	/* Note: SSL2_HEADERS == 1 */
886 	if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
887 		return
888 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
889 
890 	dataptr = _mbuffer_get_udata_ptr(bufel);
891 
892 	/* if reading a client hello of SSLv2 */
893 #ifdef ENABLE_SSL2
894 	if (unlikely
895 	    (!IS_DTLS(session)
896 	     && bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)) {
897 		handshake_header_size = SSL2_HEADERS;	/* we've already read one byte */
898 
899 		frag_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;	/* we've read the first byte */
900 
901 		if (dataptr[0] != GNUTLS_HANDSHAKE_CLIENT_HELLO)
902 			return
903 			    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
904 
905 		hsk->rtype = hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
906 
907 		hsk->sequence = 0;
908 		hsk->start_offset = 0;
909 		hsk->length = frag_size;
910 	} else
911 #endif
912 	{	/* TLS or DTLS handshake headers */
913 
914 
915 		hsk->rtype = hsk->htype = dataptr[0];
916 
917 		/* we do not use DECR_LEN because we know
918 		 * that the packet has enough data.
919 		 */
920 		hsk->length = _gnutls_read_uint24(&dataptr[1]);
921 
922 		if (IS_DTLS(session)) {
923 			hsk->sequence = _gnutls_read_uint16(&dataptr[4]);
924 			hsk->start_offset =
925 			    _gnutls_read_uint24(&dataptr[6]);
926 			frag_size =
927 			    _gnutls_read_uint24(&dataptr[9]);
928 		} else {
929 			hsk->sequence = 0;
930 			hsk->start_offset = 0;
931 			frag_size =
932 			    MIN((_mbuffer_get_udata_size(bufel) -
933 				 handshake_header_size), hsk->length);
934 		}
935 
936 		/* TLS1.3: distinguish server hello versus hello retry request.
937 		 * The epitome of slick protocol design. */
938 		if (hsk->htype == GNUTLS_HANDSHAKE_SERVER_HELLO && hsk->start_offset == 0 && !IS_DTLS(session)) {
939 			if (_mbuffer_get_udata_size(bufel) > handshake_header_size+2+GNUTLS_RANDOM_SIZE &&
940 			    memcmp(dataptr+handshake_header_size+2, HRR_RANDOM, GNUTLS_RANDOM_SIZE) == 0) {
941 				hsk->htype = GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST;
942 			}
943 		}
944 	}
945 	data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
946 
947 	if (frag_size > 0)
948 		hsk->end_offset = hsk->start_offset + frag_size - 1;
949 	else
950 		hsk->end_offset = 0;
951 
952 	_gnutls_handshake_log
953 	    ("HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
954 	     session, _gnutls_handshake2str(hsk->htype),
955 	     (unsigned) hsk->htype, (int) hsk->length, (int) data_size,
956 	     hsk->start_offset, (int) frag_size,
957 	     (int) hsk->sequence);
958 
959 	hsk->header_size = handshake_header_size;
960 	memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel),
961 	       handshake_header_size);
962 
963 	if (hsk->length > 0 && (frag_size > data_size ||
964 				(frag_size > 0 &&
965 				 hsk->end_offset >= hsk->length))) {
966 		return
967 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
968 	}
969 	else if (hsk->length == 0 && hsk->end_offset != 0
970 		 && hsk->start_offset != 0)
971 		return
972 		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
973 
974 	return handshake_header_size;
975 }
976 
_gnutls_handshake_buffer_move(handshake_buffer_st * dst,handshake_buffer_st * src)977 static void _gnutls_handshake_buffer_move(handshake_buffer_st * dst,
978 					  handshake_buffer_st * src)
979 {
980 	memcpy(dst, src, sizeof(*dst));
981 	memset(src, 0, sizeof(*src));
982 	src->htype = -1;
983 }
984 
985 /* will merge the given handshake_buffer_st to the handshake_recv_buffer
986  * list. The given hsk packet will be released in any case (success or failure).
987  * Only used in DTLS.
988  */
merge_handshake_packet(gnutls_session_t session,handshake_buffer_st * hsk)989 static int merge_handshake_packet(gnutls_session_t session,
990 				  handshake_buffer_st * hsk)
991 {
992 	int exists = 0, i, pos = 0;
993 	int ret;
994 
995 	for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) {
996 		if (session->internals.handshake_recv_buffer[i].htype ==
997 		    hsk->htype) {
998 			exists = 1;
999 			pos = i;
1000 			break;
1001 		}
1002 	}
1003 
1004 	if (!exists)
1005 		pos = session->internals.handshake_recv_buffer_size;
1006 
1007 	if (pos >= MAX_HANDSHAKE_MSGS)
1008 		return
1009 		    gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
1010 
1011 	if (!exists) {
1012 		if (hsk->length > 0 && hsk->end_offset > 0
1013 		    && hsk->end_offset - hsk->start_offset + 1 !=
1014 		    hsk->length) {
1015 			ret =
1016 			    _gnutls_buffer_resize(&hsk->data, hsk->length);
1017 			if (ret < 0)
1018 				return gnutls_assert_val(ret);
1019 
1020 			hsk->data.length = hsk->length;
1021 
1022 			memmove(&hsk->data.data[hsk->start_offset],
1023 				hsk->data.data,
1024 				hsk->end_offset - hsk->start_offset + 1);
1025 		}
1026 
1027 		session->internals.handshake_recv_buffer_size++;
1028 
1029 		/* rewrite headers to make them look as each packet came as a single fragment */
1030 		_gnutls_write_uint24(hsk->length, &hsk->header[1]);
1031 		_gnutls_write_uint24(0, &hsk->header[6]);
1032 		_gnutls_write_uint24(hsk->length, &hsk->header[9]);
1033 
1034 		_gnutls_handshake_buffer_move(&session->internals.
1035 					      handshake_recv_buffer[pos],
1036 					      hsk);
1037 
1038 	} else {
1039 		if (hsk->start_offset <
1040 		    session->internals.handshake_recv_buffer[pos].
1041 		    start_offset
1042 		    && hsk->end_offset + 1 >=
1043 		    session->internals.handshake_recv_buffer[pos].
1044 		    start_offset) {
1045 			memcpy(&session->internals.
1046 			       handshake_recv_buffer[pos].data.data[hsk->
1047 								    start_offset],
1048 			       hsk->data.data, hsk->data.length);
1049 			session->internals.handshake_recv_buffer[pos].
1050 			    start_offset = hsk->start_offset;
1051 			session->internals.handshake_recv_buffer[pos].
1052 			    end_offset =
1053 			    MIN(hsk->end_offset,
1054 				session->internals.
1055 				handshake_recv_buffer[pos].end_offset);
1056 		} else if (hsk->end_offset >
1057 			   session->internals.handshake_recv_buffer[pos].
1058 			   end_offset
1059 			   && hsk->start_offset <=
1060 			   session->internals.handshake_recv_buffer[pos].
1061 			   end_offset + 1) {
1062 			memcpy(&session->internals.
1063 			       handshake_recv_buffer[pos].data.data[hsk->
1064 								    start_offset],
1065 			       hsk->data.data, hsk->data.length);
1066 
1067 			session->internals.handshake_recv_buffer[pos].
1068 			    end_offset = hsk->end_offset;
1069 			session->internals.handshake_recv_buffer[pos].
1070 			    start_offset =
1071 			    MIN(hsk->start_offset,
1072 				session->internals.
1073 				handshake_recv_buffer[pos].start_offset);
1074 		}
1075 		_gnutls_handshake_buffer_clear(hsk);
1076 	}
1077 
1078 	return 0;
1079 }
1080 
1081 /* returns non-zero on match and zero on mismatch
1082  */
cmp_hsk_types(gnutls_handshake_description_t expected,gnutls_handshake_description_t recvd)1083 inline static int cmp_hsk_types(gnutls_handshake_description_t expected,
1084 				gnutls_handshake_description_t recvd)
1085 {
1086 	if (expected == GNUTLS_HANDSHAKE_ANY)
1087 		return 1;
1088 
1089 #ifdef ENABLE_SSL2
1090 	if (expected == GNUTLS_HANDSHAKE_CLIENT_HELLO
1091 	     && recvd == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)
1092 		return 1;
1093 #endif
1094 	if (expected != recvd)
1095 		return 0;
1096 
1097 	return 1;
1098 }
1099 
1100 #define LAST_ELEMENT (session->internals.handshake_recv_buffer_size-1)
1101 
1102 /* returns the last stored handshake packet.
1103  */
get_last_packet(gnutls_session_t session,gnutls_handshake_description_t htype,handshake_buffer_st * hsk,unsigned int optional)1104 static int get_last_packet(gnutls_session_t session,
1105 			   gnutls_handshake_description_t htype,
1106 			   handshake_buffer_st * hsk,
1107 			   unsigned int optional)
1108 {
1109 	handshake_buffer_st *recv_buf =
1110 	    session->internals.handshake_recv_buffer;
1111 
1112 	if (IS_DTLS(session)) {
1113 		if (session->internals.handshake_recv_buffer_size == 0 ||
1114 		    (session->internals.dtls.hsk_read_seq !=
1115 		     recv_buf[LAST_ELEMENT].sequence))
1116 			goto timeout;
1117 
1118 		if (htype != recv_buf[LAST_ELEMENT].htype) {
1119 			if (optional == 0)
1120 				_gnutls_audit_log(session,
1121 						  "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n",
1122 						  _gnutls_handshake2str
1123 						  (recv_buf[0].htype),
1124 						  (int) recv_buf[0].htype,
1125 						  _gnutls_handshake2str
1126 						  (htype), (int) htype);
1127 
1128 			return
1129 			    gnutls_assert_val
1130 			    (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
1131 		}
1132 
1133 		else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
1134 			  recv_buf[LAST_ELEMENT].end_offset ==
1135 			  recv_buf[LAST_ELEMENT].length - 1)
1136 			 || recv_buf[LAST_ELEMENT].length == 0) {
1137 			session->internals.dtls.hsk_read_seq++;
1138 			_gnutls_handshake_buffer_move(hsk,
1139 						      &recv_buf
1140 						      [LAST_ELEMENT]);
1141 			session->internals.handshake_recv_buffer_size--;
1142 			return 0;
1143 		} else {
1144 			/* if we don't have a complete handshake message, but we
1145 			 * have queued data waiting, try again to reconstruct the
1146 			 * handshake packet, using the queued */
1147 			if (recv_buf[LAST_ELEMENT].end_offset != recv_buf[LAST_ELEMENT].length - 1 &&
1148 			    record_check_unprocessed(session) > 0)
1149 				return gnutls_assert_val(GNUTLS_E_INT_CHECK_AGAIN);
1150 			else
1151 				goto timeout;
1152 		}
1153 	} else {		/* TLS */
1154 
1155 		if (session->internals.handshake_recv_buffer_size > 0
1156 		    && recv_buf[0].length == recv_buf[0].data.length) {
1157 			if (cmp_hsk_types(htype, recv_buf[0].htype) == 0) {
1158 				return
1159 				    gnutls_assert_val
1160 				    (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
1161 			}
1162 
1163 			_gnutls_handshake_buffer_move(hsk, &recv_buf[0]);
1164 			session->internals.handshake_recv_buffer_size--;
1165 			return 0;
1166 		} else
1167 			return
1168 			    gnutls_assert_val
1169 			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1170 	}
1171 
1172       timeout:
1173 	RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0);
1174 }
1175 
1176 /* This is a receive function for the gnutls handshake
1177  * protocol. Makes sure that we have received all data.
1178  *
1179  * htype is the next handshake packet expected.
1180  */
_gnutls_parse_record_buffered_msgs(gnutls_session_t session)1181 int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
1182 {
1183 	gnutls_datum_t msg;
1184 	mbuffer_st *bufel = NULL, *prev = NULL;
1185 	int ret;
1186 	size_t data_size;
1187 	handshake_buffer_st *recv_buf =
1188 	    session->internals.handshake_recv_buffer;
1189 
1190 	bufel =
1191 	    _mbuffer_head_get_first(&session->internals.record_buffer,
1192 				    &msg);
1193 	if (bufel == NULL)
1194 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1195 
1196 	if (!IS_DTLS(session)) {
1197 		ssize_t append, header_size;
1198 
1199 		do {
1200 			if (bufel->type != GNUTLS_HANDSHAKE)
1201 				return
1202 				    gnutls_assert_val
1203 				    (GNUTLS_E_UNEXPECTED_PACKET);
1204 
1205 			if (unlikely
1206 			    (session->internals.handshake_recv_buffer_size == 0 &&
1207 			     msg.size < HANDSHAKE_HEADER_SIZE(session) &&
1208 			     session->internals.handshake_header_recv_buffer.byte_length <
1209 			     HANDSHAKE_HEADER_SIZE(session) - msg.size)) {
1210 				bufel = _mbuffer_head_pop_first(&session->internals.record_buffer);
1211 				_mbuffer_enqueue(&session->internals.handshake_header_recv_buffer,
1212 						 bufel);
1213 				break;
1214 			} else if (session->internals.handshake_recv_buffer_size >
1215 				   0 && recv_buf[0].length > recv_buf[0].data.length) {
1216 				/* this is the rest of a previous message */
1217 				append = MIN(msg.size,
1218 					     recv_buf[0].length -
1219 					     recv_buf[0].data.length);
1220 
1221 				ret =
1222 				    _gnutls_buffer_append_data(&recv_buf
1223 							       [0].data,
1224 							       msg.data,
1225 							       append);
1226 				if (ret < 0)
1227 					return gnutls_assert_val(ret);
1228 
1229 				_mbuffer_head_remove_bytes(&session->
1230 							   internals.
1231 							   record_buffer,
1232 							   append);
1233 			} else {	/* received new message */
1234 				if (unlikely
1235 				    (session->internals.
1236 				     handshake_header_recv_buffer.length > 0)) {
1237 					bufel = _mbuffer_head_pop_first(&session->internals.
1238 									record_buffer);
1239 					_mbuffer_enqueue(&session->internals.
1240 							 handshake_header_recv_buffer,
1241 							 bufel);
1242 					ret = _mbuffer_linearize_align16(&session->internals.
1243 									 handshake_header_recv_buffer,
1244 									 get_total_headers(session));
1245 					if (ret < 0)
1246 						return gnutls_assert_val(ret);
1247 					bufel = _mbuffer_head_pop_first(&session->internals.
1248 									handshake_header_recv_buffer);
1249 					_mbuffer_head_push_first(&session->internals.
1250 								 record_buffer,
1251 								 bufel);
1252 				}
1253 
1254 				ret =
1255 				    parse_handshake_header(session, bufel,
1256 							   &recv_buf[0]);
1257 				if (ret < 0)
1258 					return gnutls_assert_val(ret);
1259 
1260 				header_size = ret;
1261 				session->internals.
1262 				    handshake_recv_buffer_size = 1;
1263 
1264 				_mbuffer_set_uhead_size(bufel,
1265 							header_size);
1266 
1267 				data_size =
1268 				    MIN(recv_buf[0].length,
1269 					_mbuffer_get_udata_size(bufel));
1270 				ret =
1271 				    _gnutls_buffer_append_data(&recv_buf
1272 							       [0].data,
1273 							       _mbuffer_get_udata_ptr
1274 							       (bufel),
1275 							       data_size);
1276 				if (ret < 0)
1277 					return gnutls_assert_val(ret);
1278 				_mbuffer_set_uhead_size(bufel, 0);
1279 				_mbuffer_head_remove_bytes(&session->
1280 							   internals.
1281 							   record_buffer,
1282 							   data_size +
1283 							   header_size);
1284 			}
1285 
1286 			/* if packet is complete then return it
1287 			 */
1288 			if (recv_buf[0].length == recv_buf[0].data.length) {
1289 				return 0;
1290 			}
1291 			bufel =
1292 			    _mbuffer_head_get_first(&session->internals.
1293 						    record_buffer, &msg);
1294 		}
1295 		while (bufel != NULL);
1296 
1297 		/* if we are here it means that the received packets were not
1298 		 * enough to complete the handshake packet.
1299 		 */
1300 		return gnutls_assert_val(GNUTLS_E_AGAIN);
1301 	} else {		/* DTLS */
1302 
1303 		handshake_buffer_st tmp;
1304 
1305 		do {
1306 			/* we now
1307 			 * 0. parse headers
1308 			 * 1. insert to handshake_recv_buffer
1309 			 * 2. sort handshake_recv_buffer on sequence numbers
1310 			 * 3. return first packet if completed or GNUTLS_E_AGAIN.
1311 			 */
1312 			do {
1313 				if (bufel->type != GNUTLS_HANDSHAKE) {
1314 					gnutls_assert();
1315 					goto next;	/* ignore packet */
1316 				}
1317 
1318 				_gnutls_handshake_buffer_init(&tmp);
1319 
1320 				ret =
1321 				    parse_handshake_header(session, bufel,
1322 							   &tmp);
1323 				if (ret < 0) {
1324 					gnutls_assert();
1325 					_gnutls_audit_log(session,
1326 							  "Invalid handshake packet headers. Discarding.\n");
1327 					break;
1328 				}
1329 
1330 				_mbuffer_consume(&session->internals.
1331 						 record_buffer, bufel,
1332 						 ret);
1333 
1334 				data_size =
1335 				    MIN(tmp.length,
1336 					tmp.end_offset - tmp.start_offset +
1337 					1);
1338 
1339 				ret =
1340 				    _gnutls_buffer_append_data(&tmp.data,
1341 							       _mbuffer_get_udata_ptr
1342 							       (bufel),
1343 							       data_size);
1344 				if (ret < 0)
1345 					return gnutls_assert_val(ret);
1346 
1347 				_mbuffer_consume(&session->internals.
1348 						 record_buffer, bufel,
1349 						 data_size);
1350 
1351 				ret =
1352 				    merge_handshake_packet(session, &tmp);
1353 				if (ret < 0)
1354 					return gnutls_assert_val(ret);
1355 
1356 			}
1357 			while (_mbuffer_get_udata_size(bufel) > 0);
1358 
1359 			prev = bufel;
1360 			bufel =
1361 			    _mbuffer_dequeue(&session->internals.
1362 					     record_buffer, bufel);
1363 
1364 			_mbuffer_xfree(&prev);
1365 			continue;
1366 
1367 		      next:
1368 			bufel = _mbuffer_head_get_next(bufel, NULL);
1369 		}
1370 		while (bufel != NULL);
1371 
1372 		/* sort in descending order */
1373 		if (session->internals.handshake_recv_buffer_size > 1)
1374 			qsort(recv_buf,
1375 			      session->internals.
1376 			      handshake_recv_buffer_size,
1377 			      sizeof(recv_buf[0]), handshake_compare);
1378 
1379 		while (session->internals.handshake_recv_buffer_size > 0 &&
1380 		       recv_buf[LAST_ELEMENT].sequence <
1381 		       session->internals.dtls.hsk_read_seq) {
1382 			_gnutls_audit_log(session,
1383 					  "Discarded replayed handshake packet with sequence %d\n",
1384 					  recv_buf[LAST_ELEMENT].sequence);
1385 			_gnutls_handshake_buffer_clear(&recv_buf
1386 						       [LAST_ELEMENT]);
1387 			session->internals.handshake_recv_buffer_size--;
1388 		}
1389 
1390 		return 0;
1391 	}
1392 }
1393 
1394 /* This is a receive function for the gnutls handshake
1395  * protocol. Makes sure that we have received all data.
1396  */
1397 ssize_t
_gnutls_handshake_io_recv_int(gnutls_session_t session,gnutls_handshake_description_t htype,handshake_buffer_st * hsk,unsigned int optional)1398 _gnutls_handshake_io_recv_int(gnutls_session_t session,
1399 			      gnutls_handshake_description_t htype,
1400 			      handshake_buffer_st * hsk,
1401 			      unsigned int optional)
1402 {
1403 	int ret;
1404 	unsigned int tleft = 0;
1405 	int retries = 7;
1406 
1407 	ret = get_last_packet(session, htype, hsk, optional);
1408 	if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED &&
1409 	    ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE &&
1410 	    ret != GNUTLS_E_INT_CHECK_AGAIN) {
1411 		return gnutls_assert_val(ret);
1412 	}
1413 
1414 	/* try using the already existing records before
1415 	 * trying to receive.
1416 	 */
1417 	ret = _gnutls_parse_record_buffered_msgs(session);
1418 
1419 	if (ret == 0) {
1420 		ret = get_last_packet(session, htype, hsk, optional);
1421 	}
1422 
1423 	if (IS_DTLS(session)) {
1424 		if (ret >= 0)
1425 			return ret;
1426 	} else {
1427 		if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1428 		     && ret < 0) || ret >= 0)
1429 			return gnutls_assert_val(ret);
1430 	}
1431 
1432 	if (htype != (gnutls_handshake_description_t) -1) {
1433 		ret = handshake_remaining_time(session);
1434 		if (ret < 0)
1435 			return gnutls_assert_val(ret);
1436 		tleft = ret;
1437 	}
1438 
1439 	do {
1440 		/* if we don't have a complete message waiting for us, try
1441 		 * receiving more */
1442 		ret =
1443 		    _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype,
1444 					    tleft);
1445 		if (ret < 0)
1446 			return gnutls_assert_val_fatal(ret);
1447 
1448 		ret = _gnutls_parse_record_buffered_msgs(session);
1449 		if (ret == 0) {
1450 			ret = get_last_packet(session, htype, hsk, optional);
1451 		}
1452 		/* we put an upper limit (retries) to the number of partial handshake
1453 		 * messages in a record packet. */
1454 	} while(IS_DTLS(session) && ret == GNUTLS_E_INT_CHECK_AGAIN && retries-- > 0);
1455 
1456 	if (unlikely(IS_DTLS(session) && ret == GNUTLS_E_INT_CHECK_AGAIN)) {
1457 		ret = gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
1458 	}
1459 
1460 	return ret;
1461 }
1462