diff options
-rw-r--r-- | actions/org.freedesktop.policykit.policy.in | 11 | ||||
-rw-r--r-- | data/org.freedesktop.PolicyKit1.Authority.xml | 2 | ||||
-rw-r--r-- | docs/man/Makefile.am | 2 | ||||
-rw-r--r-- | docs/man/pklalockdown.xml | 136 | ||||
-rw-r--r-- | docs/man/pklocalauthority.xml | 21 | ||||
-rw-r--r-- | docs/polkit/polkit-1-docs.xml | 3 | ||||
-rw-r--r-- | docs/polkit/polkit-1-sections.txt | 1 | ||||
-rw-r--r-- | src/polkit/polkitauthorizationresult.c | 25 | ||||
-rw-r--r-- | src/polkit/polkitauthorizationresult.h | 1 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendinteractiveauthority.c | 14 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendinteractiveauthority.h | 6 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthority.c | 12 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthorizationstore.c | 61 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthorizationstore.h | 3 | ||||
-rw-r--r-- | src/programs/Makefile.am | 15 | ||||
-rw-r--r-- | src/programs/pklalockdown.c | 243 |
16 files changed, 537 insertions, 19 deletions
diff --git a/actions/org.freedesktop.policykit.policy.in b/actions/org.freedesktop.policykit.policy.in index d44a0c1..3961001 100644 --- a/actions/org.freedesktop.policykit.policy.in +++ b/actions/org.freedesktop.policykit.policy.in @@ -58,4 +58,15 @@ <allow_active>auth_admin</allow_active> </defaults> </action> + + <action id="org.freedesktop.policykit.localauthority.lockdown"> + <_description>Configure lockdown on the Local Authority</_description> + <_message>Authentication is required to configure lock down policy</_message> + <defaults> + <allow_any>no</allow_any> + <allow_inactive>no</allow_inactive> + <allow_active>auth_admin</allow_active> + </defaults> + <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/pklalockdown</annotate> + </action> </policyconfig> diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml index 7854a96..e71dc20 100644 --- a/data/org.freedesktop.PolicyKit1.Authority.xml +++ b/data/org.freedesktop.PolicyKit1.Authority.xml @@ -129,7 +129,7 @@ </annotation> <annotation name="org.gtk.EggDBus.Struct.Member" value="Dict<String,String>:details"> - <annotation name="org.gtk.EggDBus.DocString" value="Details for the result or empty if not authorized. Known key/value-pairs include <literal>polkit.temporary_authorization_id</literal> (if the authorization is temporary, this is set to the opaque temporary authorization id) and <literal>polkit.retains_authorization_after_challenge</literal> (Set to a non-empty string if the authorization will be retained after authentication (if is_challenge is TRUE))."/> + <annotation name="org.gtk.EggDBus.DocString" value="Details for the result or empty if not authorized. Known key/value-pairs include <literal>polkit.temporary_authorization_id</literal> (if the authorization is temporary, this is set to the opaque temporary authorization id), <literal>polkit.retains_authorization_after_challenge</literal> (Set to a non-empty string if the authorization will be retained after authentication (if is_challenge is TRUE)) and <literal>polkit.localauthority.lockdown</literal> (set to a non-empty string if the action is locked down via pklalockdown(1))."/> </annotation> </annotation> diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 076608b..6f164c9 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -10,6 +10,7 @@ man_MANS = \ pkexec.1 \ pkcheck.1 \ pkaction.1 \ + pklalockdown.1 \ $(NULL) %.8 %.1 : %.xml @@ -24,6 +25,7 @@ EXTRA_DIST = \ pkexec.xml \ pkcheck.xml \ pkaction.xml \ + pklalockdown.xml \ $(NULL) clean-local: diff --git a/docs/man/pklalockdown.xml b/docs/man/pklalockdown.xml new file mode 100644 index 0000000..74e4f5d --- /dev/null +++ b/docs/man/pklalockdown.xml @@ -0,0 +1,136 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +<!ENTITY version SYSTEM "../version.xml"> +]> +<refentry id="pklalockdown.1" xmlns:xi="http://www.w3.org/2003/XInclude"> + <refentryinfo> + <title>pklalockdown</title> + <date>May 2009</date> + <productname>polkit</productname> + </refentryinfo> + + <refmeta> + <refentrytitle>pklalockdown</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="version"></refmiscinfo> + </refmeta> + + <refnamediv> + <refname>pklalockdown</refname> + <refpurpose>Configure lockdown for the Local Authority</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>pklalockdown</command> + <arg><option>--version</option></arg> + <arg><option>--help</option></arg> + </cmdsynopsis> + + <cmdsynopsis> + <command>pklalockdown</command> + <arg choice="plain"> + <option>--lockdown</option> + <replaceable>action</replaceable> + </arg> + </cmdsynopsis> + + <cmdsynopsis> + <command>pklalockdown</command> + <arg choice="plain"> + <option>--remove-lockdown</option> + <replaceable>action</replaceable> + </arg> + </cmdsynopsis> + + </refsynopsisdiv> + + <refsect1 id="pklalockdown-description"> + <title>DESCRIPTION</title> + <para> + <command>pklalockdown</command> is used to configure lockdown + for the Local Authority. + </para> + <para> + The effect of locking down an action is that administrator + authentication is always needed in order for subjects to acquire + the authorization for the action in question (and the subject + has to be in an active session on a local console). The obtained + authorization is temporary and as such typically expires five + minutes after being obtained. + </para> + <para> + To lock down <replaceable>action</replaceable> use the <option>--lockdown</option> option. + To remove a lockdown for <replaceable>action</replaceable> use the <option>--remove-lockdown</option> option. + </para> + </refsect1> + + <refsect1 id="pklalockdown-required-auhtz"> + <title>REQUIRED AUTHORIZATIONS</title> + <para> + The <emphasis>org.freedesktop.policykit.localauthority.lockdown</emphasis> + authorization is needed to add or remove lockdown. By default, + this authorization requires administrator authentication and + cannot be retained. + </para> + </refsect1> + + <refsect1 id="pklalockdown-impl-details"> + <title>IMPLEMENTATION DETAILS</title> + <para> + Lockdown is implemented through <filename>.pkla</filename> + files. Locked down actions supersede other most other Local + Authority configuration as the <filename>.pkla</filename> files + are placed + in <filename>/var/lib/polkit-1/localauthority90-mandatory.d</filename>. + <para> + </para> + Programs checking authorizations can check whether an action is + locked down via by checking + the <emphasis>polkit.localauthority.lockdown</emphasis> key/value pair in + the details of the authorization response. + </para> + </refsect1> + + <refsect1 id="pklalockdown-return-values"> + <title>RETURN VALUE</title> + <para> + On success <command>pklalockdown</command> returns 0. Otherwise a + non-zero value is returned and a diagnostic message is printed + on standard error. + </para> + </refsect1> + + <refsect1 id="pklalockdown-author"><title>AUTHOR</title> + <para> + Written by David Zeuthen <email>davidz@redhat.com</email> with + a lot of help from many others. + </para> + </refsect1> + + <refsect1 id="pklalockdown-bugs"> + <title>BUGS</title> + <para> + Please send bug reports to either the distribution or the + polkit-devel mailing list, + see the link <ulink url="http://lists.freedesktop.org/mailman/listinfo/polkit-devel"/> + on how to subscribe. + </para> + </refsect1> + + <refsect1 id="pklalockdown-see-also"> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pklocalauthority</refentrytitle><manvolnum>8</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> diff --git a/docs/man/pklocalauthority.xml b/docs/man/pklocalauthority.xml index 52dded2..495aa41 100644 --- a/docs/man/pklocalauthority.xml +++ b/docs/man/pklocalauthority.xml @@ -155,7 +155,7 @@ <para> Each group in a <filename>.pkla</filename> must have a name that is unique within the file it belongs to. The following keys are - required in each group + are processed. </para> <variablelist> <varlistentry> @@ -214,12 +214,23 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term><emphasis>ReturnValue</emphasis></term> + <listitem> + <para> + A semi-colon separated list of key/value pairs (of the + form key=value) that are add to the details of + authorization result on positive matches. + </para> + </listitem> + </varlistentry> </variablelist> <para> All keys specified above are required except that only at least one of <emphasis>RequireAny</emphasis>, <emphasis>RequireInactive</emphasis> - and <emphasis>RequireActive</emphasis> is present. + and <emphasis>RequireActive</emphasis> is + present. The <emphasis>ReturnValue</emphasis> key is optional. </para> </refsect1> @@ -240,8 +251,10 @@ authorization check matches the data from the authorization check, then the authorization result from <emphasis>RequireAny</emphasis>, <emphasis>RequireInactive</emphasis> - or <emphasis>RequireActive</emphasis> is used. Finally, the - authorization entries are consulted using the user identity. + or <emphasis>RequireActive</emphasis> is used + and <emphasis>ReturnValue</emphasis> is added to the + authorization result. Finally, the authorization entries are + consulted using the user identity in the same manner. </para> <para> Note that processing continues even after a match. This allows diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml index f09954b..357efdf 100644 --- a/docs/polkit/polkit-1-docs.xml +++ b/docs/polkit/polkit-1-docs.xml @@ -110,10 +110,11 @@ <title>Manual Pages</title> <xi:include href="../man/polkit.xml"/> <xi:include href="../man/polkitd.xml"/> - <xi:include href="../man/pklocalauthority.xml"/> <xi:include href="../man/pkcheck.xml"/> <xi:include href="../man/pkaction.xml"/> <xi:include href="../man/pkexec.xml"/> + <xi:include href="../man/pklocalauthority.xml"/> + <xi:include href="../man/pklalockdown.xml"/> </part> <chapter id="polkit-hierarchy"> diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt index 333e2c8..f5bc3a8 100644 --- a/docs/polkit/polkit-1-sections.txt +++ b/docs/polkit/polkit-1-sections.txt @@ -64,6 +64,7 @@ polkit_authorization_result_get_is_authorized polkit_authorization_result_get_is_challenge polkit_authorization_result_get_retains_authorization polkit_authorization_result_get_temporary_authorization_id +polkit_authorization_result_get_local_authority_lock_down polkit_authorization_result_get_details <SUBSECTION Standard> PolkitAuthorizationResultClass diff --git a/src/polkit/polkitauthorizationresult.c b/src/polkit/polkitauthorizationresult.c index 40abed1..e55ae88 100644 --- a/src/polkit/polkitauthorizationresult.c +++ b/src/polkit/polkitauthorizationresult.c @@ -276,3 +276,28 @@ polkit_authorization_result_get_temporary_authorization_id (PolkitAuthorizationR return ret; } + +/** + * polkit_authorization_result_get_local_authority_lock_down: + * @result: A #PolkitAuthorizationResult. + * + * Gets whether the action is locked down in the Local Authority via pklalockdown(1). + * + * This method simply reads the value of the key/value pair in @details with the + * key <literal>polkit.localauthority.lockdown</literal>. + * + * Returns: %TRUE if the authorization is or will be temporary. + */ +gboolean +polkit_authorization_result_get_local_authority_lock_down (PolkitAuthorizationResult *result) +{ + gboolean ret; + PolkitDetails *details; + + ret = FALSE; + details = polkit_authorization_result_get_details (result); + if (details != NULL && polkit_details_lookup (details, "polkit.localauthority.lockdown") != NULL) + ret = TRUE; + + return ret; +} diff --git a/src/polkit/polkitauthorizationresult.h b/src/polkit/polkitauthorizationresult.h index ea479fe..ae00f83 100644 --- a/src/polkit/polkitauthorizationresult.h +++ b/src/polkit/polkitauthorizationresult.h @@ -52,6 +52,7 @@ gboolean polkit_authorization_result_get_is_authorized (P gboolean polkit_authorization_result_get_is_challenge (PolkitAuthorizationResult *result); gboolean polkit_authorization_result_get_retains_authorization (PolkitAuthorizationResult *result); const gchar *polkit_authorization_result_get_temporary_authorization_id (PolkitAuthorizationResult *result); +gboolean polkit_authorization_result_get_local_authority_lock_down (PolkitAuthorizationResult *result); /* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index bf88c2b..add7a60 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -715,7 +715,8 @@ check_authorization_sync (PolkitBackendAuthority *authority, session_is_active, action_id, details, - implicit_authorization); + implicit_authorization, + result_details); /* first see if there's an implicit authorization for subject available */ if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED) @@ -844,9 +845,12 @@ polkit_backend_interactive_authority_get_admin_identities (PolkitBackendInteract * @action_id: The action we are checking an authorization for. * @details: Details about the action. * @implicit: A #PolkitImplicitAuthorization value computed from the policy file and @subject. + * @out_details: A #PolkitDetails object that will be return to @caller. * * Checks whether @subject is authorized to perform the action - * specified by @action_id and @details. + * specified by @action_id and @details. The implementation may + * append key/value pairs to @out_details to return extra information + * to @caller. * * The default implementation of this method simply returns @implicit. * @@ -862,7 +866,8 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte gboolean subject_is_active, const gchar *action_id, PolkitDetails *details, - PolkitImplicitAuthorization implicit) + PolkitImplicitAuthorization implicit, + PolkitDetails *out_details) { PolkitBackendInteractiveAuthorityClass *klass; PolkitImplicitAuthorization ret; @@ -883,7 +888,8 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte subject_is_active, action_id, details, - implicit); + implicit, + out_details); } return ret; diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.h b/src/polkitbackend/polkitbackendinteractiveauthority.h index 9820dac..408c3e4 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.h +++ b/src/polkitbackend/polkitbackendinteractiveauthority.h @@ -83,7 +83,8 @@ struct _PolkitBackendInteractiveAuthorityClass gboolean subject_is_active, const gchar *action_id, PolkitDetails *details, - PolkitImplicitAuthorization implicit); + PolkitImplicitAuthorization implicit, + PolkitDetails *out_details); /*< private >*/ /* Padding for future expansion */ @@ -138,7 +139,8 @@ PolkitImplicitAuthorization polkit_backend_interactive_authority_check_authoriza gboolean subject_is_active, const gchar *action_id, PolkitDetails *details, - PolkitImplicitAuthorization implicit); + PolkitImplicitAuthorization implicit, + PolkitDetails *out_details); G_END_DECLS diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c index a3fb7f2..932706e 100644 --- a/src/polkitbackend/polkitbackendlocalauthority.c +++ b/src/polkitbackend/polkitbackendlocalauthority.c @@ -79,7 +79,8 @@ static PolkitImplicitAuthorization polkit_backend_local_authority_check_authoriz gboolean subject_is_active, const gchar *action_id, PolkitDetails *details, - PolkitImplicitAuthorization implicit); + PolkitImplicitAuthorization implicit, + PolkitDetails *out_details); G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority, @@ -257,7 +258,8 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv gboolean subject_is_active, const gchar *action_id, PolkitDetails *details, - PolkitImplicitAuthorization implicit) + PolkitImplicitAuthorization implicit, + PolkitDetails *out_details) { PolkitBackendLocalAuthority *local_authority; PolkitBackendLocalAuthorityPrivate *priv; @@ -296,7 +298,8 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv details, &ret_any, &ret_inactive, - &ret_active)) + &ret_active, + out_details)) { if (subject_is_local && subject_is_active) { @@ -330,7 +333,8 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv details, &ret_any, &ret_inactive, - &ret_active)) + &ret_active, + out_details)) { if (subject_is_local && subject_is_active) { diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c index 1c898f7..bdd0103 100644 --- a/src/polkitbackend/polkitbackendlocalauthorizationstore.c +++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.c @@ -21,6 +21,7 @@ #include "config.h" +#include <string.h> #include <polkit/polkit.h> #include "polkitbackendlocalauthorizationstore.h" @@ -79,6 +80,8 @@ typedef struct PolkitImplicitAuthorization result_any; PolkitImplicitAuthorization result_inactive; PolkitImplicitAuthorization result_active; + + GHashTable *return_value; } LocalAuthorization; static void @@ -89,6 +92,8 @@ local_authorization_free (LocalAuthorization *authorization) g_list_free (authorization->identity_specs); g_list_foreach (authorization->action_specs, (GFunc) g_pattern_spec_free, NULL); g_list_free (authorization->action_specs); + if (authorization->return_value != NULL) + g_hash_table_unref (authorization->return_value); g_free (authorization); } @@ -105,6 +110,7 @@ local_authorization_new (GKeyFile *key_file, gchar *result_any_string; gchar *result_inactive_string; gchar *result_active_string; + gchar **return_value_strings; guint n; identity_strings = NULL; @@ -112,6 +118,7 @@ local_authorization_new (GKeyFile *key_file, result_any_string = NULL; result_inactive_string = NULL; result_active_string = NULL; + return_value_strings = NULL; authorization = g_new0 (LocalAuthorization, 1); @@ -221,6 +228,42 @@ local_authorization_new (GKeyFile *key_file, goto out; } + return_value_strings = g_key_file_get_string_list (key_file, + group, + "ReturnValue", + NULL, + error); + if (return_value_strings != NULL) + { + for (n = 0; return_value_strings[n] != NULL; n++) + { + gchar *p; + const gchar *key; + const gchar *value; + + p = strchr (return_value_strings[n], '='); + if (p == NULL) + { + g_warning ("Item `%s' in ReturnValue is malformed. Ignoring.", + return_value_strings[n]); + continue; + } + + *p = '\0'; + key = return_value_strings[n]; + value = p + 1; + + if (authorization->return_value == NULL) + { + authorization->return_value = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + } + g_hash_table_insert (authorization->return_value, g_strdup (key), g_strdup (value)); + } + } + authorization->id = g_strdup_printf ("%s::%s", filename, group); out: @@ -229,6 +272,7 @@ local_authorization_new (GKeyFile *key_file, g_free (result_any_string); g_free (result_inactive_string); g_free (result_active_string); + g_strfreev (return_value_strings); return authorization; } @@ -605,6 +649,7 @@ polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorization * @out_result_any: Return location for the result for any subjects if the look up matched. * @out_result_inactive: Return location for the result for subjects in local inactive sessions if the look up matched. * @out_result_active: Return location for the result for subjects in local active sessions if the look up matched. + * @out_details: %NULL or a #PolkitDetails object to append key/value pairs to on a positive match. * * Checks if an authorization entry from @store matches @identity, @action_id and @details. * @@ -618,7 +663,8 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization PolkitDetails *details, PolkitImplicitAuthorization *out_result_any, PolkitImplicitAuthorization *out_result_inactive, - PolkitImplicitAuthorization *out_result_active) + PolkitImplicitAuthorization *out_result_active, + PolkitDetails *out_details) { GList *l, *ll; gboolean ret; @@ -667,6 +713,19 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization *out_result_active = authorization->result_active; ret = TRUE; + if (out_details != NULL && authorization->return_value != NULL) + { + GHashTableIter iter; + const gchar *key; + const gchar *value; + + g_hash_table_iter_init (&iter, authorization->return_value); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) + { + polkit_details_insert (out_details, key, value); + } + } + #if 0 g_debug ("authorization with id `%s' matched action_id `%s' for identity `%s'", authorization->id, diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.h b/src/polkitbackend/polkitbackendlocalauthorizationstore.h index 2f2b452..865bf22 100644 --- a/src/polkitbackend/polkitbackendlocalauthorizationstore.h +++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.h @@ -77,7 +77,8 @@ gboolean polkit_backend_local_authorization_store_lookup (PolkitBackendLocalA PolkitDetails *details, PolkitImplicitAuthorization *out_result_any, PolkitImplicitAuthorization *out_result_inactive, - PolkitImplicitAuthorization *out_result_active); + PolkitImplicitAuthorization *out_result_active, + PolkitDetails *out_details); G_END_DECLS diff --git a/src/programs/Makefile.am b/src/programs/Makefile.am index 074fb39..226c9f3 100644 --- a/src/programs/Makefile.am +++ b/src/programs/Makefile.am @@ -17,7 +17,7 @@ INCLUDES = \ # ---------------------------------------------------------------------------------------------------- -bin_PROGRAMS = pkexec pkcheck pkaction +bin_PROGRAMS = pkexec pkcheck pkaction pklalockdown # ---------------------------------------------------------------------------------------------------- @@ -82,6 +82,19 @@ pkaction_LDADD = \ # ---------------------------------------------------------------------------------------------------- +pklalockdown_SOURCES = pklalockdown.c + +pklalockdown_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(NULL) + +pklalockdown_LDADD = \ + $(GLIB_LDADD) \ + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \ + $(NULL) + +# ---------------------------------------------------------------------------------------------------- + clean-local : rm -f *~ diff --git a/src/programs/pklalockdown.c b/src/programs/pklalockdown.c new file mode 100644 index 0000000..88ce660 --- /dev/null +++ b/src/programs/pklalockdown.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <grp.h> +#include <pwd.h> +#include <errno.h> +#include <glib/gstdio.h> + +#include <polkit/polkit.h> + +static gchar *get_lockdown_filename (const gchar *action_id); +static gboolean lockdown_exists (const gchar *action_id); + + +static void +usage (int argc, char *argv[]) +{ + GError *error; + + error = NULL; + if (!g_spawn_command_line_sync ("man pklalockdown", + NULL, + NULL, + NULL, + &error)) + { + g_printerr ("Cannot show manual page: %s\n", error->message); + g_error_free (error); + } +} + +int +main (int argc, char *argv[]) +{ + guint n; + guint ret; + gboolean opt_show_help; + gboolean opt_show_version; + gchar *opt_lockdown; + gchar *opt_remove_lockdown; + + ret = 1; + + opt_show_help = FALSE; + opt_show_version = FALSE; + opt_lockdown = NULL; + opt_remove_lockdown = NULL; + + /* if we are not yet uid 0, make us uid 0 through pkexec */ + if (getuid () != 0) + { + gchar **exec_argv; + + exec_argv = g_new0 (gchar *, argc + 2); + exec_argv[0] = PACKAGE_BIN_DIR "/pkexec"; + memcpy (exec_argv + 1, argv, argc * sizeof (gchar *)); + + if (execv (PACKAGE_BIN_DIR "/pkexec", exec_argv) != 0) + { + g_printerr ("Error executing " PACKAGE_BIN_DIR "/pkexec: %s\n", g_strerror (errno)); + goto out; + } + + g_assert_not_reached (); + } + + /* We are now uid 0 (by default, the user had to authenticate to get + * here) - be careful to check all incoming args + */ + for (n = 1; n < (guint) argc; n++) + { + if (strcmp (argv[n], "--help") == 0) + { + opt_show_help = TRUE; + } + else if (strcmp (argv[n], "--version") == 0) + { + opt_show_version = TRUE; + } + else if (strcmp (argv[n], "--lockdown") == 0 || strcmp (argv[n], "-l") == 0) + { + n++; + if (n >= (guint) argc) + { + usage (argc, argv); + goto out; + } + + opt_lockdown = g_strdup (argv[n]); + } + else if (strcmp (argv[n], "--remove-lockdown") == 0 || strcmp (argv[n], "-r") == 0) + { + n++; + if (n >= (guint) argc) + { + usage (argc, argv); + goto out; + } + + opt_remove_lockdown = g_strdup (argv[n]); + } + else + { + break; + } + } + + if (opt_show_help) + { + usage (argc, argv); + ret = 0; + goto out; + } + else if (opt_show_version) + { + g_print ("pkexec version %s\n", PACKAGE_VERSION); + ret = 0; + goto out; + } + else if (opt_lockdown != NULL) + { + gchar *filename; + gchar *contents; + GError *error; + + if (lockdown_exists (opt_lockdown)) + { + g_printerr ("Error: action %s is already locked down\n", opt_lockdown); + goto out; + } + + filename = get_lockdown_filename (opt_lockdown); + contents = g_strdup_printf ("# Added by pklalockdown(1)\n" + "#\n" + "[Lockdown]\n" + "Identity=unix-user:*\n" + "Action=%s\n" + "ResultAny=no\n" + "ResultInactive=no\n" + "ResultActive=auth_admin_keep\n" + "ReturnValue=polkit.localauthority.lockdown=1", + opt_lockdown); + error = NULL; + if (!g_file_set_contents (filename, + contents, + -1, + &error)) + { + g_printerr ("Error: Cannot write to file %s: %s\n", filename, error->message); + g_error_free (error); + g_free (filename); + g_free (contents); + goto out; + } + g_free (filename); + g_free (contents); + ret = 0; + goto out; + } + else if (opt_remove_lockdown != NULL) + { + gchar *filename; + + if (!lockdown_exists (opt_remove_lockdown)) + { + g_printerr ("Error: action %s is not locked down\n", opt_remove_lockdown); + goto out; + } + + filename = get_lockdown_filename (opt_remove_lockdown); + if (g_unlink (filename) != 0) + { + g_printerr ("Error: Cannot unlink file %s: %s\n", filename, g_strerror (errno)); + g_free (filename); + goto out; + } + g_free (filename); + + ret = 0; + goto out; + } + + usage (argc, argv); + + out: + g_free (opt_lockdown); + g_free (opt_remove_lockdown); + return ret; +} + +static gchar * +get_lockdown_filename (const gchar *action_id) +{ + return g_strdup_printf (PACKAGE_LOCALSTATE_DIR + "/lib/polkit-1/localauthority/90-mandatory.d/" + "org.freedesktop.policykit.localauthority.lockdown.action-%s.pkla", + action_id); +} + +static gboolean +lockdown_exists (const gchar *action_id) +{ + gchar *filename; + gboolean ret; + + ret = FALSE; + + filename = get_lockdown_filename (action_id); + if (g_file_test (filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS)) + ret = TRUE; + g_free (filename); + + return ret; +} + |