diff options
author | Jonas Ã…dahl <jadahl@gmail.com> | 2022-02-22 10:30:07 +0100 |
---|---|---|
committer | Felipe Borges <felipeborges@gnome.org> | 2022-02-26 18:19:14 +0000 |
commit | 3631338676d50ee13d839a03cdcb2333369cc0db (patch) | |
tree | 74325665ee912fceb8cc68a96b61d263d1bbb074 | |
parent | 2f298c1cb2eee52cbb764b3c75c047f507a61739 (diff) | |
download | gnome-control-center-3631338676d50ee13d839a03cdcb2333369cc0db.tar.gz |
sharing: Generate RDP TLS certificates when missing
This also hooks up the certificate verification dialog to the configured
TLS certificate.
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | panels/sharing/cc-sharing-panel.c | 214 | ||||
-rw-r--r-- | panels/sharing/cc-sharing-panel.ui | 23 | ||||
-rw-r--r-- | panels/sharing/meson.build | 1 | ||||
-rw-r--r-- | panels/sharing/sharing.css | 4 | ||||
-rw-r--r-- | panels/sharing/sharing.gresource.xml | 1 | ||||
-rw-r--r-- | panels/wwan/meson.build | 4 |
7 files changed, 244 insertions, 4 deletions
diff --git a/meson.build b/meson.build index d963651f9..73f2ba303 100644 --- a/meson.build +++ b/meson.build @@ -128,6 +128,7 @@ gudev_dep = dependency('gudev-1.0', version: '>= 232') x11_dep = dependency('x11') xi_dep = dependency('xi', version: '>= 1.2') epoxy_dep = dependency('epoxy') +gcr_dep = dependency('gcr-base-3') m_dep = cc.find_library('m') diff --git a/panels/sharing/cc-sharing-panel.c b/panels/sharing/cc-sharing-panel.c index c2f998625..9c9fcafa2 100644 --- a/panels/sharing/cc-sharing-panel.c +++ b/panels/sharing/cc-sharing-panel.c @@ -29,12 +29,17 @@ #include "cc-media-sharing.h" #include "cc-sharing-networks.h" #include "cc-gnome-remote-desktop.h" +#include "cc-tls-certificate.h" #include "org.gnome.SettingsDaemon.Sharing.h" #ifdef GDK_WINDOWING_WAYLAND #include <gdk/wayland/gdkwayland.h> #endif #include <glib/gi18n.h> + +#define GCR_API_SUBJECT_TO_CHANGE +#include <gcr/gcr-base.h> + #include <config.h> static void cc_sharing_panel_setup_label_with_hostname (CcSharingPanel *self, GtkWidget *label); @@ -82,7 +87,10 @@ struct _CcSharingPanel GtkWidget *remote_desktop_address_label; GtkWidget *remote_desktop_row; GtkWidget *remote_desktop_switch; + GtkWidget *remote_desktop_verify_encryption; GtkWidget *remote_desktop_fingerprint_dialog; + GtkWidget *remote_desktop_fingerprint_left; + GtkWidget *remote_desktop_fingerprint_right; GtkWidget *shared_folders_grid; GtkWidget *shared_folders_listbox; @@ -91,6 +99,7 @@ struct _CcSharingPanel guint remote_desktop_name_watch; guint remote_desktop_store_credentials_id; + GTlsCertificate *remote_desktop_certificate; }; CC_PANEL_REGISTER (CcSharingPanel, cc_sharing_panel) @@ -173,6 +182,54 @@ cc_sharing_panel_get_help_uri (CcPanel *panel) static void remote_desktop_show_encryption_fingerprint (CcSharingPanel *self) { + g_autoptr(GByteArray) der = NULL; + g_autoptr(GcrCertificate) gcr_cert = NULL; + g_autofree char *fingerprint = NULL; + g_auto(GStrv) fingerprintv = NULL; + g_autofree char *left_string = NULL; + g_autofree char *right_string = NULL; + + g_return_if_fail (self->remote_desktop_certificate); + + g_object_get (self->remote_desktop_certificate, + "certificate", &der, NULL); + gcr_cert = gcr_simple_certificate_new (der->data, der->len); + if (!gcr_cert) + { + g_warning ("Failed to load GCR TLS certificate representation"); + return; + } + + fingerprint = gcr_certificate_get_fingerprint_hex (gcr_cert, G_CHECKSUM_SHA256); + + fingerprintv = g_strsplit (fingerprint, " ", -1); + g_return_if_fail (g_strv_length (fingerprintv) == 32); + + left_string = g_strdup_printf ( + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n", + fingerprintv[0], fingerprintv[1], fingerprintv[2], fingerprintv[3], + fingerprintv[8], fingerprintv[9], fingerprintv[10], fingerprintv[11], + fingerprintv[16], fingerprintv[17], fingerprintv[18], fingerprintv[19], + fingerprintv[24], fingerprintv[25], fingerprintv[26], fingerprintv[27]); + + right_string = g_strdup_printf ( + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n" + "%s:%s:%s:%s\n", + fingerprintv[4], fingerprintv[5], fingerprintv[6], fingerprintv[7], + fingerprintv[12], fingerprintv[13], fingerprintv[14], fingerprintv[15], + fingerprintv[20], fingerprintv[21], fingerprintv[22], fingerprintv[23], + fingerprintv[28], fingerprintv[29], fingerprintv[30], fingerprintv[31]); + + gtk_label_set_label (GTK_LABEL (self->remote_desktop_fingerprint_left), + left_string); + gtk_label_set_label (GTK_LABEL (self->remote_desktop_fingerprint_right), + right_string); + gtk_window_set_transient_for (GTK_WINDOW (self->remote_desktop_fingerprint_dialog), GTK_WINDOW (self->remote_desktop_dialog)); gtk_window_present (GTK_WINDOW (self->remote_desktop_fingerprint_dialog)); @@ -223,8 +280,11 @@ cc_sharing_panel_class_init (CcSharingPanelClass *klass) gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_password_entry); gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_device_name_label); gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_address_label); + gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_verify_encryption); gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_dialog); gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_row); + gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_left); + gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, remote_desktop_fingerprint_right); gtk_widget_class_bind_template_child (widget_class, CcSharingPanel, shared_folders_listbox); gtk_widget_class_bind_template_callback (widget_class, remote_desktop_show_encryption_fingerprint); @@ -1049,12 +1109,155 @@ disable_gnome_remote_desktop_service (CcSharingPanel *self) } static void +calc_default_tls_paths (char **out_dir_path, + char **out_cert_path, + char **out_key_path) +{ + g_autofree char *dir_path = NULL; + + dir_path = g_strdup_printf ("%s/gnome-remote-desktop", + g_get_user_data_dir ()); + + if (out_cert_path) + *out_cert_path = g_strdup_printf ("%s/rdp-tls.crt", dir_path); + if (out_key_path) + *out_key_path = g_strdup_printf ("%s/rdp-tls.key", dir_path); + + if (out_dir_path) + *out_dir_path = g_steal_pointer (&dir_path); +} + +static void +set_tls_certificate (CcSharingPanel *self, + GTlsCertificate *tls_certificate) +{ + g_set_object (&self->remote_desktop_certificate, + tls_certificate); + gtk_widget_set_sensitive (self->remote_desktop_verify_encryption, TRUE); +} + +static void +on_certificate_generated (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + CcSharingPanel *self; + g_autoptr(GTlsCertificate) tls_certificate = NULL; + g_autoptr(GError) error = NULL; + g_autofree char *cert_path = NULL; + g_autofree char *key_path = NULL; + g_autoptr(GSettings) rdp_settings = NULL; + + tls_certificate = bonsai_tls_certificate_new_generate_finish (res, &error); + if (!tls_certificate) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Failed to generate TLS certificate: %s", error->message); + return; + } + + self = CC_SHARING_PANEL (user_data); + + calc_default_tls_paths (NULL, &cert_path, &key_path); + + rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID); + + g_settings_set_string (rdp_settings, "tls-cert", cert_path); + g_settings_set_string (rdp_settings, "tls-key", key_path); + + set_tls_certificate (self, tls_certificate); + + enable_gnome_remote_desktop_service (self); +} + +static void +enable_gnome_remote_desktop (CcSharingPanel *self) +{ + g_autofree char *dir_path = NULL; + g_autofree char *cert_path = NULL; + g_autofree char *key_path = NULL; + g_autoptr(GFile) dir = NULL; + g_autoptr(GFile) cert_file = NULL; + g_autoptr(GFile) key_file = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GSettings) rdp_settings = NULL; + + rdp_settings = g_settings_new (GNOME_REMOTE_DESKTOP_RDP_SCHEMA_ID); + cert_path = g_settings_get_string (rdp_settings, "tls-cert"); + key_path = g_settings_get_string (rdp_settings, "tls-key"); + if (strlen (cert_path) > 0 && + strlen (key_path) > 0) + { + g_autoptr(GTlsCertificate) tls_certificate = NULL; + + tls_certificate = g_tls_certificate_new_from_file (cert_path, &error); + if (tls_certificate) + { + set_tls_certificate (self, tls_certificate); + + enable_gnome_remote_desktop_service (self); + return; + } + + g_warning ("Configured TLS certificate invalid: %s", error->message); + return; + } + + calc_default_tls_paths (&dir_path, &cert_path, &key_path); + + dir = g_file_new_for_path (dir_path); + if (!g_file_query_exists (dir, NULL)) + { + if (!g_file_make_directory_with_parents (dir, NULL, &error)) + { + g_warning ("Failed to create remote desktop certificate directory: %s", + error->message); + return; + } + } + + cert_file = g_file_new_for_path (cert_path); + key_file = g_file_new_for_path (key_path); + + if (g_file_query_exists (cert_file, NULL) && + g_file_query_exists (key_file, NULL)) + { + g_autoptr(GTlsCertificate) tls_certificate = NULL; + + tls_certificate = g_tls_certificate_new_from_file (cert_path, &error); + if (tls_certificate) + { + g_settings_set_string (rdp_settings, "tls-cert", cert_path); + g_settings_set_string (rdp_settings, "tls-key", key_path); + + set_tls_certificate (self, tls_certificate); + + enable_gnome_remote_desktop_service (self); + return; + } + + g_warning ("Existing TLS certificate invalid: %s", error->message); + return; + } + + bonsai_tls_certificate_new_generate_async (cert_path, + key_path, + "US", + "GNOME", + cc_panel_get_cancellable (CC_PANEL (self)), + on_certificate_generated, + self); +} + +static void on_remote_desktop_state_changed (GtkWidget *widget, GParamSpec *pspec, CcSharingPanel *self) { if (gtk_switch_get_active (GTK_SWITCH (widget))) - enable_gnome_remote_desktop_service (self); + enable_gnome_remote_desktop (self); else disable_gnome_remote_desktop_service (self); } @@ -1253,6 +1456,8 @@ sharing_proxy_ready (GObject *source, static void cc_sharing_panel_init (CcSharingPanel *self) { + g_autoptr(GtkCssProvider) provider = NULL; + g_resources_register (cc_sharing_get_resource ()); gtk_widget_init_template (GTK_WIDGET (self)); @@ -1289,6 +1494,13 @@ cc_sharing_panel_init (CcSharingPanel *self) /* make sure the hostname entry isn't focused by default */ g_signal_connect_swapped (self, "map", G_CALLBACK (gtk_widget_grab_focus), self->main_list_box); + + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_resource (provider, + "/org/gnome/control-center/sharing/sharing.css"); + gtk_style_context_add_provider_for_display (gdk_display_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } CcSharingPanel * diff --git a/panels/sharing/cc-sharing-panel.ui b/panels/sharing/cc-sharing-panel.ui index 04fcc6b5d..093cf5635 100644 --- a/panels/sharing/cc-sharing-panel.ui +++ b/panels/sharing/cc-sharing-panel.ui @@ -379,6 +379,29 @@ <object class="AdwStatusPage"> <property name="title" translatable="yes">Encryption Fingerprint</property> <property name="description" translatable="yes">The encryption fingerprint can be seen in connecting clients and should be identical</property> + <child> + <object class="GtkBox"> + <property name="orientation">horizontal</property> + <property name="halign">center</property> + <style> + <class name="tls-cert-verification" /> + </style> + <child> + <object class="GtkLabel" id="remote_desktop_fingerprint_left"> + <style> + <class name="tls-cert-fingerprint" /> + </style> + </object> + </child> + <child> + <object class="GtkLabel" id="remote_desktop_fingerprint_right"> + <style> + <class name="tls-cert-fingerprint" /> + </style> + </object> + </child> + </object> + </child> </object> </child> </object> diff --git a/panels/sharing/meson.build b/panels/sharing/meson.build index 5d2bcba6e..1e72f935e 100644 --- a/panels/sharing/meson.build +++ b/panels/sharing/meson.build @@ -84,6 +84,7 @@ panels_libs += static_library( common_deps, libsecret_dep, gnutls_dep, + gcr_dep, ], c_args: cflags ) diff --git a/panels/sharing/sharing.css b/panels/sharing/sharing.css new file mode 100644 index 000000000..cf18ab392 --- /dev/null +++ b/panels/sharing/sharing.css @@ -0,0 +1,4 @@ +.tls-cert-fingerprint { + font-family: monospace; + margin: 10px; +} diff --git a/panels/sharing/sharing.gresource.xml b/panels/sharing/sharing.gresource.xml index 75c7f7458..275f8846e 100644 --- a/panels/sharing/sharing.gresource.xml +++ b/panels/sharing/sharing.gresource.xml @@ -3,5 +3,6 @@ <gresource prefix="/org/gnome/control-center/sharing"> <file preprocess="xml-stripblanks">cc-sharing-panel.ui</file> <file preprocess="xml-stripblanks">cc-sharing-networks.ui</file> + <file>sharing.css</file> </gresource> </gresources> diff --git a/panels/wwan/meson.build b/panels/wwan/meson.build index 04a092050..9b73b5bb1 100644 --- a/panels/wwan/meson.build +++ b/panels/wwan/meson.build @@ -1,7 +1,5 @@ -gcr_dep = [dependency('gcr-base-3')] - -deps = common_deps + network_manager_deps + gcr_dep + [polkit_gobject_dep] +deps = common_deps + network_manager_deps + [gcr_dep, polkit_gobject_dep] panels_list += cappletname desktop = 'gnome-@0@-panel.desktop'.format(cappletname) |