Пример #1
0
/* This function behaves exactly like read(). The only difference is
 * that it accepts the gnutls_session_t and the content_type_t of data to
 * receive (if called by the user the Content is Userdata only)
 * It is intended to receive data, under the current session.
 *
 * The gnutls_handshake_description_t was introduced to support SSL V2.0 client hellos.
 */
ssize_t
_gnutls_recv_int (gnutls_session_t session, content_type_t type,
                  gnutls_handshake_description_t htype,
                  uint8_t * data, size_t data_size, void* seq,
                  unsigned int ms)
{
  int ret;

  if ((type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT) && (data_size == 0 || data == NULL))
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  if (session->internals.read_eof != 0)
    {
      /* if we have already read an EOF
       */
      return 0;
    }
  else if (session_is_valid (session) != 0
           || session->internals.may_not_read != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_SESSION;
    }
    
  switch(session->internals.recv_state)
    {
      case RECV_STATE_DTLS_RETRANSMIT:
        ret = _dtls_retransmit(session);
        if (ret < 0)
          return gnutls_assert_val(ret);
        
        session->internals.recv_state = RECV_STATE_0;
      case RECV_STATE_0:

        _dtls_async_timer_check(session);
        /* If we have enough data in the cache do not bother receiving
         * a new packet. (in order to flush the cache)
         */ 
        ret = check_buffers (session, type, data, data_size, seq);
        if (ret != 0)
          return ret;

        ret = _gnutls_recv_in_buffers(session, type, htype, ms);
        if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
          return gnutls_assert_val(ret);

        return check_buffers (session, type, data, data_size, seq);
      default:
        return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
    }
}
Пример #2
0
/* Checks whether the received packet contains a handshake
 * packet with sequence higher that the previously received.
 * It must be called only when an actual packet has been
 * received.
 *
 * Returns: 0 if expected, negative value otherwise.
 */
static int is_next_hpacket_expected(gnutls_session_t session)
{
int ret;

  /* htype is arbitrary */
  ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, GNUTLS_HANDSHAKE_FINISHED, 0);
  if (ret < 0)
    return gnutls_assert_val(ret);
  
  ret = _gnutls_parse_record_buffered_msgs(session);
  if (ret < 0)
    return gnutls_assert_val(ret);

  if (session->internals.handshake_recv_buffer_size > 0)
    return 0;
  else
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
}
Пример #3
0
/* This function behaves exactly like read(). The only difference is
 * that it accepts the gnutls_session_t and the content_type_t of data to
 * receive (if called by the user the Content is Userdata only)
 * It is intended to receive data, under the current session.
 *
 * The gnutls_handshake_description_t was introduced to support SSL V2.0 client hellos.
 */
ssize_t
_gnutls_recv_int (gnutls_session_t session, content_type_t type,
                  gnutls_handshake_description_t htype,
                  uint8_t * data, size_t data_size, void* seq)
{
  int ret;

  if (type != GNUTLS_ALERT && (data_size == 0 || data == NULL))
    {
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (session->internals.read_eof != 0)
    {
      /* if we have already read an EOF
       */
      return 0;
    }
  else if (session_is_valid (session) != 0
           || session->internals.may_not_read != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_SESSION;
    }

  _dtls_async_timer_check(session);
  
  /* If we have enough data in the cache do not bother receiving
   * a new packet. (in order to flush the cache)
   */
  ret = check_buffers (session, type, data, data_size, seq);
  if (ret != 0)
    return ret;

  ret = _gnutls_recv_in_buffers(session, type, htype);
  if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
    return gnutls_assert_val(ret);

  return check_buffers (session, type, data, data_size, seq);
}
Пример #4
0
/* This is a receive function for the gnutls handshake 
 * protocol. Makes sure that we have received all data.
 */
ssize_t
_gnutls_handshake_io_recv_int (gnutls_session_t session,
                               gnutls_handshake_description_t htype,
                               handshake_buffer_st * hsk)
{
  int ret;

  ret = get_last_packet(session, htype, hsk);
  if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
    {
      return gnutls_assert_val(ret);
    }

  /* try using the already existing records before
   * trying to receive.
   */
  ret = parse_record_buffered_msgs(session, htype, hsk);
  if (IS_DTLS(session))
    {
      if (ret >= 0)
        return ret;
    }
  else
    {
      if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE && ret < 0) || ret >= 0)
        return gnutls_assert_val(ret);
    }

  /* if we don't have a complete message waiting for us, try 
   * receiving more */
  ret = _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype);
  if (ret < 0)
    return gnutls_assert_val_fatal(ret);

  return parse_record_buffered_msgs(session, htype, hsk); 
}
Пример #5
0
/* This is a receive function for the gnutls handshake 
 * protocol. Makes sure that we have received all data.
 */
ssize_t
_gnutls_handshake_io_recv_int(gnutls_session_t session,
			      gnutls_handshake_description_t htype,
			      handshake_buffer_st * hsk,
			      unsigned int optional)
{
	int ret;
	unsigned int tleft = 0;
	int retries = 7;

	ret = get_last_packet(session, htype, hsk, optional);
	if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED &&
	    ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE &&
	    ret != GNUTLS_E_INT_CHECK_AGAIN) {
		return gnutls_assert_val(ret);
	}

	/* try using the already existing records before
	 * trying to receive.
	 */
	ret = _gnutls_parse_record_buffered_msgs(session);

	if (ret == 0) {
		ret = get_last_packet(session, htype, hsk, optional);
	}

	if (IS_DTLS(session)) {
		if (ret >= 0)
			return ret;
	} else {
		if ((ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
		     && ret < 0) || ret >= 0)
			return gnutls_assert_val(ret);
	}

	if (htype != (gnutls_handshake_description_t) -1) {
		ret = handshake_remaining_time(session);
		if (ret < 0)
			return gnutls_assert_val(ret);
		tleft = ret;
	}

	do {
		/* if we don't have a complete message waiting for us, try 
		 * receiving more */
		ret =
		    _gnutls_recv_in_buffers(session, GNUTLS_HANDSHAKE, htype,
					    tleft);
		if (ret < 0)
			return gnutls_assert_val_fatal(ret);

		ret = _gnutls_parse_record_buffered_msgs(session);
		if (ret == 0) {
			ret = get_last_packet(session, htype, hsk, optional);
		}
		/* we put an upper limit (retries) to the number of partial handshake
		 * messages in a record packet. */
	} while(IS_DTLS(session) && ret == GNUTLS_E_INT_CHECK_AGAIN && retries-- > 0);

	if (unlikely(IS_DTLS(session) && ret == GNUTLS_E_INT_CHECK_AGAIN)) {
		ret = gnutls_assert_val(GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS);
	}

	return ret;
}