Skip to content

Commit

Permalink
read actions also from /etc/, /run/ and /usr/local/share/ (polkit-org…
Browse files Browse the repository at this point in the history
…#499)

As with the rules.d change, also read actions from /etc/,
/run/ and /usr/local/share/ before /usr/share/, in this order

Co-authored-by: Arvin Schnell <[email protected]>
  • Loading branch information
bluca and aschnell authored Oct 9, 2024
1 parent e4461d0 commit 9958c25
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 98 deletions.
9 changes: 6 additions & 3 deletions docs/man/polkit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@ System Context | |
| PolicyKit1 |<---------+
+------------------+ |
^ |
| +--------------------------------------+
| | /usr/share/polkit-1/actions/*.policy |
| +--------------------------------------+
| +--------------------------------------------+
| | /etc/polkit-1/actions/*.policy |
| | /run/polkit-1/actions/*.policy |
| | /usr/local/share/polkit-1/actions/*.policy |
| | /usr/share/polkit-1/actions/*.policy |
| +--------------------------------------------+
|
+--------------------------------------------+
| /etc/polkit-1/rules.d/*.rules |
Expand Down
206 changes: 116 additions & 90 deletions src/polkitbackend/polkitbackendactionpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,16 @@ static const gchar *_localize (GHashTable *translations,

typedef struct
{
/* directory with .policy files, e.g. /usr/share/polkit-1/actions */
GFile *directory;
/* directories with .policy files, e.g. /usr/share/polkit-1/actions */
GList *directories;

GFileMonitor *dir_monitor;
/* GFileMonitor instances for directories */
GList *dir_monitors;

/* maps from action_id to a ParsedAction struct */
GHashTable *parsed_actions;

/* maps from URI of parsed file to nothing */
/* maps from basename of parsed file to nothing */
GHashTable *parsed_files;

/* is TRUE only when we've read all files */
Expand All @@ -107,7 +108,7 @@ typedef struct
enum
{
PROP_0,
PROP_DIRECTORY,
PROP_DIRECTORIES,
};

enum
Expand Down Expand Up @@ -147,11 +148,11 @@ polkit_backend_action_pool_finalize (GObject *object)
pool = POLKIT_BACKEND_ACTION_POOL (object);
priv = polkit_backend_action_pool_get_instance_private (pool);

if (priv->directory != NULL)
g_object_unref (priv->directory);
if (priv->directories != NULL)
g_list_free_full (priv->directories, g_object_unref);

if (priv->dir_monitor != NULL)
g_object_unref (priv->dir_monitor);
if (priv->dir_monitors != NULL)
g_list_free_full (priv->dir_monitors, g_object_unref);

if (priv->parsed_actions != NULL)
g_hash_table_unref (priv->parsed_actions);
Expand All @@ -176,8 +177,8 @@ polkit_backend_action_pool_get_property (GObject *object,

switch (prop_id)
{
case PROP_DIRECTORY:
g_value_set_object (value, priv->directory);
case PROP_DIRECTORIES:
g_value_set_object (value, priv->directories);
break;

default:
Expand Down Expand Up @@ -242,33 +243,49 @@ polkit_backend_action_pool_set_property (GObject *object,
{
PolkitBackendActionPool *pool;
PolkitBackendActionPoolPrivate *priv;
GError *error;

pool = POLKIT_BACKEND_ACTION_POOL (object);
priv = polkit_backend_action_pool_get_instance_private (pool);

switch (prop_id)
{
case PROP_DIRECTORY:
priv->directory = g_value_dup_object (value);

error = NULL;
priv->dir_monitor = g_file_monitor_directory (priv->directory,
G_FILE_MONITOR_NONE,
NULL,
&error);
if (priv->dir_monitor == NULL)
{
g_warning ("Error monitoring actions directory: %s", error->message);
g_error_free (error);
}
else
{
g_signal_connect (priv->dir_monitor,
"changed",
(GCallback) dir_monitor_changed,
pool);
}
case PROP_DIRECTORIES:

const gchar **dir_names = (const gchar**) g_value_get_boxed (value);

for (int n = 0; dir_names[n] != NULL; n++)
{
GFile *file;
GFileMonitor *monitor;
GError *error = NULL;

const gchar *dir_name = dir_names[n];

file = g_file_new_for_path (dir_name);
priv->directories = g_list_prepend (priv->directories, file);

monitor = g_file_monitor_directory (file,
G_FILE_MONITOR_NONE,
NULL,
&error);
if (monitor == NULL)
{
g_warning ("Error monitoring actions directory: %s", error->message);
g_error_free (error);
}
else
{
g_signal_connect (monitor,
"changed",
(GCallback) dir_monitor_changed,
pool);
priv->dir_monitors = g_list_prepend (priv->dir_monitors, monitor);
}
}

priv->directories = g_list_reverse(priv->directories);
priv->dir_monitors = g_list_reverse(priv->dir_monitors);

break;

default:
Expand All @@ -292,16 +309,16 @@ polkit_backend_action_pool_class_init (PolkitBackendActionPoolClass *klass)
* The directory to load action description files from.
*/
g_object_class_install_property (gobject_class,
PROP_DIRECTORY,
g_param_spec_object ("directory",
"Directory",
"Directory to load action description files from",
G_TYPE_FILE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
PROP_DIRECTORIES,
g_param_spec_boxed ("directories",
"Directories",
"Directories to load action description files from",
G_TYPE_STRV,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));

/**
* PolkitBackendActionPool::changed:
Expand Down Expand Up @@ -329,12 +346,12 @@ polkit_backend_action_pool_class_init (PolkitBackendActionPoolClass *klass)
* Returns: A #PolkitBackendActionPool. Free with g_object_unref().
**/
PolkitBackendActionPool *
polkit_backend_action_pool_new (GFile *directory)
polkit_backend_action_pool_new (const gchar **directories)
{
PolkitBackendActionPool *pool;

pool = POLKIT_BACKEND_ACTION_POOL (g_object_new (POLKIT_BACKEND_TYPE_ACTION_POOL,
"directory", directory,
"directories", directories,
NULL));

return pool;
Expand Down Expand Up @@ -454,101 +471,110 @@ ensure_file (PolkitBackendActionPool *pool,
{
PolkitBackendActionPoolPrivate *priv;
gchar *contents;
GError *error;
gchar *uri;
GError *error = NULL;
gchar *path;
gchar *basename;

priv = polkit_backend_action_pool_get_instance_private (pool);

uri = g_file_get_uri (file);
path = g_file_get_path (file);
basename = g_file_get_basename (file);

if (g_hash_table_lookup (priv->parsed_files, uri) != NULL)
if (g_hash_table_lookup_extended (priv->parsed_files, basename, NULL, NULL) == TRUE)
goto out;

error = NULL;
if (!g_file_load_contents (file,
NULL,
&contents,
NULL,
NULL,
&error))
{
g_warning ("Error loading file with URI '%s': %s", uri, error->message);
g_warning ("Error loading file with path '%s': %s", path, error->message);
goto out;
}

if (!process_policy_file (pool,
contents,
&error))
{
g_warning ("Error parsing file with URI '%s': %s", uri, error->message);
g_warning ("Error parsing file with path '%s': %s", path, error->message);
g_free (contents);
goto out;
}

g_free (contents);

/* steal uri */
g_hash_table_insert (priv->parsed_files, uri, NULL);
uri = NULL;
/* steal basename */
g_hash_table_insert (priv->parsed_files, basename, NULL);
basename = NULL;

out:
g_free (uri);
g_free (basename);
g_free (path);
}

static void
ensure_all_files (PolkitBackendActionPool *pool)
{
PolkitBackendActionPoolPrivate *priv;
GFileEnumerator *e;
GFileInfo *file_info;
GError *error;

priv = polkit_backend_action_pool_get_instance_private (pool);
GList *files = NULL;

e = NULL;
priv = polkit_backend_action_pool_get_instance_private (pool);

if (priv->has_loaded_all_files)
goto out;
return;

for (GList *l = priv->directories; l != NULL; l = l->next)
{
GError *error = NULL;
GFileEnumerator *enumerator;

error = NULL;
e = g_file_enumerate_children (priv->directory,
"standard::name",
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
if (error != NULL)
GFile* file = l->data;

char *dir_name = g_file_get_path(file);

enumerator = g_file_enumerate_children (file,
G_FILE_ATTRIBUTE_STANDARD_NAME,
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
if (error != NULL)
{
g_warning ("Error enumerating files: %s", error->message);
goto out;
g_warning ("Error enumerating files in %s: %s", dir_name, error->message);
}

while ((file_info = g_file_enumerator_next_file (e, NULL, &error)) != NULL)
else
{
const gchar *name;

name = g_file_info_get_name (file_info);
/* only consider files with the right suffix */
if (g_str_has_suffix (name, ".policy"))
{
GFile *file;
GFileInfo *file_info;
while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
{
const gchar *name = g_file_info_get_name (file_info);
/* only consider files with the right suffix */
if (g_str_has_suffix (name, ".policy"))
files = g_list_prepend (files, g_strdup_printf ("%s/%s", dir_name, name));

file = g_file_get_child (priv->directory, name);
g_object_unref (file_info);
} /* for all files */
}

ensure_file (pool, file);
g_object_unref (enumerator);
g_free (dir_name);
}

g_object_unref (file);
}
/* standard sorting places /etc before /usr as desired */
files = g_list_sort (files, (GCompareFunc) g_strcmp0);

g_object_unref (file_info);
for (GList *l = files; l != NULL; l = l->next)
{
GFile *file = g_file_new_for_path((gchar *)l->data);
ensure_file (pool, file);
g_object_unref (file);
}

} /* for all files */
g_list_free_full (files, g_free);

priv->has_loaded_all_files = TRUE;

out:

if (e != NULL)
g_object_unref (e);
}

/* ---------------------------------------------------------------------------------------------------- */
Expand Down
2 changes: 1 addition & 1 deletion src/polkitbackend/polkitbackendactionpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct _PolkitBackendActionPoolClass
};

GType polkit_backend_action_pool_get_type (void) G_GNUC_CONST;
PolkitBackendActionPool *polkit_backend_action_pool_new (GFile *directory);
PolkitBackendActionPool *polkit_backend_action_pool_new (const gchar **);
GList *polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool,
const gchar *locale);

Expand Down
13 changes: 9 additions & 4 deletions src/polkitbackend/polkitbackendinteractiveauthority.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,17 +288,22 @@ static void
polkit_backend_interactive_authority_init (PolkitBackendInteractiveAuthority *authority)
{
PolkitBackendInteractiveAuthorityPrivate *priv;
GFile *directory;
GError *error;

const gchar* directories[] = {
PACKAGE_SYSCONF_DIR "/polkit-1/actions",
"/run/polkit-1/actions",
"/usr/local/share/polkit-1/actions",
PACKAGE_DATA_DIR "/polkit-1/actions",
NULL
};

/* Force registering error domain */
(void)POLKIT_ERROR;

priv = polkit_backend_interactive_authority_get_instance_private (authority);

directory = g_file_new_for_path (PACKAGE_DATA_DIR "/polkit-1/actions");
priv->action_pool = polkit_backend_action_pool_new (directory);
g_object_unref (directory);
priv->action_pool = polkit_backend_action_pool_new (directories);
g_signal_connect (priv->action_pool,
"changed",
(GCallback) action_pool_changed,
Expand Down

0 comments on commit 9958c25

Please sign in to comment.