/***************************************************************************
* CVSID: $Id: polkit-grant-privilege.c,v 1.4 2006-04-22 23:27:14 david Exp $
*
* 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_temporary_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}
};
gboolean is_privileged = FALSE;
gboolean is_temporary = FALSE;
LibPolKitResult result;
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));
result = libpolkit_is_uid_allowed_for_privilege (ctx,
-1,
user,
privilege,
resource,
&is_privileged,
&is_temporary);
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;
}
syntax highlighted by Code2HTML, v. 0.9.1