From 66b2ff40f7caf3a731814cbb7670e8d91c732e95 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 5 Jun 2018 18:20:54 +0200 Subject: [PATCH] run: Support accessing host trusted certificates If p11-kit server is installed on the host, we spawn a copy of this, forwarding the access to the p11-kit trust module in a read-only way. We then (if the above worked) bind mount the socket as /run/user/$UID/p11-kit/pkcs11 in the sandbox, which is the default socket path for the p11-kit-client module. We also add a configuration file in /etc/pkcs11/modules/p11-kit-trust.module that makes the trust module actually load the client module instead. This means applications automatically switch to using the host certs for trust if possible, and use the runtime ca-certificates otherwise. Additionally we add a config file that always disables pkcs user config merging, because pkcs11 modules on the host are unlikely to work in a random runtime. Closes: #1757 Approved by: alexlarsson --- common/flatpak-run.c | 30 ++++++++- session-helper/flatpak-session-helper.c | 83 +++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/common/flatpak-run.c b/common/flatpak-run.c index 5a88f399d..ca7ed0ae6 100644 --- a/common/flatpak-run.c +++ b/common/flatpak-run.c @@ -1705,6 +1705,7 @@ add_monitor_path_args (gboolean use_session_helper, { g_autoptr(AutoFlatpakSessionHelper) session_helper = NULL; g_autofree char *monitor_path = NULL; + g_autofree char *pkcs11_socket_path = NULL; g_autoptr(GVariant) session_data = NULL; if (use_session_helper) @@ -1730,6 +1731,24 @@ add_monitor_path_args (gboolean use_session_helper, "--symlink", "/run/host/monitor/host.conf", "/etc/host.conf", "--symlink", "/run/host/monitor/hosts", "/etc/hosts", NULL); + + if (g_variant_lookup (session_data, "pkcs11-socket", "s", &pkcs11_socket_path)) + { + g_autofree char *sandbox_pkcs11_socket_path = g_strdup_printf ("/run/user/%d/p11-kit/pkcs11", getuid ()); + const char *trusted_module_contents = + "# This overrides the runtime p11-kit-trusted module with a client one talking to the trust module on the host\n" + "module: p11-kit-client.so\n"; + + if (flatpak_bwrap_add_args_data (bwrap, "p11-kit-trust.module", + trusted_module_contents, -1, + "/etc/pkcs11/modules/p11-kit-trust.module", NULL)) + { + flatpak_bwrap_add_args (bwrap, + "--ro-bind", pkcs11_socket_path, sandbox_pkcs11_socket_path, + NULL); + flatpak_bwrap_unset_env (bwrap, "P11_KIT_SERVER_ADDRESS"); + } + } } else { @@ -2128,6 +2147,7 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, g_autofree char *run_dir = g_strdup_printf ("/run/user/%d", getuid ()); g_autofree char *passwd_contents = NULL; g_autofree char *group_contents = NULL; + const char *pkcs11_conf_contents = NULL; struct group *g = getgrgid (getgid ()); gulong pers; @@ -2146,6 +2166,10 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, g->gr_name, getgid (), g_get_user_name ()); + pkcs11_conf_contents = + "# Disable user pkcs11 config, because the host modules don't work in the runtime\n" + "user-config: none\n"; + flatpak_bwrap_add_args (bwrap, "--unshare-pid", "--proc", "/proc", @@ -2179,6 +2203,9 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, if (!flatpak_bwrap_add_args_data (bwrap, "group", group_contents, -1, "/etc/group", error)) return FALSE; + if (!flatpak_bwrap_add_args_data (bwrap, "pkcs11.conf", pkcs11_conf_contents, -1, "/etc/pkcs11/pkcs11.conf", error)) + return FALSE; + if (g_file_test ("/etc/machine-id", G_FILE_TEST_EXISTS)) flatpak_bwrap_add_args (bwrap, "--ro-bind", "/etc/machine-id", "/etc/machine-id", NULL); else if (g_file_test ("/var/lib/dbus/machine-id", G_FILE_TEST_EXISTS)) @@ -2212,7 +2239,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, strcmp (dent->d_name, "resolv.conf") == 0 || strcmp (dent->d_name, "host.conf") == 0 || strcmp (dent->d_name, "hosts") == 0 || - strcmp (dent->d_name, "localtime") == 0) + strcmp (dent->d_name, "localtime") == 0 || + strcmp (dent->d_name, "pkcs11") == 0) continue; src = g_build_filename (flatpak_file_get_path_cached (etc), dent->d_name, NULL); diff --git a/session-helper/flatpak-session-helper.c b/session-helper/flatpak-session-helper.c index f00c5c8d3..52d2829da 100644 --- a/session-helper/flatpak-session-helper.c +++ b/session-helper/flatpak-session-helper.c @@ -31,10 +31,26 @@ #include "flatpak-utils-private.h" static char *monitor_dir; +static char *p11_kit_server_socket_path; +static int p11_kit_server_pid = 0; static GHashTable *client_pid_data_hash = NULL; static GDBusConnection *session_bus = NULL; +static void +do_atexit (void) +{ + if (p11_kit_server_pid != 0) + kill (p11_kit_server_pid, SIGTERM); +} + +static void +handle_sigterm (int signum) +{ + do_atexit (); + _exit (1); +} + typedef struct { GPid pid; char *client; @@ -70,6 +86,9 @@ handle_request_session (FlatpakSessionHelper *object, g_variant_builder_add (&builder, "{s@v}", "path", g_variant_new_variant (g_variant_new_string (monitor_dir))); + if (p11_kit_server_socket_path) + g_variant_builder_add (&builder, "{s@v}", "pkcs11-socket", + g_variant_new_variant (g_variant_new_string (p11_kit_server_socket_path))); flatpak_session_helper_complete_request_session (object, invocation, g_variant_builder_end (&builder)); @@ -608,6 +627,15 @@ main (int argc, { NULL } }; g_autoptr(MonitorData) m_resolv_conf = NULL, m_host_conf = NULL, m_hosts = NULL, m_localtime = NULL; + struct sigaction action; + + atexit (do_atexit); + + memset(&action, 0, sizeof(struct sigaction)); + action.sa_handler = handle_sigterm; + sigaction(SIGTERM, &action, NULL); + sigaction(SIGHUP, &action, NULL); + sigaction(SIGINT, &action, NULL); setlocale (LC_ALL, ""); @@ -664,6 +692,61 @@ main (int argc, exit (1); } + if (g_find_program_in_path ("p11-kit")) + { + g_autofree char *socket_basename = g_strdup_printf ("pkcs11-flatpak-%d", getpid ()); + g_autofree char *socket_path = g_build_filename (flatpak_dir, socket_basename, NULL); + g_autofree char *p11_kit_stdout = NULL; + gint exit_status; + g_autoptr(GError) local_error = NULL; + char *p11_argv[] = { + "p11-kit", "server", + "-n", socket_path, + "--provider", "p11-kit-trust.so", + "pkcs11:model=p11-kit-trust?write-protected=yes", + NULL + }; + if (!g_spawn_sync (NULL, + p11_argv, NULL, G_SPAWN_SEARCH_PATH, + NULL, NULL, + &p11_kit_stdout, NULL, + &exit_status, &local_error)) + { + g_warning ("Unable to start p11-kit server: %s\n", local_error->message); + } + else if (exit_status != 0) + { + g_warning ("Unable to start p11-kit server, exited with status %d\n", exit_status); + } + else + { + g_auto(GStrv) stdout_lines = g_strsplit (p11_kit_stdout, "\n", 0); + int i; + + /* Output is something like: + P11_KIT_SERVER_ADDRESS=unix:path=/run/user/1000/p11-kit/pkcs11-2603742; export P11_KIT_SERVER_ADDRESS; + P11_KIT_SERVER_PID=2603743; export P11_KIT_SERVER_PID; + */ + for (i = 0; stdout_lines[i] != NULL; i++) + { + char *line = stdout_lines[i]; + + if (g_str_has_prefix (line, "P11_KIT_SERVER_PID=")) + { + char *pid = line + strlen ("P11_KIT_SERVER_PID="); + char *p = pid; + while (g_ascii_isdigit (*p)) + p++; + + *p = 0; + p11_kit_server_pid = atol (pid); + } + } + + p11_kit_server_socket_path = g_steal_pointer (&socket_path); + } + } + monitor_dir = g_build_filename (flatpak_dir, "monitor", NULL); if (g_mkdir_with_parents (monitor_dir, 0700) != 0) {