[gvfs] daemon: Add function to confirm certificate



commit 7cf5d5ff55fcbdebe0fb7b60e52ecb0c95ca63ee
Author: Ross Lagerwall <rosslagerwall gmail com>
Date:   Tue Feb 24 22:04:33 2015 +0000

    daemon: Add function to confirm certificate
    
    Add a utility function to present a certificate to the user during a
    mount to confirm whether to continue or not.
    
    This adds a dependency on Gcr, to parse information from the
    certificate.
    
    Based on a patch by Ondrej Holy.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=526582

 configure.ac             |    2 +
 daemon/Makefile.am       |    4 +-
 daemon/gvfsdaemonutils.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++
 daemon/gvfsdaemonutils.h |    7 +++
 4 files changed, 125 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 788140d..d219aba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,8 @@ AC_SUBST(DBUS_SERVICE_DIR)
 giomodulesdir=$libdir/gio/modules
 AC_SUBST(giomodulesdir)
 
+PKG_CHECK_MODULES(GCR, gcr-base-3)
+
 dnl ****************************
 dnl *** Checks for intltool  ***
 dnl ****************************
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index d55a1d9..384f18c 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS =                                 \
        -I$(top_builddir)/common                \
        $(GLIB_CFLAGS)                          \
        $(KEYRING_CFLAGS)                       \
+       $(GCR_CFLAGS)                           \
        -DLIBEXEC_DIR=\"$(libexecdir)\"         \
        -DMOUNTABLE_DIR=\"$(mountdir)\"         \
        -DGVFS_LOCALEDIR=\""$(localedir)"\"
@@ -197,7 +198,8 @@ libgvfsdaemon_la_LDFLAGS = -no-undefined -avoid-version
 libgvfsdaemon_la_LIBADD = \
        $(top_builddir)/common/libgvfscommon.la \
        $(GLIB_LIBS) \
-       $(KEYRING_LIBS)
+       $(KEYRING_LIBS) \
+       $(GCR_LIBS)
 
 gvfsd_SOURCES = \
        mount.c mount.h \
diff --git a/daemon/gvfsdaemonutils.c b/daemon/gvfsdaemonutils.c
index 2be975c..b1d7b93 100644
--- a/daemon/gvfsdaemonutils.c
+++ b/daemon/gvfsdaemonutils.c
@@ -237,3 +237,116 @@ gvfs_seek_type_to_lseek (GSeekType type)
       return -1;
     }
 }
+
+/* Convert GTlsCertificateFlags into a message to display to the user. */
+static char *
+certificate_flags_to_string (GTlsCertificateFlags errors)
+{
+  GString *reason;
+
+  g_return_val_if_fail (errors, NULL);
+
+  reason = g_string_new (NULL);
+
+  if (errors & G_TLS_CERTIFICATE_UNKNOWN_CA)
+    g_string_append_printf (reason, "\n\t%s", _("The signing certificate authority is not known."));
+  if (errors & G_TLS_CERTIFICATE_BAD_IDENTITY)
+    g_string_append_printf (reason, "\n\t%s", _("The certificate does not match the identity of the site."));
+  if (errors & G_TLS_CERTIFICATE_NOT_ACTIVATED)
+    g_string_append_printf (reason, "\n\t%s", _("The certificate's activation time is in the future."));
+  if (errors & G_TLS_CERTIFICATE_EXPIRED)
+    g_string_append_printf (reason, "\n\t%s", _("The certificate has expired."));
+  if (errors & G_TLS_CERTIFICATE_REVOKED)
+    g_string_append_printf (reason, "\n\t%s", _("The certificate has been revoked."));
+  if (errors & G_TLS_CERTIFICATE_INSECURE)
+    g_string_append_printf (reason, "\n\t%s", _("The certificate's algorithm is considered insecure."));
+  if (errors & G_TLS_CERTIFICATE_GENERIC_ERROR)
+    g_string_append_printf (reason, "\n\t%s", _("Error occurred when validating the certificate."));
+
+  return g_string_free (reason, FALSE);
+}
+
+/* Convert a GTlsCertificate into a string to display to the user.
+ * It contains the identity, the issuer, the expiry date and the certificate
+ * fingerprint. With this information, a user can make an informed decision
+ * whether to trust it or not. */
+static char *
+certificate_to_string (GTlsCertificate *certificate)
+{
+  GByteArray *certificate_data;
+  GcrCertificate *simple_certificate;
+  GDate *date;
+  char date_str[32];
+  char *subject_name, *issuer_name, *fingerprint, *certificate_str;
+
+  g_object_get (certificate, "certificate", &certificate_data, NULL);
+  simple_certificate = gcr_simple_certificate_new_static (certificate_data->data,
+                                                         certificate_data->len);
+
+  date = gcr_certificate_get_expiry_date (simple_certificate);
+  g_date_strftime (date_str, 32, "%x", date);
+  g_date_free (date);
+
+  subject_name = gcr_certificate_get_subject_name (simple_certificate);
+  issuer_name = gcr_certificate_get_issuer_name (simple_certificate);
+  fingerprint = gcr_certificate_get_fingerprint_hex (simple_certificate, G_CHECKSUM_SHA1);
+
+  certificate_str = g_strdup_printf ("Certificate information:\n"
+                                     "\tIdentity: %s\n"
+                                     "\tVerified by: %s\n"
+                                     "\tExpires: %s\n"
+                                     "\tFingerprint (SHA1): %s",
+                                     subject_name,
+                                     issuer_name,
+                                     date_str,
+                                     fingerprint);
+  g_object_unref (simple_certificate);
+  g_byte_array_unref (certificate_data);
+  g_free (subject_name);
+  g_free (issuer_name);
+  g_free (fingerprint);
+
+  return certificate_str;
+}
+
+/**
+ * gvfs_accept_certificate:
+ * @mount_source: a GMountSource to ask the user a question
+ * @certificate: the certificate presented by the site
+ * @errors: flags describing the verification failure(s)
+ *
+ * Given a certificate presented by a site whose identity can't be verified,
+ * query the user whether they accept the certificate.
+ **/
+gboolean
+gvfs_accept_certificate (GMountSource *mount_source,
+                         GTlsCertificate *certificate,
+                         GTlsCertificateFlags errors)
+{
+  const char *choices[] = {"Yes", "No", NULL};
+  int choice;
+  gboolean handled, aborted = FALSE;
+  char *certificate_str, *reason, *message;
+
+  certificate_str = certificate_to_string (certificate);
+  reason = certificate_flags_to_string (errors);
+  message = g_strdup_printf (_("The site's identity can't be verified:"
+                               "%s\n\n"
+                               "%s\n\n"
+                               "Are you really sure you would like to continue?"),
+                             reason,
+                             certificate_str);
+  handled = g_mount_source_ask_question (mount_source,
+                                         message,
+                                         choices,
+                                         &aborted,
+                                         &choice);
+  g_free (certificate_str);
+  g_free (reason);
+  g_free (message);
+
+  if (handled && choice == 0)
+    return TRUE;
+
+  return FALSE;
+}
diff --git a/daemon/gvfsdaemonutils.h b/daemon/gvfsdaemonutils.h
index f195136..f28e2ba 100644
--- a/daemon/gvfsdaemonutils.h
+++ b/daemon/gvfsdaemonutils.h
@@ -24,6 +24,9 @@
 #define __G_VFS_DAEMON_UTILS_H__
 
 #include <glib-object.h>
+#include <gmountsource.h>
+#define GCR_API_SUBJECT_TO_CHANGE
+#include <gcr/gcr-base.h>
 
 G_BEGIN_DECLS
 
@@ -42,6 +45,10 @@ void      gvfs_file_info_populate_content_types  (GFileInfo        *info,
 
 int          gvfs_seek_type_to_lseek                (GSeekType         type);
 
+gboolean     gvfs_accept_certificate                (GMountSource *mount_source,
+                                                     GTlsCertificate *certificate,
+                                                     GTlsCertificateFlags errors);
+
 G_END_DECLS
 
 #endif /* __G_VFS_DAEMON_UTILS_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]