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