Example #1
0
/* Return zero if an alert value can be ignored. */
static int check_alert(ne_socket *sock, ssize_t ret)
{
    const char *alert;

    if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) {
        alert = gnutls_alert_get_name(gnutls_alert_get(sock->ssl));
        NE_DEBUG(NE_DBG_SOCKET, "TLS warning alert: %s\n", alert);
        return 0;
    } else if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
        alert = gnutls_alert_get_name(gnutls_alert_get(sock->ssl));
        NE_DEBUG(NE_DBG_SOCKET, "TLS fatal alert: %s\n", alert);
        return -1;
    }
    return ret;
}
Example #2
0
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
			      const u8 *in_data, size_t in_len,
			      size_t *out_len)
{
	u8 *out_data;
	int ret;

	if (in_data && in_len) {
		if (conn->pull_buf) {
			wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
				   "pull_buf", __func__, conn->pull_buf_len);
			free(conn->pull_buf);
		}
		conn->pull_buf = malloc(in_len);
		if (conn->pull_buf == NULL)
			return NULL;
		memcpy(conn->pull_buf, in_data, in_len);
		conn->pull_buf_offset = conn->pull_buf;
		conn->pull_buf_len = in_len;
	}

	ret = gnutls_handshake(conn->session);
	if (ret < 0) {
		switch (ret) {
		case GNUTLS_E_AGAIN:
			break;
		case GNUTLS_E_FATAL_ALERT_RECEIVED:
			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
				   __func__, gnutls_alert_get_name(
					   gnutls_alert_get(conn->session)));
			conn->read_alerts++;
			/* continue */
		default:
			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
				   "-> %s", __func__, gnutls_strerror(ret));
			conn->failed++;
		}
	} else {
		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
		if (conn->verify_peer && tls_connection_verify_peer(conn)) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
				   "failed validation");
			conn->failed++;
			return NULL;
		}
		conn->established = 1;
		if (conn->push_buf == NULL) {
			/* Need to return something to get final TLS ACK. */
			conn->push_buf = malloc(1);
		}
	}

	out_data = conn->push_buf;
	*out_len = conn->push_buf_len;
	conn->push_buf = NULL;
	conn->push_buf_len = 0;
	return out_data;
}
Example #3
0
void CTlsSocket::PrintAlert(MessageType logLevel)
{
	gnutls_alert_description_t last_alert = gnutls_alert_get(m_session);
	const char* alert = gnutls_alert_get_name(last_alert);
	if (alert) {
		wxString str(alert, wxConvLocal);
		m_pOwner->LogMessage(logLevel, _("Received TLS alert from the server: %s (%d)"), str, last_alert);
	}
	else
		m_pOwner->LogMessage(logLevel, _("Received unknown TLS alert %d from the server"), last_alert);
}
Example #4
0
File: tls-gnu.c Project: fanf2/exim
static void
record_io_error(int ec, uschar *when, uschar *text)
{
const char *msg;

if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
  msg = string_sprintf("%s: %s", gnutls_strerror(ec),
    gnutls_alert_get_name(gnutls_alert_get(tls_session)));
else
  msg = gnutls_strerror(ec);

tls_error(when, client_host, msg);
}
Example #5
0
int
do_handshake (gnutls_session session)
{
  int ret, alert;

  do
    {
      ret = gnutls_handshake (session);
    }
  while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);

  handshake_output = ret;

  if (ret < 0 && verbose > 1)
    {
      if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
	  || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
	{
	  alert = gnutls_alert_get (session);
	  printf ("\n");
	  printf ("*** Received alert [%d]: %s\n",
		  alert, gnutls_alert_get_name (alert));
	}
    }

  if (ret < 0)
    return TEST_FAILED;

  gnutls_session_get_data (session, NULL, &session_data_size);

  if (sfree != 0)
    {
      free (session_data);
      sfree = 0;
    }
  session_data = malloc (session_data_size);
  sfree = 1;
  if (session_data == NULL)
    {
      fprintf (stderr, "Memory error\n");
      exit (1);
    }
  gnutls_session_get_data (session, session_data, &session_data_size);

  session_id_size = sizeof (session_id);
  gnutls_session_get_id (session, session_id, &session_id_size);

  return TEST_SUCCEED;
}
Example #6
0
static Eina_Bool
_process_data(gnutls_session_t client, Ecore_Fd_Handler * fd_handler)
{
	static int ret, lastret;
	static unsigned int count = 0;

	if (!done) {
		lastret = ret;
		ret = gnutls_handshake(client);
		count++;
		if (gnutls_record_get_direction(client))
			ecore_main_fd_handler_active_set(fd_handler,
							 ECORE_FD_WRITE);
		else
			ecore_main_fd_handler_active_set(fd_handler,
							 ECORE_FD_READ);
		/* avoid printing messages infinity times */
		if (lastret != ret && ret != 0 && ret != GNUTLS_E_AGAIN) {
			print("gnutls returned with: %s - %s",
			      gnutls_strerror_name(ret),
			      gnutls_strerror(ret));
			if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
			    || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
				print("Also received alert: %s",
				      gnutls_alert_get_name
				      (gnutls_alert_get(client)));
			print("last out: %s",
			      SSL_GNUTLS_PRINT_HANDSHAKE_STATUS
			      (gnutls_handshake_get_last_out(client)));
			print("last in: %s",
			      SSL_GNUTLS_PRINT_HANDSHAKE_STATUS
			      (gnutls_handshake_get_last_in(client)));
		}

		if (gnutls_error_is_fatal(ret)) {
			print("yarrr this be an error!");
			exit(1);
		}

	}
	if (ret == GNUTLS_E_SUCCESS) {
		done = 1;
		//print("Handshake successful in %u handshake calls!", count);
		ecore_main_loop_quit();
	}

	return ECORE_CALLBACK_RENEW;
}
Example #7
0
void CTlsSocket::PrintAlert()
{
	gnutls_alert_description_t last_alert = gnutls_alert_get(m_session);
	const char* alert = gnutls_alert_get_name(last_alert);
	if (alert)
	{
#if wxUSE_UNICODE
		wxString str(alert, wxConvLocal);
#else
		wxString str(alert);
#endif
		m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d: %s"), last_alert, str.c_str());
	}
	else
		m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d"), last_alert);
}
Example #8
0
/* Returns zero if the error code was successfully handled.
 */
static int
handle_error (socket_st * hd, int err)
{
  int alert, ret;
  const char *err_type, *str;

  if (err >= 0)
    return 0;

  if (gnutls_error_is_fatal (err) == 0)
    {
      ret = 0;
      err_type = "Non fatal";
    }
  else
    {
      ret = err;
      err_type = "Fatal";
    }

  str = gnutls_strerror (err);
  if (str == NULL)
    str = str_unknown;
  fprintf (stderr, "*** %s error: %s\n", err_type, str);

  if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
      || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      alert = gnutls_alert_get (hd->session);
      str = gnutls_alert_get_name (alert);
      if (str == NULL)
	str = str_unknown;
      printf ("*** Received alert [%d]: %s\n", alert, str);

      /* In SRP if the alert is MISSING_SRP_USERNAME,
       * we should read the username/password and
       * call gnutls_handshake(). This is not implemented
       * here.
       */
    }

  check_rehandshake (hd, err);

  return ret;
}
Example #9
0
/* moved down here, to keep from interrupting the flow with
   verbose error crap */
void handle_gnutls_read_error(int readbytes, struct connection_state *scs)
{
	if (gnutls_error_is_fatal(readbytes) == 1) {
		TDM(DEBUG_ERROR,
			"%s: Received corrupted data(%d) - server has terminated the connection abnormally\n",
			scs->name, readbytes);
	} else {
		if (readbytes == GNUTLS_E_WARNING_ALERT_RECEIVED
			|| readbytes == GNUTLS_E_FATAL_ALERT_RECEIVED)
			TDM(DEBUG_ERROR, "* Received alert [%d]\n",
				gnutls_alert_get(scs->tls_state));
		if (readbytes == GNUTLS_E_REHANDSHAKE)
			TDM(DEBUG_ERROR, "* Received HelloRequest message\n");
	}
	TDM(DEBUG_ERROR,
		"%s: gnutls error reading: %s\n",
		scs->name, gnutls_strerror(readbytes));
}
Example #10
0
/* Returns zero if the error code was successfully handled.
 */
static int
handle_error (socket_st * hd, int err)
{
  int alert, ret;
  const char *err_type, *str;

  if (err >= 0 || err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
    return 0;

  if (gnutls_error_is_fatal (err) == 0)
    {
      ret = 0;
      err_type = "Non fatal";
    }
  else
    {
      ret = err;
      err_type = "Fatal";
    }

  str = gnutls_strerror (err);
  if (str == NULL)
    str = str_unknown;
  fprintf (stderr, "*** %s error: %s\n", err_type, str);

  if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
      || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      alert = gnutls_alert_get (hd->session);
      str = gnutls_alert_get_name (alert);
      if (str == NULL)
        str = str_unknown;
      printf ("*** Received alert [%d]: %s\n", alert, str);
    }

  check_rehandshake (hd, err);

  return ret;
}
Example #11
0
/* This function will check whether the given return code from
 * a gnutls function (recv/send), is an alert, and will print
 * that alert.
 */
void
check_alert (gnutls_session_t session, int ret)
{
  int last_alert;

  if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
      || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      last_alert = gnutls_alert_get (session);

      /* The check for renegotiation is only useful if we are 
       * a server, and we had requested a rehandshake.
       */
      if (last_alert == GNUTLS_A_NO_RENEGOTIATION &&
	  ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
	printf ("* Received NO_RENEGOTIATION alert. "
		"Client Does not support renegotiation.\n");
      else
	printf ("* Received alert '%d': %s.\n", last_alert,
		gnutls_alert_get_name (last_alert));
    }
}
Example #12
0
static ssize_t error_gnutls(ne_socket *sock, ssize_t sret)
{
    ssize_t ret;

    switch (sret) {
    case 0:
	ret = NE_SOCK_CLOSED;
	set_error(sock, _("Connection closed"));
	break;
    case GNUTLS_E_FATAL_ALERT_RECEIVED:
        ret = NE_SOCK_ERROR;
        ne_snprintf(sock->error, sizeof sock->error, 
                    _("SSL alert received: %s"),
                    gnutls_alert_get_name(gnutls_alert_get(sock->ssl)));
        break;
    case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
        /* It's not exactly an API guarantee but this error will
         * always mean a premature EOF. */
        ret = NE_SOCK_TRUNC;
        set_error(sock, _("Secure connection truncated"));
        break;
    case GNUTLS_E_PUSH_ERROR:
        ret = NE_SOCK_RESET;
        set_error(sock, ("SSL socket write failed"));
        break;
    case GNUTLS_E_PULL_ERROR:
        ret = NE_SOCK_RESET;
        set_error(sock, _("SSL socket read failed"));
        break;
    default:
        ret = NE_SOCK_ERROR;
        ne_snprintf(sock->error, sizeof sock->error, _("SSL error: %s"),
                    gnutls_strerror(sret));
    }
    return ret;
}
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
			      const u8 *in_data, size_t in_len,
			      size_t *out_len, u8 **appl_data,
			      size_t *appl_data_len)
{
	struct tls_global *global = ssl_ctx;
	u8 *out_data;
	int ret;

	if (appl_data)
		*appl_data = NULL;

	if (in_data && in_len) {
		if (conn->pull_buf) {
			wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
				   "pull_buf", __func__, conn->pull_buf_len);
			os_free(conn->pull_buf);
		}
		conn->pull_buf = os_malloc(in_len);
		if (conn->pull_buf == NULL)
			return NULL;
		os_memcpy(conn->pull_buf, in_data, in_len);
		conn->pull_buf_offset = conn->pull_buf;
		conn->pull_buf_len = in_len;
	}

	ret = gnutls_handshake(conn->session);
	if (ret < 0) {
		switch (ret) {
		case GNUTLS_E_AGAIN:
			if (global->server && conn->established &&
			    conn->push_buf == NULL) {
				/* Need to return something to trigger
				 * completion of EAP-TLS. */
				conn->push_buf = os_malloc(1);
			}
			break;
		case GNUTLS_E_FATAL_ALERT_RECEIVED:
			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
				   __func__, gnutls_alert_get_name(
					   gnutls_alert_get(conn->session)));
			conn->read_alerts++;
			/* continue */
		default:
			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
				   "-> %s", __func__, gnutls_strerror(ret));
			conn->failed++;
		}
	} else {
		size_t size;

		if (conn->verify_peer && tls_connection_verify_peer(conn)) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
				   "failed validation");
			conn->failed++;
			return NULL;
		}

		if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
			wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
			conn->failed++;
			return NULL;
		}

		if (conn->tls_ia)
			wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
		else {
			wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
				   "successfully");
		}
		conn->established = 1;
		if (conn->push_buf == NULL) {
			/* Need to return something to get final TLS ACK. */
			conn->push_buf = os_malloc(1);
		}

		gnutls_session_get_data(conn->session, NULL, &size);
		if (global->session_data == NULL ||
		    global->session_data_size < size) {
			os_free(global->session_data);
			global->session_data = os_malloc(size);
		}
		if (global->session_data) {
			global->session_data_size = size;
			gnutls_session_get_data(conn->session,
						global->session_data,
						&global->session_data_size);
		}
	}

	out_data = conn->push_buf;
	*out_len = conn->push_buf_len;
	conn->push_buf = NULL;
	conn->push_buf_len = 0;
	return out_data;
}
Example #14
0
int
_gnutls_recv_client_certificate (gnutls_session_t session)
{
    int datasize;
    opaque *data;
    int ret = 0;
    int optional;

    if (session->internals.auth_struct->gnutls_process_client_certificate !=
            NULL)
    {

        /* if we have not requested a certificate then just return
         */
        if (session->internals.send_cert_req == 0)
        {
            return 0;
        }

        if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
            optional = MANDATORY_PACKET;
        else
            optional = OPTIONAL_PACKET;

        ret =
            _gnutls_recv_handshake (session, &data,
                                    &datasize,
                                    GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional);

        if (ret < 0)
        {
            /* Handle the case of old SSL3 clients who send
             * a warning alert instead of an empty certificate to indicate
             * no certificate.
             */
            if (optional == OPTIONAL_PACKET &&
                    ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
                    gnutls_protocol_get_version (session) == GNUTLS_SSL3 &&
                    gnutls_alert_get (session) == GNUTLS_A_SSL3_NO_CERTIFICATE)
            {

                /* SSL3 does not send an empty certificate,
                 * but this alert. So we just ignore it.
                 */
                gnutls_assert ();
                return 0;
            }

            /* certificate was required
             */
            if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
                    || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
                    && optional == MANDATORY_PACKET)
            {
                gnutls_assert ();
                return GNUTLS_E_NO_CERTIFICATE_FOUND;
            }

            return ret;
        }

        if (ret == 0 && datasize == 0 && optional == OPTIONAL_PACKET)
        {
            /* Client has not sent the certificate message.
             * well I'm not sure we should accept this
             * behaviour.
             */
            gnutls_assert ();
            return 0;
        }
        ret =
            session->internals.
            auth_struct->gnutls_process_client_certificate (session, data,
                    datasize);

        gnutls_free (data);
        if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND)
        {
            gnutls_assert ();
            return ret;
        }

        /* ok we should expect a certificate verify message now
         */
        if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET)
            ret = 0;
        else
            session->key->certificate_requested = 1;

    }

    return ret;
}
Example #15
0
struct wpabuf * tls_connection_handshake(void *tls_ctx,
					 struct tls_connection *conn,
					 const struct wpabuf *in_data,
					 struct wpabuf **appl_data)
{
	struct tls_global *global = tls_ctx;
	struct wpabuf *out_data;
	int ret;

	if (appl_data)
		*appl_data = NULL;

	if (in_data && wpabuf_len(in_data) > 0) {
		if (conn->pull_buf) {
			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
				   "pull_buf", __func__,
				   (unsigned long) wpabuf_len(conn->pull_buf));
			wpabuf_free(conn->pull_buf);
		}
		conn->pull_buf = wpabuf_dup(in_data);
		if (conn->pull_buf == NULL)
			return NULL;
		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
	}

	ret = gnutls_handshake(conn->session);
	if (ret < 0) {
		gnutls_alert_description_t alert;

		switch (ret) {
		case GNUTLS_E_AGAIN:
			if (global->server && conn->established &&
			    conn->push_buf == NULL) {
				/* Need to return something to trigger
				 * completion of EAP-TLS. */
				conn->push_buf = wpabuf_alloc(0);
			}
			break;
		case GNUTLS_E_FATAL_ALERT_RECEIVED:
			alert = gnutls_alert_get(conn->session);
			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
				   __func__, gnutls_alert_get_name(alert));
			conn->read_alerts++;
			if (conn->global->event_cb != NULL) {
				union tls_event_data ev;

				os_memset(&ev, 0, sizeof(ev));
				ev.alert.is_local = 0;
				ev.alert.type = gnutls_alert_get_name(alert);
				ev.alert.description = ev.alert.type;
				conn->global->event_cb(conn->global->cb_ctx,
						       TLS_ALERT, &ev);
			}
			/* continue */
		default:
			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
				   "-> %s", __func__, gnutls_strerror(ret));
			conn->failed++;
		}
	} else {
		size_t size;

		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");

#if GNUTLS_VERSION_NUMBER >= 0x03010a
		{
			char *desc;

			desc = gnutls_session_get_desc(conn->session);
			if (desc) {
				wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
				gnutls_free(desc);
			}
		}
#endif /* GnuTLS 3.1.10 or newer */

		conn->established = 1;
		if (conn->push_buf == NULL) {
			/* Need to return something to get final TLS ACK. */
			conn->push_buf = wpabuf_alloc(0);
		}

		gnutls_session_get_data(conn->session, NULL, &size);
		if (global->session_data == NULL ||
		    global->session_data_size < size) {
			os_free(global->session_data);
			global->session_data = os_malloc(size);
		}
		if (global->session_data) {
			global->session_data_size = size;
			gnutls_session_get_data(conn->session,
						global->session_data,
						&global->session_data_size);
		}

		if (conn->pull_buf && appl_data)
			*appl_data = gnutls_get_appl_data(conn);
	}

	out_data = conn->push_buf;
	conn->push_buf = NULL;
	return out_data;
}
Example #16
0
/* this function does a SSL/TLS (re-)handshake */
static CURLcode handshake(struct connectdata *conn,
                          int sockindex,
                          bool duringconnect,
                          bool nonblocking)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  gnutls_session session = conn->ssl[sockindex].session;
  curl_socket_t sockfd = conn->sock[sockindex];
  long timeout_ms;
  int rc;
  int what;

  for(;;) {
    /* check allowed time left */
    timeout_ms = Curl_timeleft(data, NULL, duringconnect);

    if(timeout_ms < 0) {
      /* no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      return CURLE_OPERATION_TIMEDOUT;
    }

    /* if ssl is expecting something, check if it's available. */
    if(connssl->connecting_state == ssl_connect_2_reading
       || connssl->connecting_state == ssl_connect_2_writing) {

      curl_socket_t writefd = ssl_connect_2_writing==
        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
      curl_socket_t readfd = ssl_connect_2_reading==
        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;

      what = Curl_socket_ready(readfd, writefd,
                               nonblocking?0:
                               timeout_ms?timeout_ms:1000);
      if(what < 0) {
        /* fatal error */
        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
        return CURLE_SSL_CONNECT_ERROR;
      }
      else if(0 == what) {
        if(nonblocking)
          return CURLE_OK;
        else if(timeout_ms) {
          /* timeout */
          failf(data, "SSL connection timeout at %ld", timeout_ms);
          return CURLE_OPERATION_TIMEDOUT;
        }
      }
      /* socket is readable or writable */
    }

    rc = gnutls_handshake(session);

    if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
      connssl->connecting_state =
        gnutls_record_get_direction(session)?
        ssl_connect_2_writing:ssl_connect_2_reading;
      continue;
      if(nonblocking)
        return CURLE_OK;
    }
    else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
      const char *strerr = NULL;

      if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
        int alert = gnutls_alert_get(session);
        strerr = gnutls_alert_get_name(alert);
      }

      if(strerr == NULL)
        strerr = gnutls_strerror(rc);

      failf(data, "gnutls_handshake() warning: %s", strerr);
    }
    else if(rc < 0) {
      const char *strerr = NULL;

      if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
        int alert = gnutls_alert_get(session);
        strerr = gnutls_alert_get_name(alert);
      }

      if(strerr == NULL)
        strerr = gnutls_strerror(rc);

      failf(data, "gnutls_handshake() failed: %s", strerr);
      return CURLE_SSL_CONNECT_ERROR;
    }

    /* Reset our connect state machine */
    connssl->connecting_state = ssl_connect_1;
    return CURLE_OK;
  }
}
gnutls_alert_description_t session::get_alert () const
{
    return gnutls_alert_get (s);
}
Example #18
0
static int gnutls_do_handshake(mgs_handle_t * ctxt) {
    int ret;
    int errcode;
    int maxtries = HANDSHAKE_MAX_TRIES;

    if (ctxt->status != 0 || ctxt->session == NULL) {
        return -1;
    }

tryagain:
    do {
        ret = gnutls_handshake(ctxt->session);
        maxtries--;
    } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)
            && maxtries > 0);

    if (maxtries < 1) {
        ctxt->status = -1;
#if USING_2_1_RECENT
        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c,
                "GnuTLS: Handshake Failed. Hit Maximum Attempts");
#else
        ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                ctxt->c->base_server,
                "GnuTLS: Handshake Failed. Hit Maximum Attempts");
#endif
        if (ctxt->session) {
            gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL,
                    gnutls_error_to_alert
                    (GNUTLS_E_INTERNAL_ERROR, NULL));
            gnutls_deinit(ctxt->session);
        }
        ctxt->session = NULL;
        return -1;
    }

    if (ret < 0) {
        if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
                || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
            errcode = gnutls_alert_get(ctxt->session);
            ap_log_error(APLOG_MARK, APLOG_INFO, 0,
                    ctxt->c->base_server,
                    "GnuTLS: Hanshake Alert (%d) '%s'.",
                    errcode,
                    gnutls_alert_get_name(errcode));
        }

        if (!gnutls_error_is_fatal(ret)) {
            ap_log_error(APLOG_MARK, APLOG_INFO, 0,
                    ctxt->c->base_server,
                    "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'",
                    ret, gnutls_strerror(ret));
            goto tryagain;
        }
#if USING_2_1_RECENT
        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
                "GnuTLS: Handshake Failed (%d) '%s'", ret,
                gnutls_strerror(ret));
#else
        ap_log_error(APLOG_MARK, APLOG_INFO, 0,
                ctxt->c->base_server,
                "GnuTLS: Handshake Failed (%d) '%s'", ret,
                gnutls_strerror(ret));
#endif
        ctxt->status = -1;
        if (ctxt->session) {
            gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL,
                    gnutls_error_to_alert(ret,
                    NULL));
            gnutls_deinit(ctxt->session);
        }
        ctxt->session = NULL;
        return ret;
    } else {
        /* all done with the handshake */
        ctxt->status = 1;
        /* If the session was resumed, we did not set the correct
         * server_rec in ctxt->sc.  Go Find it. (ick!)
         */
        if (gnutls_session_is_resumed(ctxt->session)) {
            mgs_srvconf_rec *sc;
            sc = mgs_find_sni_server(ctxt->session);
            if (sc) {
                ctxt->sc = sc;
            }
        }
        return 0;
    }
}
Example #19
0
struct wpabuf * tls_connection_handshake(void *tls_ctx,
					 struct tls_connection *conn,
					 const struct wpabuf *in_data,
					 struct wpabuf **appl_data)
{
	struct tls_global *global = tls_ctx;
	struct wpabuf *out_data;
	int ret;

	if (appl_data)
		*appl_data = NULL;

	if (in_data && wpabuf_len(in_data) > 0) {
		if (conn->pull_buf) {
			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
				   "pull_buf", __func__,
				   (unsigned long) wpabuf_len(conn->pull_buf));
			wpabuf_free(conn->pull_buf);
		}
		conn->pull_buf = wpabuf_dup(in_data);
		if (conn->pull_buf == NULL)
			return NULL;
		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
	}

	ret = gnutls_handshake(conn->session);
	if (ret < 0) {
		switch (ret) {
		case GNUTLS_E_AGAIN:
			if (global->server && conn->established &&
			    conn->push_buf == NULL) {
				/* Need to return something to trigger
				 * completion of EAP-TLS. */
				conn->push_buf = wpabuf_alloc(0);
			}
			break;
		case GNUTLS_E_FATAL_ALERT_RECEIVED:
			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
				   __func__, gnutls_alert_get_name(
					   gnutls_alert_get(conn->session)));
			conn->read_alerts++;
			/* continue */
		default:
			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
				   "-> %s", __func__, gnutls_strerror(ret));
			conn->failed++;
		}
	} else {
		size_t size;
		gnutls_alert_description_t err;

		if (conn->verify_peer &&
		    tls_connection_verify_peer(conn, &err)) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
				   "failed validation");
			conn->failed++;
			gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
			goto out;
		}

		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
		conn->established = 1;
		if (conn->push_buf == NULL) {
			/* Need to return something to get final TLS ACK. */
			conn->push_buf = wpabuf_alloc(0);
		}

		gnutls_session_get_data(conn->session, NULL, &size);
		if (global->session_data == NULL ||
		    global->session_data_size < size) {
			os_free(global->session_data);
			global->session_data = os_malloc(size);
		}
		if (global->session_data) {
			global->session_data_size = size;
			gnutls_session_get_data(conn->session,
						global->session_data,
						&global->session_data_size);
		}

		if (conn->pull_buf && appl_data)
			*appl_data = gnutls_get_appl_data(conn);
	}

out:
	out_data = conn->push_buf;
	conn->push_buf = NULL;
	return out_data;
}
PresentationServer::PresentationServer(const std::string & conferenceUrl,
		const std::string & managerHost, unsigned short managerPort,
		int screenWidth, int screenHeight,
		const std::string & caCertificate,
		const std::string & managerPath, const std::string & managerParam) :
_server(0), _fps(5) {

	if (caCertificate.empty()) {
		throw std::invalid_argument("no CA Certificate provided!");
	}
	//Erstmal d�rfte jetzt die Authorisierung und die Anfrage an den Manager geschehen
	//Dazu einfach �ber nen Socket ne primitive http anfrage senden und die Antwort auswerten
	//Achtung momentan ist BUF_SIZE auch die maximale Nachrichtengr��e die Empfangen werden kann!!
	//@TODO Dringend ne bessere HTTP Implementation verwenden oder selber bauen.
	const int BUF_SIZE = 2048;
	char tmpBuffer[BUF_SIZE];
	SOCKET httpSocket = rfbConnectToTcpAddr(const_cast<char*> (managerHost.c_str()), managerPort);
	std::string httpResponse;
	if (httpSocket == INVALID_SOCKET) {
		std::cerr << "Failed to connect to " << managerHost << ":" << managerPort << std::endl;
		throw std::runtime_error(STR_ERR_WEBHOST_UNREACHABLE);
		return;
	}

	//HTTPS Verbindung mit GnuTLS und handkodierter HTTP Nachricht :)
	gnutls_session_t session = 0;
	gnutls_certificate_credentials_t credentials = 0;
	gnutls_datum_t data;
	int gtlsRet = GNUTLS_E_SUCCESS;
	try {
		//Zertifikat
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) {
			std::cerr << "failed to allocate credentials." << std::endl;
			throw std::runtime_error("failed to allocate credentials.");
		}

		data.size = caCertificate.size();
		data.data = (unsigned char*) caCertificate.data();
		gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM);
		
		// Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes
		gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int {
			std::cout << "verifying certificate...";
			//Server Zertifikat prüfen:
			unsigned int verify = 0;
			if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) {
				std::cerr << "certficate verification failed." << std::endl;
				return -1;
			}
			if (verify != 0) {
				gnutls_datum_t pr;
				std::cout << "no" << std::endl;
				gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0);
				std::cerr << pr.data << std::endl;
				free(pr.data);
				return -2;
			}
			std::cout << "yes" << std::endl;
			return 0;
		});
		//Session
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) {
			std::cerr << "failed to init session." << std::endl;
			throw std::runtime_error("failed to init session.");
		}

		gnutls_server_name_set(session, GNUTLS_NAME_DNS, managerHost.data(), managerHost.length());
		gnutls_session_set_ptr(session, (void*) managerHost.c_str());

		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) {
			std::cerr << "failed to set priority." << std::endl;
			throw std::runtime_error("failed to set priority.");
		}

		gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials);
		gnutls_transport_set_int(session, httpSocket);
		gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
		if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) {
			std::cerr << "handshake failed." << std::endl;
			throw std::runtime_error("handshake failed.");
		}

		//Ciphersuite 
		std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl;
		//Prepare HTTP Request
		std::string httpRequest;
		std::string httpRequestBody = managerParam + "=" + urlencode(conferenceUrl) + "&version=" + std::to_string(TOOL_VERSION);
		httpRequest += "POST ";
		httpRequest += managerPath;
		httpRequest += " HTTP/1.1\r\n";
		httpRequest += "Host: ";
		httpRequest += managerHost + "\r\n";
		httpRequest += "Content-Type: application/x-www-form-urlencoded\r\n"; //< Beachte der Webserver kann auf der Zielroute momentan auch nichts anderes
		httpRequest += "Connection: close\r\n";
		sprintf(tmpBuffer, "%d", httpRequestBody.length());
		httpRequest += "Content-Length: " + std::string(tmpBuffer) + "\r\n";
		httpRequest += "\r\n";
		httpRequest += httpRequestBody;

		std::cout << "SEND >>" << std::endl << httpRequest << std::endl << "<<" << std::endl;

		gnutls_record_send(session, httpRequest.data(), httpRequest.length());

		std::cout << "WAITING TO RECEIVE.." << std::endl;
		//Alles lesen und hoffen dass sich der Webserver dran h�lt und die Verbindung schlie�t
		//wenn er fertig mit Senden ist
		int c = 0, r = 0;

		do {
			r = gnutls_record_recv(session, tmpBuffer + c, BUF_SIZE - c);
			if (r > 0) c += r;
		} while (r > 0 && c < BUF_SIZE);

		if (c > 1024 || c <= 0) {
			std::cout << "received " << c << " bytes" << std::endl;
			std::cout << std::string(tmpBuffer, c) << std::endl;
			std::cerr << "Couldn't receive answer." << std::endl;
			throw std::runtime_error(STR_ERR_WRONG_ANSWER);
		}

		httpResponse = std::string(tmpBuffer, c);

		//Und fertig Verbindung beenden
		gnutls_bye(session, GNUTLS_SHUT_RDWR);
		gnutls_deinit(session);
		gnutls_certificate_free_credentials(credentials);
		closesocket(httpSocket);
	} catch (...) {
		//Irgendein Fehler trat auf, dann schließen.
		std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl;
		std::cerr << gnutls_strerror(gtlsRet) << std::endl;
		std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl;
		if (session) gnutls_deinit(session);
		if (credentials) gnutls_certificate_free_credentials(credentials);
		closesocket(httpSocket);
		throw std::runtime_error(STR_ERR_TLS_FAILED); //weiterschmeißen
	}
	std::cout << "RECV >>" << std::endl << httpResponse << std::endl << "<<" << std::endl;
	/**
		Antwort sollte jetzt der typische HTTP Antwortquark sein und als Inhalt
		sollte ein Text der folgenden Form sein:

		PresentationServerUseHost: <host>\n
		PresentationServerUsePort: <port>\n
	 */
	unsigned short port;
	std::string host;
	int lifetime;

	try {
		_messageBox = utf8_to_ucs2(getParameter(httpResponse, "MessageBox", ""));
		port = atoi(getParameter(httpResponse, "PresentationServerUsePort").c_str());
		host = getParameter(httpResponse, "PresentationServerUseHost");
		_demo = atoi(getParameter(httpResponse, "Demo", "0").c_str()) ? true : false;
		lifetime = atoi(getParameter(httpResponse, "RuntimeSec", "0").c_str());
		_serverPassword = getParameter(httpResponse, "PresentationServerPassword");
	} catch (std::runtime_error e) {
		if (!_messageBox.empty())
			throw runtime_error_with_extra_msg(_messageBox, getParameter(httpResponse, "Message"));
		throw std::runtime_error(getParameter(httpResponse, "Message"));
	}

	//Wenn die erfolgreich war dann den Server erstellen, Gr��e = Desktopgr��e
	_initRfbServer(screenWidth, screenHeight, _serverPassword, managerHost, caCertificate, host, port);

	if (lifetime > 0) {
		_timeOfDeath = std::chrono::system_clock::now() + std::chrono::seconds(lifetime);
		_useTimeOfDeath = true;
	} else {
		_useTimeOfDeath = false;
	}
}
rfbNewClientAction upgradeNewClientToTls (_rfbClientRec* cl) {
	//Eine SSL Session beginnen
	gnutls_session_t session = 0;
	gnutls_certificate_credentials_t credentials = 0;
	gnutls_datum_t data;
	int gtlsRet = GNUTLS_E_SUCCESS;
	std::cout<<"New Client Connection, upgrade protocol to Tls"<<std::endl;
	try {
		//Zertifikat
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) {
			std::cerr << "failed to allocate credentials." << std::endl;
			throw std::runtime_error("failed to allocate credentials.");
		}

		data.size = g_caCertificate.size();
		data.data = (unsigned char*) g_caCertificate.data();
		gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM);

		// Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes
		gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int {
			std::cout << "verifying certificate...";
			//Server Zertifikat prüfen:
			unsigned int verify = 0;
			if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) {
				std::cerr << "certficate verification failed." << std::endl;
				return -1;
			}
			if (verify != 0) {
				gnutls_datum_t pr;
				std::cout << "no" << std::endl;
				gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0);
				std::cerr << pr.data << std::endl;
				free(pr.data);
				return -2;
			}
			std::cout << "yes" << std::endl;
			return 0;
		});
		//Session
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) {
			std::cerr << "failed to init session." << std::endl;
			throw std::runtime_error("failed to init session.");
		}

		gnutls_server_name_set(session, GNUTLS_NAME_DNS, g_peerHostName.data(), g_peerHostName.length());
		gnutls_session_set_ptr(session, (void*) g_peerHostName.c_str());

		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) {
			std::cerr << "failed to set priority." << std::endl;
			throw std::runtime_error("failed to set priority.");
		}

		gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials);
		gnutls_transport_set_int(session, cl->sock);
		gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
		if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) {
			std::cerr << "handshake failed." << std::endl;
			throw std::runtime_error("handshake failed.");
		}

		//Ciphersuite 
		std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl;

		//Send password, which was received in answer of webserver
		if ((gtlsRet = gnutls_record_send(session, (void*)g_serverPassword.data(), g_serverPassword.size())) <= 0) {
			std::cerr << "Sending Password failed." << std::endl;
			throw std::runtime_error("Sending Password failed.");
		}

		rfbssl_ctx* ctx = (rfbssl_ctx*) malloc(sizeof(struct rfbssl_ctx));
		ctx->peeklen = 0;
		ctx->peekstart = 0;
		ctx->session = session;
		ctx->x509_cred = credentials;
		ctx->dh_params = 0;
		
		cl->sslctx = (rfbSslCtx*)ctx;
	} catch (...) {
		//Irgendein Fehler trat auf, dann schließen.
		std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl;
		std::cerr << gnutls_strerror(gtlsRet) << std::endl;
		std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl;
		if (session) gnutls_deinit(session);
		if (credentials) gnutls_certificate_free_credentials(credentials);
		
		return RFB_CLIENT_REFUSE;
	}
	
	return RFB_CLIENT_ACCEPT;
}
Example #22
0
/**
 * tls_negotiate - Negotiate TLS connection
 * @param conn Connection to a server
 * @retval  0 Success
 * @retval -1 Error
 *
 * After TLS state has been initialized, attempt to negotiate TLS over the
 * wire, including certificate checks.
 */
static int tls_negotiate(struct Connection *conn)
{
  struct TlsSockData *data = mutt_mem_calloc(1, sizeof(struct TlsSockData));
  conn->sockdata = data;
  int err = gnutls_certificate_allocate_credentials(&data->xcred);
  if (err < 0)
  {
    FREE(&conn->sockdata);
    mutt_error("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
    return -1;
  }

  gnutls_certificate_set_x509_trust_file(data->xcred, C_CertificateFile, GNUTLS_X509_FMT_PEM);
  /* ignore errors, maybe file doesn't exist yet */

  if (C_SslCaCertificatesFile)
  {
    gnutls_certificate_set_x509_trust_file(data->xcred, C_SslCaCertificatesFile,
                                           GNUTLS_X509_FMT_PEM);
  }

  if (C_SslClientCert)
  {
    mutt_debug(LL_DEBUG2, "Using client certificate %s\n", C_SslClientCert);
    gnutls_certificate_set_x509_key_file(data->xcred, C_SslClientCert,
                                         C_SslClientCert, GNUTLS_X509_FMT_PEM);
  }

#ifdef HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
  /* disable checking certificate activation/expiration times
   * in gnutls, we do the checks ourselves */
  gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
#endif

  err = gnutls_init(&data->state, GNUTLS_CLIENT);
  if (err)
  {
    mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    goto fail;
  }

  /* set socket */
  gnutls_transport_set_ptr(data->state, (gnutls_transport_ptr_t)(long) conn->fd);

  if (gnutls_server_name_set(data->state, GNUTLS_NAME_DNS, conn->account.host,
                             mutt_str_strlen(conn->account.host)))
  {
    mutt_error(_("Warning: unable to set TLS SNI host name"));
  }

  if (tls_set_priority(data) < 0)
  {
    goto fail;
  }

  if (C_SslMinDhPrimeBits > 0)
  {
    gnutls_dh_set_prime_bits(data->state, C_SslMinDhPrimeBits);
  }

  /* gnutls_set_cred (data->state, GNUTLS_ANON, NULL); */

  gnutls_credentials_set(data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);

  err = gnutls_handshake(data->state);

  while (err == GNUTLS_E_AGAIN)
  {
    err = gnutls_handshake(data->state);
  }
  if (err < 0)
  {
    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
                 gnutls_alert_get_name(gnutls_alert_get(data->state)));
    }
    else
    {
      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    }
    goto fail;
  }

  if (tls_check_certificate(conn) == 0)
    goto fail;

  /* set Security Strength Factor (SSF) for SASL */
  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
  conn->ssf = gnutls_cipher_get_key_size(gnutls_cipher_get(data->state)) * 8;

  tls_get_client_cert(conn);

  if (!OptNoCurses)
  {
    mutt_message(_("SSL/TLS connection using %s (%s/%s/%s)"),
                 gnutls_protocol_get_name(gnutls_protocol_get_version(data->state)),
                 gnutls_kx_get_name(gnutls_kx_get(data->state)),
                 gnutls_cipher_get_name(gnutls_cipher_get(data->state)),
                 gnutls_mac_get_name(gnutls_mac_get(data->state)));
    mutt_sleep(0);
  }

  return 0;

fail:
  gnutls_certificate_free_credentials(data->xcred);
  gnutls_deinit(data->state);
  FREE(&conn->sockdata);
  return -1;
}
Example #23
0
static Ecore_Con_Ssl_Error
_ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl)
{
   const gnutls_datum_t *cert_list;
   unsigned int iter, cert_list_size;
   const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0";
   int ret = 0;

   switch (cl->ssl_state)
     {
      case ECORE_CON_SSL_STATE_DONE:
        return ECORE_CON_SSL_ERROR_NONE;

      case ECORE_CON_SSL_STATE_INIT:
        if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
          return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;

        switch (cl->host_server->type & ECORE_CON_SSL)
          {
           case ECORE_CON_USE_SSL3:
           case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
             priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1";
             break;

           case ECORE_CON_USE_TLS:
           case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
             priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0";
             break;

           case ECORE_CON_USE_MIXED:
           case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
             break;

           default:
             return ECORE_CON_SSL_ERROR_NONE;
          }

        _client_connected++;

        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket));
        INF("Applying priority string: %s", priority);
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert));
        //  SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s));
        if (!cl->host_server->use_cert)
          SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s));

        gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST);

        gnutls_dh_set_prime_bits(cl->session, 2048);
        gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd));
        cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;

      case ECORE_CON_SSL_STATE_HANDSHAKING:
        if (!cl->session)
          {
             DBG("Client was previously lost, going to error condition");
             goto error;
          }
        DBG("calling gnutls_handshake()");
        ret = gnutls_handshake(cl->session);
        SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));

        if (!ret)
          {
             cl->handshaking = EINA_FALSE;
             cl->ssl_state = ECORE_CON_SSL_STATE_DONE;
          }
        else
          {
             if (gnutls_record_get_direction(cl->session))
               ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
             else
               ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
             return ECORE_CON_SSL_ERROR_NONE;
          }

      default:
        break;
     }

   if (!cl->host_server->verify)
     /* not verifying certificates, so we're done! */
     return ECORE_CON_SSL_ERROR_NONE;
   ret = 0;
   /* use CRL/CA lists to verify */
   SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter));
   if (iter & GNUTLS_CERT_INVALID)
     ERR("The certificate is not trusted.");
   else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND)
     ERR("The certificate hasn't got a known issuer.");
   else if (iter & GNUTLS_CERT_REVOKED)
     ERR("The certificate has been revoked.");
   else if (iter & GNUTLS_CERT_EXPIRED)
     ERR("The certificate has expired");
   else if (iter & GNUTLS_CERT_NOT_ACTIVATED)
     ERR("The certificate is not yet activated");

   if (iter)
     goto error;

   if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509)
     {
        ERR("Warning: PGP certificates are not yet supported!");
        goto error;
     }

   SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size)));
   SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);

   DBG("SSL certificate verification succeeded!");
   return ECORE_CON_SSL_ERROR_NONE;

error:
   _gnutls_print_errors(ret);
   if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
     ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session)));
   if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE))
     {
        ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session)));
        ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session)));
     }
   _ecore_con_ssl_client_shutdown_gnutls(cl);
   return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
}
Example #24
0
static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt,
        char *buf, apr_size_t * len) {
    apr_size_t wanted = *len;
    apr_size_t bytes = 0;
    int rc;

    *len = 0;

    /* If we have something leftover from last time, try that first. */
    if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) {
        *len = bytes;
        if (ctxt->input_mode == AP_MODE_SPECULATIVE) {
            /* We want to rollback this read. */
            if (ctxt->input_cbuf.length > 0) {
                ctxt->input_cbuf.value -= bytes;
                ctxt->input_cbuf.length += bytes;
            } else {
                char_buffer_write(&ctxt->input_cbuf, buf,
                        (int) bytes);
            }
            return APR_SUCCESS;
        }
        /* This could probably be *len == wanted, but be safe from stray
         * photons.
         */
        if (*len >= wanted) {
            return APR_SUCCESS;
        }
        if (ctxt->input_mode == AP_MODE_GETLINE) {
            if (memchr(buf, APR_ASCII_LF, *len)) {
                return APR_SUCCESS;
            }
        } else {
            /* Down to a nonblock pattern as we have some data already
             */
            ctxt->input_block = APR_NONBLOCK_READ;
        }
    }

    if (ctxt->session == NULL) {
        return APR_EGENERAL;
    }

    while (1) {

        rc = gnutls_record_recv(ctxt->session, buf + bytes,
                wanted - bytes);

        if (rc > 0) {
            *len += rc;
            if (ctxt->input_mode == AP_MODE_SPECULATIVE) {
                /* We want to rollback this read. */
                char_buffer_write(&ctxt->input_cbuf, buf,
                        rc);
            }
            return ctxt->input_rc;
        } else if (rc == 0) {
            /* If EAGAIN, we will loop given a blocking read,
             * otherwise consider ourselves at EOF.
             */
            if (APR_STATUS_IS_EAGAIN(ctxt->input_rc)
                    || APR_STATUS_IS_EINTR(ctxt->input_rc)) {
                /* Already read something, return APR_SUCCESS instead.
                 * On win32 in particular, but perhaps on other kernels,
                 * a blocking call isn't 'always' blocking.
                 */
                if (*len > 0) {
                    ctxt->input_rc = APR_SUCCESS;
                    break;
                }
                if (ctxt->input_block == APR_NONBLOCK_READ) {
                    break;
                }
            } else {
                if (*len > 0) {
                    ctxt->input_rc = APR_SUCCESS;
                } else {
                    ctxt->input_rc = APR_EOF;
                }
                break;
            }
        } else { /* (rc < 0) */

            if (rc == GNUTLS_E_REHANDSHAKE) {
                /* A client has asked for a new Hankshake. Currently, we don't do it */
                ap_log_error(APLOG_MARK, APLOG_INFO,
                        ctxt->input_rc,
                        ctxt->c->base_server,
                        "GnuTLS: Error reading data. Client Requested a New Handshake."
                        " (%d) '%s'", rc,
                        gnutls_strerror(rc));
            } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
                rc = gnutls_alert_get(ctxt->session);
                ap_log_error(APLOG_MARK, APLOG_INFO,
                        ctxt->input_rc,
                        ctxt->c->base_server,
                        "GnuTLS: Warning Alert From Client: "
                        " (%d) '%s'", rc,
                        gnutls_alert_get_name(rc));
            } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
                rc = gnutls_alert_get(ctxt->session);
                ap_log_error(APLOG_MARK, APLOG_INFO,
                        ctxt->input_rc,
                        ctxt->c->base_server,
                        "GnuTLS: Fatal Alert From Client: "
                        "(%d) '%s'", rc,
                        gnutls_alert_get_name(rc));
                ctxt->input_rc = APR_EGENERAL;
                break;
            } else {
                /* Some Other Error. Report it. Die. */
                if (gnutls_error_is_fatal(rc)) {
                    ap_log_error(APLOG_MARK,
                            APLOG_INFO,
                            ctxt->input_rc,
                            ctxt->c->base_server,
                            "GnuTLS: Error reading data. (%d) '%s'",
                            rc,
                            gnutls_strerror(rc));
                } else if (*len > 0) {
                    ctxt->input_rc = APR_SUCCESS;
                    break;
                }
            }

            if (ctxt->input_rc == APR_SUCCESS) {
                ctxt->input_rc = APR_EGENERAL;
            }
            break;
        }
    }
    return ctxt->input_rc;
}
Example #25
0
static void fusion_tls_connection_handle_error (FusionTLSConnection* self, int ecode, gint where, GError** error) {
	gboolean _tmp0_ = FALSE;
	int _tmp1_ = 0;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp8_ = FALSE;
	int _tmp9_ = 0;
	gboolean _tmp12_ = FALSE;
	GError * _inner_error_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp1_ = ecode;
	if (_tmp1_ == GNUTLS_E_WARNING_ALERT_RECEIVED) {
		_tmp0_ = TRUE;
	} else {
		int _tmp2_ = 0;
		_tmp2_ = ecode;
		_tmp0_ = _tmp2_ == GNUTLS_E_FATAL_ALERT_RECEIVED;
	}
	_tmp3_ = _tmp0_;
	if (_tmp3_) {
		gnutls_alert_description_t alert = 0;
		struct gnutls_session_int* _tmp4_ = NULL;
		gnutls_alert_description_t _tmp5_ = 0;
		gnutls_alert_description_t _tmp6_ = 0;
		const gchar* _tmp7_ = NULL;
		_tmp4_ = self->tls_session;
		_tmp5_ = gnutls_alert_get (_tmp4_);
		alert = _tmp5_;
		_tmp6_ = alert;
		_tmp7_ = gnutls_alert_get_name (_tmp6_);
		g_warning ("TLSConnection.vala:74: TLS handshake alert: %s", _tmp7_);
	}
	_tmp9_ = ecode;
	if (_tmp9_ < 0) {
		int _tmp10_ = 0;
		gboolean _tmp11_ = FALSE;
		_tmp10_ = ecode;
		_tmp11_ = gnutls_error_is_fatal (_tmp10_);
		_tmp8_ = _tmp11_;
	} else {
		_tmp8_ = FALSE;
	}
	_tmp12_ = _tmp8_;
	if (_tmp12_) {
		gint _tmp13_ = 0;
		_tmp13_ = where;
		switch (_tmp13_) {
			case 0:
			{
				int _tmp14_ = 0;
				const gchar* _tmp15_ = NULL;
				GError* _tmp16_ = NULL;
				_tmp14_ = ecode;
				_tmp15_ = gnutls_strerror (_tmp14_);
				_tmp16_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Handshake failed: %s", _tmp15_);
				_inner_error_ = _tmp16_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			case 1:
			{
				int _tmp17_ = 0;
				const gchar* _tmp18_ = NULL;
				GError* _tmp19_ = NULL;
				_tmp17_ = ecode;
				_tmp18_ = gnutls_strerror (_tmp17_);
				_tmp19_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Receive failed: %s", _tmp18_);
				_inner_error_ = _tmp19_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			case 2:
			{
				int _tmp20_ = 0;
				const gchar* _tmp21_ = NULL;
				GError* _tmp22_ = NULL;
				_tmp20_ = ecode;
				_tmp21_ = gnutls_strerror (_tmp20_);
				_tmp22_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Send failed: %s", _tmp21_);
				_inner_error_ = _tmp22_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			default:
			{
				g_assert_not_reached ();
			}
		}
	}
}
Example #26
0
/* tls_negotiate: After TLS state has been initialised, attempt to negotiate
 *   TLS over the wire, including certificate checks. */
static int tls_negotiate (CONNECTION * conn)
{
  tlssockdata *data;
  int err;
  size_t nproto = 0; /* number of tls/ssl protocols */

  data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));
  conn->sockdata = data;
  err = gnutls_certificate_allocate_credentials (&data->xcred);
  if (err < 0)
  {
    FREE(&conn->sockdata);
    mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
    mutt_sleep (2);
    return -1;
  }

  gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile,
					  GNUTLS_X509_FMT_PEM);
  /* ignore errors, maybe file doesn't exist yet */

  if (SslCACertFile)
  {
    gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile,
                                            GNUTLS_X509_FMT_PEM);
  }

  if (SslClientCert)
  {
    dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert));
    gnutls_certificate_set_x509_key_file (data->xcred, SslClientCert,
                                          SslClientCert, GNUTLS_X509_FMT_PEM);
  }

#if HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
  /* disable checking certificate activation/expiration times
     in gnutls, we do the checks ourselves */
  gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
#endif

  if ((err = gnutls_init(&data->state, GNUTLS_CLIENT)))
  {
    mutt_error ("gnutls_handshake: %s", gnutls_strerror(err));
    mutt_sleep (2);
    goto fail;
  }

  /* set socket */
  gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd);

  if (option(OPTTLSV1_2))
    protocol_priority[nproto++] = GNUTLS_TLS1_2;
  if (option(OPTTLSV1_1))
    protocol_priority[nproto++] = GNUTLS_TLS1_1;
  if (option(OPTTLSV1))
    protocol_priority[nproto++] = GNUTLS_TLS1;
  if (option(OPTSSLV3))
    protocol_priority[nproto++] = GNUTLS_SSL3;
  protocol_priority[nproto] = 0;

  /* disable TLS/SSL protocols as needed */
  if (nproto == 0)
  {
    mutt_error (_("All available protocols for TLS/SSL connection disabled"));
    goto fail;
  }
  /*
  else
    use the list set above
  */

  /* We use default priorities (see gnutls documentation),
     except for protocol version */
  gnutls_set_default_priority (data->state);
  gnutls_protocol_set_priority (data->state, protocol_priority);

  if (SslDHPrimeBits > 0)
  {
    gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits);
  }

/*
  gnutls_set_cred (data->state, GNUTLS_ANON, NULL);
*/

  gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);

  err = gnutls_handshake(data->state);

  while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
  {
    err = gnutls_handshake(data->state);
  }
  if (err < 0) {
    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
		 gnutls_alert_get_name(gnutls_alert_get(data->state)));
    }
    else
    {
      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    }
    mutt_sleep (2);
    goto fail;
  }

  if (!tls_check_certificate(conn))
    goto fail;

  /* set Security Strength Factor (SSF) for SASL */
  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
  conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8;

  tls_get_client_cert (conn);

  if (!option(OPTNOCURSES)) {
    mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"),
                  gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)),
                  gnutls_kx_get_name (gnutls_kx_get (data->state)),
                  gnutls_cipher_get_name (gnutls_cipher_get (data->state)),
                  gnutls_mac_get_name (gnutls_mac_get (data->state)));
    mutt_sleep (0);
  }

  return 0;

 fail:
  gnutls_certificate_free_credentials (data->xcred);
  gnutls_deinit (data->state);
  FREE(&conn->sockdata);
  return -1;
}
Example #27
0
static const char *get_alert_text(struct ssl_proxy *proxy)
{
	return gnutls_alert_get_name(gnutls_alert_get(proxy->session));
}
Example #28
0
static void do_handle_error(liGnuTLSFilter *f, const char *gnutlsfunc, int r, gboolean writing) {
	switch (r) {
	case GNUTLS_E_AGAIN:
		if (writing) f->write_wants_read = TRUE;
		return;
	case GNUTLS_E_REHANDSHAKE:
#ifdef HAVE_SAVE_RENEGOTIATION
		if (f->initial_handshaked_finished && !gnutls_safe_renegotiation_status(f->session)) {
			_ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated unsafe renegotitation, closing connection", gnutlsfunc);
			f_close_with_alert(f, r);
		} else {
			_DEBUG(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation", gnutlsfunc);
		}
#else
		if (f->initial_handshaked_finished) {
			_ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation, closing connection", gnutlsfunc);
			f_close_with_alert(f, r);
		}
#endif
		return;
	case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
		f_close_with_alert(f, r);
		return;
	case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
	case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
		_DEBUG(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc,
			gnutls_strerror_name(r), gnutls_strerror(r));
		f_close_with_alert(f, r);
		return;
	case GNUTLS_E_FATAL_ALERT_RECEIVED:
	case GNUTLS_E_WARNING_ALERT_RECEIVED:
		{
			gnutls_alert_description_t alert_desc = gnutls_alert_get(f->session);
			const char* alert_desc_name = gnutls_alert_get_name(alert_desc);
			_INFO(f->srv, f->wrk, f->log_context, "%s (%s): %s %s (%u)", gnutlsfunc,
				gnutls_strerror_name(r), gnutls_strerror(r),
				(NULL != alert_desc_name) ? alert_desc_name : "unknown alert",
				(unsigned int) alert_desc);
		}
		/* error not handled yet: break instead of return */
		break;
	default:
		if (gnutls_error_is_fatal(r)) {
			_ERROR(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc,
				gnutls_strerror_name(r), gnutls_strerror(r));
		} else {
			_WARNING(f->srv, f->wrk, f->log_context, "%s non fatal (%s): %s", gnutlsfunc,
				gnutls_strerror_name(r), gnutls_strerror(r));
		}
		/* error not handled yet: break instead of return */
		break;
	}

	/* generic error handling */
	if (gnutls_error_is_fatal(r)) {
		if (f->initial_handshaked_finished) {
			f_close_with_alert(f, r);
		} else {
			f_abort_gnutls(f);
		}
	}
}
Example #29
0
int _gnutls_recv_client_certificate(gnutls_session_t session)
{
	gnutls_buffer_st buf;
	int ret = 0;
	int optional;

	if (session->internals.auth_struct->
	    gnutls_process_client_certificate == NULL)
		return 0;

	/* if we have not requested a certificate then just return
	 */
	if (session->internals.send_cert_req == 0) {
		return 0;
	}

	if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
		optional = 0;
	else
		optional = 1;

	ret =
	    _gnutls_recv_handshake(session,
				   GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
				   optional, &buf);

	if (ret < 0) {
		/* Handle the case of old SSL3 clients who send
		 * a warning alert instead of an empty certificate to indicate
		 * no certificate.
		 */
#ifdef ENABLE_SSL3
		if (optional != 0 &&
		    ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
		    get_num_version(session) == GNUTLS_SSL3 &&
		    gnutls_alert_get(session) ==
		    GNUTLS_A_SSL3_NO_CERTIFICATE) {

			/* SSL3 does not send an empty certificate,
			 * but this alert. So we just ignore it.
			 */
			gnutls_assert();
			return 0;
		}
#endif

		/* certificate was required 
		 */
		if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
		     || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
		    && optional == 0) {
			gnutls_assert();
			return GNUTLS_E_NO_CERTIFICATE_FOUND;
		}

		return ret;
	}

	if (ret == 0 && buf.length == 0 && optional != 0) {
		/* Client has not sent the certificate message.
		 * well I'm not sure we should accept this
		 * behaviour.
		 */
		gnutls_assert();
		ret = 0;
		goto cleanup;
	}
	ret =
	    session->internals.auth_struct->
	    gnutls_process_client_certificate(session, buf.data,
					      buf.length);

	if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) {
		gnutls_assert();
		goto cleanup;
	}

	/* ok we should expect a certificate verify message now 
	 */
	if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional != 0)
		ret = 0;
	else
		session->internals.crt_requested = 1;

      cleanup:
	_gnutls_buffer_clear(&buf);
	return ret;
}