Ejemplo n.º 1
0
	static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t session_wrap, const void* buffer, size_t size)
	{
		issl_session* session = reinterpret_cast<issl_session*>(session_wrap);
		if (session->socket->GetEventMask() & FD_WRITE_WILL_BLOCK)
		{
#ifdef _WIN32
			gnutls_transport_set_errno(session->sess, EAGAIN);
#else
			errno = EAGAIN;
#endif
			return -1;
		}

		int rv = ServerInstance->SE->Send(session->socket, reinterpret_cast<const char *>(buffer), size, 0);

#ifdef _WIN32
		if (rv < 0)
		{
			/* Windows doesn't use errno, but gnutls does, so check SocketEngine::IgnoreError()
			 * and then set errno appropriately.
			 * The gnutls library may also have a different errno variable than us, see
			 * gnutls_transport_set_errno(3).
			 */
			gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno);
		}
#endif

		if (rv < (int)size)
			ServerInstance->SE->ChangeEventMask(session->socket, FD_WRITE_WILL_BLOCK);
		return rv;
	}
	static ssize_t gnutls_pull_wrapper(gnutls_transport_ptr_t session_wrap, void* buffer, size_t size)
	{
		StreamSocket* sock = reinterpret_cast<StreamSocket*>(session_wrap);
#ifdef _WIN32
		GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook());
#endif

		if (sock->GetEventMask() & FD_READ_WILL_BLOCK)
		{
#ifdef _WIN32
			gnutls_transport_set_errno(session->sess, EAGAIN);
#else
			errno = EAGAIN;
#endif
			return -1;
		}

		int rv = SocketEngine::Recv(sock, reinterpret_cast<char *>(buffer), size, 0);

#ifdef _WIN32
		if (rv < 0)
		{
			/* Windows doesn't use errno, but gnutls does, so check SocketEngine::IgnoreError()
			 * and then set errno appropriately.
			 * The gnutls library may also have a different errno variable than us, see
			 * gnutls_transport_set_errno(3).
			 */
			gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno);
		}
#endif

		if (rv < (int)size)
			SocketEngine::ChangeEventMask(sock, FD_READ_WILL_BLOCK);
		return rv;
	}
Ejemplo n.º 3
0
ssize_t CTlsSocket::PushFunction(const void* data, size_t len)
{
	if (!m_canWriteToSocket)
	{
		gnutls_transport_set_errno(m_session, EAGAIN);
		return -1;
	}

	if (!m_pSocketBackend)
	{
		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	m_pSocketBackend->Write(data, len);

	if (m_pSocketBackend->Error())
	{
		const int error = m_pSocketBackend->LastError();
		if (error == wxSOCKET_WOULDBLOCK)
		{
			m_canWriteToSocket = false;
			gnutls_transport_set_errno(m_session, EAGAIN);
			return -1;
		}

		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	return m_pSocketBackend->LastCount();
}
Ejemplo n.º 4
0
	static ssize_t VectorPush(gnutls_transport_ptr_t transportptr, const giovec_t* iov, int iovcnt)
	{
		StreamSocket* sock = reinterpret_cast<StreamSocket*>(transportptr);
#ifdef _WIN32
		GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook());
#endif

		if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
		{
#ifdef _WIN32
			gnutls_transport_set_errno(session->sess, EAGAIN);
#else
			errno = EAGAIN;
#endif
			return -1;
		}

		// Cast the giovec_t to iovec not to IOVector so the correct function is called on Windows
		int ret = SocketEngine::WriteV(sock, reinterpret_cast<const iovec*>(iov), iovcnt);
#ifdef _WIN32
		// See the function above for more info about the usage of gnutls_transport_set_errno() on Windows
		if (ret < 0)
			gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno);
#endif

		int size = 0;
		for (int i = 0; i < iovcnt; i++)
			size += iov[i].iov_len;

		if (ret < size)
			SocketEngine::ChangeEventMask(sock, FD_WRITE_WILL_BLOCK);
		return ret;
	}
Ejemplo n.º 5
0
static void WSAtoTLSErrno(gnutls_session_t* session)
{
  switch(WSAGetLastError()) {
#if (GNUTLS_VERSION_NUMBER >= 0x029901)
  case WSAEWOULDBLOCK:
    gnutls_transport_set_errno(session, EAGAIN);
    break;
  case WSAEINTR:
    gnutls_transport_set_errno(session, EINTR);
    break;
  default:
    gnutls_transport_set_errno(session, EIO);
    break;
#else
  case WSAEWOULDBLOCK:
    gnutls_transport_set_global_errno(EAGAIN);
    break;
  case WSAEINTR:
    gnutls_transport_set_global_errno(EINTR);
    break;
  default:
    gnutls_transport_set_global_errno(EIO);
    break;
#endif
  }
}
Ejemplo n.º 6
0
ssize_t CTlsSocket::PullFunction(void* data, size_t len)
{
#if TLSDEBUG
	m_pOwner->LogMessage(Debug_Debug, _T("CTlsSocket::PullFunction(%x, %d)"), data, len);
#endif
	if (!m_pSocketBackend)
	{
		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	if (m_socketClosed)
		return 0;

	if (!m_canReadFromSocket)
	{
		gnutls_transport_set_errno(m_session, EAGAIN);
		return -1;
	}

	int error;
	int read = m_pSocketBackend->Read(data, len, error);
	if (read < 0)
	{
		if (error == EAGAIN)
		{
			m_canReadFromSocket = false;
			if (m_canCheckCloseSocket && !m_pSocketBackend->IsWaiting(CRateLimiter::inbound))
			{
				CSocketEvent *evt = new CSocketEvent(this, m_pSocketBackend, CSocketEvent::close);
				CSocketEventDispatcher::Get().SendEvent(evt);
			}
		}

		gnutls_transport_set_errno(m_session, error);
		return -1;
	}

	if (m_canCheckCloseSocket)
	{
		CSocketEvent *evt = new CSocketEvent(this, m_pSocketBackend, CSocketEvent::close);
		CSocketEventDispatcher::Get().SendEvent(evt);
	}

	if (!read)
		m_socket_eof = true;

#if TLSDEBUG
	m_pOwner->LogMessage(Debug_Debug, _T("  returning %d"), read);
#endif

	return read;
}
Ejemplo n.º 7
0
ssize_t CTlsSocket::PullFunction(void* data, size_t len)
{
#if TLSDEBUG
	m_pOwner->LogMessage(MessageType::Debug_Debug, _T("CTlsSocket::PullFunction(%d)"),  (int)len);
#endif
	if (!m_pSocketBackend) {
		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	if (m_socketClosed)
		return 0;

	if (!m_canReadFromSocket) {
		gnutls_transport_set_errno(m_session, EAGAIN);
		return -1;
	}

	int error;
	int read = m_pSocketBackend->Read(data, len, error);
	if (read < 0) {
		m_canReadFromSocket = false;
		if (error == EAGAIN) {
			if (m_canCheckCloseSocket && !m_pSocketBackend->IsWaiting(CRateLimiter::inbound)) {
				send_event<CSocketEvent>(m_pSocketBackend, SocketEventType::close, 0);
			}
		}
		else {
			m_socket_error = error;
		}
		gnutls_transport_set_errno(m_session, error);
#if TLSDEBUG
		m_pOwner->LogMessage(MessageType::Debug_Debug, _T("  returning -1 due to %d"), error);
#endif
		return -1;
	}

	if (m_canCheckCloseSocket) {
		send_event<CSocketEvent>(m_pSocketBackend, SocketEventType::close, 0);
	}

	if (!read) {
		m_socket_eof = true;
	}

#if TLSDEBUG
	m_pOwner->LogMessage(MessageType::Debug_Debug, _T("  returning %d"), read);
#endif

	return read;
}
Ejemplo n.º 8
0
ssize_t CTlsSocket::PullFunction(void* data, size_t len)
{
	if (!m_pSocketBackend)
	{
		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	if (m_socketClosed)
		return 0;

	if (!m_canReadFromSocket)
	{
		gnutls_transport_set_errno(m_session, EAGAIN);
		return -1;
	}

	m_canReadFromSocket = false;

	m_pSocketBackend->Read(data, len);
	if (m_pSocketBackend->Error())
	{
		if (m_pSocketBackend->LastError() == wxSOCKET_WOULDBLOCK)
		{
			if (m_canCheckCloseSocket)
			{
				wxSocketEvent evt(m_pSocketBackend->GetId());
				evt.m_event = wxSOCKET_LOST;
				wxPostEvent(this, evt);
			}

			gnutls_transport_set_errno(m_session, EAGAIN);
			return -1;
		}

		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	if (m_canCheckCloseSocket)
	{
		wxSocketEvent evt(m_pSocketBackend->GetId());
		evt.m_event = wxSOCKET_LOST;
		wxPostEvent(this, evt);
	}

	return m_pSocketBackend->LastCount();
}
Ejemplo n.º 9
0
static ssize_t
pull_func (gnutls_transport_ptr_t p, void *data, size_t size)
{
    priv_data_st *priv = p;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    char buffer[64];
    int ret;

    cli_addr_size = sizeof (cli_addr);
    ret =
        recvfrom (priv->fd, data, size, 0, (struct sockaddr *) &cli_addr,
                  &cli_addr_size);
    if (ret == -1)
        return ret;

    if (cli_addr_size == priv->cli_addr_size
            && memcmp (&cli_addr, priv->cli_addr, sizeof (cli_addr)) == 0)
        return ret;

    printf ("Denied connection from %s\n",
            human_addr ((struct sockaddr *)
                        &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer)));

    gnutls_transport_set_errno (priv->session, EAGAIN);
    return -1;
}
Ejemplo n.º 10
0
static gssize ekg_gnutls_pull(gnutls_transport_ptr_t connptr, gpointer buf, gsize len) {
	struct ekg_gnutls_connection *conn = connptr;
	GBufferedInputStream *s = G_BUFFERED_INPUT_STREAM(conn->connection->instream);
	gsize avail_bytes = g_buffered_input_stream_get_available(s);

	/* XXX: EOF? */

	g_assert(len > 0);

	if (avail_bytes == 0) {
		if (conn->connection_error)
			return 0; /* EOF */

		gnutls_transport_set_errno(conn->session, EAGAIN);
		return -1;
	} else {
		GError *err = NULL;
		gssize ret = g_input_stream_read(
				G_INPUT_STREAM(s),
				buf,
				MIN(avail_bytes, len),
				NULL,
				&err);
		
		if (ret == -1) {
			debug_error("ekg_gnutls_pull() failed: %s\n", err->message);
			g_error_free(err);
		}

		return ret;
	}

	g_assert_not_reached();
}
Ejemplo n.º 11
0
ssize_t TLSSocket_GnuTLS::gnutlsPullFunc(
	gnutls_transport_ptr_t trspt,
	void* data,
	size_t len
) {

	TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);

	try {

		const ssize_t n = static_cast <ssize_t>(
			sok->m_wrapped->receiveRaw(reinterpret_cast <byte_t*>(data), len)
		);

		if (n == 0) {

			gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN);
			sok->m_errno = EAGAIN;
			return -1;
		}

		return n;

	} catch (exception& e) {

		// Workaround for non-portable behaviour when throwing C++ exceptions
		// from C functions (GNU TLS)
		sok->m_ex = e.clone();
		return -1;
	}
}
Ejemplo n.º 12
0
ssize_t SslSocket::readInternal(void *buffer, size_t length)
{
    qDebug() << "readInternal, length" << length << ", available" << d->socket->bytesAvailable();

    if (d->socket->bytesAvailable() < qint64(length)) {
        gnutls_transport_set_errno(d->session, EAGAIN);
        return -1;
    }

    return d->socket->read(static_cast<char *>(buffer), length);
}
Ejemplo n.º 13
0
ssize_t CTlsSocket::PushFunction(const void* data, size_t len)
{
#if TLSDEBUG
	m_pOwner->LogMessage(Debug_Debug, _T("CTlsSocket::PushFunction(%x, %d)"), data, len);
#endif
	if (!m_canWriteToSocket)
	{
		gnutls_transport_set_errno(m_session, EAGAIN);
		return -1;
	}

	if (!m_pSocketBackend)
	{
		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

	int error;
	int written = m_pSocketBackend->Write(data, len, error);

	if (written < 0)
	{
		if (error == EAGAIN)
		{
			m_canWriteToSocket = false;
			gnutls_transport_set_errno(m_session, EAGAIN);
			return -1;
		}

		gnutls_transport_set_errno(m_session, 0);
		return -1;
	}

#if TLSDEBUG
	m_pOwner->LogMessage(Debug_Debug, _T("  returning %d"), written);
#endif

	return written;
}
Ejemplo n.º 14
0
static ssize_t
client_push_300 (gnutls_transport_ptr_t tr, const void *data, size_t len)
{
  size_t newlen;
  
  if (len > 300)
    {
      gnutls_transport_set_errno ((gnutls_session_t)tr, EMSGSIZE);
      return -1;
    }

  len = min(len, sizeof(to_server)-to_server_len);

  newlen = to_server_len + len;
  memcpy (to_server + to_server_len, data, len);
  to_server_len = newlen;
#ifdef EAGAIN_DEBUG
  fprintf(stderr, "eagain: pushed %d bytes to server (avail: %d)\n", (int)len, (int)to_server_len);
#endif
  return len;
}
Ejemplo n.º 15
0
static inline void
tls_set_errno(struct gnutella_socket *s, int errnum)
{
    gnutls_transport_set_errno(tls_socket_get_session(s), errnum);
}
Ejemplo n.º 16
0
ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr,
        void *buffer, size_t len) {
    mgs_handle_t *ctxt = ptr;
    apr_status_t rc;
    apr_size_t in = len;
    apr_read_type_e block = ctxt->input_block;

    ctxt->input_rc = APR_SUCCESS;

    /* If Len = 0, we don't do anything. */
    if (!len || buffer == NULL) {
        return 0;
    }
    if (!ctxt->input_bb) {
        ctxt->input_rc = APR_EOF;
        return -1;
    }

    if (APR_BRIGADE_EMPTY(ctxt->input_bb)) {

        rc = ap_get_brigade(ctxt->input_filter->next,
                ctxt->input_bb, AP_MODE_READBYTES,
                ctxt->input_block, in);

        /* Not a problem, there was simply no data ready yet.
         */
        if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc)
                || (rc == APR_SUCCESS
                && APR_BRIGADE_EMPTY(ctxt->input_bb))) {

            if (APR_STATUS_IS_EOF(ctxt->input_rc)) {
                return 0;
            } else {
                if (ctxt->session)
                    gnutls_transport_set_errno(ctxt->
                        session,
                        EINTR);
                return -1;
            }
        }


        if (rc != APR_SUCCESS) {
            /* Unexpected errors discard the brigade */
            apr_brigade_cleanup(ctxt->input_bb);
            ctxt->input_bb = NULL;
            return -1;
        }
    }

    ctxt->input_rc =
            brigade_consume(ctxt->input_bb, block, buffer, &len);

    if (ctxt->input_rc == APR_SUCCESS) {
        return (ssize_t) len;
    }

    if (APR_STATUS_IS_EAGAIN(ctxt->input_rc)
            || APR_STATUS_IS_EINTR(ctxt->input_rc)) {
        if (len == 0) {
            if (ctxt->session)
                gnutls_transport_set_errno(ctxt->session,
                    EINTR);
            return -1;
        }

        return (ssize_t) len;
    }

    /* Unexpected errors and APR_EOF clean out the brigade.
     * Subsequent calls will return APR_EOF.
     */
    apr_brigade_cleanup(ctxt->input_bb);
    ctxt->input_bb = NULL;

    if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) {
        /* Provide the results of this read pass,
         * without resetting the BIO retry_read flag
         */
        return (ssize_t) len;
    }

    return -1;
}