summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2011-08-11 15:46:12 -0400
committerDavid Zeuthen <davidz@redhat.com>2011-08-11 15:46:12 -0400
commitff5d150f8b20a97f02dccd7897f8df0c65136930 (patch)
tree07b58060e74063cc2781858abff8bde2e4415b4b
parent0ffe041523bd8eac3765dc4ef74c3a679870dcd6 (diff)
Add support for /etc/crypttab
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--data/org.freedesktop.UDisks2.xml107
-rw-r--r--doc/udisks2-docs.xml2
-rw-r--r--doc/udisks2-sections.txt32
-rw-r--r--doc/udisks2.types2
-rw-r--r--policy/org.freedesktop.udisks2.policy.in20
-rw-r--r--src/Makefile.am2
-rw-r--r--src/udiskscrypttabentry.c214
-rw-r--r--src/udiskscrypttabentry.h42
-rw-r--r--src/udiskscrypttabmonitor.c444
-rw-r--r--src/udiskscrypttabmonitor.h38
-rw-r--r--src/udisksdaemon.c26
-rw-r--r--src/udisksdaemon.h1
-rw-r--r--src/udisksdaemontypes.h6
-rw-r--r--src/udiskslinuxblock.c647
-rw-r--r--src/udiskslinuxprovider.c42
-rw-r--r--src/udisksprivate.h6
16 files changed, 1573 insertions, 58 deletions
diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml
index 7048cee..4a5b21c 100644
--- a/data/org.freedesktop.UDisks2.xml
+++ b/data/org.freedesktop.UDisks2.xml
@@ -372,13 +372,26 @@
<property name="IdUUID" type="ay" access="read"/>
<!-- Configuration:
- The configuration sources for the device.
+ The configuration for the device.
This is an array of pairs of (@type, @details) where @type is
a string identifying the configuration source
(e.g. <literal>fstab</literal>) and @details contains the
actual configuration data.
+ Use the
+ org.freedesktop.UDisks2.BlockDevice.AddConfigurationItem(),
+ org.freedesktop.UDisks2.BlockDevice.RemoveConfigurationItem()
+ and
+ org.freedesktop.UDisks2.BlockDevice.UpdateConfigurationItem()
+ methods to add, remove and update configuration items.
+
+ Use
+ org.freedesktop.UDisks2.BlockDevice.GetSecretConfiguration()
+ to get the secrets (e.g. passphrases) that may be part of the
+ configuration but isn't exported in this property for
+ security reasons.
+
For entries of type <literal>fstab</literal>, it means that
the block device is referenced in the system-wide
<filename>/etc/fstab</filename> file. Known configuration
@@ -410,11 +423,44 @@
</varlistentry>
</variablelist>
- Use the
+ For entries of type <literal>crypttab</literal>, it means that
+ the block device is referenced in the system-wide
+ <filename>/etc/crypttab</filename> file. Known configuration
+ items for type <literal>crypttab</literal> are
+ <variablelist>
+ <varlistentry>
+ <term>name (type <literal>'ay'</literal>)</term>
+ <listitem><para>The name to set the device up as</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>device (type <literal>'ay'</literal>)</term>
+ <listitem><para>The special device</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>passphrase-path (type <literal>'ay'</literal>)</term>
+ <listitem><para>Either empty to specify that no password is set,
+ otherwise a path to a file containing the encryption password.
+ This may also point to a special device file in <filename>/dev</filename>
+ such as <literal>/dev/random</literal>.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>passphrase-contents (type <literal>'ay'</literal>)</term>
+ <listitem><para>The contents of the file containing the encryption password, if applicable.
+ This is only available via the org.freedesktop.UDisks2.BlockDevice.GetSecretConfiguration()
+ method.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>opts (type <literal>'ay'</literal>)</term>
+ <listitem><para>Options</para></listitem>
+ </varlistentry>
+ </variablelist>
+ For security reasons, when creating a new
+ <literal>crypttab</literal> entry (via the
org.freedesktop.UDisks2.BlockDevice.AddConfigurationItem()
- and
- org.freedesktop.UDisks2.BlockDevice.RemoveConfigurationItem()
- methods to add/remove configuration items.
+ method), then the <option>passphrase-path</option> must
+ reference an unexisting file in the
+ <filename>/etc/luks-keys</filename> directory.
-->
<property name="Configuration" type="a(sa{sv})" access="read"/>
@@ -494,9 +540,10 @@
@item: The configuration item to add.
@options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
- Adds a new configuration item. See the
- #org.freedesktop.UDisks2.BlockDevice:Configuration property
- for details about valid configuration items.
+ Adds a new configuration item.
+
+ See the #org.freedesktop.UDisks2.BlockDevice:Configuration
+ property for details about valid configuration items.
-->
<method name="AddConfigurationItem">
<arg name="item" direction="in" type="(sa{sv})"/>
@@ -508,15 +555,53 @@
@item: The configuration item to remove.
@options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
- Removes a new configuration item. See the
- #org.freedesktop.UDisks2.BlockDevice:Configuration property
- for details about valid configuration items.
+ Removes an existing configuration item.
+
+ See the #org.freedesktop.UDisks2.BlockDevice:Configuration
+ property for details about valid configuration items.
-->
<method name="RemoveConfigurationItem">
<arg name="item" direction="in" type="(sa{sv})"/>
<arg name="options" direction="in" type="a{sv}"/>
</method>
+ <!--
+ UpdateConfigurationItem:
+ @old_item: The configuration item to remove.
+ @new_item: The configuration item to add. Must be of the same type as @old_item.
+ @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
+
+ Removes a configuration item and adds a new one. This is
+ equivalent to calling
+ org.freedesktop.UDisks2.BlockDevice.RemoveConfigurationItem()
+ followed by
+ org.freedesktop.UDisks2.BlockDevice.AddConfigurationItem()
+ with the change that only one PolicyKit check is made
+ and that @new_item can be validated against @old_item.
+
+ See the #org.freedesktop.UDisks2.BlockDevice:Configuration
+ property for details about valid configuration items.
+ -->
+ <method name="UpdateConfigurationItem">
+ <arg name="old_item" direction="in" type="(sa{sv})"/>
+ <arg name="new_item" direction="in" type="(sa{sv})"/>
+ <arg name="options" direction="in" type="a{sv}"/>
+ </method>
+
+ <!--
+ GetSecretConfiguration:
+ @options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
+ @configuration: The resulting configuration.
+
+ Returns the same value as in the
+ #org.freedesktop.UDisks2.BlockDevice:Configuration property
+ but without secret information filtered out.
+ -->
+ <method name="GetSecretConfiguration">
+ <arg name="options" direction="in" type="a{sv}"/>
+ <arg name="configuration" direction="out" type="a(sa{sv})"/>
+ </method>
+
</interface>
<!-- ********************************************************************** -->
diff --git a/doc/udisks2-docs.xml b/doc/udisks2-docs.xml
index 8cd93c6..854f37e 100644
--- a/doc/udisks2-docs.xml
+++ b/doc/udisks2-docs.xml
@@ -178,6 +178,8 @@
<xi:include href="xml/udisksmountmonitor.xml"/>
<xi:include href="xml/udisksfstabentry.xml"/>
<xi:include href="xml/udisksfstabmonitor.xml"/>
+ <xi:include href="xml/udiskscrypttabentry.xml"/>
+ <xi:include href="xml/udiskscrypttabmonitor.xml"/>
<xi:include href="xml/udiskspersistentstore.xml"/>
<xi:include href="xml/udiskscleanup.xml"/>
<xi:include href="xml/udisksprovider.xml"/>
diff --git a/doc/udisks2-sections.txt b/doc/udisks2-sections.txt
index b29bcc1..b6ca719 100644
--- a/doc/udisks2-sections.txt
+++ b/doc/udisks2-sections.txt
@@ -59,6 +59,7 @@ udisks_daemon_get_connection
udisks_daemon_get_object_manager
udisks_daemon_get_mount_monitor
udisks_daemon_get_fstab_monitor
+udisks_daemon_get_crypttab_monitor
udisks_daemon_get_linux_provider
udisks_daemon_get_persistent_store
udisks_daemon_get_authority
@@ -1018,3 +1019,34 @@ UDISKS_IS_FSTAB_MONITOR
<SUBSECTION Private>
udisks_fstab_monitor_get_type
</SECTION>
+
+<SECTION>
+<FILE>udiskscrypttabentry</FILE>
+<TITLE>UDisksCrypttabEntry</TITLE>
+UDisksCrypttabEntry
+udisks_crypttab_entry_get_name
+udisks_crypttab_entry_get_device
+udisks_crypttab_entry_get_passphrase_path
+udisks_crypttab_entry_get_options
+udisks_crypttab_entry_compare
+<SUBSECTION Standard>
+UDISKS_TYPE_CRYPTTAB_ENTRY
+UDISKS_CRYPTTAB_ENTRY
+UDISKS_IS_CRYPTTAB_ENTRY
+<SUBSECTION Private>
+udisks_crypttab_entry_get_type
+</SECTION>
+
+<SECTION>
+<FILE>udiskscrypttabmonitor</FILE>
+<TITLE>UDisksCrypttabMonitor</TITLE>
+UDisksCrypttabMonitor
+udisks_crypttab_monitor_new
+udisks_crypttab_monitor_get_entries
+<SUBSECTION Standard>
+UDISKS_TYPE_CRYPTTAB_MONITOR
+UDISKS_CRYPTTAB_MONITOR
+UDISKS_IS_CRYPTTAB_MONITOR
+<SUBSECTION Private>
+udisks_crypttab_monitor_get_type
+</SECTION>
diff --git a/doc/udisks2.types b/doc/udisks2.types
index 79031a2..7b0ceee 100644
--- a/doc/udisks2.types
+++ b/doc/udisks2.types
@@ -20,6 +20,8 @@ udisks_linux_manager_get_type
udisks_cleanup_get_type
udisks_fstab_entry_get_type
udisks_fstab_monitor_get_type
+udisks_crypttab_entry_get_type
+udisks_crypttab_monitor_get_type
udisks_drive_get_type
udisks_drive_proxy_get_type
diff --git a/policy/org.freedesktop.udisks2.policy.in b/policy/org.freedesktop.udisks2.policy.in
index 9d76a85..8e61608 100644
--- a/policy/org.freedesktop.udisks2.policy.in
+++ b/policy/org.freedesktop.udisks2.policy.in
@@ -132,14 +132,30 @@
</defaults>
</action>
- <!-- Manage system-wide configuration files such as /etc/fstab -->
+ <!-- Manage system-wide configuration files such as /etc/fstab or
+ /etc/crypttab ... including files referenced by these files.
+
+ It is insecure to automatically grant this to groups of users or
+ to allow a process to retain the authorization.
+ -->
<action id="org.freedesktop.udisks2.modify-system-configuration">
<_description>Modify system-wide configuration</_description>
<_message>Authentication is required to modify system-wide configuration</_message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+
+ <!-- Get secrets from system-wide configuration files -->
+ <action id="org.freedesktop.udisks2.read-system-configuration-secrets">
+ <_description>Modify system-wide configuration</_description>
+ <_message>Authentication is required to retrieve secrets from system-wide configuration</_message>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>auth_admin</allow_active>
</defaults>
</action>
diff --git a/src/Makefile.am b/src/Makefile.am
index b23e7de..962cf12 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -67,6 +67,8 @@ libudisks_daemon_la_SOURCES = \
udisksprivate.h \
udisksfstabentry.h udisksfstabentry.c \
udisksfstabmonitor.h udisksfstabmonitor.c \
+ udiskscrypttabentry.h udiskscrypttabentry.c \
+ udiskscrypttabmonitor.h udiskscrypttabmonitor.c \
$(BUILT_SOURCES) \
$(NULL)
diff --git a/src/udiskscrypttabentry.c b/src/udiskscrypttabentry.c
new file mode 100644
index 0000000..71181cc
--- /dev/null
+++ b/src/udiskscrypttabentry.c
@@ -0,0 +1,214 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <mntent.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "udiskscrypttabentry.h"
+#include "udisksprivate.h"
+
+/**
+ * SECTION:udiskscrypttabentry
+ * @title: UDisksCrypttabEntry
+ * @short_description: Object corresponding to an entry in the crypttab file
+ *
+ * Object corresponding to an entry in the
+ * <filename>/etc/crypttab</filename> file. You cannot instantiate this
+ * type yourself – use #UDisksCrypttabMonitor.
+ */
+
+/**
+ * UDisksCrypttabEntry:
+ *
+ * The #UDisksCrypttabEntry structure contains only private data and should
+ * only be accessed using the provided API.
+ */
+struct _UDisksCrypttabEntry
+{
+ GObject parent_instance;
+
+ gchar *name;
+ gchar *device;
+ gchar *passphrase_path;
+ gchar *options;
+};
+
+typedef struct _UDisksCrypttabEntryClass UDisksCrypttabEntryClass;
+
+struct _UDisksCrypttabEntryClass
+{
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (UDisksCrypttabEntry, udisks_crypttab_entry, G_TYPE_OBJECT);
+
+static void
+udisks_crypttab_entry_finalize (GObject *object)
+{
+ UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (object);
+
+ g_free (entry->name);
+ g_free (entry->device);
+ g_free (entry->passphrase_path);
+ g_free (entry->options);
+
+ if (G_OBJECT_CLASS (udisks_crypttab_entry_parent_class)->finalize)
+ G_OBJECT_CLASS (udisks_crypttab_entry_parent_class)->finalize (object);
+}
+
+static void
+udisks_crypttab_entry_init (UDisksCrypttabEntry *crypttab_entry)
+{
+}
+
+static void
+udisks_crypttab_entry_class_init (UDisksCrypttabEntryClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = udisks_crypttab_entry_finalize;
+}
+
+UDisksCrypttabEntry *
+_udisks_crypttab_entry_new (const gchar *name,
+ const gchar *device,
+ const gchar *passphrase_path,
+ const gchar *options)
+{
+ UDisksCrypttabEntry *entry;
+
+ entry = UDISKS_CRYPTTAB_ENTRY (g_object_new (UDISKS_TYPE_CRYPTTAB_ENTRY, NULL));
+ entry->name = g_strdup (name);
+ entry->device = g_strdup (device);
+ entry->passphrase_path = g_strdup (passphrase_path);
+ entry->options = g_strdup (options);
+
+ return entry;
+}
+
+/**
+ * udisks_crypttab_entry_compare:
+ * @entry: A #UDisksCrypttabEntry
+ * @other_entry: Another #UDisksCrypttabEntry.
+ *
+ * Comparison function for comparing two #UDisksCrypttabEntry objects.
+ *
+ * Returns: Negative value if @entry < @other_entry; zero if @entry = @other_entry; positive value if @entry > @other_entry.
+ */
+gint
+udisks_crypttab_entry_compare (UDisksCrypttabEntry *entry,
+ UDisksCrypttabEntry *other_entry)
+{
+ gint ret;
+
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (entry), 0);
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (other_entry), 0);
+
+ ret = g_strcmp0 (other_entry->name, entry->name);
+ if (ret != 0)
+ goto out;
+
+ ret = g_strcmp0 (other_entry->device, entry->device);
+ if (ret != 0)
+ goto out;
+
+ ret = g_strcmp0 (other_entry->passphrase_path, entry->passphrase_path);
+ if (ret != 0)
+ goto out;
+
+ ret = g_strcmp0 (other_entry->options, entry->options);
+
+ out:
+ return ret;
+}
+
+/**
+ * udisks_crypttab_entry_get_name:
+ * @entry: A #UDisksCrypttabEntry.
+ *
+ * Gets the name field of @entry.
+ *
+ * Returns: The name field.
+ */
+const gchar *
+udisks_crypttab_entry_get_name (UDisksCrypttabEntry *entry)
+{
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (entry), NULL);
+ return entry->name;
+}
+
+/**
+ * udisks_crypttab_entry_get_device:
+ * @entry: A #UDisksCrypttabEntry.
+ *
+ * Gets the device field of @entry.
+ *
+ * Returns: The device field.
+ */
+const gchar *
+udisks_crypttab_entry_get_device (UDisksCrypttabEntry *entry)
+{
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (entry), NULL);
+ return entry->device;
+}
+
+/**
+ * udisks_crypttab_entry_get_passphrase_path:
+ * @entry: A #UDisksCrypttabEntry.
+ *
+ * Gets the passphrase path field of @entry.
+ *
+ * Returns: The passphrase path field.
+ */
+const gchar *
+udisks_crypttab_entry_get_passphrase_path (UDisksCrypttabEntry *entry)
+{
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (entry), NULL);
+ return entry->passphrase_path;
+}
+
+/**
+ * udisks_crypttab_entry_get_options:
+ * @entry: A #UDisksCrypttabEntry.
+ *
+ * Gets the options field of @entry.
+ *
+ * Returns: The options field.
+ */
+const gchar *
+udisks_crypttab_entry_get_options (UDisksCrypttabEntry *entry)
+{
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_ENTRY (entry), NULL);
+ return entry->options;
+}
+
diff --git a/src/udiskscrypttabentry.h b/src/udiskscrypttabentry.h
new file mode 100644
index 0000000..f1b8734
--- /dev/null
+++ b/src/udiskscrypttabentry.h
@@ -0,0 +1,42 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __UDISKS_CRYPTTAB_ENTRY_H__
+#define __UDISKS_CRYPTTAB_ENTRY_H__
+
+#include "udisksdaemontypes.h"
+
+G_BEGIN_DECLS
+
+#define UDISKS_TYPE_CRYPTTAB_ENTRY (udisks_crypttab_entry_get_type ())
+#define UDISKS_CRYPTTAB_ENTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_CRYPTTAB_ENTRY, UDisksCrypttabEntry))
+#define UDISKS_IS_CRYPTTAB_ENTRY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_CRYPTTAB_ENTRY))
+
+GType udisks_crypttab_entry_get_type (void) G_GNUC_CONST;
+const gchar *udisks_crypttab_entry_get_name (UDisksCrypttabEntry *entry);
+const gchar *udisks_crypttab_entry_get_device (UDisksCrypttabEntry *entry);
+const gchar *udisks_crypttab_entry_get_passphrase_path (UDisksCrypttabEntry *entry);
+const gchar *udisks_crypttab_entry_get_options (UDisksCrypttabEntry *entry);
+gint udisks_crypttab_entry_compare (UDisksCrypttabEntry *entry,
+ UDisksCrypttabEntry *other_entry);
+
+G_END_DECLS
+
+#endif /* __UDISKS_CRYPTTAB_ENTRY_H__ */
diff --git a/src/udiskscrypttabmonitor.c b/src/udiskscrypttabmonitor.c
new file mode 100644
index 0000000..f3b54ea
--- /dev/null
+++ b/src/udiskscrypttabmonitor.c
@@ -0,0 +1,444 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "udiskscrypttabmonitor.h"
+#include "udiskscrypttabentry.h"
+#include "udisksprivate.h"
+#include "udiskslogging.h"
+
+/**
+ * SECTION:udiskscrypttabmonitor
+ * @title: UDisksCrypttabMonitor
+ * @short_description: Monitors entries in the crypttab file
+ *
+ * This type is used for monitoring entries in the
+ * <filename>/etc/crypttab</filename> file.
+ */
+
+/**
+ * UDisksCrypttabMonitor:
+ *
+ * The #UDisksCrypttabMonitor structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _UDisksCrypttabMonitor
+{
+ GObject parent_instance;
+
+ gboolean have_data;
+ GList *crypttab_entries;
+
+ GFileMonitor *file_monitor;
+};
+
+typedef struct _UDisksCrypttabMonitorClass UDisksCrypttabMonitorClass;
+
+struct _UDisksCrypttabMonitorClass
+{
+ GObjectClass parent_class;
+
+ void (*entry_added) (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry);
+ void (*entry_removed) (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry);
+};
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+enum
+ {
+ ENTRY_ADDED_SIGNAL,
+ ENTRY_REMOVED_SIGNAL,
+ LAST_SIGNAL,
+ };
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (UDisksCrypttabMonitor, udisks_crypttab_monitor, G_TYPE_OBJECT)
+
+static void udisks_crypttab_monitor_ensure (UDisksCrypttabMonitor *monitor);
+static void udisks_crypttab_monitor_invalidate (UDisksCrypttabMonitor *monitor);
+static void udisks_crypttab_monitor_constructed (GObject *object);
+
+static void
+udisks_crypttab_monitor_finalize (GObject *object)
+{
+ UDisksCrypttabMonitor *monitor = UDISKS_CRYPTTAB_MONITOR (object);
+
+ g_object_unref (monitor->file_monitor);
+
+ g_list_foreach (monitor->crypttab_entries, (GFunc) g_object_unref, NULL);
+ g_list_free (monitor->crypttab_entries);
+
+ if (G_OBJECT_CLASS (udisks_crypttab_monitor_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (udisks_crypttab_monitor_parent_class)->finalize (object);
+}
+
+static void
+udisks_crypttab_monitor_init (UDisksCrypttabMonitor *monitor)
+{
+ monitor->crypttab_entries = NULL;
+}
+
+static void
+udisks_crypttab_monitor_class_init (UDisksCrypttabMonitorClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->finalize = udisks_crypttab_monitor_finalize;
+ gobject_class->constructed = udisks_crypttab_monitor_constructed;
+
+ /**
+ * UDisksCrypttabMonitor::entry-added
+ * @monitor: A #UDisksCrypttabMonitor.
+ * @entry: The #UDisksCrypttabEntry that was added.
+ *
+ * Emitted when a crypttab entry is added.
+ *
+ * This signal is emitted in the
+ * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * that @monitor was created in.
+ */
+ signals[ENTRY_ADDED_SIGNAL] = g_signal_new ("entry-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (UDisksCrypttabMonitorClass, entry_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ UDISKS_TYPE_CRYPTTAB_ENTRY);
+
+ /**
+ * UDisksCrypttabMonitor::entry-removed
+ * @monitor: A #UDisksCrypttabMonitor.
+ * @entry: The #UDisksCrypttabEntry that was removed.
+ *
+ * Emitted when a crypttab entry is removed.
+ *
+ * This signal is emitted in the
+ * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * that @monitor was created in.
+ */
+ signals[ENTRY_REMOVED_SIGNAL] = g_signal_new ("entry-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (UDisksCrypttabMonitorClass, entry_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ UDISKS_TYPE_CRYPTTAB_ENTRY);
+}
+
+static void
+diff_sorted_lists (GList *list1,
+ GList *list2,
+ GCompareFunc compare,
+ GList **added,
+ GList **removed)
+{
+ int order;
+
+ *added = *removed = NULL;
+
+ while (list1 != NULL && list2 != NULL)
+ {
+ order = (*compare) (list1->data, list2->data);
+ if (order < 0)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ else if (order > 0)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+ else
+ { /* same item */
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+ }
+
+ while (list1 != NULL)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ while (list2 != NULL)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+}
+
+static void
+reload_crypttab_entries (UDisksCrypttabMonitor *monitor)
+{
+ GList *old_crypttab_entries;
+ GList *cur_crypttab_entries;
+ GList *added;
+ GList *removed;
+ GList *l;
+
+ udisks_crypttab_monitor_ensure (monitor);
+
+ old_crypttab_entries = g_list_copy (monitor->crypttab_entries);
+ g_list_foreach (old_crypttab_entries, (GFunc) g_object_ref, NULL);
+
+ udisks_crypttab_monitor_invalidate (monitor);
+ udisks_crypttab_monitor_ensure (monitor);
+
+ cur_crypttab_entries = g_list_copy (monitor->crypttab_entries);
+
+ old_crypttab_entries = g_list_sort (old_crypttab_entries, (GCompareFunc) udisks_crypttab_entry_compare);
+ cur_crypttab_entries = g_list_sort (cur_crypttab_entries, (GCompareFunc) udisks_crypttab_entry_compare);
+ diff_sorted_lists (old_crypttab_entries, cur_crypttab_entries, (GCompareFunc) udisks_crypttab_entry_compare, &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data);
+ g_signal_emit (monitor, signals[ENTRY_REMOVED_SIGNAL], 0, entry);
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data);
+ g_signal_emit (monitor, signals[ENTRY_ADDED_SIGNAL], 0, entry);
+ }
+
+ g_list_foreach (old_crypttab_entries, (GFunc) g_object_unref, NULL);
+ g_list_free (old_crypttab_entries);
+ g_list_free (cur_crypttab_entries);
+ g_list_free (removed);
+ g_list_free (added);
+}
+
+static void
+on_file_monitor_changed (GFileMonitor *file_monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ UDisksCrypttabMonitor *monitor = UDISKS_CRYPTTAB_MONITOR (user_data);
+ if (event_type == G_FILE_MONITOR_EVENT_CHANGED ||
+ event_type == G_FILE_MONITOR_EVENT_CREATED)
+ {
+ udisks_debug ("/etc/crypttab changed!");
+ reload_crypttab_entries (monitor);
+ }
+}
+
+static void
+udisks_crypttab_monitor_constructed (GObject *object)
+{
+ UDisksCrypttabMonitor *monitor = UDISKS_CRYPTTAB_MONITOR (object);
+ GError *error;
+ GFile *file;
+
+ file = g_file_new_for_path ("/etc/crypttab");
+ error = NULL;
+ monitor->file_monitor = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL, /* cancellable */
+ &error);
+ if (monitor->file_monitor == NULL)
+ {
+ udisks_error ("Error monitoring /etc/crypttab: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ }
+ else
+ {
+ g_signal_connect (monitor->file_monitor,
+ "changed",
+ G_CALLBACK (on_file_monitor_changed),
+ monitor);
+ }
+ g_object_unref (file);
+
+ if (G_OBJECT_CLASS (udisks_crypttab_monitor_parent_class)->constructed != NULL)
+ (*G_OBJECT_CLASS (udisks_crypttab_monitor_parent_class)->constructed) (object);
+}
+
+/**
+ * udisks_crypttab_monitor_new:
+ *
+ * Creates a new #UDisksCrypttabMonitor object.
+ *
+ * Signals are emitted in the <link
+ * linkend="g-main-context-push-thread-default">thread-default main
+ * loop</link> that this function is called from.
+ *
+ * Returns: A #UDisksCrypttabMonitor. Free with g_object_unref().
+ */
+UDisksCrypttabMonitor *
+udisks_crypttab_monitor_new (void)
+{
+ return UDISKS_CRYPTTAB_MONITOR (g_object_new (UDISKS_TYPE_CRYPTTAB_MONITOR, NULL));
+}
+
+static void
+udisks_crypttab_monitor_invalidate (UDisksCrypttabMonitor *monitor)
+{
+ monitor->have_data = FALSE;
+
+ g_list_foreach (monitor->crypttab_entries, (GFunc) g_object_unref, NULL);
+ g_list_free (monitor->crypttab_entries);
+ monitor->crypttab_entries = NULL;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+have_entry (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry)
+{
+ GList *l;
+ gboolean ret;
+
+ ret = FALSE;
+ for (l = monitor->crypttab_entries; l != NULL; l = l->next)
+ {
+ UDisksCrypttabEntry *other_entry = UDISKS_CRYPTTAB_ENTRY (l->data);
+ if (udisks_crypttab_entry_compare (entry, other_entry) == 0)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ }
+ out:
+ return ret;
+}
+
+static void
+udisks_crypttab_monitor_ensure (UDisksCrypttabMonitor *monitor)
+{
+ gchar *contents;
+ gchar **lines;
+ GError *error;
+ guint n;
+
+ contents = NULL;
+ lines = NULL;
+
+ if (monitor->have_data)
+ goto out;
+
+ error = NULL;
+ if (!g_file_get_contents ("/etc/crypttab",
+ &contents,
+ NULL, /* size */
+ &error))
+ {
+ udisks_warning ("Error opening /etc/crypttab file: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ goto out;
+ }
+
+ lines = g_strsplit (contents, "\n", 0);
+
+ for (n = 0; lines != NULL && lines[n] != NULL; n++)
+ {
+ gchar **tokens;
+ guint num_tokens;
+ UDisksCrypttabEntry *entry;
+
+ const gchar *line = lines[n];
+ if (strlen (line) == 0)
+ continue;
+ if (line[0] == '#')
+ continue;
+
+ tokens = g_strsplit_set (line, " \t", 0);
+ num_tokens = g_strv_length (tokens);
+ if (num_tokens < 2)
+ {
+ udisks_warning ("Line %d of /etc/crypttab only contains %d tokens", n, num_tokens);
+ goto continue_loop;
+ }
+
+ entry = _udisks_crypttab_entry_new (tokens[0],
+ tokens[1],
+ num_tokens >= 3 ? tokens[2] : NULL,
+ num_tokens >= 4 ? tokens[3] : NULL);
+ if (!have_entry (monitor, entry))
+ {
+ monitor->crypttab_entries = g_list_prepend (monitor->crypttab_entries, entry);
+ }
+ else
+ {
+ g_object_unref (entry);
+ }
+
+ continue_loop:
+ g_strfreev (tokens);
+ }
+
+ monitor->have_data = TRUE;
+
+ out:
+ g_free (contents);
+ g_strfreev (lines);
+}
+
+/**
+ * udisks_crypttab_monitor_get_entries:
+ * @monitor: A #UDisksCrypttabMonitor.
+ *
+ * Gets all /etc/crypttab entries
+ *
+ * Returns: (transfer full) (element-type UDisksCrypttabEntry): A list of #UDisksCrypttabEntry objects that must be freed with g_list_free() after each element has been freed with g_object_unref().
+ */
+GList *
+udisks_crypttab_monitor_get_entries (UDisksCrypttabMonitor *monitor)
+{
+ GList *ret;
+
+ g_return_val_if_fail (UDISKS_IS_CRYPTTAB_MONITOR (monitor), NULL);
+
+ udisks_crypttab_monitor_ensure (monitor);
+
+ ret = g_list_copy (monitor->crypttab_entries);
+ g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+ return ret;
+}
+
diff --git a/src/udiskscrypttabmonitor.h b/src/udiskscrypttabmonitor.h
new file mode 100644
index 0000000..837bc4c
--- /dev/null
+++ b/src/udiskscrypttabmonitor.h
@@ -0,0 +1,38 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __UDISKS_CRYPTTAB_MONITOR_H__
+#define __UDISKS_CRYPTTAB_MONITOR_H__
+
+#include "udisksdaemontypes.h"
+
+G_BEGIN_DECLS
+
+#define UDISKS_TYPE_CRYPTTAB_MONITOR (udisks_crypttab_monitor_get_type ())
+#define UDISKS_CRYPTTAB_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_CRYPTTAB_MONITOR, UDisksCrypttabMonitor))
+#define UDISKS_IS_CRYPTTAB_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_CRYPTTAB_MONITOR))
+
+GType udisks_crypttab_monitor_get_type (void) G_GNUC_CONST;
+UDisksCrypttabMonitor *udisks_crypttab_monitor_new (void);
+GList *udisks_crypttab_monitor_get_entries (UDisksCrypttabMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __UDISKS_CRYPTTAB_MONITOR_H__ */
diff --git a/src/udisksdaemon.c b/src/udisksdaemon.c
index 3b72b26..4532746 100644
--- a/src/udisksdaemon.c
+++ b/src/udisksdaemon.c
@@ -35,6 +35,8 @@
#include "udiskscleanup.h"
#include "udisksfstabmonitor.h"
#include "udisksfstabentry.h"
+#include "udiskscrypttabmonitor.h"
+#include "udiskscrypttabentry.h"
/**
* SECTION:udisksdaemon
@@ -69,6 +71,8 @@ struct _UDisksDaemon
UDisksCleanup *cleanup;
UDisksFstabMonitor *fstab_monitor;
+
+ UDisksCrypttabMonitor *crypttab_monitor;
};
struct _UDisksDaemonClass
@@ -83,6 +87,7 @@ enum
PROP_OBJECT_MANAGER,
PROP_MOUNT_MONITOR,
PROP_FSTAB_MONITOR,
+ PROP_CRYPTTAB_MONITOR,
};
G_DEFINE_TYPE (UDisksDaemon, udisks_daemon, G_TYPE_OBJECT);
@@ -102,6 +107,7 @@ udisks_daemon_finalize (GObject *object)
g_object_unref (daemon->mount_monitor);
g_object_unref (daemon->connection);
g_object_unref (daemon->fstab_monitor);
+ g_object_unref (daemon->crypttab_monitor);
if (G_OBJECT_CLASS (udisks_daemon_parent_class)->finalize != NULL)
G_OBJECT_CLASS (udisks_daemon_parent_class)->finalize (object);
@@ -133,6 +139,10 @@ udisks_daemon_get_property (GObject *object,
g_value_set_object (value, udisks_daemon_get_fstab_monitor (daemon));
break;
+ case PROP_CRYPTTAB_MONITOR:
+ g_value_set_object (value, udisks_daemon_get_crypttab_monitor (daemon));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -218,6 +228,7 @@ udisks_daemon_constructed (GObject *object)
daemon);
daemon->fstab_monitor = udisks_fstab_monitor_new ();
+ daemon->crypttab_monitor = udisks_crypttab_monitor_new ();
/* now add providers */
daemon->linux_provider = udisks_linux_provider_new (daemon);
@@ -371,6 +382,21 @@ udisks_daemon_get_fstab_monitor (UDisksDaemon *daemon)
}
/**
+ * udisks_daemon_get_crypttab_monitor:
+ * @daemon: A #UDisksDaemon
+ *
+ * Gets the crypttab monitor used by @daemon.
+ *
+ * Returns: A #UDisksCrypttabMonitor. Do not free, the object is owned by @daemon.
+ */
+UDisksCrypttabMonitor *
+udisks_daemon_get_crypttab_monitor (UDisksDaemon *daemon)
+{
+ g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
+ return daemon->crypttab_monitor;
+}
+
+/**
* udisks_daemon_get_linux_provider:
* @daemon: A #UDisksDaemon.
*
diff --git a/src/udisksdaemon.h b/src/udisksdaemon.h
index 684e673..56bbdaf 100644
--- a/src/udisksdaemon.h
+++ b/src/udisksdaemon.h
@@ -35,6 +35,7 @@ GDBusConnection *udisks_daemon_get_connection (UDisksDaemon *
GDBusObjectManagerServer *udisks_daemon_get_object_manager (UDisksDaemon *daemon);
UDisksMountMonitor *udisks_daemon_get_mount_monitor (UDisksDaemon *daemon);
UDisksFstabMonitor *udisks_daemon_get_fstab_monitor (UDisksDaemon *daemon);
+UDisksCrypttabMonitor *udisks_daemon_get_crypttab_monitor (UDisksDaemon *daemon);
UDisksLinuxProvider *udisks_daemon_get_linux_provider (UDisksDaemon *daemon);
UDisksPersistentStore *udisks_daemon_get_persistent_store (UDisksDaemon *daemon);
PolkitAuthority *udisks_daemon_get_authority (UDisksDaemon *daemon);
diff --git a/src/udisksdaemontypes.h b/src/udisksdaemontypes.h
index fe4b1ba..edf97c2 100644
--- a/src/udisksdaemontypes.h
+++ b/src/udisksdaemontypes.h
@@ -82,6 +82,12 @@ typedef struct _UDisksFstabMonitor UDisksFstabMonitor;
struct _UDisksFstabEntry;
typedef struct _UDisksFstabEntry UDisksFstabEntry;
+struct _UDisksCrypttabMonitor;
+typedef struct _UDisksCrypttabMonitor UDisksCrypttabMonitor;
+
+struct _UDisksCrypttabEntry;
+typedef struct _UDisksCrypttabEntry UDisksCrypttabEntry;
+
/**
* UDisksThreadedJobFunc:
* @job: A #UDisksThreadedJob.
diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c
index 027c940..d8cfe23 100644
--- a/src/udiskslinuxblock.c
+++ b/src/udiskslinuxblock.c
@@ -45,6 +45,8 @@
#include "udiskslinuxprovider.h"
#include "udisksfstabmonitor.h"
#include "udisksfstabentry.h"
+#include "udiskscrypttabmonitor.h"
+#include "udiskscrypttabentry.h"
/**
* SECTION:udiskslinuxblock
@@ -371,6 +373,48 @@ update_iface (UDisksLinuxBlock *block,
/* ---------------------------------------------------------------------------------------------------- */
+static GVariant *calculate_configuration (UDisksLinuxBlock *block,
+ gboolean include_secrets,
+ GError **error);
+
+static gboolean
+on_get_secret_configuration (UDisksBlockDevice *block,
+ GDBusMethodInvocation *invocation,
+ GVariant *options,
+ gpointer user_data)
+{
+ UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data);
+ GVariant *configuration;
+ GError *error;
+
+ error = NULL;
+ configuration = calculate_configuration (object, TRUE, &error);
+ if (configuration == NULL)
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.read-system-configuration-secrets",
+ options,
+ N_("Authentication is required to read system-level secrets"),
+ invocation))
+ {
+ g_variant_unref (configuration);
+ goto out;
+ }
+
+ udisks_block_device_complete_get_secret_configuration (object->iface_block_device, invocation,
+ configuration); /* consumes floating ref */
+
+ out:
+ return TRUE; /* returning TRUE means that we handled the method invocation */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gchar *
escape_fstab (const gchar *source)
{
@@ -442,8 +486,8 @@ out:
}
static gboolean
-add_remove_fstab_entry (GVariant *add,
- GVariant *remove,
+add_remove_fstab_entry (GVariant *remove,
+ GVariant *add,
GError **error)
{
struct mntent mntent_remove;
@@ -598,6 +642,252 @@ add_remove_fstab_entry (GVariant *add,
return ret;
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+has_whitespace (const gchar *s)
+{
+ guint n;
+ g_return_val_if_fail (s != NULL, TRUE);
+ for (n = 0; s[n] != '\0'; n++)
+ if (g_ascii_isspace (s[n]))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+add_remove_crypttab_entry (GVariant *remove,
+ GVariant *add,
+ GError **error)
+{
+ const gchar *remove_name = NULL;
+ const gchar *remove_device = NULL;
+ const gchar *remove_passphrase_path = NULL;
+ const gchar *remove_options = NULL;
+ const gchar *add_name = NULL;
+ const gchar *add_device = NULL;
+ const gchar *add_passphrase_path = NULL;
+ const gchar *add_options = NULL;
+ const gchar *add_passphrase_contents = NULL;
+ gboolean ret;
+ gchar *contents;
+ gchar **lines;
+ GString *str;
+ gboolean removed;
+ guint n;
+
+ contents = NULL;
+ lines = NULL;
+ str = NULL;
+ ret = FALSE;
+
+ if (remove != NULL)
+ {
+ if (!g_variant_lookup (remove, "name", "^&ay", &remove_name) ||
+ !g_variant_lookup (remove, "device", "^&ay", &remove_device) ||
+ !g_variant_lookup (remove, "passphrase-path", "^&ay", &remove_passphrase_path) ||
+ !g_variant_lookup (remove, "options", "^&ay", &remove_options))
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Missing name, device, passphrase-path, options or parameter in entry to remove");
+ goto out;
+ }
+ }
+
+ if (add != NULL)
+ {
+ if (!g_variant_lookup (add, "name", "^&ay", &add_name) ||
+ !g_variant_lookup (add, "device", "^&ay", &add_device) ||
+ !g_variant_lookup (add, "passphrase-path", "^&ay", &add_passphrase_path) ||
+ !g_variant_lookup (add, "options", "^&ay", &add_options) ||
+ !g_variant_lookup (add, "passphrase-contents", "^&ay", &add_passphrase_contents))
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Missing name, device, passphrase-path, options or passphrase-contents parameter in entry to add");
+ goto out;
+ }
+
+ /* reject strings with whitespace in them */
+ if (has_whitespace (add_name) ||
+ has_whitespace (add_device) ||
+ has_whitespace (add_passphrase_path) ||
+ has_whitespace (add_options))
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "One of name, device, passphrase-path or options parameter are invalid (whitespace)");
+ goto out;
+ }
+ }
+
+ if (!g_file_get_contents ("/etc/crypttab",
+ &contents,
+ NULL,
+ error))
+ goto out;
+
+ lines = g_strsplit (contents, "\n", 0);
+
+ str = g_string_new (NULL);
+ removed = FALSE;
+ for (n = 0; lines != NULL && lines[n] != NULL; n++)
+ {
+ const gchar *line = lines[n];
+ if (strlen (line) == 0 && lines[n+1] == NULL)
+ break;
+ if (remove != NULL && !removed)
+ {
+ gchar parsed_name[512];
+ gchar parsed_device[512];
+ gchar parsed_passphrase_path[512];
+ gchar parsed_options[512];
+ guint num_parsed;
+
+ num_parsed = sscanf (line, "%511s %511s %511s %511s",
+ parsed_name, parsed_device, parsed_passphrase_path, parsed_options);
+ if (num_parsed >= 2)
+ {
+ if (num_parsed < 3 || g_strcmp0 (parsed_passphrase_path, "none") == 0)
+ strcpy (parsed_passphrase_path, "");
+ if (num_parsed < 4)
+ strcpy (parsed_options, "");
+ if (g_strcmp0 (parsed_name, remove_name) == 0 &&
+ g_strcmp0 (parsed_device, remove_device) == 0 &&
+ g_strcmp0 (parsed_passphrase_path, remove_passphrase_path) == 0 &&
+ g_strcmp0 (parsed_options, remove_options) == 0)
+ {
+ /* Nuke passphrase file */
+ if (strlen (remove_passphrase_path) > 0 && !g_str_has_prefix (remove_passphrase_path, "/dev"))
+ {
+ /* Is this exploitable? No, 1. the user would have to control
+ * the /etc/crypttab file for us to delete it; and 2. editing the
+ * /etc/crypttab file requires a polkit authorization that can't
+ * be retained (e.g. the user is always asked for the password)..
+ */
+ if (unlink (remove_passphrase_path) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Error deleting file `%s' with passphrase",
+ remove_passphrase_path);
+ goto out;
+ }
+ }
+ removed = TRUE;
+ continue;
+ }
+ }
+ }
+ g_string_append (str, line);
+ g_string_append_c (str, '\n');
+ }
+
+ if (remove != NULL && !removed)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Didn't find entry to remove");
+ goto out;
+ }
+
+ if (add != NULL)
+ {
+ /* First write add_passphrase_content to add_passphrase_path,
+ * if applicable..
+ *
+ * Is this exploitable? No, because editing the /etc/crypttab
+ * file requires a polkit authorization that can't be retained
+ * (e.g. the user is always asked for the password)...
+ *
+ * Just to be on the safe side we only allow writing into the
+ * directory /etc/luks-keys if create a _new_ entry.
+ */
+ if (strlen (add_passphrase_path) > 0)
+ {
+ gchar *filename;
+ if (g_strcmp0 (add_passphrase_path, remove_passphrase_path) == 0)
+ {
+ filename = g_strdup (add_passphrase_path);
+ }
+ else
+ {
+ if (!g_str_has_prefix (add_passphrase_path, "/etc/luks-keys/"))
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Crypttab passphrase file can only be created in the /etc/luks-keys directory");
+ goto out;
+ }
+ /* ensure the directory exists */
+ if (g_mkdir_with_parents ("/etc/luks-keys", 0700) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Error creating /etc/luks-keys directory: %m");
+ goto out;
+ }
+ /* avoid symlink attacks */
+ filename = g_strdup_printf ("/etc/luks-keys/%s", strrchr (add_passphrase_path, '/') + 1);
+ }
+
+ /* Bail if the requested file already exists */
+ if (g_file_test (filename, G_FILE_TEST_EXISTS))
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Refusing to overwrite existing file %s",
+ filename);
+ g_free (filename);
+ goto out;
+ }
+
+ /* TODO: XXX: would like to use mode 0600 here - umask(3) at start-up? */
+ if (!g_file_set_contents (filename,
+ add_passphrase_contents,
+ -1,
+ error))
+ {
+ g_free (filename);
+ goto out;
+ }
+ g_free (filename);
+ }
+ g_string_append_printf (str, "%s %s %s %s\n",
+ add_name,
+ add_device,
+ strlen (add_passphrase_path) > 0 ? add_passphrase_path : "none",
+ add_options);
+ }
+
+ /* TODO: XXX: ugh, the mode is wrong.. umask(3) at start-up? */
+ if (!g_file_set_contents ("/etc/crypttab",
+ str->str,
+ -1,
+ error) != 0)
+ goto out;
+
+ ret = TRUE;
+
+ out:
+ g_strfreev (lines);
+ g_free (contents);
+ if (str != NULL)
+ g_string_free (str, TRUE);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gboolean
on_add_configuration_item (UDisksBlockDevice *block,
GDBusMethodInvocation *invocation,
@@ -612,32 +902,49 @@ on_add_configuration_item (UDisksBlockDevice *block,
g_variant_get (item, "(&s@a{sv})", &type, &details);
- if (g_strcmp0 (type, "fstab") != 0)
+ if (g_strcmp0 (type, "fstab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to add an entry to the /etc/fstab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_fstab_entry (NULL, details, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else if (g_strcmp0 (type, "crypttab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to add an entry to the /etc/crypttab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_crypttab_entry (NULL, details, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
- "Only fstab items can be added");
+ "Only /etc/fstab or /etc/crypttab items can be added");
goto out;
}
- if (!udisks_daemon_util_check_authorization_sync (object->daemon,
- NULL,
- "org.freedesktop.udisks2.modify-system-configuration",
- options,
- N_("Authentication is required to modify the /etc/fstab file"),
- invocation))
- goto out;
-
- error = NULL;
- if (!add_remove_fstab_entry (details, NULL, &error))
- {
- g_dbus_method_invocation_take_error (invocation, error);
- goto out;
- }
-
- udisks_block_device_complete_add_configuration_item (block, invocation);
-
out:
g_variant_unref (details);
return TRUE; /* returning TRUE means that we handled the method invocation */
@@ -657,34 +964,126 @@ on_remove_configuration_item (UDisksBlockDevice *block,
g_variant_get (item, "(&s@a{sv})", &type, &details);
- if (g_strcmp0 (type, "fstab") != 0)
+ if (g_strcmp0 (type, "fstab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to remove an entry from /etc/fstab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_fstab_entry (details, NULL, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else if (g_strcmp0 (type, "crypttab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to remove an entry from the /etc/crypttab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_crypttab_entry (details, NULL, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
- "Only fstab items can be removed");
+ "Only fstab or crypttab items can be removed");
goto out;
}
- if (!udisks_daemon_util_check_authorization_sync (object->daemon,
- NULL,
- "org.freedesktop.udisks2.modify-system-configuration",
- options,
- N_("Authentication is required to modify the /etc/fstab file"),
- invocation))
- goto out;
+ out:
+ g_variant_unref (details);
+ return TRUE; /* returning TRUE means that we handled the method invocation */
+}
- error = NULL;
- if (!add_remove_fstab_entry (NULL, details, &error))
+static gboolean
+on_update_configuration_item (UDisksBlockDevice *block,
+ GDBusMethodInvocation *invocation,
+ GVariant *old_item,
+ GVariant *new_item,
+ GVariant *options,
+ gpointer user_data)
+{
+ UDisksLinuxBlock *object = UDISKS_LINUX_BLOCK (user_data);
+ const gchar *old_type;
+ const gchar *new_type;
+ GVariant *old_details;
+ GVariant *new_details;
+ GError *error;
+
+ g_variant_get (old_item, "(&s@a{sv})", &old_type, &old_details);
+ g_variant_get (new_item, "(&s@a{sv})", &new_type, &new_details);
+ if (g_strcmp0 (old_type, new_type) != 0)
{
- g_dbus_method_invocation_take_error (invocation, error);
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "old and new item are not of the same type");
goto out;
}
- udisks_block_device_complete_add_configuration_item (block, invocation);
+ if (g_strcmp0 (old_type, "fstab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to modify the /etc/fstab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_fstab_entry (old_details, new_details, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else if (g_strcmp0 (old_type, "crypttab") == 0)
+ {
+ if (!udisks_daemon_util_check_authorization_sync (object->daemon,
+ NULL,
+ "org.freedesktop.udisks2.modify-system-configuration",
+ options,
+ N_("Authentication is required to modify the /etc/crypttab file"),
+ invocation))
+ goto out;
+ error = NULL;
+ if (!add_remove_crypttab_entry (old_details, new_details, &error))
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+ udisks_block_device_complete_add_configuration_item (block, invocation);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Only fstab or crypttab items can be updated");
+ goto out;
+ }
out:
- g_variant_unref (details);
+ g_variant_unref (new_details);
+ g_variant_unref (old_details);
return TRUE; /* returning TRUE means that we handled the method invocation */
}
@@ -701,6 +1100,10 @@ static void
block_device_connect (UDisksLinuxBlock *block)
{
g_signal_connect (block->iface_block_device,
+ "handle-get-secret-configuration",
+ G_CALLBACK (on_get_secret_configuration),
+ block);
+ g_signal_connect (block->iface_block_device,
"handle-add-configuration-item",
G_CALLBACK (on_add_configuration_item),
block);
@@ -708,6 +1111,10 @@ block_device_connect (UDisksLinuxBlock *block)
"handle-remove-configuration-item",
G_CALLBACK (on_remove_configuration_item),
block);
+ g_signal_connect (block->iface_block_device,
+ "handle-update-configuration-item",
+ G_CALLBACK (on_update_configuration_item),
+ block);
}
static gchar *
@@ -943,24 +1350,88 @@ find_fstab_entries_for_device (UDisksLinuxBlock *block)
return ret;
}
-static void
-block_device_update_configuration (UDisksLinuxBlock *block,
- const gchar *uevent_action,
- UDisksBlockDevice *iface,
- const gchar *device_file,
- UDisksDrive *drive)
+static GList *
+find_crypttab_entries_for_device (UDisksLinuxBlock *block)
+{
+ GList *entries;
+ GList *l;
+ GList *ret;
+
+ ret = NULL;
+
+ /* if this is too slow, we could add lookup methods to UDisksCrypttabMonitor... */
+ entries = udisks_crypttab_monitor_get_entries (udisks_daemon_get_crypttab_monitor (block->daemon));
+ for (l = entries; l != NULL; l = l->next)
+ {
+ UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data);
+ const gchar *const *symlinks;
+ const gchar *device_in_entry;
+ gchar *device;
+ guint n;
+
+ device_in_entry = udisks_crypttab_entry_get_device (entry);
+ device = NULL;
+ if (g_str_has_prefix (device_in_entry, "UUID="))
+ {
+ device = g_strdup_printf ("/dev/disk/by-uuid/%s", device_in_entry + 5);
+ }
+ else if (g_str_has_prefix (device_in_entry, "LABEL="))
+ {
+ device = g_strdup_printf ("/dev/disk/by-label/%s", device_in_entry + 6);
+ }
+ else if (g_str_has_prefix (device_in_entry, "/dev"))
+ {
+ device = g_strdup (device_in_entry);
+ }
+ else
+ {
+ /* ignore non-device entries */
+ goto continue_loop;
+ }
+
+ symlinks = udisks_block_device_get_symlinks (block->iface_block_device);
+ if (symlinks != NULL)
+ {
+ for (n = 0; symlinks[n] != NULL; n++)
+ {
+ if (g_strcmp0 (device, symlinks[n]) == 0)
+ {
+ ret = g_list_prepend (ret, g_object_ref (entry));
+ }
+ }
+ }
+
+ continue_loop:
+ g_free (device);
+ }
+
+ g_list_foreach (entries, (GFunc) g_object_unref, NULL);
+ g_list_free (entries);
+ return ret;
+}
+
+/* returns a floating GVariant */
+static GVariant *
+calculate_configuration (UDisksLinuxBlock *block,
+ gboolean include_secrets,
+ GError **error)
{
GList *entries;
GList *l;
GVariantBuilder builder;
+ GVariant *ret;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ ret = NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa{sv})"));
+ /* First the /etc/fstab entries */
entries = find_fstab_entries_for_device (block);
for (l = entries; l != NULL; l = l->next)
{
UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data);
GVariantBuilder dict_builder;
-
g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&dict_builder, "{sv}", "fsname",
g_variant_new_bytestring (udisks_fstab_entry_get_fsname (entry)));
@@ -978,12 +1449,100 @@ block_device_update_configuration (UDisksLinuxBlock *block,
"(sa{sv})",
"fstab", &dict_builder);
}
+ g_list_foreach (entries, (GFunc) g_object_unref, NULL);
+ g_list_free (entries);
- udisks_block_device_set_configuration (block->iface_block_device,
- g_variant_builder_end (&builder));
+ /* Then the /etc/crypttab entries */
+ entries = find_crypttab_entries_for_device (block);
+ for (l = entries; l != NULL; l = l->next)
+ {
+ UDisksCrypttabEntry *entry = UDISKS_CRYPTTAB_ENTRY (l->data);
+ GVariantBuilder dict_builder;
+ const gchar *passphrase_path;
+ const gchar *options;
+ gchar *passphrase_contents;
+ gsize passphrase_contents_length;
+
+ passphrase_path = udisks_crypttab_entry_get_passphrase_path (entry);
+ if (passphrase_path == NULL || g_strcmp0 (passphrase_path, "none") == 0)
+ passphrase_path = "";
+ passphrase_contents = NULL;
+ if (!(g_strcmp0 (passphrase_path, "") == 0 || g_str_has_prefix (passphrase_path, "/dev")))
+ {
+ if (include_secrets)
+ {
+ if (!g_file_get_contents (passphrase_path,
+ &passphrase_contents,
+ &passphrase_contents_length,
+ error))
+ {
+ g_prefix_error (error,
+ "Error loading secrets from file `%s' referenced in /etc/crypttab entry: ",
+ passphrase_path);
+ g_variant_builder_clear (&builder);
+ g_list_foreach (entries, (GFunc) g_object_unref, NULL);
+ g_list_free (entries);
+ goto out;
+ }
+ }
+ }
+ options = udisks_crypttab_entry_get_options (entry);
+ if (options == NULL)
+ options = "";
+
+ g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&dict_builder, "{sv}", "name",
+ g_variant_new_bytestring (udisks_crypttab_entry_get_name (entry)));
+ g_variant_builder_add (&dict_builder, "{sv}", "device",
+ g_variant_new_bytestring (udisks_crypttab_entry_get_device (entry)));
+ g_variant_builder_add (&dict_builder, "{sv}", "passphrase-path",
+ g_variant_new_bytestring (passphrase_path));
+ if (passphrase_contents != NULL)
+ {
+ g_variant_builder_add (&dict_builder, "{sv}", "passphrase-contents",
+ g_variant_new_bytestring (passphrase_contents));
+ }
+ g_variant_builder_add (&dict_builder, "{sv}", "options",
+ g_variant_new_bytestring (options));
+ g_variant_builder_add (&builder,
+ "(sa{sv})",
+ "crypttab", &dict_builder);
+ if (passphrase_contents != NULL)
+ {
+ memset (passphrase_contents, '\0', passphrase_contents_length);
+ g_free (passphrase_contents);
+ }
+ }
g_list_foreach (entries, (GFunc) g_object_unref, NULL);
g_list_free (entries);
+
+ ret = g_variant_builder_end (&builder);
+
+ out:
+ return ret;
+}
+
+static void
+block_device_update_configuration (UDisksLinuxBlock *block,
+ const gchar *uevent_action,
+ UDisksBlockDevice *iface,
+ const gchar *device_file,
+ UDisksDrive *drive)
+{
+ GVariant *configuration;
+ GError *error;
+
+ error = NULL;
+ configuration = calculate_configuration (block, FALSE, &error);
+ if (configuration == NULL)
+ {
+ udisks_warning ("Error loading configuration: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ configuration = g_variant_new ("a(sa{sv})", NULL);
+ }
+ udisks_block_device_set_configuration (block->iface_block_device, configuration);
}
static void
diff --git a/src/udiskslinuxprovider.c b/src/udiskslinuxprovider.c
index 3a4f5be..60da384 100644
--- a/src/udiskslinuxprovider.c
+++ b/src/udiskslinuxprovider.c
@@ -93,6 +93,14 @@ static void fstab_monitor_on_entry_removed (UDisksFstabMonitor *monitor,
UDisksFstabEntry *entry,
gpointer user_data);
+static void crypttab_monitor_on_entry_added (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry,
+ gpointer user_data);
+
+static void crypttab_monitor_on_entry_removed (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry,
+ gpointer user_data);
+
G_DEFINE_TYPE (UDisksLinuxProvider, udisks_linux_provider, UDISKS_TYPE_PROVIDER);
static void
@@ -120,6 +128,12 @@ udisks_linux_provider_finalize (GObject *object)
g_signal_handlers_disconnect_by_func (udisks_daemon_get_fstab_monitor (daemon),
G_CALLBACK (fstab_monitor_on_entry_removed),
provider);
+ g_signal_handlers_disconnect_by_func (udisks_daemon_get_crypttab_monitor (daemon),
+ G_CALLBACK (crypttab_monitor_on_entry_added),
+ provider);
+ g_signal_handlers_disconnect_by_func (udisks_daemon_get_crypttab_monitor (daemon),
+ G_CALLBACK (crypttab_monitor_on_entry_removed),
+ provider);
if (G_OBJECT_CLASS (udisks_linux_provider_parent_class)->finalize != NULL)
G_OBJECT_CLASS (udisks_linux_provider_parent_class)->finalize (object);
@@ -201,7 +215,7 @@ udisks_linux_provider_start (UDisksProvider *_provider)
provider->coldplug = FALSE;
- /* update BlockDevice:FstabEntries whenever fstab entries are added or removed */
+ /* update BlockDevice:Configuration whenever fstab or crypttab entries are added or removed */
g_signal_connect (udisks_daemon_get_fstab_monitor (daemon),
"entry-added",
G_CALLBACK (fstab_monitor_on_entry_added),
@@ -210,6 +224,14 @@ udisks_linux_provider_start (UDisksProvider *_provider)
"entry-removed",
G_CALLBACK (fstab_monitor_on_entry_removed),
provider);
+ g_signal_connect (udisks_daemon_get_crypttab_monitor (daemon),
+ "entry-added",
+ G_CALLBACK (crypttab_monitor_on_entry_added),
+ provider);
+ g_signal_connect (udisks_daemon_get_crypttab_monitor (daemon),
+ "entry-removed",
+ G_CALLBACK (crypttab_monitor_on_entry_removed),
+ provider);
}
@@ -586,3 +608,21 @@ fstab_monitor_on_entry_removed (UDisksFstabMonitor *monitor,
UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data);
update_all_block_devices (provider);
}
+
+static void
+crypttab_monitor_on_entry_added (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry,
+ gpointer user_data)
+{
+ UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data);
+ update_all_block_devices (provider);
+}
+
+static void
+crypttab_monitor_on_entry_removed (UDisksCrypttabMonitor *monitor,
+ UDisksCrypttabEntry *entry,
+ gpointer user_data)
+{
+ UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (user_data);
+ update_all_block_devices (provider);
+}
diff --git a/src/udisksprivate.h b/src/udisksprivate.h
index 3cc2bf8..5dfd77e 100644
--- a/src/udisksprivate.h
+++ b/src/udisksprivate.h
@@ -22,6 +22,7 @@
#define __UDISKS_PRIVATE_H__
#include "udisksdaemontypes.h"
+#include <mntent.h>
G_BEGIN_DECLS
@@ -31,6 +32,11 @@ UDisksMount *_udisks_mount_new (dev_t dev,
UDisksFstabEntry *_udisks_fstab_entry_new (const struct mntent *mntent);
+UDisksCrypttabEntry *_udisks_crypttab_entry_new (const gchar *name,
+ const gchar *device,
+ const gchar *passphrase,
+ const gchar *options);
+
G_END_DECLS
#endif /* __UDISKS_PRIVATE_H__ */