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
This commit is contained in:
Alexander Larsson
2018-06-05 18:20:54 +02:00
committed by Atomic Bot
parent b4bb890516
commit 66b2ff40f7
2 changed files with 112 additions and 1 deletions

View File

@@ -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);

View File

@@ -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)
{