PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Wed Aug 22 15:37:11 PDT 2007


 doc/spec/polkit-spec-configuration.xml |   55 ++++++++++++++++++++++
 polkit/polkit-policy-file-entry.c      |   82 ++++++++++++++++++++++++++++++++-
 polkit/polkit-policy-file-entry.h      |   20 ++++++++
 polkit/polkit-policy-file.c            |   41 +++++++++++++++-
 4 files changed, 193 insertions(+), 5 deletions(-)

New commits:
diff-tree 9924987f324953fa9e58b937dfedc1cc06ece0b3 (from 25b04730781d2ea560696f1212f661765438ad28)
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Aug 22 18:32:50 2007 -0400

    add support for annotations

diff --git a/doc/spec/polkit-spec-configuration.xml b/doc/spec/polkit-spec-configuration.xml
index a3c9046..a1cfd1a 100644
--- a/doc/spec/polkit-spec-configuration.xml
+++ b/doc/spec/polkit-spec-configuration.xml
@@ -157,6 +157,61 @@
       tool can be used to check policy files as part of the software
       release and installation process.
     </para>
+
+    <sect2>
+      <title>Annotations</title>
+      <para>
+        When declaring an Action, one can also annotate it with one or
+        more key/value pairs: 
+      </para>
+    <programlisting>
+      <![CDATA[
+  <action id="com.example.blahblaster.run-as-root">
+    <description>Run the graphical BlahBlaster application as the super user</description>
+    <message>System policy prevents the BlahBlaster application</message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.PolicyKit.run-as-superuser.path">/usr/bin/BlahBlaster</annotate>
+  </action>
+]]>
+    </programlisting>
+      <para>
+        This is useful when writing an extensible Mechanism that other
+        applications wants to use. The example declaration above is
+        dealing with an (hypothetical and setuid root) mechanism,
+        let's call it
+        <literal>run-as-superuser</literal>, that can start graphical
+        applications as uid 0. Suppose the user invokes it like this
+      </para>
+      <programlisting>
+        run-as-superuser /usr/bin/BlahBlaster
+      </programlisting>
+      <para>
+        Now, the <literal>run-as-superuser</literal> mechanism is only
+        passed a path to the application to start. In order to
+        determine if the calling user is allowed to run the given
+        application as root, we need to determine the PolicyKit Action
+        and then use libpolkit as usual to get an answer (and possibly
+        make the user authenticate to gain the privilege to run the
+        application). By using annotations,
+        the <literal>run-as-superuser</literal> mechanism can query
+        what the action is simply by searching for the Action that has
+        an annotation
+        where <literal>org.freedesktop.PolicyKit.run-as-superuser.path</literal>
+        equals the given path,
+        e.g. <literal>/usr/bin/BlahBlaster</literal>. It then becomes
+        part of the documentation for
+        the <literal>run-as-superuser</literal> program to specify
+        that applications wanting to use it, simply just needs to
+        provide a PolicyKit <literal>.policy</literal> file that
+        declares an Action with an
+        annotation <literal>org.freedesktop.PolicyKit.run-as-superuser.path</literal>
+        whose value is the path to the binary.
+      </para>
+
+    </sect2>
   </sect1>
 
   <sect1 id="beyond-defaults">
diff --git a/polkit/polkit-policy-file-entry.c b/polkit/polkit-policy-file-entry.c
index 22be5db..6f649c2 100644
--- a/polkit/polkit-policy-file-entry.c
+++ b/polkit/polkit-policy-file-entry.c
@@ -63,6 +63,7 @@ struct PolKitPolicyFileEntry
 
         char *policy_description;
         char *policy_message;
+        GHashTable *annotations;
 };
 
 extern void _polkit_policy_file_entry_set_descriptions (PolKitPolicyFileEntry *pfe,
@@ -75,12 +76,15 @@ extern PolKitPolicyDefault *_polkit_poli
 
 extern PolKitPolicyFileEntry *_polkit_policy_file_entry_new   (const char *action_id, 
                                                                PolKitResult defaults_allow_inactive,
-                                                               PolKitResult defaults_allow_active);
+                                                               PolKitResult defaults_allow_active,
+                                                               GHashTable *annotations);
 
+/* NOTE: we take ownership of the annotations object */
 extern PolKitPolicyFileEntry *
 _polkit_policy_file_entry_new   (const char *action_id, 
                                  PolKitResult defaults_allow_inactive,
-                                 PolKitResult defaults_allow_active)
+                                 PolKitResult defaults_allow_active,
+                                 GHashTable *annotations)
 {
         PolKitPolicyFileEntry *pfe;
 
@@ -93,6 +97,8 @@ _polkit_policy_file_entry_new   (const c
         if (pfe->defaults == NULL)
                 goto error;
 
+        pfe->annotations = annotations;
+
         return pfe;
 error:
         if (pfe != NULL)
@@ -186,10 +192,15 @@ polkit_policy_file_entry_unref (PolKitPo
         policy_file_entry->refcount--;
         if (policy_file_entry->refcount > 0) 
                 return;
+
         g_free (policy_file_entry->action);
+
         if (policy_file_entry->defaults != NULL)
                 polkit_policy_default_unref (policy_file_entry->defaults);
 
+        if (policy_file_entry->annotations != NULL)
+                g_hash_table_destroy (policy_file_entry->annotations);
+
         g_free (policy_file_entry->policy_description);
 
         g_free (policy_file_entry);
@@ -240,3 +251,70 @@ polkit_policy_file_entry_get_default (Po
         g_return_val_if_fail (policy_file_entry != NULL, NULL);
         return policy_file_entry->defaults;
 }
+
+typedef struct  {
+        PolKitPolicyFileEntry *pfe;
+        PolKitPolicyFileEntryAnnotationsForeachFunc cb;
+        void *user_data;
+} _AnnotationsClosure;
+
+static void
+_annotations_cb (gpointer key,
+                 gpointer value,
+                 gpointer user_data)
+{
+        _AnnotationsClosure *closure = user_data;
+        closure->cb (closure->pfe, (const char *) key, (const char *) value, closure->user_data);
+}
+
+/**
+ * polkit_policy_file_entry_annotations_foreach:
+ * @policy_file_entry: the policy file entry
+ * @cb: callback function
+ * @user_data: user data to pass to the callback function
+ *
+ * Iterate over all annotations on the policy file entry.
+ */
+void
+polkit_policy_file_entry_annotations_foreach (PolKitPolicyFileEntry *policy_file_entry,
+                                              PolKitPolicyFileEntryAnnotationsForeachFunc cb,
+                                              void *user_data)
+{
+        _AnnotationsClosure closure;
+
+        g_return_if_fail (policy_file_entry != NULL);
+        if (policy_file_entry->annotations == NULL)
+                return;
+
+        closure.pfe = policy_file_entry;
+        closure.cb = cb;
+        closure.user_data = user_data;
+
+        g_hash_table_foreach (policy_file_entry->annotations,
+                              _annotations_cb,
+                              &closure);
+}
+
+/**
+ * polkit_policy_file_entry_get_annotation:
+ * @policy_file_entry: the policy file entry
+ * @key: the key of the annotation
+ *
+ * Look of the value of a given annotation.
+ *
+ * Returns: The value of the annotation or NULL if not found.
+ */
+const char *
+polkit_policy_file_entry_get_annotation (PolKitPolicyFileEntry *policy_file_entry,
+                                         const char *key)
+{
+        const char *value;
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        g_return_val_if_fail (key != NULL, NULL);
+
+        value = NULL;
+        if (policy_file_entry->annotations != NULL) {
+                value = g_hash_table_lookup (policy_file_entry->annotations, key);
+        }
+        return value;
+}
diff --git a/polkit/polkit-policy-file-entry.h b/polkit/polkit-policy-file-entry.h
index 6e3e347..cd4d295 100644
--- a/polkit/polkit-policy-file-entry.h
+++ b/polkit/polkit-policy-file-entry.h
@@ -36,6 +36,20 @@
 struct PolKitPolicyFileEntry;
 typedef struct PolKitPolicyFileEntry PolKitPolicyFileEntry;
 
+/**
+ * PolKitPolicyFileEntryAnnotationsForeachFunc:
+ * @policy_file_entry: the policy file entry
+ * @key: key of the annotation
+ * @value: corrosponding value of the annotation
+ * @user_data: user data passed to polkit_policy_file_entry_annotations_foreach()
+ *
+ * Callback function for polkit_policy_file_entry_annotations_foreach().
+ **/
+typedef void (*PolKitPolicyFileEntryAnnotationsForeachFunc) (PolKitPolicyFileEntry *policy_file_entry,
+                                                             const char *key,
+                                                             const char *value,
+                                                             void *user_data);
+
 PolKitPolicyFileEntry *polkit_policy_file_entry_ref   (PolKitPolicyFileEntry *policy_file_entry);
 void                   polkit_policy_file_entry_unref (PolKitPolicyFileEntry *policy_file_entry);
 void                   polkit_policy_file_entry_debug (PolKitPolicyFileEntry *policy_file_entry);
@@ -46,6 +60,12 @@ PolKitPolicyDefault   *polkit_policy_fil
 const char            *polkit_policy_file_entry_get_action_description (PolKitPolicyFileEntry *policy_file_entry);
 const char            *polkit_policy_file_entry_get_action_message (PolKitPolicyFileEntry *policy_file_entry);
 
+void                   polkit_policy_file_entry_annotations_foreach (PolKitPolicyFileEntry *policy_file_entry,
+                                                                     PolKitPolicyFileEntryAnnotationsForeachFunc cb,
+                                                                     void *user_data);
+const char            *polkit_policy_file_entry_get_annotation (PolKitPolicyFileEntry *policy_file_entry,
+                                                                const char *key);
+
 
 #endif /* POLKIT_POLICY_FILE_ENTRY_H */
 
diff --git a/polkit/polkit-policy-file.c b/polkit/polkit-policy-file.c
index 0d6a9d9..299ac81 100644
--- a/polkit/polkit-policy-file.c
+++ b/polkit/polkit-policy-file.c
@@ -66,7 +66,8 @@ struct PolKitPolicyFile
 
 extern PolKitPolicyFileEntry *_polkit_policy_file_entry_new   (const char *action_id, 
                                                                PolKitResult defaults_allow_inactive,
-                                                               PolKitResult defaults_allow_active);
+                                                               PolKitResult defaults_allow_active,
+                                                               GHashTable *annotations);
 
 enum {
         STATE_NONE,
@@ -76,7 +77,8 @@ enum {
         STATE_IN_ACTION_MESSAGE,
         STATE_IN_DEFAULTS,
         STATE_IN_DEFAULTS_ALLOW_INACTIVE,
-        STATE_IN_DEFAULTS_ALLOW_ACTIVE
+        STATE_IN_DEFAULTS_ALLOW_ACTIVE,
+        STATE_IN_ANNOTATE
 };
 
 typedef struct {
@@ -103,6 +105,9 @@ typedef struct {
 
         /* the value of xml:lang for the thing we're reading in _cdata() */
         char *elem_lang;
+
+        char *annotate_key;
+        GHashTable *annotations;
 } ParserData;
 
 static void
@@ -122,6 +127,12 @@ pd_unref_action_data (ParserData *pd)
                 g_hash_table_destroy (pd->policy_messages);
                 pd->policy_messages = NULL;
         }
+        g_free (pd->annotate_key);
+        pd->annotate_key = NULL;
+        if (pd->annotations != NULL) {
+                g_hash_table_destroy (pd->annotations);
+                pd->annotations = NULL;
+        }
 }
 
 static void
@@ -174,6 +185,13 @@ _start (void *data, const char *el, cons
                                 pd->elem_lang = g_strdup (attr[1]);
                         }
                         state = STATE_IN_ACTION_MESSAGE;
+                } else if (strcmp (el, "annotate") == 0) {
+                        if (num_attr != 2 || strcmp (attr[0], "key") != 0)
+                                goto error;
+                        state = STATE_IN_ANNOTATE;
+
+                        g_free (pd->annotate_key);
+                        pd->annotate_key = g_strdup (attr[1]);
                 }
                 break;
         case STATE_IN_ACTION_DESCRIPTION:
@@ -190,6 +208,8 @@ _start (void *data, const char *el, cons
                 break;
         case STATE_IN_DEFAULTS_ALLOW_ACTIVE:
                 break;
+        case STATE_IN_ANNOTATE:
+                break;
         default:
                 break;
         }
@@ -243,6 +263,14 @@ _cdata (void *data, const char *s, int l
                 if (!polkit_result_from_string_representation (str, &pd->defaults_allow_active))
                         goto error;
                 break;
+
+        case STATE_IN_ANNOTATE:
+                if (pd->annotations == NULL) {
+                        pd->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+                }
+                g_hash_table_insert (pd->annotations, g_strdup (pd->annotate_key), g_strdup (str));
+                break;
+
         default:
                 break;
         }
@@ -328,9 +356,13 @@ _end (void *data, const char *el)
                 const char *policy_message;
                 PolKitPolicyFileEntry *pfe;
 
+                /* NOTE: caller takes ownership of the annotations object */
                 pfe = _polkit_policy_file_entry_new (pd->action_id, 
                                                      pd->defaults_allow_inactive,
-                                                     pd->defaults_allow_active);
+                                                     pd->defaults_allow_active,
+                                                     pd->annotations);
+                pd->annotations = NULL;
+
                 if (pfe == NULL)
                         goto error;
 
@@ -367,6 +399,9 @@ _end (void *data, const char *el)
         case STATE_IN_DEFAULTS_ALLOW_ACTIVE:
                 state = STATE_IN_DEFAULTS;
                 break;
+        case STATE_IN_ANNOTATE:
+                state = STATE_IN_ACTION;
+                break;
         default:
                 break;
         }


More information about the hal-commit mailing list