[sr #107464] Secure Connections on AIX using non blocking socket

Bjørn Christensen INVALID.NOREPLY at gnu.org
Wed Aug 25 14:44:31 CEST 2010


URL:
  <http://savannah.gnu.org/support/?107464>

                 Summary: Secure Connections on AIX using non blocking socket
                 Project: GnuTLS
            Submitted by: cybear
            Submitted on: Wed Aug 25 12:44:30 2010
                Category: None
                Priority: 5 - Normal
                Severity: 3 - Normal
                  Status: None
                 Privacy: Public
             Assigned to: None
        Originator Email: 
             Open/Closed: Open
         Discussion Lock: Any
        Operating System: *BSD

    _______________________________________________________

Details:




I have a tool that uses GNUTLS and are ported between different platforms
Windows, Linux and AIX. The tool are working on Windows and Linux but causing
problems on AIX.
The behaviour is failing handshake. And from the log file I can see:
 READ: -1 returned from b, errno=0 gerrno=0
Comming from line 310 of gnutls_buffers.c and followed by an assertion in
line 329 of gnutls_buffers.c

>From inspecting the code it looks like recv is returning -1 but not setting
the errno. I am uncertain what could cause recv to return result like this. I
am using non-blocking sockets and recv are called with the MSG_PEEK option.



I have made the changes below to make the GNUTLS library complete the
Handshake.

I am changing the err from 0 to EAGAIN 
err=err==0?EAGAIN:err;  // HACK by BHC


All of the _gnutls_read function below from version (2.10.1)

/* This function is like read. But it does not return -1 on error.
 * It does return gnutls_errno instead.
 *
 * Flags are only used if the default recv() function is being used.
 */
static ssize_t
_gnutls_read (gnutls_session_t session, void *iptr,
	      size_t sizeOfPtr, int flags)
{
  size_t left;
  ssize_t i = 0;
  char *ptr = iptr;
  unsigned j, x, sum = 0;
  gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;

  session->internals.direction = 0;

  left = sizeOfPtr;
  while (left > 0)
    {

      session->internals.errnum = 0;

      if (session->internals._gnutls_pull_func == NULL)
	{
	  i = recv (GNUTLS_POINTER_TO_INT (fd), &ptr[sizeOfPtr - left],
		    left, flags);
_gnutls_read_log ("BHC: %d returned from %p, errno=%d gerrno=%d\n",
			    (int) i, fd, errno, session->internals.errnum);
#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_pull_func (fd,
						  &ptr[sizeOfPtr -
						       left], left);

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

	  _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
			    (int) i, fd, errno, session->internals.errnum);
	  err=err==0?EAGAIN:err;  // HACK by BHC
	  if (err == EAGAIN || err == EINTR)
	    {
	      if (sizeOfPtr - left > 0)
		{

		  _gnutls_read_log ("READ: returning %d bytes from %p\n",
				    (int) (sizeOfPtr - left), fd);

		  goto finish;
		}

	      if (err == EAGAIN)
		return GNUTLS_E_AGAIN;
	      return GNUTLS_E_INTERRUPTED;
	    }
	  else
	    {
	      gnutls_assert ();
	      return GNUTLS_E_PULL_ERROR;
	    }
	}
      else
	{

	  _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);

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

      left -= i;

    }

finish:

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


      _gnutls_read_log ("READ: read %d bytes from %p\n",
			(int) (sizeOfPtr - left), fd);

      for (x = 0; x < ((sizeOfPtr - left) / 16) + 1; x++)
	{
	  line[0] = 0;

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

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

  return (sizeOfPtr - left);
}






    _______________________________________________________

Reply to this item at:

  <http://savannah.gnu.org/support/?107464>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.gnu.org/





More information about the Gnutls-devel mailing list