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