summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Lagerwall <rosslagerwall@gmail.com>2015-02-24 22:04:33 +0000
committerRoss Lagerwall <rosslagerwall@gmail.com>2015-04-09 22:10:17 +0100
commit7cf5d5ff55fcbdebe0fb7b60e52ecb0c95ca63ee (patch)
tree975db49fb85169ae761b030207c72c2facea07dc
parentab4e591a40bbcd2d0e3b11e966fad42eaf259c28 (diff)
downloadgvfs-7cf5d5ff55fcbdebe0fb7b60e52ecb0c95ca63ee.tar.gz
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
-rw-r--r--configure.ac2
-rw-r--r--daemon/Makefile.am4
-rw-r--r--daemon/gvfsdaemonutils.c113
-rw-r--r--daemon/gvfsdaemonutils.h7
4 files changed, 125 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 788140d5..d219aba1 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 d55a1d9b..384f18c0 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 2be975ce..b1d7b93f 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 f1951361..f28e2ba2 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__ */