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