PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Mon Nov 19 20:25:44 PST 2007
doc/man/polkit-auth.xml | 19 ++
src/polkit-dbus/polkit-simple.c | 2
src/polkit-grant/polkit-authorization-db-write.c | 145 ++++++++++++++++-----
src/polkit-grant/polkit-explicit-grant-helper.c | 33 +++-
src/polkit-grant/polkit-revoke-helper.c | 9 -
src/polkit/polkit-authorization-db.c | 156 +++++++++++++++++++++--
src/polkit/polkit-authorization-db.h | 17 ++
src/polkit/polkit-authorization.c | 19 ++
src/polkit/polkit-authorization.h | 3
src/polkit/polkit-context.c | 38 +++--
tools/polkit-auth.c | 57 ++++++--
tools/polkit-bash-completion.sh | 12 -
12 files changed, 414 insertions(+), 96 deletions(-)
New commits:
commit 45f52acbfd1d898e37f4ccaa830d6425fa4bc2da
Author: David Zeuthen <davidz at redhat.com>
Date: Mon Nov 19 23:25:30 2007 -0500
add support for negative authorizations
Negative authorizations is a way to block an entity; previously the
algorithm was something like (ignoring the config file for now)
Result is_authorized() {
res = has_implicit_auth();
if (res == YES) {
return YES;
} else if (has_explicit_auth()) {
return YES;
}
return res;
}
Now it's
Result is_authorized() {
res = has_implicit_auth();
expl = has_explicit_auth();
is_blocked = has_negative_explicit_auth();
if (is_blocked)
return NO;
if (res == YES) {
return YES;
} else if (has_explicit_auth()) {
return YES;
}
return res;
}
E.g. just a single negative auth will force NO to be returned. I
really, really need to write into the spec how this works; my mental
L1 cache can't contain it anymore. Once it's formally defined we need
to craft a test suite to verify that the code works according to
spec...
diff --git a/doc/man/polkit-auth.xml b/doc/man/polkit-auth.xml
index 793395a..638f3bb 100644
--- a/doc/man/polkit-auth.xml
+++ b/doc/man/polkit-auth.xml
@@ -24,6 +24,7 @@
<arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit</option></arg>
<arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit-detail</option></arg>
<arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --grant <replaceable>action</replaceable></option><arg><option>--constraint <replaceable>constraint</replaceable></option></arg></arg>
+ <arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --block <replaceable>action</replaceable></option><arg><option>--constraint <replaceable>constraint</replaceable></option></arg></arg>
<arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --revoke <replaceable>action</replaceable></option></arg>
<arg><option>--version</option></arg>
<arg><option>--help</option></arg>
@@ -110,6 +111,24 @@
</varlistentry>
<varlistentry>
+ <term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --block <replaceable>action</replaceable></option><arg><option>--constraint <replaceable>constraint</replaceable></option></arg></term>
+ <listitem>
+ <para>
+ Grant an negative authorization for an action. Negative
+ authorizations are normally used to block users that would
+ normally be authorized due to implicit
+ authorizations. Optionally, a constraint on the granted
+ negative authorization can be specified; allowed values
+ are: <literal>local</literal>,
+ <literal>active</literal>, <literal>local+active</literal>.
+ The authorization needed to grant negative authorizations is
+ <literal>org.freedesktop.policykit.grant</literal> if the
+ "beneficiary" is another user.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --revoke <replaceable>action</replaceable></option></term>
<listitem>
<para>
diff --git a/src/polkit-dbus/polkit-simple.c b/src/polkit-dbus/polkit-simple.c
index b6d9ac9..af1c3c9 100644
--- a/src/polkit-dbus/polkit-simple.c
+++ b/src/polkit-dbus/polkit-simple.c
@@ -157,6 +157,8 @@ polkit_check_authv (pid_t pid, const char **action_ids)
ret = 0;
errno = ENOENT;
+ context = NULL;
+ caller = NULL;
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
diff --git a/src/polkit-grant/polkit-authorization-db-write.c b/src/polkit-grant/polkit-authorization-db-write.c
index 145aed9..fecd475 100644
--- a/src/polkit-grant/polkit-authorization-db-write.c
+++ b/src/polkit-grant/polkit-authorization-db-write.c
@@ -533,6 +533,9 @@ polkit_authorization_db_add_entry_always (PolKitAuthorizationDB *authd
typedef struct {
char *action_id;
PolKitAuthorizationConstraint *constraint;
+
+ polkit_bool_t is_authorized;
+ polkit_bool_t is_negative_authorized;
} CheckDataGrant;
static polkit_bool_t
@@ -540,6 +543,7 @@ _check_auth_for_grant (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth,
{
uid_t pimp;
polkit_bool_t ret;
+ polkit_bool_t is_negative;
CheckDataGrant *cd = (CheckDataGrant *) user_data;
ret = FALSE;
@@ -547,42 +551,34 @@ _check_auth_for_grant (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth,
if (strcmp (polkit_authorization_get_action_id (auth), cd->action_id) != 0)
goto no_match;
- if (!polkit_authorization_was_granted_explicitly (auth, &pimp))
+ if (!polkit_authorization_was_granted_explicitly (auth, &pimp, &is_negative))
goto no_match;
if (!polkit_authorization_constraint_equal (polkit_authorization_get_constraint (auth), cd->constraint))
goto no_match;
- ret = TRUE;
+ if (is_negative) {
+ cd->is_authorized = FALSE;
+ cd->is_negative_authorized = TRUE;
+ /* it only takes a single negative auth to block things so stop iterating */
+ ret = TRUE;
+ } else {
+ cd->is_authorized = TRUE;
+ cd->is_negative_authorized = FALSE;
+ /* keep iterating; we may find negative auths... */
+ }
no_match:
return ret;
}
-/**
- * polkit_authorization_db_grant_to_uid:
- * @authdb: authorization database
- * @action: action
- * @uid: uid to grant to
- * @constraint: what constraint to put on the authorization
- * @error: return location for error
- *
- * Grants an authorization to a user for a specific action. This
- * requires the org.freedesktop.policykit.grant authorization.
- *
- * This function is in <literal>libpolkit-grant</literal>.
- *
- * Returns: #TRUE if the authorization was granted, #FALSE otherwise
- * and error will be set
- *
- * Since: 0.7
- */
-polkit_bool_t
-polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
- PolKitAction *action,
- uid_t uid,
- PolKitAuthorizationConstraint *constraint,
- PolKitError **error)
+static polkit_bool_t
+_grant_internal (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitAuthorizationConstraint *constraint,
+ PolKitError **error,
+ polkit_bool_t is_negative)
{
GError *g_error;
char *helper_argv[6] = {PACKAGE_LIBEXEC_DIR "/polkit-explicit-grant-helper", NULL, NULL, NULL, NULL, NULL};
@@ -590,6 +586,7 @@ polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
gint exit_status;
char cbuf[256];
CheckDataGrant cd;
+ polkit_bool_t did_exist;
ret = FALSE;
@@ -614,16 +611,29 @@ polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
/* check if we have the auth already */
cd.constraint = constraint;
- if (!polkit_authorization_db_foreach_for_uid (authdb,
- uid,
- _check_auth_for_grant,
- &cd,
- error)) {
- /* happens if caller can't read auths of target user */
- if (error != NULL && polkit_error_is_set (*error)) {
- goto out;
- }
+ cd.is_authorized = FALSE;
+ cd.is_negative_authorized = FALSE;
+ polkit_authorization_db_foreach_for_uid (authdb,
+ uid,
+ _check_auth_for_grant,
+ &cd,
+ error);
+
+ /* happens if caller can't read auths of target user */
+ if (error != NULL && polkit_error_is_set (*error)) {
+ goto out;
+ }
+
+ did_exist = FALSE;
+ if (is_negative) {
+ if (cd.is_negative_authorized)
+ did_exist = TRUE;
} else {
+ if (cd.is_authorized)
+ did_exist = TRUE;
+ }
+
+ if (did_exist) {
/* so it did exist.. */
polkit_error_set_error (error,
POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS,
@@ -635,7 +645,10 @@ polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
helper_argv[1] = cd.action_id;
helper_argv[2] = cbuf;
- helper_argv[3] = "uid";
+ if (is_negative)
+ helper_argv[3] = "uid-negative";
+ else
+ helper_argv[3] = "uid";
helper_argv[4] = g_strdup_printf ("%d", uid);
helper_argv[5] = NULL;
@@ -676,5 +689,65 @@ polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
out:
g_free (helper_argv[4]);
return ret;
+}
+
+/**
+ * polkit_authorization_db_grant_to_uid:
+ * @authdb: authorization database
+ * @action: action
+ * @uid: uid to grant to
+ * @constraint: what constraint to put on the authorization
+ * @error: return location for error
+ *
+ * Grants an authorization to a user for a specific action. This
+ * requires the org.freedesktop.policykit.grant authorization.
+ *
+ * This function is in <literal>libpolkit-grant</literal>.
+ *
+ * Returns: #TRUE if the authorization was granted, #FALSE otherwise
+ * and error will be set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitAuthorizationConstraint *constraint,
+ PolKitError **error)
+{
+ return _grant_internal (authdb, action, uid, constraint, error, FALSE);
+}
+/**
+ * polkit_authorization_db_grant_negative_to_uid:
+ * @authdb: authorization database
+ * @action: action
+ * @uid: uid to grant to
+ * @constraint: what constraint to put on the authorization
+ * @error: return location for error
+ *
+ * Grants a negative authorization to a user for a specific action. If
+ * @uid differs from the calling user, the
+ * org.freedesktop.policykit.grant authorization is required. In other
+ * words, users may "grant" negative authorizations to themselves.
+ *
+ * A negative authorization is normally used to block users that would
+ * normally be authorized from an implicit authorization.
+ *
+ * This function is in <literal>libpolkit-grant</literal>.
+ *
+ * Returns: #TRUE if the authorization was granted, #FALSE otherwise
+ * and error will be set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_grant_negative_to_uid (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitAuthorizationConstraint *constraint,
+ PolKitError **error)
+{
+ return _grant_internal (authdb, action, uid, constraint, error, TRUE);
}
diff --git a/src/polkit-grant/polkit-explicit-grant-helper.c b/src/polkit-grant/polkit-explicit-grant-helper.c
index 7d08448..0c7ac60 100644
--- a/src/polkit-grant/polkit-explicit-grant-helper.c
+++ b/src/polkit-grant/polkit-explicit-grant-helper.c
@@ -124,9 +124,16 @@ main (int argc, char *argv[])
#define TARGET_UID 0
int target;
uid_t target_uid = -1;
+ polkit_bool_t is_negative;
- /* (third, fourth) is one of: ("uid", uid) */
- if (strcmp (argv[3], "uid") == 0) {
+ is_negative = FALSE;
+
+ /* (third, fourth) is one of: ("uid", uid), ("uid-negative", uid) */
+ if (strcmp (argv[3], "uid") == 0 || strcmp (argv[3], "uid-negative") == 0) {
+
+ if (strcmp (argv[3], "uid") != 0) {
+ is_negative = TRUE;
+ }
target = TARGET_UID;
target_uid = strtol (argv[4], &endp, 10);
@@ -147,14 +154,19 @@ main (int argc, char *argv[])
/* OK, we're done parsing ... check if the user is authorized */
if (invoking_uid != 0) {
- pid_t ppid;
-
- ppid = getppid ();
- if (ppid == 1)
- goto out;
- if (polkit_check_auth (ppid, "org.freedesktop.policykit.grant", NULL) == 0) {
- goto out;
+ if (is_negative && (invoking_uid == target_uid)) {
+ /* it's fine to grant negative-auths to one self... */
+ } else {
+ pid_t ppid;
+
+ ppid = getppid ();
+ if (ppid == 1)
+ goto out;
+
+ if (polkit_check_auth (ppid, "org.freedesktop.policykit.grant", NULL) == 0) {
+ goto out;
+ }
}
}
@@ -169,7 +181,8 @@ main (int argc, char *argv[])
if (snprintf (grant_line,
sizeof (grant_line),
- "grant:%s:%Lu:%d:%s\n",
+ is_negative ? "grant-negative:%s:%Lu:%d:%s\n" :
+ "grant:%s:%Lu:%d:%s\n" ,
action_id,
(polkit_uint64_t) now.tv_sec,
invoking_uid,
diff --git a/src/polkit-grant/polkit-revoke-helper.c b/src/polkit-grant/polkit-revoke-helper.c
index 6453f81..b59d0c2 100644
--- a/src/polkit-grant/polkit-revoke-helper.c
+++ b/src/polkit-grant/polkit-revoke-helper.c
@@ -185,7 +185,8 @@ main (int argc, char *argv[])
root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
} else if (strcmp (scope, "always") == 0) {
root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
- } else if (strcmp (scope, "grant") == 0) {
+ } else if (strcmp (scope, "grant") == 0 ||
+ strcmp (scope, "grant-negative") == 0) {
uid_t granted_by;
root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
@@ -208,8 +209,10 @@ main (int argc, char *argv[])
}
if (invoking_uid != 0) {
- /* Check that the caller is privileged to do this... */
- if (not_granted_by_self || (invoking_uid != uid_to_revoke)) {
+ /* Check that the caller is privileged to do this... basically, callers can only
+ * revoke auths granted by themselves...
+ */
+ if (not_granted_by_self) {
pid_t ppid;
ppid = getppid ();
diff --git a/src/polkit/polkit-authorization-db.c b/src/polkit/polkit-authorization-db.c
index d31183e..7322355 100644
--- a/src/polkit/polkit-authorization-db.c
+++ b/src/polkit/polkit-authorization-db.c
@@ -340,7 +340,10 @@ _authdb_get_auths_for_uid (PolKitAuthorizationDB *authdb,
auth = _polkit_authorization_new_for_uid (line, uid2);
if (auth != NULL) {
- ret = kit_list_prepend (ret, auth);
+ /* we need the authorizations in the chronological order...
+ * (TODO: optimized: prepend, then reverse after all items have been inserted)
+ */
+ ret = kit_list_append (ret, auth);
}
}
@@ -540,12 +543,17 @@ typedef struct {
uid_t session_uid;
char *session_objpath;
PolKitSession *session;
+
+ polkit_bool_t *out_is_authorized;
+ polkit_bool_t *out_is_negative_authorized;
} CheckDataSession;
static polkit_bool_t
_check_auth_for_session (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
{
polkit_bool_t ret;
+ uid_t pimp_uid;
+ polkit_bool_t is_negative;
CheckDataSession *cd = (CheckDataSession *) user_data;
PolKitAuthorizationConstraint *constraint;
@@ -573,7 +581,29 @@ _check_auth_for_session (PolKitAuthorizationDB *authdb, PolKitAuthorization *aut
break;
}
- ret = TRUE;
+ if (!polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative))
+ is_negative = FALSE;
+
+ if (is_negative) {
+ *(cd->out_is_authorized) = FALSE;
+ *(cd->out_is_negative_authorized) = TRUE;
+ } else {
+ *(cd->out_is_authorized) = TRUE;
+ *(cd->out_is_negative_authorized) = FALSE;
+ }
+
+ /* keep iterating; we may find negative auths... */
+
+ if (is_negative) {
+ *(cd->out_is_authorized) = FALSE;
+ *(cd->out_is_negative_authorized) = TRUE;
+ /* it only takes a single negative auth to block things so stop iterating */
+ ret = TRUE;
+ } else {
+ *(cd->out_is_authorized) = TRUE;
+ *(cd->out_is_negative_authorized) = FALSE;
+ /* keep iterating; we may find negative auths... */
+ }
no_match:
return ret;
@@ -585,9 +615,14 @@ no_match:
* @action: the action to check for
* @session: the session to check for
* @out_is_authorized: return location
+ * @out_is_negative_authorized: return location
*
* Looks in the authorization database and determine if processes from
- * the given session are authorized to do the given specific action.
+ * the given session are authorized to do the given specific
+ * action. If there is an authorization record that matches the
+ * session, @out_is_authorized will be set to %TRUE. If there is a
+ * negative authorization record matching the session
+ * @out_is_negative_authorized will be set to %TRUE.
*
* Returns: #TRUE if the look up was performed; #FALSE if the caller
* of this function lacks privileges to ask this question (e.g. asking
@@ -599,7 +634,8 @@ polkit_bool_t
polkit_authorization_db_is_session_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitSession *session,
- polkit_bool_t *out_is_authorized)
+ polkit_bool_t *out_is_authorized,
+ polkit_bool_t *out_is_negative_authorized)
{
polkit_bool_t ret;
CheckDataSession cd;
@@ -624,13 +660,17 @@ polkit_authorization_db_is_session_authorized (PolKitAuthorizationDB *authdb,
ret = TRUE;
+ cd.out_is_authorized = out_is_authorized;
+ cd.out_is_negative_authorized = out_is_negative_authorized;
*out_is_authorized = FALSE;
+ *out_is_negative_authorized = FALSE;
+
if (polkit_authorization_db_foreach_for_uid (authdb,
cd.session_uid,
_check_auth_for_session,
&cd,
NULL)) {
- *out_is_authorized = TRUE;
+ ;
}
return ret;
@@ -644,13 +684,17 @@ typedef struct {
char *session_objpath;
PolKitCaller *caller;
polkit_bool_t revoke_if_one_shot;
+
+ polkit_bool_t *out_is_authorized;
+ polkit_bool_t *out_is_negative_authorized;
} CheckData;
static polkit_bool_t
_check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
{
-
polkit_bool_t ret;
+ uid_t pimp_uid;
+ polkit_bool_t is_negative;
pid_t caller_pid;
polkit_uint64_t caller_pid_start_time;
CheckData *cd = (CheckData *) user_data;
@@ -701,7 +745,19 @@ _check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth
break;
}
- ret = TRUE;
+ if (!polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative))
+ is_negative = FALSE;
+
+ if (is_negative) {
+ *(cd->out_is_authorized) = FALSE;
+ *(cd->out_is_negative_authorized) = TRUE;
+ /* it only takes a single negative auth to block things so stop iterating */
+ ret = TRUE;
+ } else {
+ *(cd->out_is_authorized) = TRUE;
+ *(cd->out_is_negative_authorized) = FALSE;
+ /* keep iterating; we may find negative auths... */
+ }
no_match:
@@ -716,9 +772,13 @@ no_match:
* @revoke_if_one_shot: Whether to revoke one-shot authorizations. See
* discussion in polkit_context_is_caller_authorized() for details.
* @out_is_authorized: return location
+ * @out_is_negative_authorized: return location
*
* Looks in the authorization database if the given caller is
- * authorized to do the given action.
+ * authorized to do the given action. If there is an authorization
+ * record that matches the caller, @out_is_authorized will be set to
+ * %TRUE. If there is a negative authorization record matching the
+ * caller @out_is_negative_authorized will be set to %TRUE.
*
* Returns: #TRUE if the look up was performed; #FALSE if the caller
* of this function lacks privileges to ask this question (e.g. asking
@@ -731,7 +791,8 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitCaller *caller,
polkit_bool_t revoke_if_one_shot,
- polkit_bool_t *out_is_authorized)
+ polkit_bool_t *out_is_authorized,
+ polkit_bool_t *out_is_negative_authorized)
{
PolKitSession *session;
polkit_bool_t ret;
@@ -769,13 +830,17 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
ret = TRUE;
+ cd.out_is_authorized = out_is_authorized;
+ cd.out_is_negative_authorized = out_is_negative_authorized;
*out_is_authorized = FALSE;
+ *out_is_negative_authorized = FALSE;
+
if (polkit_authorization_db_foreach_for_uid (authdb,
cd.caller_uid,
_check_auth_for_caller,
&cd,
NULL)) {
- *out_is_authorized = TRUE;
+ ;
}
return ret;
@@ -849,6 +914,77 @@ out:
return ret;
}
+static polkit_bool_t
+_check_self_block_foreach (PolKitAuthorizationDB *authdb,
+ PolKitAuthorization *auth,
+ void *user_data)
+{
+ polkit_bool_t *is_self_blocked = (polkit_bool_t *) user_data;
+ polkit_bool_t is_negative;
+ uid_t pimp_uid;
+ polkit_bool_t ret;
+
+ if (!polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative))
+ is_negative = FALSE;
+
+ if (is_negative) {
+ if (pimp_uid == getuid ()) {
+ *is_self_blocked = TRUE;
+ /* can't stop iterating.. there may be another one who blocked us too! */
+ } else {
+ *is_self_blocked = FALSE;
+ ret = TRUE;
+ /* nope; someone else blocked us.. that's enough to ruin it */
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * polkit_authorization_db_is_uid_blocked_by_self:
+ * @authdb: the authorization database
+ * @action: the action to check for
+ * @uid: the user to check for
+ * @error: return location for error
+ *
+ * Determine whether there exists negative authorizations for the
+ * particular uid on the given action and whether those negative
+ * authorization are "granted" by the uid itself.
+ *
+ * If uid is different from getuid(), e.g. if the calling process asks
+ * for auths of another user this function will set an error if the
+ * calling user is not authorized for org.freedesktop.policykit.read.
+ *
+ * Returns: Result of computation described above; if error is set
+ * will return %FALSE.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_is_uid_blocked_by_self (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitError **error)
+{
+ polkit_bool_t is_self_blocked;
+
+ kit_return_val_if_fail (authdb != NULL, FALSE);
+ kit_return_val_if_fail (action != NULL, FALSE);
+
+ is_self_blocked = FALSE;
+ polkit_authorization_db_foreach_for_action_for_uid (authdb,
+ action,
+ uid,
+ _check_self_block_foreach,
+ &is_self_blocked,
+ error);
+
+ return is_self_blocked;
+}
+
+
+
#ifdef POLKIT_BUILD_TESTS
static polkit_bool_t
diff --git a/src/polkit/polkit-authorization-db.h b/src/polkit/polkit-authorization-db.h
index 8089bd4..3e4dffe 100644
--- a/src/polkit/polkit-authorization-db.h
+++ b/src/polkit/polkit-authorization-db.h
@@ -68,13 +68,15 @@ polkit_bool_t polkit_authorization_db_validate (PolKitAuthorizati
polkit_bool_t polkit_authorization_db_is_session_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitSession *session,
- polkit_bool_t *out_is_authorized);
+ polkit_bool_t *out_is_authorized,
+ polkit_bool_t *out_is_negative_authorized);
polkit_bool_t polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
PolKitAction *action,
PolKitCaller *caller,
polkit_bool_t revoke_if_one_shot,
- polkit_bool_t *out_is_authorized);
+ polkit_bool_t *out_is_authorized,
+ polkit_bool_t *out_is_negative_authorized);
/**
* PolKitAuthorizationDBForeach:
@@ -144,11 +146,22 @@ polkit_bool_t polkit_authorization_db_grant_to_uid (PolKitAuthorizatio
PolKitAuthorizationConstraint *constraint,
PolKitError **error);
+polkit_bool_t polkit_authorization_db_grant_negative_to_uid (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitAuthorizationConstraint *constraint,
+ PolKitError **error);
+
polkit_bool_t polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
PolKitAuthorization *auth,
PolKitError **error);
+polkit_bool_t polkit_authorization_db_is_uid_blocked_by_self (PolKitAuthorizationDB *authdb,
+ PolKitAction *action,
+ uid_t uid,
+ PolKitError **error);
+
POLKIT_END_DECLS
#endif /* POLKIT_AUTHORIZATION_DB_H */
diff --git a/src/polkit/polkit-authorization.c b/src/polkit/polkit-authorization.c
index 265d37f..cf11342 100644
--- a/src/polkit/polkit-authorization.c
+++ b/src/polkit/polkit-authorization.c
@@ -83,6 +83,8 @@ struct _PolKitAuthorization
polkit_bool_t explicitly_granted;
uid_t explicitly_granted_by;
+ polkit_bool_t is_negative;
+
char *session_id;
};
@@ -250,11 +252,16 @@ _polkit_authorization_new_for_uid (const char *entry_in_auth_file, uid_t uid)
* authc_str) >= (int) sizeof (grant_line)) {
*
*/
- else if (strcmp (t[0], "grant") == 0) {
+ else if (strcmp (t[0], "grant") == 0 ||
+ strcmp (t[0], "grant-negative") == 0) {
if (num_t != 5)
goto error;
+ if (strcmp (t[0], "grant-negative") == 0) {
+ auth->is_negative = TRUE;
+ }
+
auth->scope = POLKIT_AUTHORIZATION_SCOPE_ALWAYS;
auth->explicitly_granted = TRUE;
@@ -545,6 +552,7 @@ polkit_authorization_was_granted_via_defaults (PolKitAuthorization *auth,
* polkit_authorization_was_granted_explicitly:
* @auth: the object
* @out_by_whom: return location
+ * @out_is_negative: return location
*
* Determine if the authorization was explicitly granted by a
* sufficiently privileged user.
@@ -553,21 +561,26 @@ polkit_authorization_was_granted_via_defaults (PolKitAuthorization *auth,
* one of these functions can return #TRUE.
*
* Returns: #TRUE if the authorization was explicitly granted by a
- * sufficiently privileger user.
+ * sufficiently privileger user. If %TRUE, the user who granted the
+ * authorization is returned in %out_by_whom. If the authorization is
+ * negative, %TRUE is returned in %out_is_negative.
*
* Since: 0.7
*/
polkit_bool_t
polkit_authorization_was_granted_explicitly (PolKitAuthorization *auth,
- uid_t *out_by_whom)
+ uid_t *out_by_whom,
+ polkit_bool_t *out_is_negative)
{
kit_return_val_if_fail (auth != NULL, FALSE);
kit_return_val_if_fail (out_by_whom != NULL, FALSE);
+ kit_return_val_if_fail (out_is_negative != NULL, FALSE);
if (!auth->explicitly_granted)
return FALSE;
*out_by_whom = auth->explicitly_granted_by;
+ *out_is_negative = auth->is_negative;
return TRUE;
}
diff --git a/src/polkit/polkit-authorization.h b/src/polkit/polkit-authorization.h
index 0e107be..96841bf 100644
--- a/src/polkit/polkit-authorization.h
+++ b/src/polkit/polkit-authorization.h
@@ -91,7 +91,8 @@ polkit_bool_t polkit_authorization_was_granted_via_defaults (PolKitAuthorizatio
uid_t *out_user_authenticated_as);
polkit_bool_t polkit_authorization_was_granted_explicitly (PolKitAuthorization *auth,
- uid_t *out_by_whom);
+ uid_t *out_by_whom,
+ polkit_bool_t *out_is_negative);
POLKIT_END_DECLS
diff --git a/src/polkit/polkit-context.c b/src/polkit/polkit-context.c
index a7e0091..88685bf 100644
--- a/src/polkit/polkit-context.c
+++ b/src/polkit/polkit-context.c
@@ -448,6 +448,7 @@ polkit_context_is_session_authorized (PolKitContext *pk_context,
PolKitResult result_from_config;
PolKitResult result_from_grantdb;
polkit_bool_t from_authdb;
+ polkit_bool_t from_authdb_negative;
PolKitResult result;
PolKitConfig *config;
@@ -493,10 +494,12 @@ polkit_context_is_session_authorized (PolKitContext *pk_context,
result_from_config = polkit_config_can_session_do_action (config, action, session);
result_from_grantdb = POLKIT_RESULT_UNKNOWN;
+ from_authdb_negative = FALSE;
if (polkit_authorization_db_is_session_authorized (pk_context->authdb,
action,
session,
- &from_authdb)) {
+ &from_authdb,
+ &from_authdb_negative)) {
if (from_authdb)
result_from_grantdb = POLKIT_RESULT_YES;
}
@@ -529,13 +532,15 @@ polkit_context_is_session_authorized (PolKitContext *pk_context,
goto found;
}
- /* Otherwise, fall back to defaults as specified in the .policy file */
- policy_default = polkit_policy_file_entry_get_default (pfe);
- if (policy_default == NULL) {
- kit_warning ("no default policy for action!");
- goto out;
+ /* Otherwise, unless we found a negative auth, fall back to defaults as specified in the .policy file */
+ if (!from_authdb_negative) {
+ policy_default = polkit_policy_file_entry_get_default (pfe);
+ if (policy_default == NULL) {
+ kit_warning ("no default policy for action!");
+ goto out;
+ }
+ result = polkit_policy_default_can_session_do_action (policy_default, action, session);
}
- result = polkit_policy_default_can_session_do_action (policy_default, action, session);
found:
/* Never return UNKNOWN to user */
@@ -600,6 +605,7 @@ polkit_context_is_caller_authorized (PolKitContext *pk_context,
PolKitPolicyDefault *policy_default;
PolKitConfig *config;
polkit_bool_t from_authdb;
+ polkit_bool_t from_authdb_negative;
result = POLKIT_RESULT_NO;
kit_return_val_if_fail (pk_context != NULL, result);
@@ -643,11 +649,13 @@ polkit_context_is_caller_authorized (PolKitContext *pk_context,
result_from_config = polkit_config_can_caller_do_action (config, action, caller);
result_from_grantdb = POLKIT_RESULT_UNKNOWN;
+ from_authdb_negative = FALSE;
if (polkit_authorization_db_is_caller_authorized (pk_context->authdb,
action,
caller,
revoke_if_one_shot,
- &from_authdb)) {
+ &from_authdb,
+ &from_authdb_negative)) {
if (from_authdb)
result_from_grantdb = POLKIT_RESULT_YES;
}
@@ -680,13 +688,15 @@ polkit_context_is_caller_authorized (PolKitContext *pk_context,
goto found;
}
- /* Otherwise, fall back to defaults as specified in the .policy file */
- policy_default = polkit_policy_file_entry_get_default (pfe);
- if (policy_default == NULL) {
- kit_warning ("no default policy for action!");
- goto out;
+ /* Otherwise, unless we found a negative auth, fall back to defaults as specified in the .policy file */
+ if (!from_authdb_negative) {
+ policy_default = polkit_policy_file_entry_get_default (pfe);
+ if (policy_default == NULL) {
+ kit_warning ("no default policy for action!");
+ goto out;
+ }
+ result = polkit_policy_default_can_caller_do_action (policy_default, action, caller);
}
- result = polkit_policy_default_can_caller_do_action (policy_default, action, caller);
found:
diff --git a/tools/polkit-auth.c b/tools/polkit-auth.c
index ac4d96c..4d73c0a 100644
--- a/tools/polkit-auth.c
+++ b/tools/polkit-auth.c
@@ -56,6 +56,7 @@ static polkit_bool_t opt_show_obtainable;
static char *opt_revoke_action_id;
static char *opt_user;
static char *opt_grant_action_id;
+static char *opt_block_action_id;
static char *opt_constraint;
typedef struct {
@@ -414,8 +415,6 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
g_hash_table_insert (already_shown, g_strdup (action_id), (gpointer) 1);
}
- printf ("%s\n", action_id);
-
if (opt_show_explicit_detail) {
char *s;
time_t time_granted;
@@ -423,6 +422,7 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
char time_string[128];
uid_t auth_uid;
uid_t pimp_uid;
+ polkit_bool_t is_negative;
pid_t pid;
polkit_uint64_t pid_start_time;
const char *cstr;
@@ -431,6 +431,8 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
PolKitResult pk_result;
char exe[PATH_MAX];
+ printf ("%s\n", action_id);
+
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, action_id);
pk_result = polkit_context_is_caller_authorized (pk_context, pk_action, pk_caller, FALSE, NULL);
@@ -461,11 +463,12 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
time_granted = polkit_authorization_get_time_of_grant (auth);
time_tm = localtime (&time_granted);
+ is_negative = FALSE;
if (polkit_authorization_was_granted_via_defaults (auth, &auth_uid)) {
s = g_strdup_printf ("%%c by auth as %s (uid %d)", get_name_from_uid (auth_uid), auth_uid);
strftime (time_string, sizeof (time_string), s, time_tm);
g_free (s);
- } else if (polkit_authorization_was_granted_explicitly (auth, &pimp_uid)) {
+ } else if (polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative)) {
s = g_strdup_printf ("%%c from %s (uid %d)", get_name_from_uid (pimp_uid), pimp_uid);
strftime (time_string, sizeof (time_string), s, time_tm);
g_free (s);
@@ -489,7 +492,20 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
}
printf (" Constraints: %s\n", cstr);
+ if (is_negative) {
+ printf (" Negative: Yes\n");
+ }
+
printf ("\n");
+ } else {
+ uid_t pimp_uid;
+ polkit_bool_t is_negative;
+
+ if (!polkit_authorization_was_granted_explicitly (auth, &pimp_uid, &is_negative))
+ is_negative = FALSE;
+
+ if (!is_negative)
+ printf ("%s\n", action_id);
}
@@ -681,6 +697,7 @@ main (int argc, char *argv[])
opt_is_version = FALSE;
opt_obtain_action_id = NULL;
opt_grant_action_id = NULL;
+ opt_block_action_id = NULL;
opt_constraint = NULL;
opt_revoke_action_id = NULL;
opt_show_obtainable = FALSE;
@@ -695,6 +712,7 @@ main (int argc, char *argv[])
{"explicit-detail", 0, NULL, 0},
{"obtain", 1, NULL, 0},
{"grant", 1, NULL, 0},
+ {"block", 1, NULL, 0},
{"constraint", 1, NULL, 0},
{"revoke", 1, NULL, 0},
{"show-obtainable", 0, NULL, 0},
@@ -721,6 +739,8 @@ main (int argc, char *argv[])
opt_obtain_action_id = strdup (optarg);
} else if (strcmp (opt, "grant") == 0) {
opt_grant_action_id = strdup (optarg);
+ } else if (strcmp (opt, "block") == 0) {
+ opt_block_action_id = strdup (optarg);
} else if (strcmp (opt, "constraint") == 0) {
opt_constraint = strdup (optarg);
} else if (strcmp (opt, "revoke") == 0) {
@@ -765,10 +785,12 @@ main (int argc, char *argv[])
if (!obtain_authorization (opt_obtain_action_id))
goto out;
ret = 0;
- } else if (opt_grant_action_id != NULL) {
+ } else if (opt_grant_action_id != NULL ||
+ opt_block_action_id != NULL) {
PolKitAction *pk_action;
PolKitError *pk_error;
PolKitAuthorizationConstraint *constraint;
+ polkit_bool_t res;
if (opt_user == NULL && uid == 0) {
fprintf (stderr, "polkit-auth: Cowardly refusing to grant authorization to uid 0 (did you forget to specify what user to grant to?). To force, run with --user root.\n");
@@ -776,7 +798,10 @@ main (int argc, char *argv[])
}
pk_action = polkit_action_new ();
- polkit_action_set_action_id (pk_action, opt_grant_action_id);
+ if (opt_block_action_id != NULL)
+ polkit_action_set_action_id (pk_action, opt_block_action_id);
+ else
+ polkit_action_set_action_id (pk_action, opt_grant_action_id);
if (opt_constraint != NULL) {
constraint = polkit_authorization_constraint_from_string (opt_constraint);
@@ -789,18 +814,28 @@ main (int argc, char *argv[])
}
pk_error = NULL;
- if (!polkit_authorization_db_grant_to_uid (pk_authdb,
- pk_action,
- uid,
- constraint,
- &pk_error)) {
+ if (opt_block_action_id != NULL) {
+ res = polkit_authorization_db_grant_negative_to_uid (pk_authdb,
+ pk_action,
+ uid,
+ constraint,
+ &pk_error);
+ } else {
+ res = polkit_authorization_db_grant_to_uid (pk_authdb,
+ pk_action,
+ uid,
+ constraint,
+ &pk_error);
+ }
+
+ if (!res) {
fprintf (stderr, "polkit-auth: %s: %s\n",
polkit_error_get_error_name (pk_error),
polkit_error_get_error_message (pk_error));
polkit_error_free (pk_error);
goto out;
}
-
+
ret = 0;
} else if (opt_revoke_action_id != NULL) {
diff --git a/tools/polkit-bash-completion.sh b/tools/polkit-bash-completion.sh
index 2f94048..8d1d2a4 100644
--- a/tools/polkit-bash-completion.sh
+++ b/tools/polkit-bash-completion.sh
@@ -7,7 +7,7 @@ __polkit_auth() {
case $COMP_CWORD in
1)
- COMPREPLY=($(IFS=: compgen -S' ' -W "--obtain:--show-obtainable:--explicit:--explicit-detail:--grant:--revoke:--user:--version:--help" -- $cur))
+ COMPREPLY=($(IFS=: compgen -S' ' -W "--obtain:--show-obtainable:--explicit:--explicit-detail:--grant:--block:--revoke:--user:--version:--help" -- $cur))
;;
2)
case "${COMP_WORDS[1]}" in
@@ -17,7 +17,7 @@ __polkit_auth() {
--revoke)
COMPREPLY=($(compgen -W "$(polkit-auth --explicit)" -- $cur))
;;
- --grant)
+ --grant|--block)
COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
;;
--user)
@@ -28,9 +28,9 @@ __polkit_auth() {
3)
case "${COMP_WORDS[1]}" in
--user)
- COMPREPLY=($(IFS=: compgen -S' ' -W "--explicit:--explicit-detail:--grant:--revoke" -- $cur))
+ COMPREPLY=($(IFS=: compgen -S' ' -W "--explicit:--explicit-detail:--grant:--block:--revoke" -- $cur))
;;
- --grant)
+ --grant|--block)
COMPREPLY=($(IFS=: compgen -S' ' -W "--constraint" -- $cur))
;;
esac
@@ -54,7 +54,7 @@ __polkit_auth() {
;;
esac
;;
- --grant)
+ --grant|--block)
COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
;;
--constraint)
@@ -64,7 +64,7 @@ __polkit_auth() {
;;
5)
case "${COMP_WORDS[3]}" in
- --grant)
+ --grant|--block)
COMPREPLY=($(IFS=: compgen -S' ' -W "--constraint" -- $cur))
;;
esac
More information about the hal-commit
mailing list