[evolution-data-server] Introduce CamelSession::trust_prompt()
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Introduce CamelSession::trust_prompt()
- Date: Fri, 14 Dec 2012 14:27:56 +0000 (UTC)
commit f58f4faca264ae98a3ff1d97df09b14c828cfcf1
Author: Milan Crha <mcrha redhat com>
Date: Fri Dec 14 15:25:55 2012 +0100
Introduce CamelSession::trust_prompt()
This way a trust-prompt dialog from EUserPrompter service can be used
with all its features and a view consistency between components.
camel/camel-disco-diary.c | 4 +-
camel/camel-session.c | 45 +++++-
camel/camel-session.h | 19 ++-
camel/camel-tcp-stream-ssl.c | 256 ++++++-----------------------
camel/providers/imap/camel-imap-command.c | 2 +-
camel/providers/imap/camel-imap-journal.c | 2 +-
configure.ac | 2 +-
7 files changed, 115 insertions(+), 215 deletions(-)
---
diff --git a/camel/camel-disco-diary.c b/camel/camel-disco-diary.c
index 47202ef..2be544c 100644
--- a/camel/camel-disco-diary.c
+++ b/camel/camel-disco-diary.c
@@ -210,7 +210,7 @@ camel_disco_diary_log (CamelDiscoDiary *diary,
"reconnect to the network."),
g_strerror (errno));
camel_session_alert_user (
- session, CAMEL_SESSION_ALERT_ERROR, msg, NULL);
+ session, CAMEL_SESSION_ALERT_ERROR, msg, NULL, NULL);
g_free (msg);
fclose (diary->file);
@@ -276,7 +276,7 @@ diary_decode_folder (CamelDiscoDiary *diary,
camel_session_alert_user (
camel_service_get_session (CAMEL_SERVICE (diary->store)),
CAMEL_SESSION_ALERT_WARNING,
- msg, NULL);
+ msg, NULL, cancellable);
g_free (msg);
g_free (name);
}
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 94fce5b..302f14e 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -1278,6 +1278,7 @@ camel_session_forget_password (CamelSession *session,
* @type: the type of alert (info, warning, or error)
* @prompt: the message for the user
* @button_captions: List of button captions to use. If NULL, only "Dismiss" button is shown.
+ * @cancellable: (allow-non): optional #GCancellable object, or %NULL
*
* Presents the given @prompt to the user, in the style indicated by
* @type. If @cancel is %TRUE, the user will be able to accept or
@@ -1289,7 +1290,8 @@ gint
camel_session_alert_user (CamelSession *session,
CamelSessionAlertType type,
const gchar *prompt,
- GSList *button_captions)
+ GSList *button_captions,
+ GCancellable *cancellable)
{
CamelSessionClass *class;
@@ -1299,7 +1301,46 @@ camel_session_alert_user (CamelSession *session,
class = CAMEL_SESSION_GET_CLASS (session);
g_return_val_if_fail (class->alert_user != NULL, -1);
- return class->alert_user (session, type, prompt, button_captions);
+ return class->alert_user (session, type, prompt, button_captions, cancellable);
+}
+
+/**
+ * camel_session_trust_prompt:
+ * @session: a #CamelSession
+ * @host: host name, to which the @certificate belongs
+ * @certificate: base64-encoded DER certificate on which to ask
+ * @certificate_errors: errors found with the certificate; a bit-OR of a #GTlsCertificateFlags
+ * @issuers: (allow-none): chain of issuers, or %NULL
+ * @cancellable: (allow-non): optional #GCancellable object, or %NULL
+ *
+ * Prompts user about trust of a certificate. The @certificate is not
+ * considered trusted, due to reasons set in @certificate_errors.
+ * There can be passed a list of @issuers, which has as items also base64-encoded
+ * DER certificates. The first item in the list is an issuer of the @certificate,
+ * the second item is an issuer of the first item, and so on.
+ *
+ * Returns: What trust level should be used for this certificate. It returns
+ * #CAMEL_CERT_TRUST_UNKNOWN on error or if user cancelled the dialog prompt.
+ *
+ * Since: 3.8
+ **/
+CamelCertTrust
+camel_session_trust_prompt (CamelSession *session,
+ const gchar *host,
+ const gchar *certificate,
+ guint32 certificate_errors,
+ const GSList *issuers,
+ GCancellable *cancellable)
+{
+ CamelSessionClass *class;
+
+ g_return_val_if_fail (CAMEL_IS_SESSION (session), CAMEL_CERT_TRUST_UNKNOWN);
+ g_return_val_if_fail (certificate != NULL, CAMEL_CERT_TRUST_UNKNOWN);
+
+ class = CAMEL_SESSION_GET_CLASS (session);
+ g_return_val_if_fail (class->trust_prompt != NULL, CAMEL_CERT_TRUST_UNKNOWN);
+
+ return class->trust_prompt (session, host, certificate, certificate_errors, issuers, cancellable);
}
/**
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 93b5150..0c7a338 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -36,6 +36,7 @@
#include <camel/camel-msgport.h>
#include <camel/camel-provider.h>
#include <camel/camel-service.h>
+#include <camel/camel-certdb.h>
/* Standard GObject macros */
#define CAMEL_TYPE_SESSION \
@@ -115,7 +116,14 @@ struct _CamelSessionClass {
gint (*alert_user) (CamelSession *session,
CamelSessionAlertType type,
const gchar *prompt,
- GSList *button_captions);
+ GSList *button_captions,
+ GCancellable *cancellable);
+ CamelCertTrust (*trust_prompt) (CamelSession *session,
+ const gchar *host,
+ const gchar *certificate,
+ guint32 certificate_errors,
+ const GSList *issuers,
+ GCancellable *cancellable);
CamelFilterDriver *
(*get_filter_driver) (CamelSession *session,
const gchar *type,
@@ -208,7 +216,14 @@ gboolean camel_session_forget_password (CamelSession *session,
gint camel_session_alert_user (CamelSession *session,
CamelSessionAlertType type,
const gchar *prompt,
- GSList *button_captions);
+ GSList *button_captions,
+ GCancellable *cancellable);
+CamelCertTrust camel_session_trust_prompt (CamelSession *session,
+ const gchar *host,
+ const gchar *certificate,
+ guint32 certificate_errors,
+ const GSList *issuers,
+ GCancellable *cancellable);
gchar * camel_session_build_password_prompt
(const gchar *type,
const gchar *user,
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index d1f1bb7..cd3cbc7 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -425,33 +425,6 @@ camel_certdb_nss_cert_set (CamelCertDB *certdb,
g_free (filename);
}
-#if 0
-/* used by the mozilla-like code below */
-static gchar *
-get_nickname (CERTCertificate *cert)
-{
- gchar *server, *nick = NULL;
- gint i;
- PRBool status = PR_TRUE;
-
- server = CERT_GetCommonName (&cert->subject);
- if (server == NULL)
- return NULL;
-
- for (i = 1; status == PR_TRUE; i++) {
- if (nick) {
- g_free (nick);
- nick = g_strdup_printf ("%s #%d", server, i);
- } else {
- nick = g_strdup (server);
- }
- status = SEC_CertNicknameConflict (server, &cert->derSubject, cert->dbhandle);
- }
-
- return nick;
-}
-#endif
-
static void
tcp_stream_cancelled (GCancellable *cancellable,
PRThread *thread)
@@ -467,10 +440,8 @@ ssl_bad_cert (gpointer data,
CamelCertDB *certdb = NULL;
CamelCert *ccert = NULL;
gboolean ccert_is_new = FALSE;
- gchar *prompt, *cert_str, *fingerprint;
CamelTcpStreamSSL *ssl;
CERTCertificate *cert;
- SECStatus status = SECFailure;
g_return_val_if_fail (data != NULL, SECFailure);
g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (data), SECFailure);
@@ -493,59 +464,66 @@ ssl_bad_cert (gpointer data,
}
if (ccert->trust == CAMEL_CERT_TRUST_UNKNOWN) {
- GSList *button_captions = NULL;
- gint button_id;
-
- status = CERT_VerifyCertNow (cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL);
- fingerprint = cert_fingerprint (cert);
- cert_str = g_strdup_printf (_(
- " Issuer: %s\n"
- " Subject: %s\n"
- " Fingerprint: %s\n"
- " Signature: %s"),
- CERT_NameToAscii (&cert->issuer),
- CERT_NameToAscii (&cert->subject),
- fingerprint,
- status == SECSuccess ? _("GOOD") : _("BAD"));
- g_free (fingerprint);
+ CERTCertificate *issuer;
+ CamelCertTrust trust_response;
+ gchar *base64;
+ guint32 certificate_errors = 0;
+ GSList *issuers = NULL;
+
+ if (CERT_VerifyCertNow (cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL) != SECSuccess) {
+ gint pr_error;
+
+ pr_error = PR_GetError ();
+
+ switch (pr_error) {
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ certificate_errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ break;
+ case SSL_ERROR_BAD_CERT_DOMAIN:
+ certificate_errors |= G_TLS_CERTIFICATE_BAD_IDENTITY;
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ certificate_errors |= G_TLS_CERTIFICATE_EXPIRED;
+ break;
+ }
+ }
- /* construct our user prompt */
- prompt = g_strdup_printf (
- _("SSL Certificate for '%s' is not trusted. "
- "Do you wish to accept it?\n\n"
- "Detailed information about the certificate:\n%s"),
- ssl->priv->expected_host, cert_str);
- g_free (cert_str);
+ issuer = cert;
+ while (issuer) {
+ if (SECITEM_CompareItem (&issuer->derIssuer, &issuer->derSubject) == SECEqual)
+ break;
- button_captions = g_slist_append (button_captions, _("_Reject"));
- button_captions = g_slist_append (button_captions, _("Accept _Temporarily"));
- button_captions = g_slist_append (button_captions, _("_Accept Permanently"));
+ issuer = CERT_FindCertIssuer (issuer, PR_Now (), certUsageSSLClient);
+ if (!issuer)
+ break;
+
+ base64 = g_base64_encode (issuer->derIssuer.data, issuer->derIssuer.len);
+ if (!base64)
+ break;
+
+ issuers = g_slist_append (issuers, base64);
+ }
+
+ base64 = g_base64_encode (cert->derCert.data, cert->derCert.len);
/* query the user to find out if we want to accept this certificate */
- button_id = camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, button_captions);
- g_slist_free (button_captions);
- g_free (prompt);
+ trust_response = camel_session_trust_prompt (ssl->priv->session, ssl->priv->expected_host, base64, certificate_errors, issuers, NULL);
+
+ g_free (base64);
+ g_slist_free_full (issuers, g_free);
+
+ accept = trust_response != CAMEL_CERT_TRUST_UNKNOWN &&
+ trust_response != CAMEL_CERT_TRUST_NEVER;
- accept = button_id != 0;
if (ccert_is_new) {
camel_certdb_nss_cert_set (certdb, ccert, cert);
camel_certdb_put (certdb, ccert);
}
- switch (button_id) {
- case 0: /* Reject */
- camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_NEVER);
- break;
- case 1: /* Accept temporarily */
- camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_TEMPORARY);
- break;
- case 2: /* Accept permanently */
- camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_FULLY);
- break;
- default: /* anything else means failure and will ask again */
- accept = FALSE;
- break;
- }
+ if (trust_response != CAMEL_CERT_TRUST_UNKNOWN)
+ camel_cert_set_trust (certdb, ccert, trust_response);
+
camel_certdb_touch (certdb);
} else {
accept = ccert->trust != CAMEL_CERT_TRUST_NEVER;
@@ -556,140 +534,6 @@ ssl_bad_cert (gpointer data,
g_object_unref (certdb);
return accept ? SECSuccess : SECFailure;
-
-#if 0
- gint i, error;
- CERTCertTrust trust;
- SECItem *certs[1];
- gint go = 1;
- gchar *host, *nick;
-
- error = PR_GetError ();
-
- /* This code is basically what mozilla does - however it doesn't seem to work here
- * very reliably :-/ */
- while (go && status != SECSuccess) {
- gchar *prompt = NULL;
-
- printf ("looping, error '%d'\n", error);
-
- switch (error) {
- case SEC_ERROR_UNKNOWN_ISSUER:
- case SEC_ERROR_CA_CERT_INVALID:
- case SEC_ERROR_UNTRUSTED_ISSUER:
- case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
- /* add certificate */
- printf ("unknown issuer, adding ... \n");
- prompt = g_strdup_printf (_("Certificate problem: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
- if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
-
- nick = get_nickname (cert);
- if (NULL == nick) {
- g_free (prompt);
- status = SECFailure;
- break;
- }
-
- printf ("adding cert '%s'\n", nick);
-
- if (!cert->trust) {
- cert->trust = (CERTCertTrust *) PORT_ArenaZAlloc (cert->arena, sizeof (CERTCertTrust));
- CERT_DecodeTrustString (cert->trust, "P");
- }
-
- certs[0] = &cert->derCert;
- /*CERT_ImportCerts (cert->dbhandle, certUsageSSLServer, 1, certs, NULL, TRUE, FALSE, nick);*/
- CERT_ImportCerts (cert->dbhandle, certUsageUserCertImport, 1, certs, NULL, TRUE, FALSE, nick);
- g_free (nick);
-
- printf (" cert type %08x\n", cert->nsCertType);
-
- memset ((gpointer) &trust, 0, sizeof (trust));
- if (CERT_GetCertTrust (cert, &trust) != SECSuccess) {
- CERT_DecodeTrustString (&trust, "P");
- }
- trust.sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
- if (CERT_ChangeCertTrust (cert->dbhandle, cert, &trust) != SECSuccess) {
- printf ("couldn't change cert trust?\n");
- }
-
- /*status = SECSuccess;*/
-#if 1
- /* re-verify? */
- status = CERT_VerifyCertNow (cert->dbhandle, cert, TRUE, certUsageSSLServer, NULL);
- error = PR_GetError ();
- printf ("re-verify status %d, error %d\n", status, error);
-#endif
-
- printf (" cert type %08x\n", cert->nsCertType);
- } else {
- printf ("failed/cancelled\n");
- go = 0;
- }
-
- break;
- case SSL_ERROR_BAD_CERT_DOMAIN:
- printf ("bad domain\n");
-
- prompt = g_strdup_printf (_("Bad certificate domain: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
- if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
- host = SSL_RevealURL (sockfd);
- status = CERT_AddOKDomainName (cert, host);
- printf ("add ok domain name : %s\n", status == SECFailure?"fail":"ok");
- error = PR_GetError ();
- if (status == SECFailure)
- go = 0;
- } else {
- go = 0;
- }
-
- break;
-
- case SEC_ERROR_EXPIRED_CERTIFICATE:
- printf ("expired\n");
-
- prompt = g_strdup_printf (_("Certificate expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
- if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
- cert->timeOK = PR_TRUE;
- status = CERT_VerifyCertNow (cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL);
- error = PR_GetError ();
- if (status == SECFailure)
- go = 0;
- } else {
- go = 0;
- }
-
- break;
-
- case SEC_ERROR_CRL_EXPIRED:
- printf ("crl expired\n");
-
- prompt = g_strdup_printf (_("Certificate revocation list expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
- if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
- host = SSL_RevealURL (sockfd);
- status = CERT_AddOKDomainName (cert, host);
- }
-
- go = 0;
- break;
-
- default:
- printf ("generic error\n");
- go = 0;
- break;
- }
-
- g_free (prompt);
- }
-
- CERT_DestroyCertificate (cert);
-
- return status;
-#endif
}
static PRFileDesc *
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
index 4584413..bbe1e69 100644
--- a/camel/providers/imap/camel-imap-command.c
+++ b/camel/providers/imap/camel-imap-command.c
@@ -430,7 +430,7 @@ camel_imap_command_response (CamelImapStore *store,
user, host, alert);
camel_session_alert_user (
session, CAMEL_SESSION_ALERT_WARNING,
- msg, NULL);
+ msg, NULL, cancellable);
g_free (msg);
}
}
diff --git a/camel/providers/imap/camel-imap-journal.c b/camel/providers/imap/camel-imap-journal.c
index e743253..6491c80 100644
--- a/camel/providers/imap/camel-imap-journal.c
+++ b/camel/providers/imap/camel-imap-journal.c
@@ -318,7 +318,7 @@ journal_decode_folder (CamelIMAPJournal *journal,
camel_service_get_session (
CAMEL_SERVICE (parent_store)),
CAMEL_SESSION_ALERT_WARNING,
- msg, NULL);
+ msg, NULL, cancellable);
g_free (msg);
}
}
diff --git a/configure.ac b/configure.ac
index 31995d4..212736c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,7 +125,7 @@ LIBEBOOK_CURRENT=17
LIBEBOOK_REVISION=1
LIBEBOOK_AGE=3
-LIBCAMEL_CURRENT=42
+LIBCAMEL_CURRENT=43
LIBCAMEL_REVISION=0
LIBCAMEL_AGE=0
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]