static gboolean verify_certificate(HevImpathyTLSVerifier *self,
			gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer,
			TpTLSCertificateRejectReason *reason)
{
	guint verify_output = 0;
	gint res = 0;

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

	res = gnutls_x509_crt_verify(cert, &issuer, 1, 0, &verify_output);

	return verification_output_to_reason(res, verify_output, reason);
}
static gboolean verify_last_certificate(HevImpathyTLSVerifier *self,
			gnutls_x509_crt_t cert, TpTLSCertificateRejectReason *reason)
{
	guint verify_output = 0;
	gint res = 0;
	gnutls_x509_crt_t *trusted_ca_list = NULL;
	HevImpathyTLSVerifierPrivate *priv =
		HEV_IMPATHY_TLS_VERIFIER_GET_PRIVATE(self);

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

	if(0 < priv->trusted_ca_list->len)
	{
		trusted_ca_list = ptr_array_to_x509_crt_list(priv->trusted_ca_list);
		res = gnutls_x509_crt_verify(cert, trusted_ca_list,
					priv->trusted_ca_list->len, 0, &verify_output);

		g_free(trusted_ca_list);
	}
	else
	{
		/* check it against itself to see if it's structurally valid */
		res = gnutls_x509_crt_verify(cert, &cert, 1, 0, &verify_output);

		/* if it's valid, return the SelfSigned error, so that we can add it
		* later to our trusted CAs whitelist.
		*/
		if(GNUTLS_E_SUCCESS == res)
		{
			*reason = TP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED;
			return FALSE;
		}
	}

	return verification_output_to_reason (res, verify_output, reason);
}
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);
}