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 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 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 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