Commit a0267b82 authored by David Zeuthen's avatar David Zeuthen

give a little love to polkit-list-actions(1) and polkit-grant(1)

In addition polkit-grant(1) gained a few new features

 --list          : for listing all grants
 --delete <user> : for deleting all grants given to an user
parent 9924987f
......@@ -39,6 +39,7 @@
#include <glib.h>
#include <polkit/polkit-grant-database.h>
#include <polkit/polkit-debug.h>
/**
* SECTION:polkit-grant-database
......@@ -312,3 +313,184 @@ _polkit_grantdb_check_can_caller_do_action (PolKitContext *pk_context,
out:
return result;
}
void
_polkit_grantdb_foreach (PolKitGrantDbForeachFunc callback, void *user_data)
{
GDir *dir;
const char *name;
time_t when;
g_return_if_fail (callback != NULL);
_pk_debug ("Looking at run");
dir = g_dir_open (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 0, NULL);
if (dir != NULL) {
while ((name = g_dir_read_name (dir)) != NULL) {
int uid;
char *endptr;
char *action;
char *path;
struct stat statbuf;
path = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/%s", name);
if (stat (path, &statbuf) != 0) {
g_free (path);
continue;
}
when = statbuf.st_mtime;
g_free (path);
if (!g_str_has_prefix (name, "uid"))
continue;
if (!g_str_has_suffix (name, ".grant"))
continue;
uid = strtol (name + 3 /* uid */, &endptr, 10);
if (endptr == NULL || *endptr != '-')
continue;
if (strncmp (endptr + 1, "pid-", 4) == 0) {
int pid;
unsigned long long pid_time;
pid = strtol (endptr + 1 + 4 /*pid-*/, &endptr, 10);
if (endptr == NULL || *endptr != '@')
continue;
pid_time = strtol (endptr + 1, NULL, 10);
while (*endptr != '-' && *endptr != '\0')
endptr++;
if (*endptr == '\0')
continue;
action = g_strdup (endptr + 1);
if (strlen (action) < 6) /* .grant */
continue;
action[strlen(action) - 6] = '\0';
callback (action, uid, when, POLKIT_GRANTDB_GRANT_TYPE_PROCESS,
pid, pid_time, NULL, user_data);
g_free (action);
} else if (strncmp (endptr + 1, "session-", 8) == 0) {
int n;
char *session;
session = g_strdup (endptr + 1 + 8);
for (n = 0; session[n] != '-' && session[n] != '\0'; n++)
;
session[n] = '\0';
action = g_strdup (endptr + 1 + 8 + n + 1);
if (strlen (action) < 6) /* .grant */
continue;
action[strlen(action) - 6] = '\0';
callback (action, uid, when, POLKIT_GRANTDB_GRANT_TYPE_SESSION,
(pid_t) -1, 0, session, user_data);
g_free (action);
g_free (session);
}
}
g_dir_close (dir);
}
_pk_debug ("Looking at lib");
dir = g_dir_open (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", 0, NULL);
if (dir != NULL) {
while ((name = g_dir_read_name (dir)) != NULL) {
int uid;
char *action;
char *endptr;
char *path;
struct stat statbuf;
path = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/%s", name);
if (stat (path, &statbuf) != 0) {
g_free (path);
continue;
}
when = statbuf.st_mtime;
g_free (path);
if (!g_str_has_prefix (name, "uid"))
continue;
if (!g_str_has_suffix (name, ".grant"))
continue;
uid = strtol (name + 3 /* uid */, &endptr, 10);
if (endptr == NULL || *endptr != '-')
continue;
action = g_strdup (endptr + 1);
if (strlen (action) < 6) /* .grant */
continue;
action[strlen(action) - 6] = '\0';
callback (action, uid, when, POLKIT_GRANTDB_GRANT_TYPE_ALWAYS,
(pid_t) -1, 0, NULL, user_data);
g_free (action);
}
g_dir_close (dir);
}
}
polkit_bool_t
_polkit_grantdb_delete_for_user (uid_t uid)
{
int n;
GDir *dir;
const char *name;
polkit_bool_t ret;
ret = FALSE;
_pk_debug ("deleting grants for uid %d", uid);
for (n = 0; n < 2; n++) {
if (n == 0)
dir = g_dir_open (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 0, NULL);
else
dir = g_dir_open (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", 0, NULL);
if (dir != NULL) {
while ((name = g_dir_read_name (dir)) != NULL) {
uid_t uid_in_grant;
char *endptr;
char *path;
if (!g_str_has_prefix (name, "uid"))
continue;
if (!g_str_has_suffix (name, ".grant"))
continue;
uid_in_grant = (uid_t) strtol (name + 3 /* uid */, &endptr, 10);
if (endptr == NULL || *endptr != '-')
continue;
if (uid_in_grant != uid)
continue;
if (n == 0)
path = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit/%s", name);
else
path = g_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/%s", name);
if (unlink (path) != 0) {
_pk_debug ("Error deleting grant file '%s': %s", path, strerror (errno));
goto out;
}
_pk_debug ("Deleting file %s", path);
g_free (path);
}
g_dir_close (dir);
}
}
ret = TRUE;
out:
return ret;
}
......@@ -38,4 +38,41 @@ polkit_bool_t _polkit_grantdb_write_keep_session (const char *action_id, const c
polkit_bool_t _polkit_grantdb_write_pid (const char *action_id, pid_t pid);
/**
* PolKitGrantDbGrantType:
*
*/
typedef enum {
POLKIT_GRANTDB_GRANT_TYPE_PROCESS,
POLKIT_GRANTDB_GRANT_TYPE_SESSION,
POLKIT_GRANTDB_GRANT_TYPE_ALWAYS
} PolKitGrantDbGrantType;
/**
* PolKitGrantDbForeachFunc:
* @action_id: Identifer for the action granted
* @when: when the privilege was granted
* @grant_type: the type of grant; one of #PolKitGrantDbGrantType
* @pid: the process id, or -1 if the passed grant_type is not POLKIT_GRANTDB_GRANT_TYPE_PROCESS
* @pid_time: the start time of the process (only if pid is set)
* @session_id: the session id, or NULL if the passed grant_type is not POLKIT_GRANTDB_GRANT_TYPE_SESSION
* @uid: the UNIX process id, or -1 if the passed grant_type is not POLKIT_GRANTDB_GRANT_TYPE_ALWAYS
*
* @user_data: user data passed to polkit_grantdb_foreach()
*
* Callback function for polkit_policy_cache_foreach().
**/
typedef void (*PolKitGrantDbForeachFunc) (const char *action_id,
uid_t uid,
time_t when,
PolKitGrantDbGrantType grant_type,
pid_t pid,
unsigned long long pid_time,
const char *session_id,
void *user_data);
void _polkit_grantdb_foreach (PolKitGrantDbForeachFunc callback, void *user_data);
polkit_bool_t _polkit_grantdb_delete_for_user (uid_t uid);
#endif /* POLKIT_GRANT_DATABASE_H */
......@@ -204,6 +204,43 @@ polkit_policy_cache_debug (PolKitPolicyCache *policy_cache)
}
}
/**
* polkit_policy_cache_get_entry_by_id:
* @policy_cache: the cache
* @action: the action identifier
*
* Given a action identifier, find the object describing the
* definition of the policy; e.g. data stemming from files in
* /usr/share/PolicyKit/policy.
*
* Returns: A #PolKitPolicyFileEntry entry on sucess; otherwise
* #NULL if the action wasn't identified. Caller shall not unref
* this object.
**/
PolKitPolicyFileEntry*
polkit_policy_cache_get_entry_by_id (PolKitPolicyCache *policy_cache, const char *action_id)
{
GSList *i;
PolKitPolicyFileEntry *pfe;
g_return_val_if_fail (policy_cache != NULL, NULL);
g_return_val_if_fail (action_id != NULL, NULL);
pfe = NULL;
for (i = policy_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
pfe = i->data;
if (strcmp (polkit_policy_file_entry_get_id (pfe), action_id) == 0) {
goto out;
}
}
pfe = NULL;
out:
return pfe;
}
/**
* polkit_policy_cache_get_entry:
* @policy_cache: the cache
......@@ -211,7 +248,7 @@ polkit_policy_cache_debug (PolKitPolicyCache *policy_cache)
*
* Given a action, find the object describing the definition of the
* policy; e.g. data stemming from files in
* /etc/PolicyKit/policy.
* /usr/share/PolicyKit/policy.
*
* Returns: A #PolKitPolicyFileEntry entry on sucess; otherwise
* #NULL if the action wasn't identified. Caller shall not unref
......@@ -221,29 +258,20 @@ PolKitPolicyFileEntry*
polkit_policy_cache_get_entry (PolKitPolicyCache *policy_cache,
PolKitAction *action)
{
char *priv_id;
GSList *i;
char *action_id;
PolKitPolicyFileEntry *pfe;
pfe = NULL;
/* I'm sure it would be easy to make this O(1)... */
g_return_val_if_fail (policy_cache != NULL, NULL);
g_return_val_if_fail (action != NULL, NULL);
if (!polkit_action_get_action_id (action, &priv_id))
goto out;
for (i = policy_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
pfe = i->data;
if (strcmp (polkit_policy_file_entry_get_id (pfe), priv_id) == 0) {
goto out;
}
}
pfe = NULL;
if (!polkit_action_get_action_id (action, &action_id))
goto out;
pfe = polkit_policy_cache_get_entry_by_id (policy_cache, action_id);
out:
return pfe;
}
......
......@@ -54,6 +54,8 @@ void polkit_policy_cache_unref (PolKitPolicyCache *policy_
void polkit_policy_cache_debug (PolKitPolicyCache *policy_cache);
PolKitPolicyFileEntry* polkit_policy_cache_get_entry (PolKitPolicyCache *policy_cache,
PolKitAction *action);
PolKitPolicyFileEntry* polkit_policy_cache_get_entry_by_id (PolKitPolicyCache *policy_cache,
const char *action_id);
void polkit_policy_cache_foreach (PolKitPolicyCache *policy_cache,
PolKitPolicyCacheForeachFunc callback,
void *user_data);
......
......@@ -23,7 +23,7 @@ polkit_policy_file_validate_SOURCES = polkit-policy-file-validate.c
polkit_policy_file_validate_LDADD = $(top_builddir)/polkit/libpolkit.la
polkit_grant_SOURCES = polkit-grant.c
polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-grant/libpolkit-grant.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-grant/libpolkit-grant.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit/libpolkit-grant-private.la
polkit_list_actions_SOURCES = polkit-list-actions.c
polkit_list_actions_LDADD = $(GLIB) $(top_builddir)/polkit/libpolkit.la
......
......@@ -39,6 +39,7 @@
#include <polkit-dbus/polkit-dbus.h>
#include <polkit-grant/polkit-grant.h>
#include <polkit/polkit-grant-database.h>
#include <glib.h>
......@@ -47,16 +48,16 @@ usage (int argc, char *argv[])
{
fprintf (stderr,
"\n"
"usage : polkit-grant\n"
" --action <action>\n"
"usage : polkit-grant [--gain <action>] [--list] [--delete <user>]\n"
" [--version] [--help]\n");
fprintf (stderr,
"\n"
" --action Requested action\n"
" --version Show version and exit\n"
" --help Show this information and exit\n"
"\n"
"TODO.\n");
" --gain Attempt to gain the privilege to do an action\n"
" --list List all grants\n"
" --delete Delete all grants for a given user\n"
" --version Show version and exit\n"
" --help Show this information and exit\n"
"\n");
}
typedef struct {
......@@ -299,11 +300,63 @@ remove_watch (PolKitGrant *polkit_auth, int watch_id)
g_source_remove (watch_id);
}
static void
_print_grants (const char *action_id,
uid_t uid,
time_t when,
PolKitGrantDbGrantType grant_type,
pid_t pid,
unsigned long long pid_time,
const char *session_id,
void *user_data)
{
char *user;
char *when_str;
struct passwd *passwd;
passwd = getpwuid (uid);
if (passwd != NULL)
user = passwd->pw_name;
else
user = "NON_EXISTING_USER";
when_str = ctime (&when);
switch (grant_type) {
case POLKIT_GRANTDB_GRANT_TYPE_PROCESS:
printf ("process:\n"
" user: %s (uid %d)\n"
" pid: %d@%lld\n"
" action: %s\n"
" granted: %s\n",
user, uid, pid, pid_time, action_id, when_str);
break;
case POLKIT_GRANTDB_GRANT_TYPE_SESSION:
printf ("session:\n"
" user: %s (uid %d)\n"
" session: %s\n"
" action: %s\n"
" granted: %s\n",
user, uid, session_id, action_id, when_str);
break;
case POLKIT_GRANTDB_GRANT_TYPE_ALWAYS:
printf ("always:\n"
" user: %s (uid %d)\n"
" action: %s\n"
" granted: %s\n",
user, uid, action_id, when_str);
break;
default:
break;
}
}
int
main (int argc, char *argv[])
{
char *action_id = NULL;
gboolean is_version = FALSE;
char *gain_action_id;
gboolean is_version;
DBusConnection *bus;
DBusError error;
PolKitContext *pol_ctx;
......@@ -313,27 +366,34 @@ main (int argc, char *argv[])
PolKitGrant *polkit_grant;
int ret;
UserData ud;
polkit_bool_t list_grants;
char *delete_for_user;
ret = 2;
ret = 1;
if (argc <= 1) {
usage (argc, argv);
return 1;
goto out;
}
list_grants = FALSE;
delete_for_user = NULL;
is_version = FALSE;
gain_action_id = NULL;
while (1) {
int c;
int option_index = 0;
const char *opt;
static struct option long_options[] = {
{"action", 1, NULL, 0},
{"list", 0, NULL, 0},
{"delete", 1, NULL, 0},
{"gain", 1, NULL, 0},
{"version", 0, NULL, 0},
{"help", 0, NULL, 0},
{NULL, 0, NULL, 0}
};
c = getopt_long (argc, argv, "",
long_options, &option_index);
c = getopt_long (argc, argv, "", long_options, &option_index);
if (c == -1)
break;
......@@ -346,90 +406,107 @@ main (int argc, char *argv[])
return 0;
} else if (strcmp (opt, "version") == 0) {
is_version = TRUE;
} else if (strcmp (opt, "action") == 0) {
action_id = strdup (optarg);
} else if (strcmp (opt, "gain") == 0) {
gain_action_id = strdup (optarg);
} else if (strcmp (opt, "list") == 0) {
list_grants = TRUE;
} else if (strcmp (opt, "delete") == 0) {
delete_for_user = strdup (optarg);
}
break;
default:
usage (argc, argv);
goto error;
goto out;
}
}
if (is_version) {
printf ("polkit-grant " PACKAGE_VERSION "\n");
return 0;
}
if (action_id == NULL) {
usage (argc, argv);
goto error;
}
printf ("Attempting to gain the privilege for %s.\n", action_id);
ud.loop = g_main_loop_new (NULL, TRUE);
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
fprintf (stderr, "error: dbus_bus_get(): %s: %s\n", error.name, error.message);
goto error;
ret = 0;
goto out;
}
p_error = NULL;
pol_ctx = polkit_context_new ();
if (!polkit_context_init (pol_ctx, &p_error)) {
fprintf (stderr, "error: polkit_context_init: %s\n", polkit_error_get_error_message (p_error));
polkit_error_free (p_error);
goto error;
}
action = polkit_action_new ();
polkit_action_set_action_id (action, action_id);
caller = polkit_caller_new_from_dbus_name (bus, dbus_bus_get_unique_name (bus), &error);
if (caller == NULL) {
if (dbus_error_is_set (&error)) {
fprintf (stderr, "error: polkit_caller_new_from_dbus_name(): %s: %s\n",
error.name, error.message);
goto error;
if (gain_action_id != NULL) {
printf ("Attempting to gain the privilege for %s.\n", gain_action_id);
ud.loop = g_main_loop_new (NULL, TRUE);
dbus_error_init (&error);
bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
fprintf (stderr, "error: dbus_bus_get(): %s: %s\n", error.name, error.message);
goto out;
}
p_error = NULL;
pol_ctx = polkit_context_new ();
if (!polkit_context_init (pol_ctx, &p_error)) {
fprintf (stderr, "error: polkit_context_init: %s\n", polkit_error_get_error_message (p_error));
polkit_error_free (p_error);
goto out;
}
action = polkit_action_new ();
polkit_action_set_action_id (action, gain_action_id);
caller = polkit_caller_new_from_dbus_name (bus, dbus_bus_get_unique_name (bus), &error);
if (caller == NULL) {
if (dbus_error_is_set (&error)) {
fprintf (stderr, "error: polkit_caller_new_from_dbus_name(): %s: %s\n",
error.name, error.message);
goto out;
}
}
polkit_grant = polkit_grant_new ();
polkit_grant_set_functions (polkit_grant,
add_io_watch,
add_child_watch,
remove_watch,
conversation_type,
conversation_select_admin_user,
conversation_pam_prompt_echo_off,
conversation_pam_prompt_echo_on,
conversation_pam_error_msg,
conversation_pam_text_info,
conversation_override_grant_type,
conversation_done,
&ud);
if (!polkit_grant_initiate_auth (polkit_grant,
action,
caller)) {
printf ("Failed to initiate privilege grant.\n");
ret = 1;
goto out;
}
g_main_loop_run (ud.loop);
polkit_grant_unref (polkit_grant);
if (ud.gained_privilege)
printf ("Successfully gained the privilege for %s.\n", gain_action_id);
else
printf ("Failed to gain the privilege for %s.\n", gain_action_id);
ret = ud.gained_privilege ? 0 : 1;
} else if (list_grants) {
_polkit_grantdb_foreach (_print_grants, NULL);
ret = 0;
} else if (delete_for_user != NULL) {
struct passwd *passwd;
passwd = getpwnam (delete_for_user);
if (passwd == NULL) {
printf ("No such user '%s'.\n", delete_for_user);
goto out;
}
if (!_polkit_grantdb_delete_for_user (passwd->pw_uid)) {
printf ("Error deleting grants for user '%s'. Got root?\n", delete_for_user);
}