summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2012-05-24 14:51:46 -0400
committerDavid Zeuthen <davidz@redhat.com>2012-05-24 14:51:46 -0400
commit0e85f07781f8eab9670e06cee32b38657e3b62ce (patch)
tree49d2f57f45e52265ab2d678803fa2ade40cde31e
parent2ec9e681e0ee17bcc60a0724b201b2e19b573abb (diff)
downloadpolkit-0e85f07781f8eab9670e06cee32b38657e3b62ce.tar.gz
Combine action and details parameters
This also removes the ability to change detail parameters which is actually a good thing. If we later need a way to change the authentication message, we can always add something like polkit.addAuthenticationMessageRule() so the user can register a function returning a string. Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--docs/man/polkit.xml379
-rw-r--r--src/polkitbackend/50-default.rules2
-rw-r--r--src/polkitbackend/init.js26
-rw-r--r--src/polkitbackend/polkitbackendjsauthority.c106
-rw-r--r--test/data/etc/polkit-1/rules.d/10-testing.rules83
-rw-r--r--test/data/etc/polkit-1/rules.d/15-testing.rules19
-rw-r--r--test/data/usr/share/polkit-1/rules.d/10-testing.rules12
-rw-r--r--test/data/usr/share/polkit-1/rules.d/20-testing.rules22
-rw-r--r--test/polkitbackend/test-polkitbackendjsauthority.c85
9 files changed, 382 insertions, 352 deletions
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index de4bb4a..9718541 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -484,120 +484,196 @@ System Context | |
programming language and interface with <command>polkitd</command>
through the global
<literal>polkit</literal> object (of type <type>Polkit</type>).
- The following methods are available:
</para>
- <funcsynopsis>
- <funcprototype>
- <?dbhtml funcsynopsis-style='ansi'?>
- <funcdef>void <function>addRule</function></funcdef>
- <paramdef>string <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <funcsynopsis>
- <funcprototype>
- <?dbhtml funcsynopsis-style='ansi'?>
- <funcdef>void <function>addAdminRule</function></funcdef>
- <paramdef>string[] <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <funcsynopsis>
- <funcprototype>
- <?dbhtml funcsynopsis-style='ansi'?>
- <funcdef>void <function>log</function></funcdef>
- <paramdef>string <parameter>message</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
-
- <funcsynopsis>
- <funcprototype>
- <?dbhtml funcsynopsis-style='ansi'?>
- <funcdef>string <function>spawn</function></funcdef>
- <paramdef>string[] <parameter>argv</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
+ <refsect2 id="polkit-rules-actions">
+ <title>The <type>Polkit</type> type</title>
- <para>
- The <function>addRule()</function> method is used for adding a
- function that may be called whenever an authorization check for
- <parameter>action</parameter>, <parameter>subject</parameter>
- and <parameter>details</parameter> is performed. Functions are
- called in the order they have been added until one of the
- functions returns a value. Hence, to add an authorization rule
- that is processed before other rules, put it in a file in
- <filename class='directory'>/etc/polkit-1/rules.d</filename>
- with a name that sorts before other rules files, for example
- <filename>00-early-checks.rules</filename>. Each function should
- return one of the values <literal>"no"</literal>,
- <literal>"yes"</literal>, <literal>"auth_self"</literal>,
- <literal>"auth_self_keep"</literal>,
- <literal>"auth_admin"</literal>,
- <literal>"auth_admin_keep"</literal> as defined above. If the
- function returns <constant>null</constant>,
- <constant>undefined</constant> or does not return a value at
- all, the next function is tried.
- </para>
+ <para>
+ The following methods are available on the <literal>polkit</literal> object:
+ </para>
- <para>
- The <function>addAdminRule()</function> method is used for
- adding a function may be called whenever administrator
- authentication is required. The function is used to specify what
- identies may be used for administrator authentication for the
- authorization check identified by <parameter>action</parameter>,
- <parameter>subject</parameter> and
- <parameter>details</parameter>. Functions added are called in
- the order they have been added until one of the functions
- returns a value. Each function should return an array of strings
- where each string is of the form
- <literal>"unix-group:&lt;group&gt;"</literal>,
- <literal>"unix-netgroup:&lt;netgroup&gt;"</literal> or
- <literal>"unix-user:&lt;user&gt;"</literal>. If the function
- returns <constant>null</constant>,
- <constant>undefined</constant> or does not return a value at
- all, the next function is tried.
- </para>
+ <funcsynopsis>
+ <funcprototype>
+ <?dbhtml funcsynopsis-style='ansi'?>
+ <funcdef>void <function>addRule</function></funcdef>
+ <paramdef>string <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>) {...}</paramdef>
+ </funcprototype>
+ </funcsynopsis>
- <para>
- There is no guarantee that a function registered with
- <function>addRule()</function> or
- <function>addAdminRule()</function> is ever called - for example
- an early rules file could register a function that always return
- a value, hence ensuring that functions added later are never
- called.
- </para>
+ <funcsynopsis>
+ <funcprototype>
+ <?dbhtml funcsynopsis-style='ansi'?>
+ <funcdef>void <function>addAdminRule</function></funcdef>
+ <paramdef>string[] <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>) {...}</paramdef>
+ </funcprototype>
+ </funcsynopsis>
- <para>
- If user-provided code takes a long time to execute an exception
- will be thrown which normally results in the function being
- terminated (the current limit is 15 seconds). This is used to
- catch runaway scripts.
- </para>
+ <funcsynopsis>
+ <funcprototype>
+ <?dbhtml funcsynopsis-style='ansi'?>
+ <funcdef>void <function>log</function></funcdef>
+ <paramdef>string <parameter>message</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
- <para>
- The <function>log()</function> method writes the given
- <parameter>message</parameter> to the system logger. Log entries
- are emitted using the <constant>LOG_AUTHPRIV</constant> flag
- meaning that the log entries usually ends up in the file
- <filename>/var/log/secure</filename>. The
- <function>log()</function> method is usually only used when
- debugging rules.
- </para>
+ <funcsynopsis>
+ <funcprototype>
+ <?dbhtml funcsynopsis-style='ansi'?>
+ <funcdef>string <function>spawn</function></funcdef>
+ <paramdef>string[] <parameter>argv</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
- <para>
- The <function>spawn()</function> method spawns an external
- helper identified by the argument vector
- <parameter>argv</parameter> and waits for it to terminate. If an
- error occurs or the helper doesn't exit normally with exit code
- 0, an exception is thrown. If the helper does not exit within 10
- seconds it is killed. Otherwise, the program's
- <emphasis>standard output</emphasis> is returned as a string.
- The <function>spawn()</function> method should be used sparingly
- as helpers may take a very long or indeterminate amount of time
- to complete and no other authorization check can be handled
- while the helper is running.
- </para>
+ <para>
+ The <function>addRule()</function> method is used for adding a
+ function that may be called whenever an authorization check for
+ <parameter>action</parameter> and <parameter>subject</parameter>
+ is performed. Functions are
+ called in the order they have been added until one of the
+ functions returns a value. Hence, to add an authorization rule
+ that is processed before other rules, put it in a file in
+ <filename class='directory'>/etc/polkit-1/rules.d</filename>
+ with a name that sorts before other rules files, for example
+ <filename>00-early-checks.rules</filename>. Each function should
+ return one of the values <literal>"no"</literal>,
+ <literal>"yes"</literal>, <literal>"auth_self"</literal>,
+ <literal>"auth_self_keep"</literal>,
+ <literal>"auth_admin"</literal>,
+ <literal>"auth_admin_keep"</literal> as defined above. If the
+ function returns <constant>null</constant>,
+ <constant>undefined</constant> or does not return a value at
+ all, the next function is tried.
+ </para>
+
+ <para>
+ The <function>addAdminRule()</function> method is used for
+ adding a function may be called whenever administrator
+ authentication is required. The function is used to specify what
+ identies may be used for administrator authentication for the
+ authorization check identified by <parameter>action</parameter>
+ and <parameter>subject</parameter>. Functions added are called in
+ the order they have been added until one of the functions
+ returns a value. Each function should return an array of strings
+ where each string is of the form
+ <literal>"unix-group:&lt;group&gt;"</literal>,
+ <literal>"unix-netgroup:&lt;netgroup&gt;"</literal> or
+ <literal>"unix-user:&lt;user&gt;"</literal>. If the function
+ returns <constant>null</constant>,
+ <constant>undefined</constant> or does not return a value at
+ all, the next function is tried.
+ </para>
+
+ <para>
+ There is no guarantee that a function registered with
+ <function>addRule()</function> or
+ <function>addAdminRule()</function> is ever called - for example
+ an early rules file could register a function that always return
+ a value, hence ensuring that functions added later are never
+ called.
+ </para>
+
+ <para>
+ If user-provided code takes a long time to execute an exception
+ will be thrown which normally results in the function being
+ terminated (the current limit is 15 seconds). This is used to
+ catch runaway scripts.
+ </para>
+
+ <para>
+ The <function>spawn()</function> method spawns an external
+ helper identified by the argument vector
+ <parameter>argv</parameter> and waits for it to terminate. If an
+ error occurs or the helper doesn't exit normally with exit code
+ 0, an exception is thrown. If the helper does not exit within 10
+ seconds it is killed. Otherwise, the program's
+ <emphasis>standard output</emphasis> is returned as a string.
+ The <function>spawn()</function> method should be used sparingly
+ as helpers may take a very long or indeterminate amount of time
+ to complete and no other authorization check can be handled
+ while the helper is running.
+ </para>
+
+ <para>
+ The <function>log()</function> method writes the given
+ <parameter>message</parameter> to the system logger prefixed
+ with the JavaScript filename and line number. Log entries are
+ emitted using the <constant>LOG_AUTHPRIV</constant> flag meaning
+ that the log entries usually ends up in the file
+ <filename>/var/log/secure</filename>. The
+ <function>log()</function> method is usually only used when
+ debugging rules. The <type>Action</type> and
+ <type>Subject</type> types has suitable
+ <function>toString()</function> methods defined for easy
+ logging, for example,
+ </para>
+ <programlisting><![CDATA[
+polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.policykit.exec") {
+ polkit.log("action=" + action);
+ polkit.log("subject=" + subject);
+ }
+});
+]]></programlisting>
+ <para>
+ will produce the following when the user runs 'pkexec bash -i' from a shelll:
+ </para>
+ <programlisting><![CDATA[
+May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:3: action=[Action id='org.freedesktop.policykit.exec' command_line='/usr/bin/bash -i' program='/usr/bin/bash' user_full='root (root)' user='root']
+May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:4: subject=[Subject pid=1352 user='davidz' groups=davidz,wheel, seat='seat0' session='1' local=true active=true]
+]]></programlisting>
+
+ </refsect2>
+
+ <refsect2 id="polkit-rules-actions">
+ <title>The <type>Action</type> type</title>
+
+ <para>
+ The <parameter>action</parameter> parameter passed to user
+ functions is an object with information about the action
+ being checked. It is of type <type>Action</type> and has
+ the following attribute:
+ </para>
+
+ <variablelist id="polkit-js-action-attributes">
+ <varlistentry>
+ <term><type>string</type> id</term>
+ <listitem>
+ <para>
+ The action identifier, for example
+ <emphasis>org.freedesktop.policykit.exec</emphasis>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ The following methods are available on the <type>Action</type> type:
+ </para>
+
+ <funcsynopsis>
+ <funcprototype>
+ <?dbhtml funcsynopsis-style='ansi'?>
+ <funcdef>string <function>lookup</function></funcdef>
+ <paramdef>string <parameter>key</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+
+ <para>
+ The <function>lookup()</function> method is used to lookup the
+ polkit variables passed from the mechanism. For example, the
+ <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+ mechanism sets the variable <parameter>program</parameter>
+ which can be obtained in Javascript using the expression
+ <literal>action.lookup("program")</literal>. If there is
+ no value for the given <parameter>key</parameter>,
+ then <constant>undefined</constant> is returned.
+ </para>
+ <para>
+ Consult the documentation for each mechanism for what
+ variables are available for each action.
+ </para>
+ </refsect2>
<refsect2 id="polkit-rules-subject">
<title>The <type>Subject</type> type</title>
@@ -700,52 +776,6 @@ System Context | |
<function>isInNetGroup()</function> can be used to check if
the subject is in a given netgroup.
</para>
-
- </refsect2>
-
- <refsect2 id="polkit-rules-details">
- <title>The <type>Details</type> type</title>
-
- <para>
- The <parameter>details</parameter> parameter passed to user
- functions is an object with more information about the action
- being checked. It is of type <type>Details</type> and has
- details being set by the mechanism as attributes. For example,
- the <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
- mechanism sets the variable <parameter>program</parameter>
- which can be obtained in Javascript using the expression
- <literal>details["program"]</literal>. Consult the
- documentation for each mechanism for what variables are
- available for each action.
- </para>
-
- <para>
- The <parameter>details</parameter> also has the following
- well-known attributes:
- </para>
- <variablelist>
- <varlistentry>
- <term><emphasis>polkit.message</emphasis></term>
- <listitem>
- <para>
- The message to show in the authentication dialog (only
- used if authentication is needed). Its initial value is
- taken from the action declaration (the <literal>message</literal> element in the <filename
- class='extension'>.policy</filename> file) but the value
- can be overridden by the mechanism setting this key in
- the <parameter>details</parameter> passed when doing the
- <link
- linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
- call.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- Note that a rule can set the
- <parameter>polkit.message</parameter> attribute to change the
- message shown in the authentication dialog.
- </para>
</refsect2>
<refsect2 id="polkit-rules-examples">
@@ -757,8 +787,8 @@ System Context | |
users:
</para>
<programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
- if (action == "org.freedesktop.accounts.user-administration" &&
+polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.accounts.user-administration" &&
subject.isInGroup("admin")) {
return "yes";
}
@@ -769,20 +799,21 @@ polkit.addRule(function(action, subject, details) {
Define administrative users to be the users in the <literal>wheel</literal> group:
</para>
<programlisting><![CDATA[
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
return ["unix-group:wheel"];
});
]]></programlisting>
<para>
Forbid users in group <literal>children</literal> to change
- hostname configuration (that is, any action starting with
- <literal>org.freedesktop.hostname1.</literal>) and allow
- anyone else to do it after authenticating as themselves:
+ hostname configuration (that is, any action with an identifier
+ starting with <literal>org.freedesktop.hostname1.</literal>)
+ and allow anyone else to do it after authenticating as
+ themselves:
</para>
<programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
- if (action.indexOf("org.freedesktop.hostname1.") == 0) {
+polkit.addRule(function(action, subject) {
+ if (action.id.indexOf("org.freedesktop.hostname1.") == 0) {
if (subject.isInGroup("children")) {
return "no";
} else {
@@ -796,8 +827,8 @@ polkit.addRule(function(action, subject, details) {
Run an external helper to determine if the current user may reboot the system:
</para>
<programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
- if (action.indexOf("org.freedesktop.login1.reboot") == 0) {
+polkit.addRule(function(action, subject) {
+ if (action.id.indexOf("org.freedesktop.login1.reboot") == 0) {
try {
// user-may-reboot exits with succeess (exit code 0)
// only if the passed username is authorized
@@ -813,17 +844,15 @@ polkit.addRule(function(action, subject, details) {
]]></programlisting>
<para>
- The following example showcases two things
+ The following example shows how the authorization decision
+ can depend on variables passed by the
+ <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+ mechanism:
</para>
- <itemizedlist mark='opencircle' spacing='compact'>
- <listitem><para>how the authorization decision can depend on variables passed by the mechanism</para></listitem>
- <listitem><para>how to override the message shown in the authentication dialog</para></listitem>
- </itemizedlist>
<programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
- if (action == "org.freedesktop.policykit.exec" &&
- details["program"] == "/usr/bin/cat") {
- details["polkit.message"] = "Achtung! You need to authenticate as yourself to cat(1) files!";
+polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.policykit.exec" &&
+ action.lookup("program") == "/usr/bin/cat") {
return "auth_self";
}
});
@@ -843,10 +872,10 @@ polkit.addRule(function(action, subject, details) {
// Allow users in group 'engineers' to perform any operation on
// some drives without having to authenticate
//
-polkit.addRule(function(action, subject, details) {
- if (action.indexOf("org.freedesktop.udisks2.") == 0 &&
- details["drive.vendor"] == "SEAGATE" &&
- details["drive.model"] == "ST3300657SS" &&
+polkit.addRule(function(action, subject) {
+ if (action.id.indexOf("org.freedesktop.udisks2.") == 0 &&
+ action.lookup("drive.vendor") == "SEAGATE" &&
+ action.lookup("drive.model") == "ST3300657SS" &&
subject.isInGroup("engineers")) {
return "yes";
}
diff --git a/src/polkitbackend/50-default.rules b/src/polkitbackend/50-default.rules
index 9d3c33d..f427ae1 100644
--- a/src/polkitbackend/50-default.rules
+++ b/src/polkitbackend/50-default.rules
@@ -7,6 +7,6 @@
// See the polkit(8) man page for more information
// about configuring polkit.
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
return ["unix-group:wheel"];
});
diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 29f13fc..16862d4 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -1,14 +1,17 @@
/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
-function Details() {
+function Action() {
+ this.lookup = function(name) {
+ return this["_detail_" + name];
+ },
+
this.toString = function() {
- var ret = "[Details";
+ var ret = "[Action id='" + this.id + "'";
for (var i in this) {
- if (typeof this[i] != "function") {
- if (typeof this[i] == "string")
- ret += " " + i + "='" + this[i] + "'";
- else
- ret += " " + i + "=" + this[i];
+ if (i.indexOf("_detail_") == 0) {
+ var key = i.substr(8);
+ var value = this[i];
+ ret += " " + key + "='" + value + "'";
}
}
ret += "]";
@@ -17,7 +20,6 @@ function Details() {
};
function Subject() {
-
this.isInGroup = function(group) {
for (var n = 0; n < this.groups.length; n++) {
if (this.groups[n] == group)
@@ -47,11 +49,11 @@ function Subject() {
polkit._adminRuleFuncs = [];
polkit.addAdminRule = function(callback) {this._adminRuleFuncs.push(callback);};
-polkit._runAdminRules = function(action, subject, details) {
+polkit._runAdminRules = function(action, subject) {
var ret = null;
for (var n = 0; n < this._adminRuleFuncs.length; n++) {
var func = this._adminRuleFuncs[n];
- var func_ret = func(action, subject, details);
+ var func_ret = func(action, subject);
if (func_ret) {
ret = func_ret;
break
@@ -62,11 +64,11 @@ polkit._runAdminRules = function(action, subject, details) {
polkit._ruleFuncs = [];
polkit.addRule = function(callback) {this._ruleFuncs.push(callback);};
-polkit._runRules = function(action, subject, details) {
+polkit._runRules = function(action, subject) {
var ret = null;
for (var n = 0; n < this._ruleFuncs.length; n++) {
var func = this._ruleFuncs[n];
- var func_ret = func(action, subject, details);
+ var func_ret = func(action, subject);
if (func_ret) {
ret = func_ret;
break
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index cc805e8..d71f85f 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -806,10 +806,11 @@ subject_to_jsval (PolkitBackendJsAuthority *authority,
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
-details_to_jsval (PolkitBackendJsAuthority *authority,
- PolkitDetails *details,
- jsval *out_jsval,
- GError **error)
+action_and_details_to_jsval (PolkitBackendJsAuthority *authority,
+ const gchar *action_id,
+ PolkitDetails *details,
+ jsval *out_jsval,
+ GError **error)
{
gboolean ret = FALSE;
jsval ret_jsval;
@@ -818,8 +819,7 @@ details_to_jsval (PolkitBackendJsAuthority *authority,
gchar **keys;
guint n;
- src = "new Details();";
-
+ src = "new Action();";
if (!JS_EvaluateScript (authority->priv->cx,
authority->priv->js_global,
src, strlen (src),
@@ -831,18 +831,18 @@ details_to_jsval (PolkitBackendJsAuthority *authority,
}
obj = JSVAL_TO_OBJECT (ret_jsval);
+
+ set_property_str (authority, obj, "id", action_id);
+
keys = polkit_details_get_keys (details);
for (n = 0; keys != NULL && keys[n] != NULL; n++)
{
- const gchar *key = keys[n];
- JSString *value_jsstr;
- jsval value_jsval;
+ gchar *key;
const gchar *value;
-
+ key = g_strdup_printf ("_detail_%s", keys[n]);
value = polkit_details_lookup (details, keys[n]);
- value_jsstr = JS_NewStringCopyZ (authority->priv->cx, value);
- value_jsval = STRING_TO_JSVAL (value_jsstr);
- JS_SetProperty (authority->priv->cx, obj, key, &value_jsval);
+ set_property_str (authority, obj, key, value);
+ g_free (key);
}
g_free (keys);
@@ -990,31 +990,27 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
{
PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
GList *ret = NULL;
- jsval argv[3] = {0};
+ jsval argv[2] = {0};
jsval rval = {0};
- JSString *action_id_jstr;
guint n;
GError *error = NULL;
JSString *ret_jsstr;
gchar *ret_str = NULL;
gchar **ret_strs = NULL;
- action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
- argv[0] = STRING_TO_JSVAL (action_id_jstr);
-
- if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
+ if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
{
polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
- "Error converting subject to JS object: %s",
+ "Error converting action and details to JS object: %s",
error->message);
g_clear_error (&error);
goto out;
}
- if (!details_to_jsval (authority, details, &argv[2], &error))
+ if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
{
polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
- "Error converting details to JS object: %s",
+ "Error converting subject to JS object: %s",
error->message);
g_clear_error (&error);
goto out;
@@ -1022,7 +1018,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
if (!call_js_function_with_runaway_killer (authority,
"_runAdminRules",
- 3,
+ 2,
argv,
&rval))
{
@@ -1093,34 +1089,27 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
{
PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
PolkitImplicitAuthorization ret = implicit;
- jsval argv[3] = {0};
+ jsval argv[2] = {0};
jsval rval = {0};
- JSString *action_id_jstr;
GError *error = NULL;
JSString *ret_jsstr;
const jschar *ret_utf16;
gchar *ret_str = NULL;
gboolean good = FALSE;
- JSIdArray *ids;
- JSObject *details_obj;
- gint n;
- action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
- argv[0] = STRING_TO_JSVAL (action_id_jstr);
-
- if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
+ if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
{
polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
- "Error converting subject to JS object: %s",
+ "Error converting action and details to JS object: %s",
error->message);
g_clear_error (&error);
goto out;
}
- if (!details_to_jsval (authority, details, &argv[2], &error))
+ if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
{
polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
- "Error converting details to JS object: %s",
+ "Error converting subject to JS object: %s",
error->message);
g_clear_error (&error);
goto out;
@@ -1169,53 +1158,6 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
goto out;
}
-
- /* the JS code may have modifed @details - update PolkitDetails
- * object accordingly
- */
- details_obj = JSVAL_TO_OBJECT (argv[2]);
- ids = JS_Enumerate (authority->priv->cx, details_obj);
- if (ids == NULL)
- {
- polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
- "Failed to enumerate properties of Details object");
- goto out;
- }
- for (n = 0; n < ids->length; n++)
- {
- jsval id_val;
- jsval value_val;
- char *id_s = NULL;
- char *value_s = NULL;
-
- if (!JS_IdToValue (authority->priv->cx, ids->vector[n], &id_val))
- {
- g_warning ("Error getting string for property id %d", n);
- goto cont;
- }
- id_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (id_val));
-
- if (!JS_GetPropertyById (authority->priv->cx, details_obj, ids->vector[n], &value_val))
- {
- g_warning ("Error getting value string for property value %s", id_s);
- goto cont;
- }
-
- /* skip e.g. functions */
- if (!JSVAL_IS_STRING (value_val) && !JSVAL_IS_NULL (value_val))
- goto cont;
-
- value_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (value_val));
-
- polkit_details_insert (details, id_s, value_s);
- cont:
- if (id_s != NULL)
- JS_free (authority->priv->cx, id_s);
- if (value_s != NULL)
- JS_free (authority->priv->cx, value_s);
- }
- JS_DestroyIdArray (authority->priv->cx, ids);
-
good = TRUE;
out:
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 1dba38a..4a17f8c 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -4,55 +4,75 @@
/* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
-polkit.addAdminRule(function(action, subject, details) {
- if (action == "net.company.action1") {
+// ---------------------------------------------------------------------
+// admin rules
+
+polkit.addAdminRule(function(action, subject) {
+ if (action.id == "net.company.action1") {
return ["unix-group:admin"];
}
});
-polkit.addAdminRule(function(action, subject, details) {
- if (action == "net.company.action2") {
+polkit.addAdminRule(function(action, subject) {
+ if (action.id == "net.company.action2") {
return ["unix-group:users"];
}
});
-polkit.addAdminRule(function(action, subject, details) {
- if (action == "net.company.action3") {
+polkit.addAdminRule(function(action, subject) {
+ if (action.id == "net.company.action3") {
return ["unix-netgroup:foo"];
}
});
// Fallback
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
return ["unix-group:admin", "unix-user:root"];
});
// -----
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.productA.action0") {
+// ---------------------------------------------------------------------
+// basics
+
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.productA.action0") {
return "auth_admin";
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.productA.action1") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.productA.action1") {
return "auth_self";
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order0") {
- details["test_detail"] = "a";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order0") {
return "yes";
}
});
// ---------------------------------------------------------------------
+// variables
+
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.group.variables") {
+ if (action.lookup("foo") == "1")
+ return "yes";
+ else if (action.lookup("foo") == "2")
+ return "auth_self";
+ else
+ return "auth_admin";
+ }
+});
+
+
+// ---------------------------------------------------------------------
// group membership
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.group.only_group_users") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.group.only_group_users") {
if (subject.isInGroup("users"))
return "yes";
else
@@ -63,8 +83,8 @@ polkit.addRule(function(action, subject, details) {
// ---------------------------------------------------------------------
// netgroup membership
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.group.only_netgroup_users") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.group.only_netgroup_users") {
if (subject.isInNetGroup("foo"))
return "yes";
else
@@ -75,8 +95,8 @@ polkit.addRule(function(action, subject, details) {
// ---------------------------------------------------------------------
// spawning
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.spawning.non_existing_helper") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.spawning.non_existing_helper") {
try {
polkit.spawn(["/path/to/non/existing/helper"]);
return "no";
@@ -86,8 +106,8 @@ polkit.addRule(function(action, subject, details) {
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.spawning.successful_helper") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.spawning.successful_helper") {
try {
polkit.spawn(["/bin/true"]);
return "yes";
@@ -97,8 +117,8 @@ polkit.addRule(function(action, subject, details) {
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.spawning.failing_helper") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.spawning.failing_helper") {
try {
polkit.spawn(["/bin/false"]);
return "no";
@@ -108,8 +128,8 @@ polkit.addRule(function(action, subject, details) {
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.spawning.helper_with_output") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.spawning.helper_with_output") {
try {
var out = polkit.spawn(["echo", "-n", "-e", "Hello\nWorld"]);
if (out == "Hello\nWorld")
@@ -122,8 +142,8 @@ polkit.addRule(function(action, subject, details) {
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.spawning.helper_timeout") {
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.spawning.helper_timeout") {
try {
polkit.spawn(["sleep", "20"]);
return "no";
@@ -135,8 +155,11 @@ polkit.addRule(function(action, subject, details) {
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.run_away_script") {
+// ---------------------------------------------------------------------
+// runaway scripts
+
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.run_away_script") {
try {
// The following code will never terminate so the runaway
// script killer will step in after 15 seconds and throw
diff --git a/test/data/etc/polkit-1/rules.d/15-testing.rules b/test/data/etc/polkit-1/rules.d/15-testing.rules
index 9968aa7..b64d731 100644
--- a/test/data/etc/polkit-1/rules.d/15-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/15-testing.rules
@@ -2,23 +2,20 @@
/* see test/polkitbackend/test-polkitbackendjsauthority.c */
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order0") {
- details["test_detail"] = "c";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order0") {
+ return "no"; // earlier rule should win
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order1") {
- details["test_detail"] = "c";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order1") {
+ return "no"; // earlier rule should win
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order2") {
- details["test_detail"] = "c";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order2") {
return "yes";
}
});
diff --git a/test/data/usr/share/polkit-1/rules.d/10-testing.rules b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
index 48c4957..c60e262 100644
--- a/test/data/usr/share/polkit-1/rules.d/10-testing.rules
+++ b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
@@ -4,16 +4,14 @@
/* NOTE: this is the /usr/share/polkit-1/rules.d version of 10-testing.rules */
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order0") {
- details["test_detail"] = "c";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order0") {
+ return "no"; // earlier rule should win
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order1") {
- details["test_detail"] = "b";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order1") {
return "yes";
}
});
diff --git a/test/data/usr/share/polkit-1/rules.d/20-testing.rules b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
index 16dd039..5c5bb2c 100644
--- a/test/data/usr/share/polkit-1/rules.d/20-testing.rules
+++ b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
@@ -2,24 +2,20 @@
/* see test/polkitbackend/test-polkitbackendjsauthority.c */
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order0") {
- polkit.log("blabla");
- details["test_detail"] = "d";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order0") {
+ return "no"; // earlier rule should win
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order1") {
- details["test_detail"] = "d";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order1") {
+ return "no"; // earlier rule should win
}
});
-polkit.addRule(function(action, subject, details) {
- if (action == "net.company.order2") {
- details["test_detail"] = "d";
- return "yes";
+polkit.addRule(function(action, subject) {
+ if (action.id == "net.company.order2") {
+ return "no"; // earlier rule should win
}
});
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 728b433..0a5d0e8 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -24,6 +24,8 @@
#include "glib.h"
#include <locale.h>
+#include <string.h>
+
#include <polkit/polkit.h>
#include <polkitbackend/polkitbackendjsauthority.h>
#include <polkittesthelper.h>
@@ -156,8 +158,8 @@ struct RulesTestCase
const gchar *test_name;
const gchar *action_id;
const gchar *identity;
+ const gchar *vars;
PolkitImplicitAuthorization expected_result;
- const gchar *expected_detail;
};
static const RulesTestCase rules_test_cases[] = {
@@ -166,15 +168,15 @@ static const RulesTestCase rules_test_cases[] = {
"basic0",
"net.company.productA.action0",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
- NULL
},
{
"basic1",
"net.company.productA.action1",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
- NULL
},
/* Ordering tests ... we have four rules files, check they are
@@ -192,24 +194,47 @@ static const RulesTestCase rules_test_cases[] = {
"order0",
"net.company.order0",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- "a"
},
{
/* defined in file b, c, d - should pick file b */
"order1",
"net.company.order1",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- "b"
},
{
/* defined in file c, d - should pick file c */
"order2",
"net.company.order2",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- "c"
+ },
+
+ /* variables */
+ {
+ "variables1",
+ "net.company.group.variables",
+ "unix-user:root",
+ "foo=1",
+ POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+ },
+ {
+ "variables2",
+ "net.company.group.variables",
+ "unix-user:root",
+ "foo=2",
+ POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
+ },
+ {
+ "variables3",
+ "net.company.group.variables",
+ "unix-user:root",
+ NULL,
+ POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
},
/* check group membership */
@@ -218,16 +243,16 @@ static const RulesTestCase rules_test_cases[] = {
"group_membership_with_member",
"net.company.group.only_group_users",
"unix-user:john",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
/* sally is not a member of group 'users', see test/etc/group */
"group_membership_with_non_member",
"net.company.group.only_group_users",
"unix-user:sally",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
- NULL
},
/* check netgroup membership */
@@ -236,16 +261,16 @@ static const RulesTestCase rules_test_cases[] = {
"netgroup_membership_with_member",
"net.company.group.only_netgroup_users",
"unix-user:john",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
/* sally is not a member of netgroup 'foo', see test/etc/netgroup */
"netgroup_membership_with_non_member",
"net.company.group.only_netgroup_users",
"unix-user:sally",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
- NULL
},
/* spawning */
@@ -253,43 +278,45 @@ static const RulesTestCase rules_test_cases[] = {
"spawning_non_existing_helper",
"net.company.spawning.non_existing_helper",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
"spawning_successful_helper",
"net.company.spawning.successful_helper",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
"spawning_failing_helper",
"net.company.spawning.failing_helper",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
"spawning_helper_with_output",
"net.company.spawning.helper_with_output",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
{
- "runaway_script",
- "net.company.run_away_script",
+ "spawning_helper_timeout",
+ "net.company.spawning.helper_timeout",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
+
+ /* runaway scripts */
{
- "spawning_helper_timeout",
- "net.company.spawning.helper_timeout",
+ "runaway_script",
+ "net.company.run_away_script",
"unix-user:root",
+ NULL,
POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
- NULL
},
};
@@ -316,6 +343,23 @@ rules_test_func (gconstpointer user_data)
details = polkit_details_new ();
+ if (tc->vars != NULL)
+ {
+ gchar *s;
+ const gchar *key;
+ const gchar *value;
+
+ s = g_strdup (tc->vars);
+ key = s;
+ value = strchr (key, '=');
+ g_assert (value != NULL);
+ *((gchar *) value) = '\0';
+ value += 1;
+
+ polkit_details_insert (details, key, value);
+ g_free (s);
+ }
+
result = polkit_backend_interactive_authority_check_authorization_sync (POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
caller,
subject,
@@ -326,7 +370,6 @@ rules_test_func (gconstpointer user_data)
details,
POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN);
g_assert_cmpint (result, ==, tc->expected_result);
- g_assert_cmpstr (polkit_details_lookup (details, "test_detail"), ==, tc->expected_detail);
g_clear_object (&user_for_subject);
g_clear_object (&subject);