PolicyKit: Branch 'master' - 2 commits
David Zeuthen
david at kemper.freedesktop.org
Mon Aug 20 14:55:03 PDT 2007
doc/TODO | 9 -
doc/api/polkit/polkit-docs.xml | 2
doc/man/PolicyKit.conf.5.in | 44 +++++
polkit-grant/polkit-grant-helper.c | 237 ++++++++++++++++++++++++++++--
polkit-grant/polkit-grant.c | 85 +++++++----
polkit-grant/polkit-grant.h | 20 ++
polkit/Makefile.am | 3
polkit/polkit-config.c | 283 ++++++++++++++++++++++++++++---------
polkit/polkit-config.h | 25 +++
polkit/polkit-context.c | 20 ++
polkit/polkit-context.h | 9 -
polkit/polkit-policy-file.c | 206 +++++++++++++++++++++-----
12 files changed, 782 insertions(+), 161 deletions(-)
New commits:
diff-tree 07bd50776b1be13f506f9a75763ecc32a469d408 (from af39b832e3bf2e46fe58af74304d7f6f85e853bf)
Author: David Zeuthen <davidz at redhat.com>
Date: Mon Aug 20 17:51:02 2007 -0400
properly support i18n'ed messages from .policy files
Ugh, I'm not sure if there's a smarter way of dealing with xml:lang
when using expat (google searches for this suggests no) but the way I
fixed this is surely a bitch.
diff --git a/polkit/polkit-policy-file.c b/polkit/polkit-policy-file.c
index 1efdbee..b5224f6 100644
--- a/polkit/polkit-policy-file.c
+++ b/polkit/polkit-policy-file.c
@@ -85,6 +85,7 @@ enum {
typedef struct {
XML_Parser parser;
int state;
+
char *group_id;
char *action_id;
@@ -95,12 +96,56 @@ typedef struct {
polkit_bool_t load_descriptions;
- char *group_description;
- char *policy_description;
- char *policy_message;
+ GHashTable *group_descriptions;
+ GHashTable *policy_descriptions;
+ GHashTable *policy_messages;
+
+ char *group_description_nolang;
+ char *policy_description_nolang;
+ char *policy_message_nolang;
+
+ /* the language according to $LANG (e.g. en_US, da_DK, fr, en_CA minus the encoding) */
+ char *lang;
+
+ /* the value of xml:lang for the thing we're reading in _cdata() */
+ char *elem_lang;
} ParserData;
static void
+pd_unref_action_data (ParserData *pd)
+{
+ g_free (pd->action_id);
+ pd->action_id = NULL;
+ g_free (pd->policy_description_nolang);
+ pd->policy_description_nolang = NULL;
+ g_free (pd->policy_message_nolang);
+ pd->policy_message_nolang = NULL;
+ if (pd->policy_descriptions != NULL) {
+ g_hash_table_destroy (pd->policy_descriptions);
+ pd->policy_descriptions = NULL;
+ }
+ if (pd->policy_messages != NULL) {
+ g_hash_table_destroy (pd->policy_messages);
+ pd->policy_messages = NULL;
+ }
+}
+
+static void
+pd_unref_group_data (ParserData *pd)
+{
+ pd_unref_action_data (pd);
+
+ g_free (pd->group_id);
+ pd->group_id = NULL;
+ g_free (pd->group_description_nolang);
+ pd->group_description_nolang = NULL;
+ if (pd->group_descriptions != NULL) {
+ g_hash_table_destroy (pd->group_descriptions);
+ pd->group_descriptions = NULL;
+ }
+}
+
+static void
_start (void *data, const char *el, const char **attr)
{
int state;
@@ -122,41 +167,50 @@ _start (void *data, const char *el, cons
if (strcmp (el, "group") == 0) {
if (num_attr != 2 || strcmp (attr[0], "id") != 0)
goto error;
- g_free (pd->group_id);
- pd->group_id = g_strdup (attr[1]);
state = STATE_IN_GROUP;
- g_free (pd->group_description);
- pd->group_description = NULL;
+ pd_unref_group_data (pd);
+ pd->group_id = g_strdup (attr[1]);
+ pd->group_descriptions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
break;
case STATE_IN_GROUP:
if (strcmp (el, "policy") == 0) {
if (num_attr != 2 || strcmp (attr[0], "id") != 0)
goto error;
- g_free (pd->action_id);
- pd->action_id = g_strdup (attr[1]);
state = STATE_IN_POLICY;
- pd->policy_description = NULL;
- pd->policy_message = NULL;
+ pd_unref_action_data (pd);
+ pd->action_id = g_strdup (attr[1]);
+ pd->policy_descriptions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ pd->policy_messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
/* initialize defaults */
pd->defaults_allow_inactive = POLKIT_RESULT_NO;
pd->defaults_allow_active = POLKIT_RESULT_NO;
- }
- else if (strcmp (el, "description") == 0)
+ } else if (strcmp (el, "description") == 0) {
+ if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) {
+ pd->elem_lang = g_strdup (attr[1]);
+ }
state = STATE_IN_GROUP_DESCRIPTION;
+ }
break;
case STATE_IN_GROUP_DESCRIPTION:
break;
case STATE_IN_POLICY:
if (strcmp (el, "defaults") == 0)
state = STATE_IN_DEFAULTS;
- else if (strcmp (el, "description") == 0)
+ else if (strcmp (el, "description") == 0) {
+ if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) {
+ pd->elem_lang = g_strdup (attr[1]);
+ }
state = STATE_IN_POLICY_DESCRIPTION;
- else if (strcmp (el, "message") == 0)
+ } else if (strcmp (el, "message") == 0) {
+ if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) {
+ pd->elem_lang = g_strdup (attr[1]);
+ }
state = STATE_IN_POLICY_MESSAGE;
+ }
break;
case STATE_IN_POLICY_DESCRIPTION:
break;
@@ -197,25 +251,35 @@ _cdata (void *data, const char *s, int l
case STATE_IN_GROUP_DESCRIPTION:
if (pd->load_descriptions) {
- if (pd->group_description != NULL)
- g_free (pd->group_description);
- pd->group_description = g_strdup (str);
+
+ if (pd->elem_lang == NULL) {
+ g_free (pd->group_description_nolang);
+ pd->group_description_nolang = g_strdup (str);
+ } else {
+ g_hash_table_insert (pd->group_descriptions, g_strdup (pd->elem_lang), g_strdup (str));
+ }
}
break;
case STATE_IN_POLICY_DESCRIPTION:
if (pd->load_descriptions) {
- if (pd->policy_description != NULL)
- g_free (pd->policy_description);
- pd->policy_description = g_strdup (str);
+ if (pd->elem_lang == NULL) {
+ g_free (pd->policy_description_nolang);
+ pd->policy_description_nolang = g_strdup (str);
+ } else {
+ g_hash_table_insert (pd->policy_descriptions, g_strdup (pd->elem_lang), g_strdup (str));
+ }
}
break;
case STATE_IN_POLICY_MESSAGE:
if (pd->load_descriptions) {
- if (pd->policy_message != NULL)
- g_free (pd->policy_message);
- pd->policy_message = g_strdup (str);
+ if (pd->elem_lang == NULL) {
+ g_free (pd->policy_message_nolang);
+ pd->policy_message_nolang = g_strdup (str);
+ } else {
+ g_hash_table_insert (pd->policy_messages, g_strdup (pd->elem_lang), g_strdup (str));
+ }
}
break;
@@ -243,6 +307,53 @@ extern void _polkit_policy_file_entry_se
const char *policy_description,
const char *policy_message);
+/**
+ * _localize:
+ * @translations: a mapping from xml:lang to the value, e.g. 'da' -> 'Smadre', 'en_CA' -> 'Punch, Aye!'
+ * @untranslated: the untranslated value, e.g. 'Punch'
+ * @lang: the locale we're interested in, e.g. 'da_DK', 'da', 'en_CA', 'en_US'; basically just $LANG
+ * with the encoding cut off. Maybe be NULL.
+ *
+ * Pick the correct translation to use.
+ *
+ * Returns: the localized string to use
+ */
+static const char *
+_localize (GHashTable *translations, const char *untranslated, const char *lang)
+{
+ const char *result;
+ char *lang2;
+ int n;
+
+ if (lang == NULL) {
+ result = untranslated;
+ goto out;
+ }
+
+ /* first see if we have the translation */
+ result = g_hash_table_lookup (translations, lang);
+ if (result != NULL)
+ goto out;
+
+ /* we could have a translation for 'da' but lang=='da_DK'; cut off the last part and try again */
+ lang2 = g_strdup (lang);
+ for (n = 0; lang2[n] != '\0'; n++) {
+ if (lang2[n] == '_') {
+ lang2[n] = '\0';
+ break;
+ }
+ }
+ result = g_hash_table_lookup (translations, lang2);
+ g_free (lang2);
+ if (result != NULL)
+ goto out;
+
+ /* fall back to untranslated */
+ result = untranslated;
+out:
+ return result;
+}
+
static void
_end (void *data, const char *el)
{
@@ -251,6 +362,9 @@ _end (void *data, const char *el)
state = STATE_NONE;
+ g_free (pd->elem_lang);
+ pd->elem_lang = NULL;
+
switch (pd->state) {
case STATE_NONE:
break;
@@ -265,6 +379,9 @@ _end (void *data, const char *el)
break;
case STATE_IN_POLICY:
{
+ const char *group_description;
+ const char *policy_description;
+ const char *policy_message;
PolKitPolicyFileEntry *pfe;
pfe = _polkit_policy_file_entry_new (pd->group_id, pd->action_id,
@@ -273,11 +390,15 @@ _end (void *data, const char *el)
if (pfe == NULL)
goto error;
+ group_description = _localize (pd->group_descriptions, pd->group_description_nolang, pd->lang);
+ policy_description = _localize (pd->policy_descriptions, pd->policy_description_nolang, pd->lang);
+ policy_message = _localize (pd->policy_messages, pd->policy_message_nolang, pd->lang);
+
if (pd->load_descriptions)
_polkit_policy_file_entry_set_descriptions (pfe,
- pd->group_description,
- pd->policy_description,
- pd->policy_message);
+ group_description,
+ policy_description,
+ policy_message);
pd->pf->entries = g_slist_prepend (pd->pf->entries, pfe);
@@ -327,6 +448,7 @@ polkit_policy_file_new (const char *path
PolKitPolicyFile *pf;
ParserData pd;
int xml_res;
+ char *lang;
pf = NULL;
@@ -351,6 +473,9 @@ polkit_policy_file_new (const char *path
goto error;
}
+ /* clear parser data */
+ memset (&pd, 0, sizeof (ParserData));
+
pd.parser = XML_ParserCreate (NULL);
if (pd.parser == NULL) {
polkit_error_set_error (error, POLKIT_ERROR_OUT_OF_MEMORY,
@@ -366,23 +491,24 @@ polkit_policy_file_new (const char *path
pf = g_new0 (PolKitPolicyFile, 1);
pf->refcount = 1;
+ /* init parser data */
pd.state = STATE_NONE;
- pd.group_id = NULL;
- pd.action_id = NULL;
- pd.group_description = NULL;
- pd.policy_description = NULL;
- pd.policy_message = NULL;
pd.pf = pf;
pd.load_descriptions = load_descriptions;
+ lang = getenv ("LANG");
+ if (lang != NULL) {
+ int n;
+ pd.lang = g_strdup (lang);
+ for (n = 0; pd.lang[n] != '\0'; n++) {
+ if (pd.lang[n] == '.') {
+ pd.lang[n] = '\0';
+ break;
+ }
+ }
+ }
xml_res = XML_Parse (pd.parser, buf, buflen, 1);
- g_free (pd.group_id);
- g_free (pd.action_id);
- g_free (pd.group_description);
- g_free (pd.policy_description);
- g_free (pd.policy_message);
-
if (xml_res == 0) {
polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
"%s:%d: parse error: %s",
@@ -396,12 +522,12 @@ polkit_policy_file_new (const char *path
}
XML_ParserFree (pd.parser);
g_free (buf);
-
+ pd_unref_group_data (&pd);
return pf;
error:
if (pf != NULL)
polkit_policy_file_unref (pf);
-
+ pd_unref_group_data (&pd);
return NULL;
}
diff-tree af39b832e3bf2e46fe58af74304d7f6f85e853bf (from 7034e0c24e37963d72a50371ed6ad6a51a740d02)
Author: David Zeuthen <davidz at redhat.com>
Date: Mon Aug 13 13:44:33 2007 -0400
export PolKitConfig and provide a <define_admin_auth/> config file directive
Also change the libpolkit-grant API a bit to work with these changes.
diff --git a/doc/TODO b/doc/TODO
index e4495aa..311a44b 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -3,7 +3,8 @@
- Verify the security model
- - Audit all code; especially the setgid helper
+ - Audit all code; especially the setgid polkit_user helper and setuid
+ root pam specific helper
- Granted privileges are currently world-visible; see
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=244941
@@ -24,12 +25,6 @@
- Make sure API coverage is 100%
- - Have support for systems that don't use the root account; e.g.
- instead of authenticating as root, authenticate a user in
- e.g. the 'wheel' group. Probably means we need a combobox in the UI
- bits (e.g. PolicyKit-gnome + friends) for selecting the user to
- auth as.
-
- Potentially drop the glib dependency (it's not visible in the
external API). This is mainly to be able to handle OOM for
mechanisms that will need this (such as dbus-daemon)
diff --git a/doc/api/polkit/polkit-docs.xml b/doc/api/polkit/polkit-docs.xml
index 8358039..fd5f811 100644
--- a/doc/api/polkit/polkit-docs.xml
+++ b/doc/api/polkit/polkit-docs.xml
@@ -76,7 +76,7 @@
<xi:include href="xml/polkit-seat.xml"/>
<xi:include href="xml/polkit-session.xml"/>
<xi:include href="xml/polkit-caller.xml"/>
- <xi:include href="xml/polkit-module.xml"/>
+ <xi:include href="xml/polkit-config.xml"/>
</reference>
<index>
diff --git a/doc/man/PolicyKit.conf.5.in b/doc/man/PolicyKit.conf.5.in
index c75d307..1374b29 100644
--- a/doc/man/PolicyKit.conf.5.in
+++ b/doc/man/PolicyKit.conf.5.in
@@ -100,15 +100,15 @@ is supported and it can assume the follo
.B no
Access denied.
.TP
-.B auth_root
+.B auth_admin
Access denied, but authentication of the caller as root will grant
access to only that caller.
.TP
-.B auth_root_keep_session
+.B auth_admin_keep_session
Access denied, but authentication of the caller as root will grant
access for the remainder of the session the caller stems from.
.TP
-.B auth_root_keep_always
+.B auth_admin_keep_always
Access denied, but authentication of the caller as root will grant
access to the user of the caller in the future.
.TP
@@ -127,6 +127,44 @@ access to the user of the caller in the
.B yes
Access granted.
+.PP
+
+.I define_admin_auth
+
+This element is used to specify the meaning of "authenticate as
+administrator". It is normally used at the top-level but can also be
+used deep inside a number of
+.I match
+elements for conditional behavior.
+
+There can only be a single attribute in each
+.I define_admin_auth
+element. POSIX Extended Regular Expression syntax are
+.B not
+supported in the value part, however multiple values to match on can
+be separated with the bar (|) character. The following attributes
+are supported:
+
+.TP
+.B user
+Administrator authentication means authenticate as the given user.
+If no
+.I define_admin_auth
+element is given, the default is to use
+.B user="root"
+e.g. administrator authentication mean authenticate as the super user.
+
+.TP
+.B group
+Administrator authentication means that any user in the groups matching
+the given value can be used to authenticate. Typically, on a system
+with the root account disabled one wants to use something like
+.B group="wheel"
+to e.g. enable all UNIX users in the UNIX group
+.B wheel
+to be able to authentication whenever administrator authentication
+is required.
+
.SH EXAMPLES
For brevity the standard XML and doctype headers are omitted in the
diff --git a/polkit-grant/polkit-grant-helper.c b/polkit-grant/polkit-grant-helper.c
index 049d10c..0358973 100644
--- a/polkit-grant/polkit-grant-helper.c
+++ b/polkit-grant/polkit-grant-helper.c
@@ -78,13 +78,24 @@
* the right to do the Action.
*
* <-- Tell libpolkit-grant about grant details, e.g.
- * {self,admin}_{,keep_session,keep_always}
- * using stdout
+ * {self,admin}_{,keep_session,keep_always} +
+ * what users can authenticate using stdout
*
* Receive grant details on stdin.
* Caller prepares UI dialog depending
* on grant details.
*
+ * if admin_users is not empty, wait for
+ * user name of admin user to auth on stdin
+ *
+ * if admin_users is not empty, write
+ * user name of admin user to auth on stdout -->
+ *
+ *
+ * verify that given username is
+ * in admin_users
+ *
+ *
* Spawn polkit-grant-helper-pam
* with no args -->
*
@@ -132,8 +143,13 @@
*/
-/* the authentication itself is done via a setuid root helper; this is
- * to make the code running as uid 0 easier to audit. */
+/**
+ * do_auth:
+ *
+ * the authentication itself is done via a setuid root helper; this is
+ * to make the code running as uid 0 easier to audit.
+ *
+ */
static polkit_bool_t
do_auth (const char *user_to_auth)
{
@@ -208,6 +224,7 @@ do_auth (const char *user_to_auth)
/* read from parent */
if (fgets (buf, sizeof buf, stdin) == NULL)
goto out;
+
#ifdef PGH_DEBUG
fprintf (stderr, "received: '%s' from parent; sending to child\n", buf);
#endif /* PGH_DEBUG */
@@ -224,11 +241,32 @@ out:
return ret;
}
+/**
+ * verify_with_polkit:
+ * @caller_pid: the process id of the caller
+ * @action_name: name of the action
+ * @result: return location for result AKA how the user can auth
+ * @out_session_objpath: return location for ConsoleKit session identifier
+ * @out_admin_users: return location for a NULL-terminated array of
+ * strings that can be user to auth as admin. Is set to NULL if the
+ * super user (e.g. uid 0) should be user to auth as admin.
+ *
+ * Verify that the given caller can authenticate to gain a privilege
+ * to do the given action. If the authentication requires
+ * administrator privileges, also return a list of users that can be
+ * used to do this cf. the <define_admin_auth/> element in the
+ * configuration file; see the PolicyKit.conf(5) manual page for
+ * details.
+ *
+ * Returns: TRUE if, and only if, the given caller can authenticate to
+ * gain a privilege to do the given action.
+ */
static polkit_bool_t
verify_with_polkit (pid_t caller_pid,
const char *action_name,
PolKitResult *result,
- char **out_session_objpath)
+ char **out_session_objpath,
+ char ***out_admin_users)
{
PolKitCaller *caller;
PolKitSession *session;
@@ -287,6 +325,103 @@ verify_with_polkit (pid_t caller_pid,
goto error;
}
+ *out_admin_users = NULL;
+
+ /* for admin auth, get a list of users that can be used - this is basically evaluating the
+ * <define_admin_auth/> directives in the config file...
+ */
+ if (*result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+ *result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
+ *result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
+ PolKitConfig *pk_config;
+ PolKitConfigAdminAuthType admin_auth_type;
+ const char *admin_auth_data;
+
+ pk_config = polkit_context_get_config (pol_ctx);
+ if (polkit_config_determine_admin_auth_type (pk_config,
+ action,
+ caller,
+ &admin_auth_type,
+ &admin_auth_data)) {
+#ifdef PGH_DEBUG
+ fprintf (stderr, "polkit-grant-helper: admin_auth_type=%d data='%s'\n", admin_auth_type, admin_auth_data);
+#endif /* PGH_DEBUG */
+ switch (admin_auth_type) {
+ case POLKIT_CONFIG_ADMIN_AUTH_TYPE_USER:
+ if (admin_auth_data != NULL)
+ *out_admin_users = g_strsplit (admin_auth_data, "|", 0);
+ break;
+ case POLKIT_CONFIG_ADMIN_AUTH_TYPE_GROUP:
+ if (admin_auth_data != NULL) {
+ int n;
+ char **groups;
+ GSList *i;
+ GSList *users;
+
+
+ users = NULL;
+ groups = g_strsplit (admin_auth_data, "|", 0);
+ for (n = 0; groups[n] != NULL; n++) {
+ int m;
+ struct group *group;
+
+ /* This is fine; we're a single-threaded app */
+ if ((group = getgrnam (groups[n])) == NULL)
+ continue;
+
+ for (m = 0; group->gr_mem[m] != NULL; m++) {
+ const char *user;
+ gboolean found;
+
+ user = group->gr_mem[m];
+ found = FALSE;
+
+#ifdef PGH_DEBUG
+ fprintf (stderr, "polkit-grant-helper: examining member '%s' of group '%s'\n", user, groups[n]);
+#endif /* PGH_DEBUG */
+
+ /* skip user 'root' since he is often member of 'wheel' etc. */
+ if (strcmp (user, "root") == 0)
+ continue;
+ /* TODO: we should probably only consider users with an uid
+ * in a given "safe" range, e.g. between 500 and 32000 or
+ * something like that...
+ */
+
+ for (i = users; i != NULL; i = g_slist_next (i)) {
+ if (strcmp (user, (const char *) i->data) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+#ifdef PGH_DEBUG
+ fprintf (stderr, "polkit-grant-helper: added user '%s'\n", user);
+#endif /* PGH_DEBUG */
+
+ users = g_slist_prepend (users, g_strdup (user));
+ }
+
+ }
+ g_strfreev (groups);
+
+ users = g_slist_sort (users, (GCompareFunc) strcmp);
+
+ *out_admin_users = g_new0 (char *, g_slist_length (users) + 1);
+ for (i = users, n = 0; i != NULL; i = g_slist_next (i)) {
+ (*out_admin_users)[n++] = i->data;
+ }
+
+ g_slist_free (users);
+ }
+ break;
+ }
+ }
+ }
+
+
/* TODO: we should probably clean up */
return TRUE;
@@ -298,6 +433,7 @@ static polkit_bool_t
get_and_validate_override_details (PolKitResult *result)
{
char buf[256];
+ char *textual_result;
PolKitResult desired_result;
if (fgets (buf, sizeof buf, stdin) == NULL)
@@ -305,10 +441,17 @@ get_and_validate_override_details (PolKi
if (strlen (buf) > 0 &&
buf[strlen (buf) - 1] == '\n')
buf[strlen (buf) - 1] = '\0';
-
- fprintf (stderr, "polkit-grant-helper: caller said '%s'\n", buf);
- if (!polkit_result_from_string_representation (buf, &desired_result))
+ if (strncmp (buf,
+ "POLKIT_GRANT_CALLER_PASS_OVERRIDE_GRANT_TYPE ",
+ sizeof "POLKIT_GRANT_CALLER_PASS_OVERRIDE_GRANT_TYPE " - 1) != 0) {
+ goto error;
+ }
+ textual_result = buf + sizeof "POLKIT_GRANT_CALLER_PASS_OVERRIDE_GRANT_TYPE " - 1;
+
+ fprintf (stderr, "polkit-grant-helper: caller said '%s'\n", textual_result);
+
+ if (!polkit_result_from_string_representation (textual_result, &desired_result))
goto error;
fprintf (stderr, "polkit-grant-helper: testing for voluntarily downgrade from '%s' to '%s'\n",
@@ -386,6 +529,7 @@ main (int argc, char *argv[])
char *session_objpath;
struct passwd *pw;
polkit_bool_t dbres;
+ char **admin_users;
ret = 3;
@@ -461,10 +605,20 @@ main (int argc, char *argv[])
* - figure out if the caller can really auth to do the action
* - learn what ConsoleKit session the caller belongs to
*/
- if (!verify_with_polkit (caller_pid, action_name, &result, &session_objpath))
+ if (!verify_with_polkit (caller_pid, action_name, &result, &session_objpath, &admin_users))
goto out;
#ifdef PGH_DEBUG
+ if (admin_users != NULL) {
+ int n;
+ fprintf (stderr, "polkit-grant-helper: admin_users: ");
+ for (n = 0; admin_users[n] != NULL; n++)
+ fprintf (stderr, "'%s' ", admin_users[n]);
+ fprintf (stderr, "\n");
+ }
+#endif /* PGH_DEBUG */
+
+#ifdef PGH_DEBUG
fprintf (stderr, "polkit-grant-helper: polkit result = '%s'\n",
polkit_result_to_string_representation (result));
fprintf (stderr, "polkit-grant-helper: session_objpath = '%s'\n", session_objpath);
@@ -477,21 +631,70 @@ main (int argc, char *argv[])
polkit_result_to_string_representation (result));
fflush (stdout);
- /* figure out what user to auth */
- if (result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
- result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
- result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
- /* TODO: with wheel support, figure out what user to auth */
- user_to_auth = "root";
+ /* if admin auth is required, tell caller about possible users */
+ if (admin_users != NULL) {
+ int n;
+ fprintf (stdout, "POLKIT_GRANT_HELPER_TELL_ADMIN_USERS");
+ for (n = 0; admin_users[n] != NULL; n++)
+ fprintf (stdout, " %s", admin_users[n]);
+ fprintf (stdout, "\n");
+ fflush (stdout);
+ }
+
+
+ /* wait for libpolkit-grant to tell us what user to use */
+ if (admin_users != NULL) {
+ int n;
+ char buf[256];
+
+#ifdef PGH_DEBUG
+ fprintf (stderr, "waiting for admin user name...\n");
+#endif /* PGH_DEBUG */
+
+ /* read from parent */
+ if (fgets (buf, sizeof buf, stdin) == NULL)
+ goto out;
+ if (strlen (buf) > 0 && buf[strlen (buf) - 1] == '\n')
+ buf[strlen (buf) - 1] = '\0';
+
+ if (strncmp (buf,
+ "POLKIT_GRANT_CALLER_SELECT_ADMIN_USER ",
+ sizeof "POLKIT_GRANT_CALLER_SELECT_ADMIN_USER " - 1) != 0) {
+ goto out;
+ }
+
+ user_to_auth = strdup (buf) + sizeof "POLKIT_GRANT_CALLER_SELECT_ADMIN_USER " - 1;
+#ifdef PGH_DEBUG
+ fprintf (stderr, "libpolkit-grant wants to auth as '%s'\n", user_to_auth);
+#endif /* PGH_DEBUG */
+
+ /* now sanity check that returned user is actually in admin_users */
+ for (n = 0; admin_users[n] != NULL; n++) {
+ if (strcmp (admin_users[n], user_to_auth) == 0)
+ break;
+ }
+ if (admin_users[n] == NULL) {
+ ret = 2;
+ goto out;
+ }
+
} else {
- user_to_auth = invoking_user_name;
+ /* figure out what user to auth */
+ if (result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+ result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
+ result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
+ user_to_auth = "root";
+ } else {
+ user_to_auth = invoking_user_name;
+ }
}
ret = 1;
/* Start authentication */
- if (!do_auth (user_to_auth))
+ if (!do_auth (user_to_auth)) {
goto out;
+ }
/* Ask caller if he want to slim down grant type... e.g. he
* might want to go from auth_self_keep_always to
diff --git a/polkit-grant/polkit-grant.c b/polkit-grant/polkit-grant.c
index 1217217..a79c86b 100644
--- a/polkit-grant/polkit-grant.c
+++ b/polkit-grant/polkit-grant.c
@@ -60,6 +60,7 @@ struct PolKitGrant
PolKitGrantAddChildWatch func_add_child_watch;
PolKitGrantRemoveWatch func_remove_watch;
PolKitGrantType func_type;
+ PolKitGrantSelectAdminUser func_select_admin_user;
PolKitGrantConversationPromptEchoOff func_prompt_echo_off;
PolKitGrantConversationPromptEchoOn func_prompt_echo_on;
PolKitGrantConversationErrorMessage func_error_message;
@@ -77,7 +78,7 @@ struct PolKitGrant
int io_watch_id;
gboolean success;
- gboolean auth_in_progress;
+ gboolean helper_is_running;
};
/**
@@ -162,6 +163,7 @@ polkit_grant_unref (PolKitGrant *polkit_
* @func_add_child_watch: Callback function
* @func_remove_watch: Callback function
* @func_type: Callback function
+ * @func_select_admin_user: Callback function
* @func_prompt_echo_off: Callback function
* @func_prompt_echo_on: Callback function
* @func_error_message: Callback function
@@ -174,23 +176,25 @@ polkit_grant_unref (PolKitGrant *polkit_
**/
void
polkit_grant_set_functions (PolKitGrant *polkit_grant,
- PolKitGrantAddIOWatch func_add_io_watch,
- PolKitGrantAddChildWatch func_add_child_watch,
- PolKitGrantRemoveWatch func_remove_watch,
- PolKitGrantType func_type,
- PolKitGrantConversationPromptEchoOff func_prompt_echo_off,
- PolKitGrantConversationPromptEchoOn func_prompt_echo_on,
- PolKitGrantConversationErrorMessage func_error_message,
- PolKitGrantConversationTextInfo func_text_info,
- PolKitGrantOverrideGrantType func_override_grant_type,
- PolKitGrantDone func_done,
- void *user_data)
+ PolKitGrantAddIOWatch func_add_io_watch,
+ PolKitGrantAddChildWatch func_add_child_watch,
+ PolKitGrantRemoveWatch func_remove_watch,
+ PolKitGrantType func_type,
+ PolKitGrantSelectAdminUser func_select_admin_user,
+ PolKitGrantConversationPromptEchoOff func_prompt_echo_off,
+ PolKitGrantConversationPromptEchoOn func_prompt_echo_on,
+ PolKitGrantConversationErrorMessage func_error_message,
+ PolKitGrantConversationTextInfo func_text_info,
+ PolKitGrantOverrideGrantType func_override_grant_type,
+ PolKitGrantDone func_done,
+ void *user_data)
{
g_return_if_fail (polkit_grant != NULL);
g_return_if_fail (func_add_io_watch != NULL);
g_return_if_fail (func_add_child_watch != NULL);
g_return_if_fail (func_remove_watch != NULL);
g_return_if_fail (func_type != NULL);
+ g_return_if_fail (func_select_admin_user != NULL);
g_return_if_fail (func_prompt_echo_off != NULL);
g_return_if_fail (func_prompt_echo_on != NULL);
g_return_if_fail (func_error_message != NULL);
@@ -200,6 +204,7 @@ polkit_grant_set_functions (PolKitGrant
polkit_grant->func_add_child_watch = func_add_child_watch;
polkit_grant->func_remove_watch = func_remove_watch;
polkit_grant->func_type = func_type;
+ polkit_grant->func_select_admin_user = func_select_admin_user;
polkit_grant->func_prompt_echo_off = func_prompt_echo_off;
polkit_grant->func_prompt_echo_on = func_prompt_echo_on;
polkit_grant->func_error_message = func_error_message;
@@ -227,7 +232,7 @@ polkit_grant_child_func (PolKitGrant *po
polkit_bool_t input_was_bogus;
g_return_if_fail (polkit_grant != NULL);
- g_return_if_fail (polkit_grant->auth_in_progress);
+ g_return_if_fail (polkit_grant->helper_is_running);
g_debug ("pid %d terminated", pid);
waitpid (pid, &status, 0);
@@ -238,6 +243,7 @@ polkit_grant_child_func (PolKitGrant *po
input_was_bogus = FALSE;
polkit_grant->success = (exit_code == 0);
+ polkit_grant->helper_is_running = FALSE;
polkit_grant->func_done (polkit_grant, polkit_grant->success, input_was_bogus, polkit_grant->user_data);
}
@@ -259,22 +265,23 @@ polkit_grant_io_func (PolKitGrant *polki
char *id;
size_t id_len;
char *response;
+ char *response_prefix;
g_return_if_fail (polkit_grant != NULL);
- g_return_if_fail (polkit_grant->auth_in_progress);
+ g_return_if_fail (polkit_grant->helper_is_running);
while (getline (&line, &line_len, polkit_grant->child_stdout_f) != -1) {
if (strlen (line) > 0 &&
line[strlen (line) - 1] == '\n')
line[strlen (line) - 1] = '\0';
- //printf ("from child '%s'\n", line);
-
response = NULL;
+ response_prefix = NULL;
id = "PAM_PROMPT_ECHO_OFF ";
if (g_str_has_prefix (line, id)) {
id_len = strlen (id);
+ response_prefix = "";
response = polkit_grant->func_prompt_echo_off (polkit_grant,
line + id_len,
polkit_grant->user_data);
@@ -284,6 +291,7 @@ polkit_grant_io_func (PolKitGrant *polki
id = "PAM_PROMPT_ECHO_ON ";
if (g_str_has_prefix (line, id)) {
id_len = strlen (id);
+ response_prefix = "";
response = polkit_grant->func_prompt_echo_on (polkit_grant,
line + id_len,
polkit_grant->user_data);
@@ -311,16 +319,36 @@ polkit_grant_io_func (PolKitGrant *polki
id = "POLKIT_GRANT_HELPER_TELL_TYPE ";
if (g_str_has_prefix (line, id)) {
PolKitResult result;
+ char *result_textual;
+
id_len = strlen (id);
- if (!polkit_result_from_string_representation (line + id_len, &result)) {
+ result_textual = line + id_len;
+ if (!polkit_result_from_string_representation (result_textual, &result)) {
/* TODO: danger will robinson */
}
+
polkit_grant->func_type (polkit_grant,
result,
polkit_grant->user_data);
goto processed;
}
+ id = "POLKIT_GRANT_HELPER_TELL_ADMIN_USERS ";
+ if (g_str_has_prefix (line, id)) {
+ char **admin_users;
+
+ id_len = strlen (id);
+ admin_users = g_strsplit (line + id_len, " ", 0);
+
+ response_prefix = "POLKIT_GRANT_CALLER_SELECT_ADMIN_USER ";
+ response = polkit_grant->func_select_admin_user (polkit_grant,
+ admin_users,
+ polkit_grant->user_data);
+ g_strfreev (admin_users);
+
+ goto processed;
+ }
+
id = "POLKIT_GRANT_HELPER_ASK_OVERRIDE_GRANT_TYPE ";
if (g_str_has_prefix (line, id)) {
PolKitResult override;
@@ -332,19 +360,27 @@ polkit_grant_io_func (PolKitGrant *polki
override = polkit_grant->func_override_grant_type (polkit_grant,
result,
polkit_grant->user_data);
+ response_prefix = "POLKIT_GRANT_CALLER_PASS_OVERRIDE_GRANT_TYPE ";
response = g_strdup (polkit_result_to_string_representation (override));
goto processed;
}
processed:
- if (response != NULL) {
+ if (response != NULL && response_prefix != NULL) {
+ char *buf;
+ gboolean add_newline;
+
/* add a newline if there isn't one already... */
+ add_newline = FALSE;
if (response[strlen (response) - 1] != '\n') {
- char *old = response;
- response = g_strdup_printf ("%s\n", response);
- g_free (old);
+ add_newline = TRUE;
}
- write (polkit_grant->child_stdin, response, strlen (response));
+ buf = g_strdup_printf ("%s%s%c",
+ response_prefix,
+ response,
+ add_newline ? '\n' : '\0');
+ write (polkit_grant->child_stdin, buf, strlen (buf));
+ g_free (buf);
free (response);
}
}
@@ -364,7 +400,7 @@ polkit_grant_cancel_auth (PolKitGrant *p
{
GPid pid;
g_return_if_fail (polkit_grant != NULL);
- g_return_if_fail (polkit_grant->auth_in_progress);
+ g_return_if_fail (polkit_grant->helper_is_running);
pid = polkit_grant->child_pid;
polkit_grant->child_pid = 0;
@@ -372,6 +408,7 @@ polkit_grant_cancel_auth (PolKitGrant *p
int status;
kill (pid, SIGTERM);
waitpid (pid, &status, 0);
+ polkit_grant->helper_is_running = FALSE;
}
polkit_grant->func_done (polkit_grant, FALSE, FALSE, polkit_grant->user_data);
}
@@ -463,7 +500,7 @@ polkit_grant_initiate_auth (PolKitGrant
polkit_grant->success = FALSE;
- polkit_grant->auth_in_progress = TRUE;
+ polkit_grant->helper_is_running = TRUE;
return TRUE;
error:
diff --git a/polkit-grant/polkit-grant.h b/polkit-grant/polkit-grant.h
index 5211b6f..e619625 100644
--- a/polkit-grant/polkit-grant.h
+++ b/polkit-grant/polkit-grant.h
@@ -50,6 +50,25 @@ typedef void (*PolKitGrantType) (PolKitG
void *user_data);
/**
+ * PolKitGrantSelectAdminUser:
+ * @polkit_grant: the grant object
+ * @admin_users: a NULL-terminated array of users that can be used for
+ * authentication for admin grants.
+ * @user_data: user data pointed as passed into polkit_grant_set_functions()
+ *
+ * Type for callback function that describes the possible users that
+ * can be chosen for authentication when administrator privileges are
+ * required.
+ *
+ * Returns: the chosen user; must be allocated with malloc(3) and will
+ * be freed by the #PolKitGrant class.
+ **/
+typedef char* (*PolKitGrantSelectAdminUser) (PolKitGrant *polkit_grant,
+ char **admin_users,
+ void *user_data);
+
+
+/**
* PolKitGrantConversationPromptEchoOff:
* @polkit_grant: the grant object
* @prompt: prompt passed by the authentication layer; do not free this string
@@ -323,6 +342,7 @@ void polkit_grant_set_functions
PolKitGrantAddChildWatch func_add_child_watch,
PolKitGrantRemoveWatch func_remove_watch,
PolKitGrantType func_type,
+ PolKitGrantSelectAdminUser func_select_admin_user,
PolKitGrantConversationPromptEchoOff func_prompt_echo_off,
PolKitGrantConversationPromptEchoOn func_prompt_echo_on,
PolKitGrantConversationErrorMessage func_error_message,
diff --git a/polkit/Makefile.am b/polkit/Makefile.am
index 8099be8..155367a 100644
--- a/polkit/Makefile.am
+++ b/polkit/Makefile.am
@@ -36,7 +36,8 @@ libpolkitinclude_HEADERS =
polkit-policy-file-entry.h \
polkit-policy-file.h \
polkit-policy-cache.h \
- polkit-policy-default.h
+ polkit-policy-default.h \
+ polkit-config.h
libpolkit_la_SOURCES = \
polkit.h \
diff --git a/polkit/polkit-config.c b/polkit/polkit-config.c
index d0de655..782796c 100644
--- a/polkit/polkit-config.c
+++ b/polkit/polkit-config.c
@@ -49,7 +49,10 @@
* SECTION:polkit-config
* @short_description: Configuration file.
*
- * This class is used to represent the /etc/PolicyKit/PolicyKit.conf configuration file.
+ * This class is used to represent the /etc/PolicyKit/PolicyKit.conf
+ * configuration file. Applications using PolicyKit should never use
+ * this class; it's only here for integration with other PolicyKit
+ * components.
**/
enum {
@@ -57,6 +60,7 @@ enum {
STATE_IN_CONFIG,
STATE_IN_MATCH,
STATE_IN_RETURN,
+ STATE_IN_DEFINE_ADMIN_AUTH,
};
struct ConfigNode;
@@ -65,7 +69,10 @@ typedef struct ConfigNode ConfigNode;
/**
* PolKitConfig:
*
- * This class represents the system-wide configuration file for PolicyKit.
+ * This class represents the system-wide configuration file for
+ * PolicyKit. Applications using PolicyKit should never use this
+ * class; it's only here for integration with other PolicyKit
+ * components.
**/
struct PolKitConfig
{
@@ -90,6 +97,7 @@ enum {
NODE_TYPE_TOP,
NODE_TYPE_MATCH,
NODE_TYPE_RETURN,
+ NODE_TYPE_DEFINE_ADMIN_AUTH,
};
enum {
@@ -103,6 +111,12 @@ static const char * const match_names[]
"user",
};
+static const char * const define_admin_auth_names[] =
+{
+ "user",
+ "group",
+};
+
struct ConfigNode
{
int node_type;
@@ -119,6 +133,11 @@ struct ConfigNode
PolKitResult result;
} node_return;
+ struct {
+ PolKitConfigAdminAuthType admin_type;
+ char *data;
+ } node_define_admin_auth;
+
} data;
GSList *children;
@@ -161,6 +180,14 @@ config_node_dump_real (ConfigNode *node,
polkit_result_to_string_representation (node->data.node_return.result),
node->data.node_return.result);
break;
+ case NODE_TYPE_DEFINE_ADMIN_AUTH:
+ _pk_debug ("%sDEFINE_ADMIN_AUTH %s (%d) with '%s'",
+ buf,
+ define_admin_auth_names[node->data.node_define_admin_auth.admin_type],
+ node->data.node_define_admin_auth.admin_type,
+ node->data.node_define_admin_auth.data);
+ break;
+ break;
}
for (i = node->children; i != NULL; i = g_slist_next (i)) {
@@ -190,6 +217,9 @@ config_node_unref (ConfigNode *node)
break;
case NODE_TYPE_RETURN:
break;
+ case NODE_TYPE_DEFINE_ADMIN_AUTH:
+ g_free (node->data.node_define_admin_auth.data);
+ break;
}
for (i = node->children; i != NULL; i = g_slist_next (i)) {
@@ -208,7 +238,7 @@ _start (void *data, const char *el, cons
ParserData *pd = data;
ConfigNode *node;
- _pk_debug ("_start for node '%s'", el);
+ _pk_debug ("_start for node '%s' (at depth=%d)", el, pd->stack_depth);
for (num_attr = 0; attr[num_attr] != NULL; num_attr++)
;
@@ -280,6 +310,28 @@ _start (void *data, const char *el, cons
_pk_debug ("parsed return node ('%s' (%d))",
attr[1],
node->data.node_return.result);
+ } else if ((strcmp (el, "define_admin_auth") == 0) && (num_attr == 2)) {
+
+ node = config_node_new ();
+ node->node_type = NODE_TYPE_DEFINE_ADMIN_AUTH;
+ if (strcmp (attr[0], "user") == 0) {
+ node->data.node_define_admin_auth.admin_type = POLKIT_CONFIG_ADMIN_AUTH_TYPE_USER;
+ } else if (strcmp (attr[0], "group") == 0) {
+ node->data.node_define_admin_auth.admin_type = POLKIT_CONFIG_ADMIN_AUTH_TYPE_GROUP;
+ } else {
+ _pk_debug ("Unknown define_admin_auth rule '%s'", attr[0]);
+ goto error;
+ }
+
+ node->data.node_define_admin_auth.data = g_strdup (attr[1]);
+
+ state = STATE_IN_DEFINE_ADMIN_AUTH;
+ _pk_debug ("parsed define_admin_auth node ('%s' (%d) -> '%s')",
+ attr[0],
+ node->data.node_define_admin_auth.admin_type,
+ node->data.node_define_admin_auth.data);
+
+
}
break;
}
@@ -301,7 +353,7 @@ _start (void *data, const char *el, cons
}
pd->stack_depth++;
- _pk_debug ("state = %d", pd->state);
+ _pk_debug ("now in state=%d (after _start, depth=%d)", pd->state, pd->stack_depth);
return;
error:
@@ -321,15 +373,18 @@ _end (void *data, const char *el)
{
ParserData *pd = data;
- _pk_debug ("_end for node '%s'", el);
+ _pk_debug ("_end for node '%s' (at depth=%d)", el, pd->stack_depth);
--pd->stack_depth;
if (pd->stack_depth < 0 || pd->stack_depth >= PARSER_MAX_DEPTH) {
_pk_debug ("reached max depth?");
goto error;
}
- pd->state = pd->state_stack[pd->stack_depth];
- _pk_debug ("state = %d", pd->state);
+ if (pd->stack_depth > 0)
+ pd->state = pd->state_stack[pd->stack_depth - 1];
+ else
+ pd->state = STATE_NONE;
+ _pk_debug ("now in state=%d (after _end, depth=%d)", pd->state, pd->stack_depth);
return;
error:
XML_StopParser (pd->parser, FALSE);
@@ -456,79 +511,96 @@ polkit_config_unref (PolKitConfig *pk_co
g_free (pk_config);
}
-/* exactly one of the parameters caller and session must be NULL */
-static PolKitResult
-config_node_test (ConfigNode *node, PolKitAction *action, PolKitCaller *caller, PolKitSession *session)
+static gboolean
+config_node_match (ConfigNode *node,
+ PolKitAction *action,
+ PolKitCaller *caller,
+ PolKitSession *session)
{
- gboolean match;
- gboolean recurse;
- PolKitResult result;
char *str;
char *str1;
char *str2;
uid_t uid;
+ gboolean match;
+
+ match = FALSE;
+ str1 = NULL;
+ str2 = NULL;
+ switch (node->data.node_match.match_type) {
+
+ case MATCH_TYPE_ACTION:
+ if (!polkit_action_get_action_id (action, &str))
+ goto out;
+ str1 = g_strdup (str);
+ break;
+
+ case MATCH_TYPE_USER:
+ if (caller != NULL) {
+ if (!polkit_caller_get_uid (caller, &uid))
+ goto out;
+ } else if (session != NULL) {
+ if (!polkit_session_get_uid (session, &uid))
+ goto out;
+ } else
+ goto out;
+
+ str1 = g_strdup_printf ("%d", uid);
+ {
+ struct passwd pd;
+ struct passwd* pwdptr=&pd;
+ struct passwd* tempPwdPtr;
+ char pwdbuffer[256];
+ int pwdlinelen = sizeof(pwdbuffer);
+
+ if ((getpwuid_r (uid, pwdptr, pwdbuffer, pwdlinelen, &tempPwdPtr)) !=0 )
+ goto out;
+ str2 = g_strdup (pd.pw_name);
+ }
+ break;
+ }
+
+ if (str1 != NULL) {
+ if (regexec (&(node->data.node_match.preq), str1, 0, NULL, 0) == 0)
+ match = TRUE;
+ }
+ if (!match && str2 != NULL) {
+ if (regexec (&(node->data.node_match.preq), str2, 0, NULL, 0) == 0)
+ match = TRUE;
+ }
+
+out:
+ g_free (str1);
+ g_free (str2);
+ return match;
+}
+
+
+/* exactly one of the parameters caller and session must be NULL */
+static PolKitResult
+config_node_test (ConfigNode *node,
+ PolKitAction *action,
+ PolKitCaller *caller,
+ PolKitSession *session)
+{
+ gboolean recurse;
+ PolKitResult result;
- result = POLKIT_RESULT_UNKNOWN;
recurse = FALSE;
+ result = POLKIT_RESULT_UNKNOWN;
switch (node->node_type) {
case NODE_TYPE_TOP:
recurse = TRUE;
break;
case NODE_TYPE_MATCH:
- match = FALSE;
- str1 = NULL;
- str2 = NULL;
- switch (node->data.node_match.match_type) {
- case MATCH_TYPE_ACTION:
- if (!polkit_action_get_action_id (action, &str))
- goto out;
- str1 = g_strdup (str);
- break;
- case MATCH_TYPE_USER:
- if (caller != NULL) {
- if (!polkit_caller_get_uid (caller, &uid))
- goto out;
- } else if (session != NULL) {
- if (!polkit_session_get_uid (session, &uid))
- goto out;
- } else
- goto out;
-
- str1 = g_strdup_printf ("%d", uid);
- {
- struct passwd pd;
- struct passwd* pwdptr=&pd;
- struct passwd* tempPwdPtr;
- char pwdbuffer[256];
- int pwdlinelen = sizeof(pwdbuffer);
-
- if ((getpwuid_r (uid, pwdptr, pwdbuffer, pwdlinelen, &tempPwdPtr)) !=0 )
- goto out;
- str2 = g_strdup (pd.pw_name);
- }
- break;
- }
-
- if (str1 != NULL) {
- if (regexec (&(node->data.node_match.preq), str1, 0, NULL, 0) == 0)
- match = TRUE;
- }
- if (!match && str2 != NULL) {
- if (regexec (&(node->data.node_match.preq), str2, 0, NULL, 0) == 0)
- match = TRUE;
- }
-
-
- if (match)
+ if (config_node_match (node, action, caller, session))
recurse = TRUE;
-
- g_free (str1);
- g_free (str2);
break;
case NODE_TYPE_RETURN:
result = node->data.node_return.result;
break;
+ default:
+ break;
}
if (recurse) {
@@ -553,7 +625,7 @@ out:
* @session: the session in question
*
* Determine if the /etc/PolicyKit/PolicyKit.conf configuration file
- * says that a given session can do a given action.
+ * says that a given session can do a given action.
*
* Returns: A #PolKitResult - returns #POLKIT_RESULT_UNKNOWN if there
* was no match in the configuration file.
@@ -595,3 +667,88 @@ polkit_config_can_caller_do_action (PolK
result = POLKIT_RESULT_UNKNOWN;
return result;
}
+
+
+static polkit_bool_t
+config_node_determine_admin_auth (ConfigNode *node,
+ PolKitAction *action,
+ PolKitCaller *caller,
+ PolKitConfigAdminAuthType *out_admin_auth_type,
+ const char **out_data)
+{
+ gboolean recurse;
+ gboolean result_set;
+
+ recurse = FALSE;
+ result_set = FALSE;
+
+ switch (node->node_type) {
+ case NODE_TYPE_TOP:
+ recurse = TRUE;
+ break;
+ case NODE_TYPE_MATCH:
+ if (config_node_match (node, action, caller, NULL))
+ recurse = TRUE;
+ break;
+ case NODE_TYPE_DEFINE_ADMIN_AUTH:
+ if (out_admin_auth_type != NULL)
+ *out_admin_auth_type = node->data.node_define_admin_auth.admin_type;
+ if (out_data != NULL)
+ *out_data = node->data.node_define_admin_auth.data;
+ result_set = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ if (recurse) {
+ GSList *i;
+ for (i = node->children; i != NULL; i = g_slist_next (i)) {
+ ConfigNode *child_node = i->data;
+
+ result_set = config_node_determine_admin_auth (child_node,
+ action,
+ caller,
+ out_admin_auth_type,
+ out_data) || result_set;
+ }
+ }
+
+ return result_set;
+}
+
+/**
+ * polkit_config_determine_auth_type:
+ * @pk_config: the PolicyKit context
+ * @action: the type of access to check for
+ * @caller: the caller in question
+ * @out_admin_auth_type: return location for the authentication type
+ * @out_data: return location for the match value of the given
+ * authentication type. Caller shall not manipulate or free this
+ * string.
+ *
+ * Determine what "Authenticate as admin" means for a given caller and
+ * a given action. This basically returns the result of the
+ * "define_admin_auth" in the configuration file when drilling down
+ * for a specific caller / action.
+ *
+ * Returns: TRUE if value was returned
+ */
+polkit_bool_t
+polkit_config_determine_admin_auth_type (PolKitConfig *pk_config,
+ PolKitAction *action,
+ PolKitCaller *caller,
+ PolKitConfigAdminAuthType *out_admin_auth_type,
+ const char **out_data)
+{
+ if (pk_config->top_config_node != NULL) {
+ return config_node_determine_admin_auth (pk_config->top_config_node,
+ action,
+ caller,
+ out_admin_auth_type,
+ out_data);
+ } else {
+ return FALSE;
+ }
+}
+
diff --git a/polkit/polkit-config.h b/polkit/polkit-config.h
index 24f5658..8a9a3a5 100644
--- a/polkit/polkit-config.h
+++ b/polkit/polkit-config.h
@@ -30,10 +30,11 @@
#ifndef POLKIT_CONFIG_H
#define POLKIT_CONFIG_H
+#include <sys/types.h>
+#include <regex.h>
#include <polkit/polkit-error.h>
#include <polkit/polkit-types.h>
#include <polkit/polkit-result.h>
-#include <polkit/polkit-context.h>
#include <polkit/polkit-action.h>
#include <polkit/polkit-session.h>
#include <polkit/polkit-caller.h>
@@ -55,6 +56,28 @@ polkit_config_can_caller_do_action
PolKitAction *action,
PolKitCaller *caller);
+/**
+ * PolKitConfigAdminAuthType:
+ * @POLKIT_CONFIG_ADMIN_AUTH_TYPE_USER: Authentication as
+ * administrator matches one or more users
+ * @POLKIT_CONFIG_ADMIN_AUTH_TYPE_GROUP: Authentication as
+ * administrator matches users from one or more groups
+ *
+ * This enumeration reflects results defined in the
+ * "define_admin_auth" configuration element.
+ */
+typedef enum
+{
+ POLKIT_CONFIG_ADMIN_AUTH_TYPE_USER,
+ POLKIT_CONFIG_ADMIN_AUTH_TYPE_GROUP
+} PolKitConfigAdminAuthType;
+
+polkit_bool_t polkit_config_determine_admin_auth_type (PolKitConfig *pk_config,
+ PolKitAction *action,
+ PolKitCaller *caller,
+ PolKitConfigAdminAuthType *out_admin_auth_type,
+ const char **out_data);
+
#endif /* POLKIT_CONFIG_H */
diff --git a/polkit/polkit-context.c b/polkit/polkit-context.c
index d8f2ed0..073b306 100644
--- a/polkit/polkit-context.c
+++ b/polkit/polkit-context.c
@@ -564,3 +564,23 @@ out:
_pk_debug ("... result was %s", polkit_result_to_string_representation (result));
return result;
}
+
+/**
+ * polkit_context_get_config:
+ * @pk_context: the PolicyKit context
+ *
+ * Returns an object that provides access to the
+ * /etc/PolicyKit/PolicyKit.conf configuration files. Applications
+ * using PolicyKit should never use this method; it's only here for
+ * integration with other PolicyKit components.
+ *
+ * Returns: A #PolKitConfig object
+ */
+PolKitConfig *
+polkit_context_get_config (PolKitContext *pk_context)
+{
+ g_return_val_if_fail (pk_context != NULL, NULL);
+ return pk_context->config;
+}
+
+
diff --git a/polkit/polkit-context.h b/polkit/polkit-context.h
index 3e4fe29..b75f5a3 100644
--- a/polkit/polkit-context.h
+++ b/polkit/polkit-context.h
@@ -39,6 +39,7 @@
#include <polkit/polkit-session.h>
#include <polkit/polkit-caller.h>
#include <polkit/polkit-policy-cache.h>
+#include <polkit/polkit-config.h>
struct PolKitContext;
typedef struct PolKitContext PolKitContext;
@@ -154,16 +155,16 @@ void polkit_context_io_func
PolKitPolicyCache *polkit_context_get_policy_cache (PolKitContext *pk_context);
-PolKitResult
-polkit_context_can_session_do_action (PolKitContext *pk_context,
+PolKitResult polkit_context_can_session_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitSession *session);
-PolKitResult
-polkit_context_can_caller_do_action (PolKitContext *pk_context,
+PolKitResult polkit_context_can_caller_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitCaller *caller);
+PolKitConfig *polkit_context_get_config (PolKitContext *pk_context);
+
#endif /* POLKIT_CONTEXT_H */
More information about the hal-commit
mailing list