예제 #1
0
/* returns the last stored handshake packet.
 */
static int get_last_packet(gnutls_session_t session, gnutls_handshake_description_t htype,
  handshake_buffer_st * hsk)
{
handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;

  if (IS_DTLS(session))
    {
      if (session->internals.handshake_recv_buffer_size == 0 ||
        (session->internals.dtls.hsk_read_seq != recv_buf[LAST_ELEMENT].sequence))
        goto timeout;

      if (htype != recv_buf[LAST_ELEMENT].htype)
        {
          hsk->htype = recv_buf[LAST_ELEMENT].htype;
          return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
        }

      else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
        recv_buf[LAST_ELEMENT].end_offset == recv_buf[LAST_ELEMENT].length -1) || 
        recv_buf[LAST_ELEMENT].length == 0)
        {
          session->internals.dtls.hsk_read_seq++;
          _gnutls_handshake_buffer_move(hsk, &recv_buf[LAST_ELEMENT]);
          session->internals.handshake_recv_buffer_size--;
          return 0;
        }
      else
        goto timeout;
    }
  else /* TLS */
    {
      if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length == recv_buf[0].data.length)
        {
          if (cmp_hsk_types(htype, recv_buf[0].htype) == 0)
            {
              hsk->htype = recv_buf[LAST_ELEMENT].htype;
              return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
            }

          _gnutls_handshake_buffer_move(hsk, &recv_buf[0]);
          session->internals.handshake_recv_buffer_size--;
          return 0;
        }
      else
        return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
    }

timeout:
  if (time(0)-session->internals.dtls.handshake_start_time > session->internals.dtls.total_timeout/1000) 
    return gnutls_assert_val(GNUTLS_E_TIMEDOUT);
  else
    {
      if (session->internals.dtls.blocking != 0)
        millisleep(50);
        
      return gnutls_assert_val(GNUTLS_E_AGAIN);
    }
}
예제 #2
0
파일: buffers.c 프로젝트: gnutls/gnutls
/* will merge the given handshake_buffer_st to the handshake_recv_buffer
 * list. The given hsk packet will be released in any case (success or failure).
 * Only used in DTLS.
 */
static int merge_handshake_packet(gnutls_session_t session,
				  handshake_buffer_st * hsk)
{
	int exists = 0, i, pos = 0;
	int ret;

	for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) {
		if (session->internals.handshake_recv_buffer[i].htype ==
		    hsk->htype) {
			exists = 1;
			pos = i;
			break;
		}
	}

	if (!exists)
		pos = session->internals.handshake_recv_buffer_size;

	if (pos >= MAX_HANDSHAKE_MSGS)
		return
		    gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);

	if (!exists) {
		if (hsk->length > 0 && hsk->end_offset > 0
		    && hsk->end_offset - hsk->start_offset + 1 !=
		    hsk->length) {
			ret =
			    _gnutls_buffer_resize(&hsk->data, hsk->length);
			if (ret < 0)
				return gnutls_assert_val(ret);

			hsk->data.length = hsk->length;

			memmove(&hsk->data.data[hsk->start_offset],
				hsk->data.data,
				hsk->end_offset - hsk->start_offset + 1);
		}

		session->internals.handshake_recv_buffer_size++;

		/* rewrite headers to make them look as each packet came as a single fragment */
		_gnutls_write_uint24(hsk->length, &hsk->header[1]);
		_gnutls_write_uint24(0, &hsk->header[6]);
		_gnutls_write_uint24(hsk->length, &hsk->header[9]);

		_gnutls_handshake_buffer_move(&session->internals.
					      handshake_recv_buffer[pos],
					      hsk);

	} else {
		if (hsk->start_offset <
		    session->internals.handshake_recv_buffer[pos].
		    start_offset
		    && hsk->end_offset + 1 >=
		    session->internals.handshake_recv_buffer[pos].
		    start_offset) {
			memcpy(&session->internals.
			       handshake_recv_buffer[pos].data.data[hsk->
								    start_offset],
			       hsk->data.data, hsk->data.length);
			session->internals.handshake_recv_buffer[pos].
			    start_offset = hsk->start_offset;
			session->internals.handshake_recv_buffer[pos].
			    end_offset =
			    MIN(hsk->end_offset,
				session->internals.
				handshake_recv_buffer[pos].end_offset);
		} else if (hsk->end_offset >
			   session->internals.handshake_recv_buffer[pos].
			   end_offset
			   && hsk->start_offset <=
			   session->internals.handshake_recv_buffer[pos].
			   end_offset + 1) {
			memcpy(&session->internals.
			       handshake_recv_buffer[pos].data.data[hsk->
								    start_offset],
			       hsk->data.data, hsk->data.length);

			session->internals.handshake_recv_buffer[pos].
			    end_offset = hsk->end_offset;
			session->internals.handshake_recv_buffer[pos].
			    start_offset =
			    MIN(hsk->start_offset,
				session->internals.
				handshake_recv_buffer[pos].start_offset);
		}
		_gnutls_handshake_buffer_clear(hsk);
	}

	return 0;
}
예제 #3
0
파일: buffers.c 프로젝트: gnutls/gnutls
/* returns the last stored handshake packet.
 */
static int get_last_packet(gnutls_session_t session,
			   gnutls_handshake_description_t htype,
			   handshake_buffer_st * hsk,
			   unsigned int optional)
{
	handshake_buffer_st *recv_buf =
	    session->internals.handshake_recv_buffer;

	if (IS_DTLS(session)) {
		if (session->internals.handshake_recv_buffer_size == 0 ||
		    (session->internals.dtls.hsk_read_seq !=
		     recv_buf[LAST_ELEMENT].sequence))
			goto timeout;

		if (htype != recv_buf[LAST_ELEMENT].htype) {
			if (optional == 0)
				_gnutls_audit_log(session,
						  "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n",
						  _gnutls_handshake2str
						  (recv_buf[0].htype),
						  (int) recv_buf[0].htype,
						  _gnutls_handshake2str
						  (htype), (int) htype);

			return
			    gnutls_assert_val
			    (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
		}

		else if ((recv_buf[LAST_ELEMENT].start_offset == 0 &&
			  recv_buf[LAST_ELEMENT].end_offset ==
			  recv_buf[LAST_ELEMENT].length - 1)
			 || recv_buf[LAST_ELEMENT].length == 0) {
			session->internals.dtls.hsk_read_seq++;
			_gnutls_handshake_buffer_move(hsk,
						      &recv_buf
						      [LAST_ELEMENT]);
			session->internals.handshake_recv_buffer_size--;
			return 0;
		} else {
			/* if we don't have a complete handshake message, but we
			 * have queued data waiting, try again to reconstruct the
			 * handshake packet, using the queued */
			if (recv_buf[LAST_ELEMENT].end_offset != recv_buf[LAST_ELEMENT].length - 1 &&
			    record_check_unprocessed(session) > 0)
				return gnutls_assert_val(GNUTLS_E_INT_CHECK_AGAIN);
			else
				goto timeout;
		}
	} else {		/* TLS */

		if (session->internals.handshake_recv_buffer_size > 0
		    && recv_buf[0].length == recv_buf[0].data.length) {
			if (cmp_hsk_types(htype, recv_buf[0].htype) == 0) {
				return
				    gnutls_assert_val
				    (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
			}

			_gnutls_handshake_buffer_move(hsk, &recv_buf[0]);
			session->internals.handshake_recv_buffer_size--;
			return 0;
		} else
			return
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
	}

      timeout:
	RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, 0);
}