hal: Branch 'master' - 3 commits

David Zeuthen david at kemper.freedesktop.org
Tue Jun 12 11:23:34 PDT 2007


 doc/spec/hal-spec-interfaces.xml |   48 +++++++++
 doc/spec/hal-spec-properties.xml |    3 
 policy/hal-device-file.policy    |   14 +-
 tools/hal-acl-tool.c             |  192 +++++++++++++++++++++++++++++++++------
 4 files changed, 221 insertions(+), 36 deletions(-)

New commits:
diff-tree e55f40c21abbb207ebb4812d194bd1e131d6fb4a (from b3c16b648f49760498de3aede818e7024620b96f)
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue Jun 12 14:23:38 2007 -0400

    change PolicyKit policy such only active sessions have access to devices
    
    We make an exception for optical drives; even inactive users can access
    these - think CD burning and coasters.

diff --git a/policy/hal-device-file.policy b/policy/hal-device-file.policy
index 4eccbfb..4660792 100644
--- a/policy/hal-device-file.policy
+++ b/policy/hal-device-file.policy
@@ -29,7 +29,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -41,7 +41,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -65,7 +65,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -77,7 +77,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -89,7 +89,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -101,7 +101,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
@@ -113,7 +113,7 @@ file are instantly applied.
       <defaults>
         <allow_remote_inactive>no</allow_remote_inactive>
         <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>yes</allow_local_inactive>
+        <allow_local_inactive>no</allow_local_inactive>
         <allow_local_active>yes</allow_local_active>
       </defaults>
     </policy>
diff-tree b3c16b648f49760498de3aede818e7024620b96f (from a157eb506a950fb1bc2d944c5ef3e7ea7b3d52bb)
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue Jun 12 14:22:39 2007 -0400

    add the code in hal-acl-tool to emit ACLAdded and ACLRemoved signals

diff --git a/tools/hal-acl-tool.c b/tools/hal-acl-tool.c
index 5872497..d8d7471 100644
--- a/tools/hal-acl-tool.c
+++ b/tools/hal-acl-tool.c
@@ -38,6 +38,7 @@
 /* How this works (or "An introduction to this code")
  *
  * - all ACL's granted by this tool is kept in /var/lib/hal/acl-list
+ *   See below for the format.
  *
  * - every time tool is launched we read this file and keep each line
  *   as an ACLCurrent instance. These are kept in a list.
@@ -53,6 +54,7 @@
  *     - ACL's to be added are appended to the list and add -> TRUE
  *   - we then compute the argument vector to setfacl(1) for adding /
  *     removing ACL's
+ *   - we emit signals ACLAdded and ACLRemoved
  *   - if setfacl(1) succeeds (rc == 0) then we write the new acl-current-list
  *
  * Notably, the HAL daemon will invoke us with --reconfigure on every
@@ -84,24 +86,24 @@
  * of ACL's that have been set by HAL and as such are currently
  * applied
  *
- *   <device-file>    <type>    <uid-or-gid>
+ *   <device-file>    <udi>    <type>    <uid-or-gid>
  *
  * where <type>='u'|'g' for respectively uid and gid (the spacing represent tabs).
  *
  * Example:
  *
- *   /dev/snd/controlC0    u    500
- *   /dev/snd/controlC0    u    501
- *   /dev/snd/controlC0    g    1001
+ *   /dev/snd/controlC0    /org/freedesktop/Hal/devices/pci_8086_27d8_alsa_control__1    u    500
+ *   /dev/snd/controlC0    /org/freedesktop/Hal/devices/pci_8086_27d8_alsa_control__1    u    501
+ *   /dev/snd/controlC0    /org/freedesktop/Hal/devices/pci_8086_27d8_alsa_control__1    g    1001
  */
 typedef struct ACLCurrent_s {
+        char *udi;
 	char *device;
 	int type;
 	union {
 		uid_t uid;
 		gid_t gid;
 	} v;
-
 	gboolean remove;
 	gboolean add;
 } ACLCurrent;
@@ -114,9 +116,39 @@ enum {
 
 static PolKitContext *pk_context = NULL;
 
+static LibHalContext *hal_ctx = NULL;
+
+static gboolean in_device_added = FALSE;
+
+static gboolean
+ensure_hal_ctx (void)
+{
+        gboolean ret;
+	DBusError error;
+
+        ret = FALSE;
+        if (hal_ctx != NULL) {
+                ret = TRUE;
+                goto out;
+        }
+
+	dbus_error_init (&error);
+	if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		printf ("%d: Cannot connect to hald: %s: %s\n", getpid (), error.name, error.message);
+		LIBHAL_FREE_DBUS_ERROR (&error);
+                goto out;
+	}
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+
 static void
 hal_acl_free (ACLCurrent *ha)
 {
+        g_free (ha->udi);
 	g_free (ha->device);
 	g_free (ha);
 }
@@ -138,6 +170,7 @@ acl_apply_changes (GSList *new_acl_list,
 	gboolean ret;
 	GError *error = NULL;
 	int exit_status;
+        gboolean messages_were_sent = FALSE;
 
 	ret = FALSE;
 
@@ -159,7 +192,6 @@ acl_apply_changes (GSList *new_acl_list,
 						(ha->type == HAL_ACL_UID) ? 'u' : 'g',
 						(ha->type == HAL_ACL_UID) ? ha->v.uid : ha->v.gid,
 						ha->device);
-			continue;
 		}
 
 		if (ha->add) {
@@ -170,13 +202,17 @@ acl_apply_changes (GSList *new_acl_list,
 						(ha->type == HAL_ACL_UID) ? 'u' : 'g',
 						(ha->type == HAL_ACL_UID) ? ha->v.uid : ha->v.gid,
 						ha->device);
+
 		}
 
-		g_string_append_printf (str, 
-					"%s\t%c\t%d\n",
-					ha->device,
-					(ha->type == HAL_ACL_UID) ? 'u' : 'g',
-					(ha->type == HAL_ACL_UID) ? ha->v.uid : ha->v.gid);
+                if (!ha->remove) {
+                        g_string_append_printf (str, 
+                                                "%s\t%s\t%c\t%d\n",
+                                                ha->device,
+                                                ha->udi,
+                                                (ha->type == HAL_ACL_UID) ? 'u' : 'g',
+                                                (ha->type == HAL_ACL_UID) ? ha->v.uid : ha->v.gid);
+                }
 	}
 	new_acl_file_contents = g_string_free (str, FALSE);
 
@@ -227,6 +263,79 @@ acl_apply_changes (GSList *new_acl_list,
 			     strlen (new_acl_file_contents),
 			     NULL);
 
+        /* now that we've added/removed ACL's: emit D-Bus signals.. we need to do this _after_ 
+         * having updated the ACL - to avoid possible race conditions 
+         */
+        messages_were_sent = FALSE;
+	for (i = new_acl_list; i != NULL; i = g_slist_next (i)) {
+		ACLCurrent *ha = (ACLCurrent *) i->data;
+
+                /* emit signal ACLGranted or ACLRemoved - but avoid doing it on device add because the device
+                 * object doesn't exist just yet
+                 */
+                if (ha->type == HAL_ACL_UID && ha->udi != NULL && (ha->add || ha->remove) && !in_device_added) {
+                        DBusMessage *message;
+                        DBusConnection *connection;
+
+                        printf ("Emmitting %s for udi %s, uid %d\n", 
+                                ha->add ? "ACLAdded" : "ACLRemoved",
+                                ha->udi,
+                                ha->v.uid);
+
+                        if (!ensure_hal_ctx ()) {
+				printf ("%d: cannot get libhal context\n", getpid ());
+                                goto no_dbus_signal;
+                        }
+
+                        connection = libhal_ctx_get_dbus_connection (hal_ctx);
+                        if (connection == NULL) {
+				printf ("%d: cannot get D-Bus connection\n", getpid());
+                                goto no_dbus_signal;
+                        }
+
+                        message = dbus_message_new_signal (ha->udi,
+                                                           "org.freedesktop.Hal.Device.AccessControl",
+                                                           ha->add ? "ACLAdded" : "ACLRemoved");
+                        if (message == NULL) {
+				printf ("%d: cannot create message\n", getpid());
+                                goto no_dbus_signal;
+                        }
+
+                        if (!dbus_message_append_args (message, 
+                                                       DBUS_TYPE_UINT32, &(ha->v.uid),
+                                                       DBUS_TYPE_INVALID)) {
+				printf ("%d: cannot append to message\n", getpid());
+                                dbus_message_unref (message);
+                                goto no_dbus_signal;
+                        }
+
+                        if (!dbus_connection_send (connection, message, NULL)) {
+				printf ("%d: cannot send message\n", getpid());
+                                dbus_message_unref (message);
+                                goto no_dbus_signal;
+                        }
+                        dbus_message_unref (message);
+
+                        messages_were_sent = TRUE;
+                }
+
+        no_dbus_signal:
+                ;
+        }
+
+        /* apparently we need to flush the signals - otherwise they
+         * may be lost because we're exiting right after this
+         */
+        if (messages_were_sent) {
+                if (ensure_hal_ctx ()) {
+                        DBusConnection *connection;
+                        connection = libhal_ctx_get_dbus_connection (hal_ctx);
+                        if (connection != NULL) {
+                                dbus_connection_flush (connection);
+                        }
+                }
+        }
+
 	ret = TRUE;
 
 out:
@@ -261,27 +370,45 @@ get_current_acl_list (GSList **l)
 		ACLCurrent *ha;
 		char **val;
 		char *endptr;
+                gboolean old_format = FALSE;
+                int n;
+
+                /* supporting the old format is important; because at hald startup we call hal-acl-tool --remove-all */
 
 		ha = g_new0 (ACLCurrent, 1);
 		val = g_strsplit(buf, "\t", 0);
-		if (g_strv_length (val) != 3) {
-			printf ("Line is malformed: '%s'\n", buf);
-			g_strfreev (val);
-			goto out;
-		}
+		if (g_strv_length (val) == 3) {
+			printf ("Line is from old format: '%s'\n", buf);
+                        old_format = TRUE;
+		} else {
+                        if (g_strv_length (val) != 4) {
+                                printf ("Line is malformed: '%s'\n", buf);
+                                g_strfreev (val);
+                                goto out;
+                        }
+                }
+
+                n = 0;
 
-		ha->device = g_strdup (val[0]);
-		if (strcmp (val[1], "u") == 0) {
+		ha->device = g_strdup (val[n++]);
+
+                if (old_format) {
+                        ha->udi = NULL;
+                } else {
+                        ha->udi = g_strdup (val[n++]);
+                }
+
+		if (strcmp (val[n], "u") == 0) {
 			ha->type = HAL_ACL_UID;
-			ha->v.uid = strtol (val[2], &endptr, 10);
+			ha->v.uid = strtol (val[n + 1], &endptr, 10);
 			if (*endptr != '\0' && *endptr != '\n') {
 				printf ("Line is malformed: '%s'\n", buf);
 				g_strfreev (val);
 				goto out;
 			}
-		} else if (strcmp (val[1], "g") == 0) {
+		} else if (strcmp (val[n], "g") == 0) {
 			ha->type = HAL_ACL_GID;
-			ha->v.gid = strtol (val[2], &endptr, 10);
+			ha->v.gid = strtol (val[n + 1], &endptr, 10);
 			if (*endptr != '\0' && *endptr != '\n') {
 				printf ("Line is malformed: '%s'\n", buf);
 				g_strfreev (val);
@@ -762,11 +889,19 @@ acl_compute_changes (GSList *afd_list, g
 		 */
 		for (j = afd->uid; j != NULL; j = g_slist_next (j)) {
 			ACLCurrent *ha;
+                        uid_t uid;
+
+                        uid = GPOINTER_TO_INT (j->data);
+                        /* never grant ACL's to the super user */
+                        if (uid == 0)
+                                continue;
+
 			ha = g_new0 (ACLCurrent, 1);
 			ha->add = TRUE;
 			ha->device = g_strdup (afd->device);
+                        ha->udi = g_strdup (afd->udi);
 			ha->type = HAL_ACL_UID;
-			ha->v.uid = GPOINTER_TO_INT (j->data);
+			ha->v.uid = uid;
 			current_acl_list = g_slist_prepend (current_acl_list, ha);
 		}
 		for (j = afd->gid; j != NULL; j = g_slist_next (j)) {
@@ -774,6 +909,7 @@ acl_compute_changes (GSList *afd_list, g
 			ha = g_new0 (ACLCurrent, 1);
 			ha->add = TRUE;
 			ha->device = g_strdup (afd->device);
+                        ha->udi = g_strdup (afd->udi);
 			ha->type = HAL_ACL_GID;
 			ha->v.gid = GPOINTER_TO_INT (j->data);
 			current_acl_list = g_slist_prepend (current_acl_list, ha);
@@ -811,6 +947,8 @@ acl_device_added (void)
 	GSList *afd_list = NULL;
 	ACLForDevice *afd = NULL;
 
+        in_device_added = TRUE;
+
 	/* we can avoid round-trips to the HAL daemon by using what's in the environment */
 
 	if ((udi = getenv ("UDI")) == NULL)
@@ -907,18 +1045,14 @@ acl_reconfigure_all (void)
 	int num_devices;
 	char **udis;
 	DBusError error;
-	LibHalContext *hal_ctx;
 	GSList *afd_list = NULL;
 
 	printf ("%d: reconfiguring all ACL's\n", getpid ());
 
-	dbus_error_init (&error);
-	if ((hal_ctx = libhal_ctx_init_direct (&error)) == NULL) {
-		printf ("%d: Cannot connect to hald: %s: %s\n", getpid (), error.name, error.message);
-		LIBHAL_FREE_DBUS_ERROR (&error);
-		goto out;
-	}
+        if (!ensure_hal_ctx ())
+                goto out;
 
+	dbus_error_init (&error);
 	if ((udis = libhal_find_device_by_capability (hal_ctx, "access_control", &num_devices, &error)) == NULL) {
 		printf ("%d: Cannot get list of devices of capability 'acl'\n", getpid ());
 		goto out;
diff-tree a157eb506a950fb1bc2d944c5ef3e7ea7b3d52bb (from 89d9fbf8cef868f4a3535ff60a1055c95323ccde)
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue Jun 12 14:21:50 2007 -0400

    add suport for ACLAdded and ACLRemoved signals on Device.AccessControl if
    
    Both signals have a single parameter; an unsigned 32-bit integer being
    the UNIX user id.

diff --git a/doc/spec/hal-spec-interfaces.xml b/doc/spec/hal-spec-interfaces.xml
index a8f9e3d..2511011 100644
--- a/doc/spec/hal-spec-interfaces.xml
+++ b/doc/spec/hal-spec-interfaces.xml
@@ -1233,6 +1233,54 @@ $ dbus-send --system --print-reply --des
 
   </sect1>
 
+  <sect1 id="interface-device-accesscontrol">
+    <title>org.freedesktop.Hal.Device.AccessControl interface</title>
+    <para>
+      This interface provides a mechanism for discovering when an ACL
+      is added or removed for a device file. The following signals are
+      available:
+    </para>
+
+    <informaltable>
+      <tgroup cols="2">
+        <thead>
+          <row>
+            <entry>Method</entry>
+            <entry>Parameters</entry>
+            <entry>Description</entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry>ACLAdded</entry>
+            <entry>UInt unix_user_id</entry>
+            <entry>
+              Emitted when an ACL have been added for a UNIX user on a
+              device object with the <literal>access_control</literal>
+              capability.
+            </entry>
+          </row>
+
+          <row>
+            <entry>ACLRemoved</entry>
+            <entry>UInt unix_user_id</entry>
+            <entry>
+              Emitted when an ACL have been removed for a UNIX user on
+              a device object with
+              the <literal>access_control</literal> capability.
+            </entry>
+          </row>
+
+        </tbody>
+      </tgroup>
+    </informaltable>
+
+    <para>
+      This interface does not export any methods.
+    </para>
+
+  </sect1>
+
 <!--
   <sect1 id="interface-device-foo">
     <title>org.freedesktop.Hal.Device.Foo interface</title>
diff --git a/doc/spec/hal-spec-properties.xml b/doc/spec/hal-spec-properties.xml
index c99da84..730f826 100644
--- a/doc/spec/hal-spec-properties.xml
+++ b/doc/spec/hal-spec-properties.xml
@@ -6689,6 +6689,9 @@ org.freedesktop.Hal.Device.Volume.method
           </tbody>
         </tgroup>
       </informaltable>
+      <para>
+        See also <xref linkend="interface-device-accesscontrol"/>.
+      </para>
     </sect2>
   </sect1>
 


More information about the hal-commit mailing list