diff options
Diffstat (limited to 'tools/polkit-grant-privilege.c')
-rw-r--r-- | tools/polkit-grant-privilege.c | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/tools/polkit-grant-privilege.c b/tools/polkit-grant-privilege.c new file mode 100644 index 0000000..0a2d58c --- /dev/null +++ b/tools/polkit-grant-privilege.c @@ -0,0 +1,434 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * polkit-grant-privilege.c : Grant privileges + * + * Copyright (C) 2006 David Zeuthen, <david@fubar.dk> + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <getopt.h> +#include <string.h> +#include <errno.h> + +#include <glib/gstdio.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include <libpolkit/libpolkit.h> + +#include "polkit-interface-manager-glue.h" +#include "polkit-interface-session-glue.h" + +static char *grant_user = NULL; +static char *grant_privilege = NULL; +static char *grant_resource = NULL; +static char *auth_user = NULL; +static char *auth_pam_service_name = NULL; + +static void +have_questions_handler (DBusGProxy *session, gpointer user_data) +{ + int i; + char **questions; + char **answers; + int num_a; + GError *error = NULL; + + if (auth_user != NULL) { + if (grant_resource != NULL) + g_print ("\n" + "Authentication needed for user '%s' in order to grant the\n" + "privilege '%s' to user '%s' for the \n" + "resource '%s'.\n" + "\n" + "The privilege is configured to use PAM service '%s'.\n" + "\n", + auth_user, + grant_privilege, grant_user, + grant_resource, + auth_pam_service_name); + else + g_print ("\n" + "Authentication needed for user '%s' in order to grant the\n" + "privilege '%s' to user '%s'.\n" + "\n" + "The privilege is configured to use PAM service '%s'.\n" + "\n", + auth_user, + grant_privilege, grant_user, + auth_pam_service_name); + g_free (auth_user); + g_free (auth_pam_service_name); + auth_user = NULL; + auth_pam_service_name = NULL; + } + + if (!org_freedesktop_PolicyKit_Session_get_questions (session, + &questions, + &error)) { + g_warning ("GetQuestions: %s", error->message); + g_error_free (error); + goto out; + } + + answers = g_new0 (char *, g_strv_length (questions) + 1); + num_a = 0; + + for (i = 0; questions[i] != NULL && questions[i+1] != NULL; i++) { + char *answer; + char *question = questions[i+1]; + char *qtype = questions[i]; + + /*g_debug ("Question 1: '%s' (pamtype %s)\n(warning; secret will be echoed to stdout)", question, qtype);*/ + + if (strcmp (qtype, "PamPromptEchoOff") == 0) { + answer = getpass (question); + answers[num_a++] = g_strdup (answer); + + /*g_debug ("Provding answer: '%s'", answer);*/ + + } else if (strcmp (qtype, "PamPromptEchoOn") == 0) { + char buf[1024]; + + fputs (question, stderr); + answer = fgets (question, sizeof (buf), stdin); + answers[num_a++] = g_strdup (answer); + + /*g_debug ("Provding answer: '%s'", answer);*/ + + } else if (strcmp (qtype, "PamErrorMsg") == 0) { + /*g_debug ("Not providing answer");*/ + ; + } else if (strcmp (qtype, "PamTextInfo") == 0) { + /*g_debug ("Not providing answer");*/ + ; + } + } + answers[num_a] = NULL; + + g_strfreev (questions); + + if (!org_freedesktop_PolicyKit_Session_provide_answers (session, + (const char **) answers, + &error)) { + g_warning ("ProvideAnswers: %s", error->message); + g_error_free (error); + goto out; + } + + g_strfreev (answers); + +out: + ; +} + +static void +auth_done_handler (DBusGProxy *session, gpointer user_data) +{ + gboolean auth_result; + GError *error = NULL; + + /*g_debug ("in %s", __FUNCTION__);*/ + + if (!org_freedesktop_PolicyKit_Session_is_authenticated (session, + &auth_result, + &error)) { + g_warning ("IsAuthenticated: %s", error->message); + g_error_free (error); + goto out; + } + + /*g_message ("Authentication done. %s", auth_result);*/ + + if (!auth_result) { + char *auth_denied_reason; + + if (!org_freedesktop_PolicyKit_Session_get_auth_denied_reason (session, + &auth_denied_reason, + &error)) { + g_warning ("GetAuthDeniedReason: %s", error->message); + g_error_free (error); + goto out; + } + + g_print ("\n" + "Authentication failed (reason: '%s').\n", auth_denied_reason); + g_free (auth_denied_reason); + } else { + g_print ("\n" + "Authentication succeeded.\n"); + + /* don't restrict privilege to callers PID */ + if (!org_freedesktop_PolicyKit_Session_grant_privilege_temporarily (session, + FALSE, + &error)) { + g_warning ("GrantPrivilegeTemporarily: %s", error->message); + g_error_free (error); + } + } + +out: + + /* don't revoke privilege when we close the session */ + if (!org_freedesktop_PolicyKit_Session_close (session, + TRUE, + &error)) { + g_warning ("Close: %s", error->message); + g_error_free (error); + } + + exit (0); +} + +static void +do_grant_privilege (DBusGConnection *conn, const char *user, const char *privilege, const char *resource) +{ + GError *error = NULL; + DBusGProxy *manager; + DBusGProxy *session; + char *session_objpath; + GMainLoop *mainloop; + + grant_user = g_strdup (user); + grant_privilege = g_strdup (privilege); + grant_resource = g_strdup (resource); + + mainloop = g_main_loop_new (NULL, FALSE); + + manager = dbus_g_proxy_new_for_name (conn, + "org.freedesktop.PolicyKit", + "/org/freedesktop/PolicyKit/Manager", + "org.freedesktop.PolicyKit.Manager"); + if (manager == NULL) { + goto out; + } + + if (!org_freedesktop_PolicyKit_Manager_initiate_privilege_grant (manager, + user, + privilege, + resource, + &session_objpath, + &error)) { + g_warning ("GrantPrivilege: %s", error->message); + g_error_free (error); + goto out; + } + + /*g_debug ("session_objpath = %s", session_objpath);*/ + + session = dbus_g_proxy_new_for_name (conn, + "org.freedesktop.PolicyKit", + session_objpath, + "org.freedesktop.PolicyKit.Session"); + if (session == NULL) { + goto out; + } + + dbus_g_proxy_add_signal (session, "HaveQuestions", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (session, "HaveQuestions", G_CALLBACK (have_questions_handler), + NULL, NULL); + + dbus_g_proxy_add_signal (session, "AuthenticationDone", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (session, "AuthenticationDone", G_CALLBACK (auth_done_handler), + NULL, NULL); + + if (!org_freedesktop_PolicyKit_Session_get_auth_details (session, + &auth_user, + &auth_pam_service_name, + &error)) { + g_warning ("GetAuthDetails: %s", error->message); + g_error_free (error); + goto out; + } + + if (!org_freedesktop_PolicyKit_Session_initiate_auth (session, + &error)) { + g_warning ("InitiateAuth: %s", error->message); + g_error_free (error); + goto out; + } + + g_main_loop_run (mainloop); + + + g_free (session_objpath); +out: + ; +} + +static void +usage (int argc, char *argv[]) +{ + fprintf (stderr, "polkit-grant-privilege version " PACKAGE_VERSION "\n"); + + fprintf (stderr, "\n" "usage : %s -p <privilege> [-u user] [-r <resource>]\n", argv[0]); + fprintf (stderr, + "\n" + "Options:\n" + " -u, --user User to grant privilege to\n" + " -p, --privilege Privilege to grant\n" + " -r, --resource Resource\n" + " -h, --help Show this information and exit\n" + " -v, --verbose Verbose operation\n" + " -V, --version Print version number\n" + "\n" + "Grant a privilege for accessing a resource. The resource may\n" + "be omitted.\n"); +} + +static gboolean is_verbose = FALSE; + +int +main (int argc, char **argv) +{ + int rc; + GError *error = NULL; + DBusGConnection *bus; + LibPolKitContext *ctx; + char *user = NULL; + char *resource = NULL; + char *privilege = NULL; + static const struct option long_options[] = { + {"user", required_argument, NULL, 'u'}, + {"resource", required_argument, NULL, 'r'}, + {"privilege", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, 'h'}, + {"verbose", no_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; + + g_type_init (); + + rc = 1; + + while (TRUE) { + int c; + + c = getopt_long (argc, argv, "u:r:p:hVv", long_options, NULL); + + if (c == -1) + break; + + switch (c) { + case 'u': + user = g_strdup (optarg); + break; + + case 'r': + resource = g_strdup (optarg); + break; + + case 'p': + privilege = g_strdup (optarg); + break; + + case 'v': + is_verbose = TRUE; + break; + + case 'h': + usage (argc, argv); + rc = 0; + goto out; + + case 'V': + printf ("polkit-grant-privilege version " PACKAGE_VERSION "\n"); + rc = 0; + goto out; + + default: + usage (argc, argv); + goto out; + } + } + + if (privilege == NULL) { + usage (argc, argv); + return 1; + } + + if (user == NULL) { + user = g_strdup (g_get_user_name ()); + } + + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + g_warning ("dbus_g_bus_get: %s", error->message); + g_error_free (error); + return 1; + } + + ctx = libpolkit_new_context (dbus_g_connection_get_connection (bus)); + + gboolean is_privileged = FALSE; + LibPolKitResult result; + + result = libpolkit_is_uid_allowed_for_privilege (ctx, + -1, + user, + privilege, + resource, + &is_privileged); + switch (result) { + case LIBPOLKIT_RESULT_OK: + if (is_privileged) { + if (resource == NULL) { + g_print ("User '%s' already has privilege '%s'.\n", user, privilege); + } else { + g_print ("User '%s' already has privilege '%s' for accessing\n" + "resource '%s'.\n", + user, privilege, resource); + } + rc = 0; + goto out; + } + break; + + case LIBPOLKIT_RESULT_ERROR: + g_print ("Error granting resource.\n"); + goto out; + + case LIBPOLKIT_RESULT_INVALID_CONTEXT: + g_print ("Invalid context.\n"); + goto out; + + case LIBPOLKIT_RESULT_NOT_PRIVILEGED: + g_print ("Not privileged.\n"); + goto out; + + case LIBPOLKIT_RESULT_NO_SUCH_PRIVILEGE: + g_print ("No such privilege '%s'.\n", privilege); + goto out; + + case LIBPOLKIT_RESULT_NO_SUCH_USER: + g_print ("No such user '%s'.\n", user); + goto out; + } + + do_grant_privilege (bus, user, privilege, resource); + +out: + return rc; +} |