Example #1
0
/* Buffer for handshake packets. Keeps the packets in order
 * for finished messages to use them. Used in HMAC calculation
 * and finished messages.
 */
int
_gnutls_handshake_buffer_put (gnutls_session_t session, opaque * data,
                              size_t length)
{

    if (length == 0)
        return 0;

    if ((session->internals.max_handshake_data_buffer_size > 0) &&
            ((length + session->internals.handshake_hash_buffer.length) >
             session->internals.max_handshake_data_buffer_size))
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", length);

    if (_gnutls_buffer_append (&session->internals.handshake_hash_buffer,
                               data, length) < 0)
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    return 0;
}
int
_gnutls_gen_supplemental (gnutls_session_t session, gnutls_buffer * buf)
{
  gnutls_supplemental_entry *p;
  int ret;

  /* Make room for 3 byte length field. */
  ret = _gnutls_buffer_append (buf, "\0\0\0", 3);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  for (p = _gnutls_supplemental; p->name; p++)
    {
      supp_send_func supp_send = p->supp_send_func;
      size_t sizepos = buf->length;

      /* Make room for supplement type and length byte length field. */
      ret = _gnutls_buffer_append (buf, "\0\0\0\0", 4);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      ret = supp_send (session, buf);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      /* If data were added, store type+length, otherwise reset. */
      if (buf->length > sizepos + 4)
	{
	  buf->data[sizepos] = 0;
	  buf->data[sizepos + 1] = p->type;
	  buf->data[sizepos + 2] = ((buf->length - sizepos - 4) >> 8) & 0xFF;
	  buf->data[sizepos + 3] = (buf->length - sizepos - 4) & 0xFF;
	}
      else
Example #3
0
/* Buffers received packets of type APPLICATION DATA and
 * HANDSHAKE DATA.
 */
int
_gnutls_record_buffer_put (content_type_t type,
                           gnutls_session_t session, opaque * data,
                           size_t length)
{
    gnutls_buffer *buf;

    if (length == 0)
        return 0;

    switch (type)
    {
    case GNUTLS_APPLICATION_DATA:
        buf = &session->internals.application_data_buffer;
        _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
                             length, type);
        break;

    case GNUTLS_HANDSHAKE:
        buf = &session->internals.handshake_data_buffer;
        _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data(%d)\n",
                             length, type);
        break;

    case GNUTLS_INNER_APPLICATION:
        buf = &session->internals.ia_data_buffer;
        _gnutls_buffers_log ("BUF[IA]: Inserted %d bytes of Data(%d)\n",
                             length, type);
        break;

    default:
        gnutls_assert ();
        return GNUTLS_E_INVALID_REQUEST;
    }

    if (_gnutls_buffer_append (buf, data, length) < 0)
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    return 0;
}
Example #4
0
inline static int
_gnutls_buffer_insert (gnutls_buffer * buffer,
                       const opaque * _data, size_t data_size)
{

    if ((MEMSUB (_data, buffer->data) >= 0)
            && (MEMSUB (_data, buffer->data) < (ssize_t) buffer->length))
    {
        /* the given _data is part of the buffer.
         */
        if (data_size > buffer->length)
        {
            gnutls_assert ();
            /* this shouldn't have happened */
            return GNUTLS_E_INTERNAL_ERROR;
        }

        if (_data == buffer->data)
        {   /* then don't even memmove */
            buffer->length = data_size;
            return 0;
        }

        memmove (buffer->data, _data, data_size);
        buffer->length = data_size;

        return 0;

    }

    if (_gnutls_buffer_append (buffer, _data, data_size) < 0)
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    return 0;
}
Example #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,
			       content_type_t type,
			       gnutls_handshake_description_t htype,
			       void *iptr, size_t sizeOfPtr)
{
  size_t left;
  ssize_t i;
  opaque *ptr;
  size_t dsize;

  ptr = iptr;
  left = sizeOfPtr;

  if (sizeOfPtr == 0 || iptr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (session->internals.handshake_recv_buffer.length > 0)
    {
      size_t tmp;
      
      /* if we have already received some data */
      if (sizeOfPtr <= session->internals.handshake_recv_buffer.length)
	{
	  /* if requested less data then return it.
	   */
	  gnutls_assert ();
	  
	  tmp = sizeOfPtr;
	  _gnutls_string_get_data( &session->internals.handshake_recv_buffer, iptr, &tmp);
	  return tmp;
	}
      gnutls_assert ();

      tmp = sizeOfPtr; 
      _gnutls_string_get_data( &session->internals.handshake_recv_buffer, iptr, &tmp);
      left -= tmp;

      htype = session->internals.handshake_recv_buffer_htype;
      type = session->internals.handshake_recv_buffer_type;
    }

  while (left > 0)
    {
      dsize = sizeOfPtr - left;
      i = _gnutls_recv_int (session, type, htype, &ptr[dsize], left);
      if (i < 0)
	{

	  if (dsize > 0 && (i == GNUTLS_E_INTERRUPTED || i == GNUTLS_E_AGAIN))
	    {
	      gnutls_assert ();

	      _gnutls_buffer_append (&session->internals.handshake_recv_buffer, iptr,
		      dsize);

	      session->internals.handshake_recv_buffer_htype = htype;
	      session->internals.handshake_recv_buffer_type = type;
	    }

	  gnutls_assert ();

	  return i;
	}
      else
	{
	  if (i == 0)
	    break;		/* EOF */
	}

      left -= i;

    }

  session->internals.handshake_recv_buffer.length = 0;

  return sizeOfPtr - left;
}
Example #6
0
/* This is a send function for the gnutls handshake 
 * protocol. Just makes sure that all data have been sent.
 */
ssize_t
_gnutls_handshake_io_send_int (gnutls_session_t session,
			       content_type_t type,
			       gnutls_handshake_description_t htype,
			       const void *iptr, size_t n)
{
  size_t left;
  ssize_t ret = 0;
  const opaque *ptr;
  ssize_t retval = 0;

  ptr = iptr;

  if (session->internals.handshake_send_buffer.length > 0 && ptr == NULL
      && n == 0)
    {
      gnutls_datum bdata;

      /* resuming previously interrupted write
       */
      gnutls_assert ();

      /* checking is handled above */
      _gnutls_buffer_get_datum (&session->internals.handshake_send_buffer, &bdata, session->internals.handshake_send_buffer.length);

      ptr = bdata.data;
      n = bdata.size;

      type = session->internals.handshake_send_buffer_type;
      htype = session->internals.handshake_send_buffer_htype;

    }
  else if (session->internals.handshake_send_buffer.length > 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }
#ifdef WRITE_DEBUG
  else
    {
      size_t sum = 0, x, j;

      _gnutls_write_log ("HWRITE: will write %d bytes to %d.\n", n,
			 gnutls_transport_get_ptr (session));
      for (x = 0; x < ((n) / 16) + 1; x++)
	{
	  if (sum > n)
	    break;

	  _gnutls_write_log ("%.4x - ", x);
	  for (j = 0; j < 16; j++)
	    {
	      if (sum < n)
		{
		  _gnutls_write_log ("%.2x ", ((unsigned char *) ptr)[sum++]);
		}
	      else
		break;
	    }
	  _gnutls_write_log ("\n");
	}
      _gnutls_write_log ("\n");
    }
#endif

  if (n == 0)
    {				/* if we have no data to send */
      gnutls_assert ();
      return 0;
    }
  else if (ptr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }


  left = n;
  while (left > 0)
    {
      ret = _gnutls_send_int (session, type, htype, &ptr[n - left], left);

      if (ret <= 0)
	{
	  if (ret == 0)
	    {
	      gnutls_assert ();
	      ret = GNUTLS_E_INTERNAL_ERROR;
	    }

	  if (left > 0
	      && (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN))
	    {
	      gnutls_assert ();

	      retval =
		_gnutls_buffer_append (&session->internals.
				       handshake_send_buffer, &ptr[n - left],
				       left);
	      if (retval < 0)
		{
		  gnutls_assert ();
		  return retval;
		}

	      session->internals.handshake_send_buffer_prev_size += n - left;

	      session->internals.handshake_send_buffer_type = type;
	      session->internals.handshake_send_buffer_htype = htype;

	    }
	  else
	    {
	      session->internals.handshake_send_buffer_prev_size = 0;
	      session->internals.handshake_send_buffer.length = 0;
	    }

	  gnutls_assert ();
	  return ret;
	}
      left -= ret;
    }

  retval = n + session->internals.handshake_send_buffer_prev_size;

  session->internals.handshake_send_buffer.length = 0;
  session->internals.handshake_send_buffer_prev_size = 0;

  return retval;

}
Example #7
0
/* This function is like write. But it does not return -1 on error.
 * It does return gnutls_errno instead.
 *
 * In case of E_AGAIN and E_INTERRUPTED errors, you must call gnutls_write_flush(),
 * until it returns ok (0).
 *
 * We need to push exactly the data in n, since we cannot send less
 * data. In TLS the peer must receive the whole packet in order
 * to decrypt and verify the integrity. 
 *
 */
ssize_t
_gnutls_io_write_buffered (gnutls_session_t session,
			   const void *iptr, size_t n)
{
  size_t left;
  unsigned j, x, sum = 0;
  ssize_t retval, i;
  const opaque *ptr;
  gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;

  /* to know where the procedure was interrupted.
   */
  session->internals.direction = 1;

  ptr = iptr;

  /* In case the previous write was interrupted, check if the
   * iptr != NULL and we have data in the buffer.
   * If this is true then return an error.
   */
  if (session->internals.record_send_buffer.length > 0 && iptr != NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* If data in the buffer exist
   */
  if (iptr == NULL)
    {
      gnutls_datum bdata;
      /* checking is handled above */
      _gnutls_buffer_get_datum (&session->internals.record_send_buffer, &bdata, session->internals.record_send_buffer.length);

      ptr = bdata.data;
      n = bdata.size;

      _gnutls_write_log
	("WRITE: Restoring old write. (%d bytes to send)\n", n);
    }

  _gnutls_write_log ("WRITE: Will write %d bytes to %p.\n", n, fd);

  i = 0;
  left = n;
  while (left > 0)
    {

      session->internals.errnum = 0;

      if (session->internals._gnutls_push_func == NULL)
	{
	  i = send (GNUTLS_POINTER_TO_INT (fd), &ptr[n - left], left, 0);
#if HAVE_WINSOCK2_H
	  if (i < 0)
	    {
	      int tmperr = WSAGetLastError ();
	      switch (tmperr)
		{
		case WSAEWOULDBLOCK:
		  session->internals.errnum = EAGAIN;
		  break;

		case WSAEINTR:
		  session->internals.errnum = EINTR;
		  break;

		default:
		  session->internals.errnum = EIO;
		  break;
		}
	      WSASetLastError (tmperr);
	    }
#endif
	}
      else
	i = session->internals._gnutls_push_func (fd, &ptr[n - left], left);

      if (i == -1)
	{
	  int err = session->internals.errnum ? session->internals.errnum
	    : errno;

	  if (err == EAGAIN || err == EINTR)
	    {
	      session->internals.record_send_buffer_prev_size += n - left;

	      retval =
		_gnutls_buffer_append (&session->internals.record_send_buffer,
				       &ptr[n - left], left);
	      if (retval < 0)
		{
		  gnutls_assert ();
		  return retval;
		}

	      _gnutls_write_log
		("WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n",
		 left, n - left);

	      if (err == EAGAIN)
		return GNUTLS_E_AGAIN;
	      return GNUTLS_E_INTERRUPTED;
	    }
	  else
	    {
	      gnutls_assert ();
	      return GNUTLS_E_PUSH_ERROR;
	    }
	}
      left -= i;


      if (_gnutls_log_level >= 7)
	{
	  char line[128];
	  char tmp[16];


	  _gnutls_write_log
	    ("WRITE: wrote %d bytes to %p. Left %d bytes. Total %d bytes.\n",
	     i, fd, left, n);
	  for (x = 0; x < (unsigned) ((i) / 16) + 1; x++)
	    {
	      line[0] = 0;

	      if (sum > n - left)
		break;

	      sprintf (tmp, "%.4x - ", x);
	      _gnutls_str_cat (line, sizeof (line), tmp);

	      for (j = 0; j < 16; j++)
		{
		  if (sum < n - left)
		    {
		      sprintf (tmp, "%.2x ",
			       ((const unsigned char *) ptr)[sum++]);
		      _gnutls_str_cat (line, sizeof (line), tmp);
		    }
		  else
		    break;
		}
	      _gnutls_write_log ("%s\n", line);
	    }
	}
    }

  retval = n + session->internals.record_send_buffer_prev_size;

  session->internals.record_send_buffer.length = 0;
  session->internals.record_send_buffer_prev_size = 0;

  return retval;

}