static void real_start_verification(HevImpathyTLSVerifier *self)
{
	HevImpathyTLSVerifierPrivate *priv =
		HEV_IMPATHY_TLS_VERIFIER_GET_PRIVATE(self);
	gnutls_x509_crt_t first_cert = 0, last_cert = 0;
	gint idx = 0;
	gboolean res = FALSE;
	gint num_certs = 0;
	TpTLSCertificateRejectReason reason =
		TP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN;

	g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);

	/* check if the certificate matches the hostname first. */
	first_cert = g_ptr_array_index(priv->cert_chain, 0);
	if(0 == gnutls_x509_crt_check_hostname(first_cert, priv->hostname))
	{
		gchar *certified_hostname = NULL;

		reason = TP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH;
		certified_hostname =
			(gchar *)hev_impathy_get_x509_certificate_hostname(first_cert);
		tp_asv_set_string(priv->details,
					"expected-hostname", priv->hostname);
		tp_asv_set_string(priv->details,
					"certificate-hostname", certified_hostname);

		g_free(certified_hostname);
		
		goto out;
	}

	num_certs = priv->cert_chain->len;

	if(0 < priv->trusted_ca_list->len)
	{
		/* if the last certificate is self-signed, and we have a list of
		* trusted CAs, ignore it, as we want to check the chain against our
		* trusted CAs list first.
		* if we have only one certificate in the chain, don't ignore it though,
		* as it's the CA certificate itself.
		*/
		last_cert = g_ptr_array_index(priv->cert_chain, num_certs - 1);

		if((0<gnutls_x509_crt_check_issuer(last_cert, last_cert)) &&
					(1<num_certs))
		  num_certs --;
	}

	for (idx = 1; idx < num_certs; idx++)
	{
		res = verify_certificate(self,
					g_ptr_array_index(priv->cert_chain, idx-1),
		g_ptr_array_index(priv->cert_chain, idx), &reason);

		if(!res)
		{
			abort_verification(self, reason);
			return;
		}
	}

	res = verify_last_certificate(self,
				g_ptr_array_index(priv->cert_chain,
					num_certs - 1), &reason);

out:
	if(!res)
	{
		abort_verification(self, reason);
		return;
	}

	complete_verification(self);
}
static void
perform_verification (EmpathyTLSVerifier *self,
        GcrCertificateChain *chain)
{
  gboolean ret = FALSE;
  EmpTLSCertificateRejectReason reason =
    EMP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN;
  gnutls_x509_crt_t *list, *anchors;
  guint n_list, n_anchors;
  guint verify_output;
  gint res;
  gint i;
  gboolean matched = FALSE;
  EmpathyTLSVerifierPriv *priv = GET_PRIV (self);

  DEBUG ("Performing verification");
  debug_certificate_chain (chain);

  list = anchors = NULL;
  n_list = n_anchors = 0;

  /*
   * If the first certificate is an pinned certificate then we completely
   * ignore the rest of the verification process.
   */
  if (gcr_certificate_chain_get_status (chain) == GCR_CERTIFICATE_CHAIN_PINNED)
    {
      DEBUG ("Found pinned certificate for %s", priv->hostname);
      complete_verification (self);
      goto out;
  }

  build_certificate_list_for_gnutls (chain, &list, &n_list,
          &anchors, &n_anchors);
  if (list == NULL || n_list == 0) {
      g_warn_if_reached ();
      abort_verification (self, EMP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN);
      goto out;
  }

  verify_output = 0;
  res = gnutls_x509_crt_list_verify (list, n_list, anchors, n_anchors,
           NULL, 0, 0, &verify_output);
  ret = verification_output_to_reason (res, verify_output, &reason);

  DEBUG ("Certificate verification gave result %d with reason %u", ret,
          reason);

  if (!ret) {
      abort_verification (self, reason);
      goto out;
  }

  /* now check if the certificate matches one of the reference identities. */
  if (priv->reference_identities != NULL)
    {
      for (i = 0, matched = FALSE; priv->reference_identities[i] != NULL; ++i)
        {
          if (gnutls_x509_crt_check_hostname (list[0],
                  priv->reference_identities[i]) == 1)
            {
              matched = TRUE;
              break;
            }
        }
    }

  if (!matched)
    {
      gchar *certified_hostname;

      certified_hostname = empathy_get_x509_certificate_hostname (list[0]);
      tp_asv_set_string (priv->details,
          "expected-hostname", priv->hostname);
      tp_asv_set_string (priv->details,
          "certificate-hostname", certified_hostname);

      DEBUG ("Hostname mismatch: got %s but expected %s",
          certified_hostname, priv->hostname);

      g_free (certified_hostname);
      abort_verification (self,
              EMP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
      goto out;
    }

  DEBUG ("Hostname matched");
  complete_verification (self);

 out:
  free_certificate_list_for_gnutls (list, n_list);
  free_certificate_list_for_gnutls (anchors, n_anchors);
}