/*************************************************************************** * * libpolkit.c : Wraps a subset of methods on the PolicyKit daemon * * Copyright (C) 2006 David Zeuthen, * * Licensed under the Academic Free License version 2.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * **************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include "libpolkit.h" #define LIBPOLKIT_MAGIC 0x3117beef #ifdef __SUNPRO_C #define __FUNCTION__ __func__ #endif #define LIBPOLKIT_CHECK_CONTEXT(_ctx_, _ret_) \ do { \ if (_ctx_ == NULL) { \ g_warning ("%s: given LibPolKitContext is NULL", \ __FUNCTION__); \ return _ret_; \ } \ if (_ctx_->magic != LIBPOLKIT_MAGIC) { \ g_warning ("%s: given LibPolKitContext is invalid (read magic 0x%08x, should be 0x%08x)", \ __FUNCTION__, _ctx_->magic, LIBPOLKIT_MAGIC); \ return _ret_; \ } \ } while(0) struct LibPolKitContext_s { guint32 magic; DBusConnection *connection; }; /** Get a new context. * * @return Pointer to new context or NULL if an error occured */ LibPolKitContext * libpolkit_new_context (DBusConnection *connection) { LibPolKitContext *ctx; ctx = g_new0 (LibPolKitContext, 1); ctx->magic = LIBPOLKIT_MAGIC; ctx->connection = connection; return ctx; } /** Free a context * * @param ctx The context obtained from libpolkit_new_context * @return Pointer to new context or NULL if an error occured */ gboolean libpolkit_free_context (LibPolKitContext *ctx) { LIBPOLKIT_CHECK_CONTEXT (ctx, FALSE); ctx->magic = 0; g_free (ctx); return TRUE; } LibPolKitResult libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx, const char *user, const char *privilege, GList **resources, GList **restrictions, int *num_non_temporary) { LibPolKitResult res; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; char **resource_list; int num_resources; char **restriction_list; int num_restrictions; int i; LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT); res = LIBPOLKIT_RESULT_ERROR; *resources = NULL; *restrictions = NULL; message = dbus_message_new_method_call ("org.freedesktop.PolicyKit", "/org/freedesktop/PolicyKit/Manager", "org.freedesktop.PolicyKit.Manager", "GetAllowedResourcesForPrivilege"); if (message == NULL) { g_warning ("Could not allocate D-BUS message"); goto out; } if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &user, DBUS_TYPE_STRING, &privilege, DBUS_TYPE_INVALID)) { g_warning ("Could not append args to D-BUS message"); goto out; } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &error); if (dbus_error_is_set (&error)) { if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NotPrivileged") == 0) { res = LIBPOLKIT_RESULT_NOT_PRIVILEGED; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.Error") == 0) { res = LIBPOLKIT_RESULT_ERROR; } dbus_error_free (&error); goto out; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &resource_list, &num_resources, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &restriction_list, &num_restrictions, DBUS_TYPE_INT32, num_non_temporary, DBUS_TYPE_INVALID)) { g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message); dbus_error_free (&error); goto out; } for (i = 0; i < num_resources; i++) { *resources = g_list_append (*resources, g_strdup (resource_list[i])); } dbus_free_string_array (resource_list); for (i = 0; i < num_restrictions; i++) { *restrictions = g_list_append (*restrictions, g_strdup (restriction_list[i])); } dbus_free_string_array (restriction_list); res = LIBPOLKIT_RESULT_OK; out: if (reply != NULL) dbus_message_unref (reply); if (message != NULL) dbus_message_unref (message); return res; } LibPolKitResult libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx, const char *system_bus_unique_name, const char *user, const char *privilege, const char *resource, gboolean *out_is_allowed, gboolean *out_is_temporary, char **out_is_privileged_but_restricted_to_system_bus_unique_name) { LibPolKitResult res; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; const char *myresource = ""; const char *mysystem_bus_unique_name = ""; char *but_restricted_to = NULL; LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT); res = LIBPOLKIT_RESULT_ERROR; *out_is_allowed = FALSE; *out_is_temporary = FALSE; message = dbus_message_new_method_call ("org.freedesktop.PolicyKit", "/org/freedesktop/PolicyKit/Manager", "org.freedesktop.PolicyKit.Manager", "IsUserPrivileged"); if (message == NULL) { g_warning ("Could not allocate D-BUS message"); goto out; } if (resource != NULL) myresource = resource; if (system_bus_unique_name != NULL) mysystem_bus_unique_name = system_bus_unique_name; if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &mysystem_bus_unique_name, DBUS_TYPE_STRING, &user, DBUS_TYPE_STRING, &privilege, DBUS_TYPE_STRING, &myresource, DBUS_TYPE_INVALID)) { g_warning ("Could not append args to D-BUS message"); goto out; } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &error); if (dbus_error_is_set (&error)) { if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NoSuchUser") == 0) { res = LIBPOLKIT_RESULT_NO_SUCH_USER; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NoSuchPrivilege") == 0) { res = LIBPOLKIT_RESULT_NO_SUCH_PRIVILEGE; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NotPrivileged") == 0) { res = LIBPOLKIT_RESULT_NOT_PRIVILEGED; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.Error") == 0) { res = LIBPOLKIT_RESULT_ERROR; } dbus_error_free (&error); goto out; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, out_is_allowed, DBUS_TYPE_BOOLEAN, out_is_temporary, DBUS_TYPE_STRING, &but_restricted_to, DBUS_TYPE_INVALID)) { g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message); dbus_error_free (&error); goto out; } if (out_is_privileged_but_restricted_to_system_bus_unique_name != NULL) { if (but_restricted_to != NULL && strlen (but_restricted_to) > 0) { *out_is_privileged_but_restricted_to_system_bus_unique_name = strdup (but_restricted_to); } else { *out_is_privileged_but_restricted_to_system_bus_unique_name = NULL; } //dbus_free (but_restricted_to); } res = LIBPOLKIT_RESULT_OK; out: if (reply != NULL) dbus_message_unref (reply); if (message != NULL) dbus_message_unref (message); return res; } LibPolKitResult libpolkit_revoke_temporary_privilege (LibPolKitContext *ctx, const char *user, const char *privilege, const char *resource, gboolean *result) { LibPolKitResult res; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; const char *myresource = ""; LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT); res = LIBPOLKIT_RESULT_ERROR; *result = FALSE; message = dbus_message_new_method_call ("org.freedesktop.PolicyKit", "/org/freedesktop/PolicyKit/Manager", "org.freedesktop.PolicyKit.Manager", "RevokeTemporaryPrivilege"); if (message == NULL) { g_warning ("Could not allocate D-BUS message"); goto out; } if (resource != NULL) myresource = resource; if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &user, DBUS_TYPE_STRING, &privilege, DBUS_TYPE_STRING, &myresource, DBUS_TYPE_INVALID)) { g_warning ("Could not append args to D-BUS message"); goto out; } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &error); if (dbus_error_is_set (&error)) { if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NoSuchUser") == 0) { res = LIBPOLKIT_RESULT_NO_SUCH_USER; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NoSuchPrivilege") == 0) { res = LIBPOLKIT_RESULT_NO_SUCH_PRIVILEGE; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NotPrivileged") == 0) { res = LIBPOLKIT_RESULT_NOT_PRIVILEGED; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.Error") == 0) { res = LIBPOLKIT_RESULT_ERROR; } dbus_error_free (&error); goto out; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, result, DBUS_TYPE_INVALID)) { g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message); dbus_error_free (&error); goto out; } res = LIBPOLKIT_RESULT_OK; out: if (reply != NULL) dbus_message_unref (reply); if (message != NULL) dbus_message_unref (message); return res; } LibPolKitResult libpolkit_get_privilege_list (LibPolKitContext *ctx, GList **result) { LibPolKitResult res; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; char **privilege_list; int num_privileges; int i; LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT); res = LIBPOLKIT_RESULT_ERROR; *result = NULL; message = dbus_message_new_method_call ("org.freedesktop.PolicyKit", "/org/freedesktop/PolicyKit/Manager", "org.freedesktop.PolicyKit.Manager", "ListPrivileges"); if (message == NULL) { g_warning ("Could not allocate D-BUS message"); goto out; } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &error); if (dbus_error_is_set (&error)) { if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.NotPrivileged") == 0) { res = LIBPOLKIT_RESULT_NOT_PRIVILEGED; } else if (strcmp (error.name, "org.freedesktop.PolicyKit.Manager.Error") == 0) { res = LIBPOLKIT_RESULT_ERROR; } dbus_error_free (&error); goto out; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &privilege_list, &num_privileges, DBUS_TYPE_INVALID)) { g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message); dbus_error_free (&error); goto out; } for (i = 0; i < num_privileges; i++) { *result = g_list_append (*result, g_strdup (privilege_list[i])); } dbus_free_string_array (privilege_list); res = LIBPOLKIT_RESULT_OK; out: if (reply != NULL) dbus_message_unref (reply); if (message != NULL) dbus_message_unref (message); return res; }