1d2ec54f7Sphitran /***************************************************************************
2d2ec54f7Sphitran * CVSID: $Id$
3d2ec54f7Sphitran *
4d2ec54f7Sphitran * hal-is-caller-privileged.c : Determine if a caller is privileged
5d2ec54f7Sphitran *
6d2ec54f7Sphitran * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
7d2ec54f7Sphitran *
8d2ec54f7Sphitran * Licensed under the Academic Free License version 2.1
9d2ec54f7Sphitran *
10d2ec54f7Sphitran * This program is free software; you can redistribute it and/or modify
11d2ec54f7Sphitran * it under the terms of the GNU General Public License as published by
12d2ec54f7Sphitran * the Free Software Foundation; either version 2 of the License, or
13d2ec54f7Sphitran * (at your option) any later version.
14d2ec54f7Sphitran *
15d2ec54f7Sphitran * This program is distributed in the hope that it will be useful,
16d2ec54f7Sphitran * but WITHOUT ANY WARRANTY; without even the implied warranty of
17d2ec54f7Sphitran * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18d2ec54f7Sphitran * GNU General Public License for more details.
19d2ec54f7Sphitran *
20d2ec54f7Sphitran * You should have received a copy of the GNU General Public License
21d2ec54f7Sphitran * along with this program; if not, write to the Free Software
22d2ec54f7Sphitran * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23d2ec54f7Sphitran *
24d2ec54f7Sphitran **************************************************************************/
25d2ec54f7Sphitran
26d2ec54f7Sphitran
27d2ec54f7Sphitran #ifdef HAVE_CONFIG_H
28d2ec54f7Sphitran # include <config.h>
29d2ec54f7Sphitran #endif
30d2ec54f7Sphitran
31d2ec54f7Sphitran #include <stdio.h>
32d2ec54f7Sphitran #include <string.h>
33d2ec54f7Sphitran #include <unistd.h>
34d2ec54f7Sphitran #include <getopt.h>
35d2ec54f7Sphitran #include <glib.h>
36d2ec54f7Sphitran #include <stdlib.h>
37d2ec54f7Sphitran
38d2ec54f7Sphitran #include <libhal.h>
39d2ec54f7Sphitran #ifdef HAVE_POLKIT
40d2ec54f7Sphitran #include <libpolkit.h>
41d2ec54f7Sphitran #endif
42d2ec54f7Sphitran
43*55fea89dSDan Cross /**
44d2ec54f7Sphitran * usage:
45d2ec54f7Sphitran * @argc: Number of arguments given to program
46d2ec54f7Sphitran * @argv: Arguments given to program
47d2ec54f7Sphitran *
48*55fea89dSDan Cross * Print out program usage.
49d2ec54f7Sphitran */
50d2ec54f7Sphitran static void
usage(int argc,char * argv[])51d2ec54f7Sphitran usage (int argc, char *argv[])
52d2ec54f7Sphitran {
53d2ec54f7Sphitran fprintf (stderr,
54d2ec54f7Sphitran "\n"
55d2ec54f7Sphitran "usage : hal-is-caller-privileged --udi <udi> --action <action>\n"
56d2ec54f7Sphitran " --caller <caller-name>\n"
57d2ec54f7Sphitran " [--help] [--version]\n");
58d2ec54f7Sphitran fprintf (stderr,
59d2ec54f7Sphitran "\n"
60d2ec54f7Sphitran " --udi Unique Device Id\n"
61d2ec54f7Sphitran " --action PolicyKit action to check for\n"
62d2ec54f7Sphitran " --caller The name of the caller\n"
63d2ec54f7Sphitran " --version Show version and exit\n"
64d2ec54f7Sphitran " --help Show this information and exit\n"
65d2ec54f7Sphitran "\n"
66d2ec54f7Sphitran "This program determines if a given process on the system bus is\n"
67d2ec54f7Sphitran "privileged for a given PolicyKit action for a given device. If an error\n"
68d2ec54f7Sphitran "occurs this program exits with a non-zero exit code. Otherwise\n"
69d2ec54f7Sphitran "the textual reply will be printed on stdout and this program will\n"
70d2ec54f7Sphitran "exit with exit code 0. Note that only the super user (root)\n"
71d2ec54f7Sphitran "or other privileged users can use this tool.\n"
72d2ec54f7Sphitran "\n");
73d2ec54f7Sphitran }
74d2ec54f7Sphitran
75d2ec54f7Sphitran #ifdef HAVE_POLKIT
76d2ec54f7Sphitran static void
permission_denied_privilege(const char * privilege,const char * uid)77d2ec54f7Sphitran permission_denied_privilege (const char *privilege, const char *uid)
78d2ec54f7Sphitran {
79d2ec54f7Sphitran fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n"
80d2ec54f7Sphitran );
81d2ec54f7Sphitran fprintf (stderr, "%s refused uid %s\n", privilege, uid);
82d2ec54f7Sphitran exit (1);
83d2ec54f7Sphitran }
84d2ec54f7Sphitran #endif
85d2ec54f7Sphitran
86*55fea89dSDan Cross /**
87d2ec54f7Sphitran * main:
88d2ec54f7Sphitran * @argc: Number of arguments given to program
89d2ec54f7Sphitran * @argv: Arguments given to program
90d2ec54f7Sphitran *
91d2ec54f7Sphitran * Returns: Return code
92d2ec54f7Sphitran *
93*55fea89dSDan Cross * Main entry point
94d2ec54f7Sphitran */
95d2ec54f7Sphitran int
main(int argc,char * argv[])96d2ec54f7Sphitran main (int argc, char *argv[])
97d2ec54f7Sphitran {
98d2ec54f7Sphitran char *udi = NULL;
99d2ec54f7Sphitran char *action = NULL;
100d2ec54f7Sphitran char *caller = NULL;
101d2ec54f7Sphitran dbus_bool_t is_version = FALSE;
102d2ec54f7Sphitran DBusError error;
103d2ec54f7Sphitran #ifdef HAVE_POLKIT
104d2ec54f7Sphitran LibPolKitContext *pol_ctx = NULL;
105d2ec54f7Sphitran #endif
106d2ec54f7Sphitran DBusConnection *system_bus = NULL;
107d2ec54f7Sphitran uid_t calling_uid;
108d2ec54f7Sphitran char *privilege = NULL;
109d2ec54f7Sphitran const char *invoked_by_uid;
110d2ec54f7Sphitran gboolean allowed_by_privilege = FALSE;
111d2ec54f7Sphitran gboolean is_temporary_privilege;
112d2ec54f7Sphitran
113d2ec54f7Sphitran if (argc <= 1) {
114d2ec54f7Sphitran usage (argc, argv);
115d2ec54f7Sphitran return 1;
116d2ec54f7Sphitran }
117d2ec54f7Sphitran
118d2ec54f7Sphitran while (1) {
119d2ec54f7Sphitran int c;
120d2ec54f7Sphitran int option_index = 0;
121d2ec54f7Sphitran const char *opt;
122d2ec54f7Sphitran static struct option long_options[] = {
123d2ec54f7Sphitran {"udi", 1, NULL, 0},
124d2ec54f7Sphitran {"action", 1, NULL, 0},
125d2ec54f7Sphitran {"caller", 1, NULL, 0},
126d2ec54f7Sphitran {"version", 0, NULL, 0},
127d2ec54f7Sphitran {"help", 0, NULL, 0},
128d2ec54f7Sphitran {NULL, 0, NULL, 0}
129d2ec54f7Sphitran };
130d2ec54f7Sphitran
131d2ec54f7Sphitran c = getopt_long (argc, argv, "",
132d2ec54f7Sphitran long_options, &option_index);
133d2ec54f7Sphitran if (c == -1)
134d2ec54f7Sphitran break;
135d2ec54f7Sphitran
136d2ec54f7Sphitran switch (c) {
137d2ec54f7Sphitran case 0:
138d2ec54f7Sphitran opt = long_options[option_index].name;
139d2ec54f7Sphitran
140d2ec54f7Sphitran if (strcmp (opt, "help") == 0) {
141d2ec54f7Sphitran usage (argc, argv);
142d2ec54f7Sphitran return 0;
143d2ec54f7Sphitran } else if (strcmp (opt, "version") == 0) {
144d2ec54f7Sphitran is_version = TRUE;
145d2ec54f7Sphitran } else if (strcmp (opt, "udi") == 0) {
146d2ec54f7Sphitran udi = strdup (optarg);
147d2ec54f7Sphitran } else if (strcmp (opt, "caller") == 0) {
148d2ec54f7Sphitran caller = strdup (optarg);
149d2ec54f7Sphitran } else if (strcmp (opt, "action") == 0) {
150d2ec54f7Sphitran privilege = strdup (optarg);
151d2ec54f7Sphitran }
152d2ec54f7Sphitran break;
153d2ec54f7Sphitran
154d2ec54f7Sphitran default:
155d2ec54f7Sphitran usage (argc, argv);
156d2ec54f7Sphitran return 1;
157d2ec54f7Sphitran break;
158d2ec54f7Sphitran }
159d2ec54f7Sphitran }
160d2ec54f7Sphitran
161d2ec54f7Sphitran if (is_version) {
162d2ec54f7Sphitran printf ("hal-is-caller-privileged " PACKAGE_VERSION "\n");
163d2ec54f7Sphitran return 0;
164d2ec54f7Sphitran }
165d2ec54f7Sphitran
166d2ec54f7Sphitran if (udi == NULL || caller == NULL || privilege == NULL) {
167d2ec54f7Sphitran usage (argc, argv);
168d2ec54f7Sphitran return 1;
169d2ec54f7Sphitran }
170d2ec54f7Sphitran
171d2ec54f7Sphitran dbus_error_init (&error);
172d2ec54f7Sphitran system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
173d2ec54f7Sphitran if (system_bus == NULL) {
174d2ec54f7Sphitran printf ("Cannot connect to the system bus\n");
175d2ec54f7Sphitran LIBHAL_FREE_DBUS_ERROR (&error);
176d2ec54f7Sphitran fprintf (stderr, "This program should only be started by hald.\n");
177d2ec54f7Sphitran exit (1);
178d2ec54f7Sphitran }
179d2ec54f7Sphitran
180d2ec54f7Sphitran #ifdef HAVE_POLKIT
181d2ec54f7Sphitran pol_ctx = libpolkit_new_context (system_bus);
182d2ec54f7Sphitran if (pol_ctx == NULL) {
183d2ec54f7Sphitran printf ("Cannot get libpolkit context\n");
184d2ec54f7Sphitran }
185d2ec54f7Sphitran invoked_by_uid = getenv("HAL_METHOD_INVOKED_BY_UID");
186d2ec54f7Sphitran
187d2ec54f7Sphitran if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
188d2ec54f7Sphitran caller,
189d2ec54f7Sphitran invoked_by_uid,
190d2ec54f7Sphitran privilege,
191d2ec54f7Sphitran udi,
192d2ec54f7Sphitran &allowed_by_privilege,
193d2ec54f7Sphitran &is_temporary_privilege,
194d2ec54f7Sphitran NULL) != LIBPOLKIT_RESULT_OK
195d2ec54f7Sphitran ) {
196d2ec54f7Sphitran printf ("cannot lookup privilege\n");
197d2ec54f7Sphitran fprintf (stderr, "Cannot lookup privilege from PolicyKit");
198d2ec54f7Sphitran exit (1);
199d2ec54f7Sphitran }
200d2ec54f7Sphitran
201d2ec54f7Sphitran if (!allowed_by_privilege) {
202d2ec54f7Sphitran printf ("caller don't possess privilege\n");
203d2ec54f7Sphitran permission_denied_privilege (privilege, invoked_by_uid);
204d2ec54f7Sphitran }
205d2ec54f7Sphitran #endif
206d2ec54f7Sphitran
207d2ec54f7Sphitran printf("yes\n");
208d2ec54f7Sphitran return 0;
209d2ec54f7Sphitran }
210