d2ec54f7875f7e05edd56195adbeb593c947763fphitran/***************************************************************************
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * CVSID: $Id$
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * hal-is-caller-privileged.c : Determine if a caller is privileged
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Licensed under the Academic Free License version 2.1
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * This program is free software; you can redistribute it and/or modify
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * it under the terms of the GNU General Public License as published by
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * the Free Software Foundation; either version 2 of the License, or
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * (at your option) any later version.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * This program is distributed in the hope that it will be useful,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * but WITHOUT ANY WARRANTY; without even the implied warranty of
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * GNU General Public License for more details.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * You should have received a copy of the GNU General Public License
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * along with this program; if not, write to the Free Software
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran **************************************************************************/
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef HAVE_CONFIG_H
d2ec54f7875f7e05edd56195adbeb593c947763fphitran# include <config.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <stdio.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <string.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <unistd.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <getopt.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <glib.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <stdlib.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <libhal.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef HAVE_POLKIT
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#include <libpolkit.h>
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * usage:
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @argc: Number of arguments given to program
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @argv: Arguments given to program
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Print out program usage.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranstatic void
d2ec54f7875f7e05edd56195adbeb593c947763fphitranusage (int argc, char *argv[])
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "usage : hal-is-caller-privileged --udi <udi> --action <action>\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --caller <caller-name>\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " [--help] [--version]\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --udi Unique Device Id\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --action PolicyKit action to check for\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --caller The name of the caller\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --version Show version and exit\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran " --help Show this information and exit\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "This program determines if a given process on the system bus is\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "privileged for a given PolicyKit action for a given device. If an error\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "occurs this program exits with a non-zero exit code. Otherwise\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "the textual reply will be printed on stdout and this program will\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "exit with exit code 0. Note that only the super user (root)\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "or other privileged users can use this tool.\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran "\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef HAVE_POLKIT
d2ec54f7875f7e05edd56195adbeb593c947763fphitranstatic void
d2ec54f7875f7e05edd56195adbeb593c947763fphitranpermission_denied_privilege (const char *privilege, const char *uid)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n"
d2ec54f7875f7e05edd56195adbeb593c947763fphitran);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr, "%s refused uid %s\n", privilege, uid);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran exit (1);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * main:
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @argc: Number of arguments given to program
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @argv: Arguments given to program
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Returns: Return code
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Main entry point
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranint
d2ec54f7875f7e05edd56195adbeb593c947763fphitranmain (int argc, char *argv[])
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran char *udi = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran char *action = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran char *caller = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran dbus_bool_t is_version = FALSE;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran DBusError error;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef HAVE_POLKIT
d2ec54f7875f7e05edd56195adbeb593c947763fphitran LibPolKitContext *pol_ctx = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran DBusConnection *system_bus = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran uid_t calling_uid;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran char *privilege = NULL;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran const char *invoked_by_uid;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran gboolean allowed_by_privilege = FALSE;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran gboolean is_temporary_privilege;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (argc <= 1) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran usage (argc, argv);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 1;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran while (1) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran int c;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran int option_index = 0;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran const char *opt;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran static struct option long_options[] = {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {"udi", 1, NULL, 0},
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {"action", 1, NULL, 0},
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {"caller", 1, NULL, 0},
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {"version", 0, NULL, 0},
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {"help", 0, NULL, 0},
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {NULL, 0, NULL, 0}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran };
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran c = getopt_long (argc, argv, "",
d2ec54f7875f7e05edd56195adbeb593c947763fphitran long_options, &option_index);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (c == -1)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran break;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran switch (c) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran case 0:
d2ec54f7875f7e05edd56195adbeb593c947763fphitran opt = long_options[option_index].name;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (strcmp (opt, "help") == 0) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran usage (argc, argv);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 0;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran } else if (strcmp (opt, "version") == 0) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran is_version = TRUE;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran } else if (strcmp (opt, "udi") == 0) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran udi = strdup (optarg);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran } else if (strcmp (opt, "caller") == 0) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran caller = strdup (optarg);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran } else if (strcmp (opt, "action") == 0) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran privilege = strdup (optarg);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran break;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran default:
d2ec54f7875f7e05edd56195adbeb593c947763fphitran usage (argc, argv);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 1;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran break;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (is_version) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf ("hal-is-caller-privileged " PACKAGE_VERSION "\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 0;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (udi == NULL || caller == NULL || privilege == NULL) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran usage (argc, argv);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 1;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran dbus_error_init (&error);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (system_bus == NULL) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf ("Cannot connect to the system bus\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran LIBHAL_FREE_DBUS_ERROR (&error);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr, "This program should only be started by hald.\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran exit (1);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef HAVE_POLKIT
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pol_ctx = libpolkit_new_context (system_bus);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (pol_ctx == NULL) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf ("Cannot get libpolkit context\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran invoked_by_uid = getenv("HAL_METHOD_INVOKED_BY_UID");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran caller,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran invoked_by_uid,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran privilege,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran udi,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran &allowed_by_privilege,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran &is_temporary_privilege,
d2ec54f7875f7e05edd56195adbeb593c947763fphitran NULL) != LIBPOLKIT_RESULT_OK
d2ec54f7875f7e05edd56195adbeb593c947763fphitran) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf ("cannot lookup privilege\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran fprintf (stderr, "Cannot lookup privilege from PolicyKit");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran exit (1);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (!allowed_by_privilege) {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf ("caller don't possess privilege\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran permission_denied_privilege (privilege, invoked_by_uid);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran printf("yes\n");
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return 0;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}