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); }