summaryrefslogtreecommitdiff
path: root/src/extras/udev-acl/udev-acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/extras/udev-acl/udev-acl.c')
-rw-r--r--src/extras/udev-acl/udev-acl.c724
1 files changed, 362 insertions, 362 deletions
diff --git a/src/extras/udev-acl/udev-acl.c b/src/extras/udev-acl/udev-acl.c
index 41e2536e03..628cfbed4e 100644
--- a/src/extras/udev-acl/udev-acl.c
+++ b/src/extras/udev-acl/udev-acl.c
@@ -28,403 +28,403 @@
static int debug;
enum{
- ACTION_NONE = 0,
- ACTION_REMOVE,
- ACTION_ADD,
- ACTION_CHANGE
+ ACTION_NONE = 0,
+ ACTION_REMOVE,
+ ACTION_ADD,
+ ACTION_CHANGE
};
static int set_facl(const char* filename, uid_t uid, int add)
{
- int get;
- acl_t acl;
- acl_entry_t entry = NULL;
- acl_entry_t e;
- acl_permset_t permset;
- int ret;
-
- /* don't touch ACLs for root */
- if (uid == 0)
- return 0;
-
- /* read current record */
- acl = acl_get_file(filename, ACL_TYPE_ACCESS);
- if (!acl)
- return -1;
-
- /* locate ACL_USER entry for uid */
- get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e);
- while (get == 1) {
- acl_tag_t t;
-
- acl_get_tag_type(e, &t);
- if (t == ACL_USER) {
- uid_t *u;
-
- u = (uid_t*)acl_get_qualifier(e);
- if (u == NULL) {
- ret = -1;
- goto out;
- }
- if (*u == uid) {
- entry = e;
- acl_free(u);
- break;
- }
- acl_free(u);
- }
-
- get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e);
- }
-
- /* remove ACL_USER entry for uid */
- if (!add) {
- if (entry == NULL) {
- ret = 0;
- goto out;
- }
- acl_delete_entry(acl, entry);
- goto update;
- }
-
- /* create ACL_USER entry for uid */
- if (entry == NULL) {
- ret = acl_create_entry(&acl, &entry);
- if (ret != 0)
- goto out;
- acl_set_tag_type(entry, ACL_USER);
- acl_set_qualifier(entry, &uid);
- }
-
- /* add permissions for uid */
- acl_get_permset(entry, &permset);
- acl_add_perm(permset, ACL_READ|ACL_WRITE);
+ int get;
+ acl_t acl;
+ acl_entry_t entry = NULL;
+ acl_entry_t e;
+ acl_permset_t permset;
+ int ret;
+
+ /* don't touch ACLs for root */
+ if (uid == 0)
+ return 0;
+
+ /* read current record */
+ acl = acl_get_file(filename, ACL_TYPE_ACCESS);
+ if (!acl)
+ return -1;
+
+ /* locate ACL_USER entry for uid */
+ get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e);
+ while (get == 1) {
+ acl_tag_t t;
+
+ acl_get_tag_type(e, &t);
+ if (t == ACL_USER) {
+ uid_t *u;
+
+ u = (uid_t*)acl_get_qualifier(e);
+ if (u == NULL) {
+ ret = -1;
+ goto out;
+ }
+ if (*u == uid) {
+ entry = e;
+ acl_free(u);
+ break;
+ }
+ acl_free(u);
+ }
+
+ get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e);
+ }
+
+ /* remove ACL_USER entry for uid */
+ if (!add) {
+ if (entry == NULL) {
+ ret = 0;
+ goto out;
+ }
+ acl_delete_entry(acl, entry);
+ goto update;
+ }
+
+ /* create ACL_USER entry for uid */
+ if (entry == NULL) {
+ ret = acl_create_entry(&acl, &entry);
+ if (ret != 0)
+ goto out;
+ acl_set_tag_type(entry, ACL_USER);
+ acl_set_qualifier(entry, &uid);
+ }
+
+ /* add permissions for uid */
+ acl_get_permset(entry, &permset);
+ acl_add_perm(permset, ACL_READ|ACL_WRITE);
update:
- /* update record */
- if (debug)
- printf("%c%u %s\n", add ? '+' : '-', uid, filename);
- acl_calc_mask(&acl);
- ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl);
- if (ret != 0)
- goto out;
+ /* update record */
+ if (debug)
+ printf("%c%u %s\n", add ? '+' : '-', uid, filename);
+ acl_calc_mask(&acl);
+ ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl);
+ if (ret != 0)
+ goto out;
out:
- acl_free(acl);
- return ret;
+ acl_free(acl);
+ return ret;
}
/* check if a given uid is listed */
static int uid_in_list(GSList *list, uid_t uid)
{
- GSList *l;
+ GSList *l;
- for (l = list; l != NULL; l = g_slist_next(l))
- if (uid == GPOINTER_TO_UINT(l->data))
- return 1;
- return 0;
+ for (l = list; l != NULL; l = g_slist_next(l))
+ if (uid == GPOINTER_TO_UINT(l->data))
+ return 1;
+ return 0;
}
/* return list of current uids of local active sessions */
static GSList *uids_with_local_active_session(const char *own_id)
{
- GSList *list = NULL;
- GKeyFile *keyfile;
-
- keyfile = g_key_file_new();
- if (g_key_file_load_from_file(keyfile, "/var/run/ConsoleKit/database", 0, NULL)) {
- gchar **groups;
-
- groups = g_key_file_get_groups(keyfile, NULL);
- if (groups != NULL) {
- int i;
-
- for (i = 0; groups[i] != NULL; i++) {
- uid_t u;
-
- if (!g_str_has_prefix(groups[i], "Session "))
- continue;
- if (own_id != NULL &&g_str_has_suffix(groups[i], own_id))
- continue;
- if (!g_key_file_get_boolean(keyfile, groups[i], "is_local", NULL))
- continue;
- if (!g_key_file_get_boolean(keyfile, groups[i], "is_active", NULL))
- continue;
- u = g_key_file_get_integer(keyfile, groups[i], "uid", NULL);
- if (u > 0 && !uid_in_list(list, u))
- list = g_slist_prepend(list, GUINT_TO_POINTER(u));
- }
- g_strfreev(groups);
- }
- }
- g_key_file_free(keyfile);
-
- return list;
+ GSList *list = NULL;
+ GKeyFile *keyfile;
+
+ keyfile = g_key_file_new();
+ if (g_key_file_load_from_file(keyfile, "/var/run/ConsoleKit/database", 0, NULL)) {
+ gchar **groups;
+
+ groups = g_key_file_get_groups(keyfile, NULL);
+ if (groups != NULL) {
+ int i;
+
+ for (i = 0; groups[i] != NULL; i++) {
+ uid_t u;
+
+ if (!g_str_has_prefix(groups[i], "Session "))
+ continue;
+ if (own_id != NULL &&g_str_has_suffix(groups[i], own_id))
+ continue;
+ if (!g_key_file_get_boolean(keyfile, groups[i], "is_local", NULL))
+ continue;
+ if (!g_key_file_get_boolean(keyfile, groups[i], "is_active", NULL))
+ continue;
+ u = g_key_file_get_integer(keyfile, groups[i], "uid", NULL);
+ if (u > 0 && !uid_in_list(list, u))
+ list = g_slist_prepend(list, GUINT_TO_POINTER(u));
+ }
+ g_strfreev(groups);
+ }
+ }
+ g_key_file_free(keyfile);
+
+ return list;
}
/* ConsoleKit calls us with special variables */
static int consolekit_called(const char *ck_action, uid_t *uid, uid_t *uid2, const char **remove_session_id, int *action)
{
- int a = ACTION_NONE;
- uid_t u = 0;
- uid_t u2 = 0;
- const char *s;
- const char *s2;
- const char *old_session = NULL;
-
- if (ck_action == NULL || strcmp(ck_action, "seat_active_session_changed") != 0)
- return -1;
-
- /* We can have one of: remove, add, change, no-change */
- s = getenv("CK_SEAT_OLD_SESSION_ID");
- s2 = getenv("CK_SEAT_SESSION_ID");
- if (s == NULL && s2 == NULL) {
- return -1;
- } else if (s2 == NULL) {
- a = ACTION_REMOVE;
- } else if (s == NULL) {
- a = ACTION_ADD;
- } else {
- a = ACTION_CHANGE;
- }
-
- switch (a) {
- case ACTION_ADD:
- s = getenv("CK_SEAT_SESSION_USER_UID");
- if (s == NULL)
- return -1;
- u = strtoul(s, NULL, 10);
-
- s = getenv("CK_SEAT_SESSION_IS_LOCAL");
- if (s == NULL)
- return -1;
- if (strcmp(s, "true") != 0)
- return 0;
-
- break;
- case ACTION_REMOVE:
- s = getenv("CK_SEAT_OLD_SESSION_USER_UID");
- if (s == NULL)
- return -1;
- u = strtoul(s, NULL, 10);
-
- s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL");
- if (s == NULL)
- return -1;
- if (strcmp(s, "true") != 0)
- return 0;
-
- old_session = getenv("CK_SEAT_OLD_SESSION_ID");
- if (old_session == NULL)
- return -1;
-
- break;
- case ACTION_CHANGE:
- s = getenv("CK_SEAT_OLD_SESSION_USER_UID");
- if (s == NULL)
- return -1;
- u = strtoul(s, NULL, 10);
- s = getenv("CK_SEAT_SESSION_USER_UID");
- if (s == NULL)
- return -1;
- u2 = strtoul(s, NULL, 10);
-
- s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL");
- s2 = getenv("CK_SEAT_SESSION_IS_LOCAL");
- if (s == NULL || s2 == NULL)
- return -1;
- /* don't process non-local session changes */
- if (strcmp(s, "true") != 0 && strcmp(s2, "true") != 0)
- return 0;
-
- if (strcmp(s, "true") == 0 && strcmp(s, "true") == 0) {
- /* process the change */
- if (u == u2) {
- /* special case: we noop if we are
- * changing between local sessions for
- * the same uid */
- a = ACTION_NONE;
- }
- old_session = getenv("CK_SEAT_OLD_SESSION_ID");
- if (old_session == NULL)
- return -1;
- } else if (strcmp(s, "true") == 0) {
- /* only process the removal */
- a = ACTION_REMOVE;
- old_session = getenv("CK_SEAT_OLD_SESSION_ID");
- if (old_session == NULL)
- return -1;
- } else if (strcmp(s2, "true") == 0) {
- /* only process the addition */
- a = ACTION_ADD;
- u = u2;
- }
- break;
- }
-
- *remove_session_id = old_session;
- *uid = u;
- *uid2 = u2;
- *action = a;
- return 0;
+ int a = ACTION_NONE;
+ uid_t u = 0;
+ uid_t u2 = 0;
+ const char *s;
+ const char *s2;
+ const char *old_session = NULL;
+
+ if (ck_action == NULL || strcmp(ck_action, "seat_active_session_changed") != 0)
+ return -1;
+
+ /* We can have one of: remove, add, change, no-change */
+ s = getenv("CK_SEAT_OLD_SESSION_ID");
+ s2 = getenv("CK_SEAT_SESSION_ID");
+ if (s == NULL && s2 == NULL) {
+ return -1;
+ } else if (s2 == NULL) {
+ a = ACTION_REMOVE;
+ } else if (s == NULL) {
+ a = ACTION_ADD;
+ } else {
+ a = ACTION_CHANGE;
+ }
+
+ switch (a) {
+ case ACTION_ADD:
+ s = getenv("CK_SEAT_SESSION_USER_UID");
+ if (s == NULL)
+ return -1;
+ u = strtoul(s, NULL, 10);
+
+ s = getenv("CK_SEAT_SESSION_IS_LOCAL");
+ if (s == NULL)
+ return -1;
+ if (strcmp(s, "true") != 0)
+ return 0;
+
+ break;
+ case ACTION_REMOVE:
+ s = getenv("CK_SEAT_OLD_SESSION_USER_UID");
+ if (s == NULL)
+ return -1;
+ u = strtoul(s, NULL, 10);
+
+ s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL");
+ if (s == NULL)
+ return -1;
+ if (strcmp(s, "true") != 0)
+ return 0;
+
+ old_session = getenv("CK_SEAT_OLD_SESSION_ID");
+ if (old_session == NULL)
+ return -1;
+
+ break;
+ case ACTION_CHANGE:
+ s = getenv("CK_SEAT_OLD_SESSION_USER_UID");
+ if (s == NULL)
+ return -1;
+ u = strtoul(s, NULL, 10);
+ s = getenv("CK_SEAT_SESSION_USER_UID");
+ if (s == NULL)
+ return -1;
+ u2 = strtoul(s, NULL, 10);
+
+ s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL");
+ s2 = getenv("CK_SEAT_SESSION_IS_LOCAL");
+ if (s == NULL || s2 == NULL)
+ return -1;
+ /* don't process non-local session changes */
+ if (strcmp(s, "true") != 0 && strcmp(s2, "true") != 0)
+ return 0;
+
+ if (strcmp(s, "true") == 0 && strcmp(s, "true") == 0) {
+ /* process the change */
+ if (u == u2) {
+ /* special case: we noop if we are
+ * changing between local sessions for
+ * the same uid */
+ a = ACTION_NONE;
+ }
+ old_session = getenv("CK_SEAT_OLD_SESSION_ID");
+ if (old_session == NULL)
+ return -1;
+ } else if (strcmp(s, "true") == 0) {
+ /* only process the removal */
+ a = ACTION_REMOVE;
+ old_session = getenv("CK_SEAT_OLD_SESSION_ID");
+ if (old_session == NULL)
+ return -1;
+ } else if (strcmp(s2, "true") == 0) {
+ /* only process the addition */
+ a = ACTION_ADD;
+ u = u2;
+ }
+ break;
+ }
+
+ *remove_session_id = old_session;
+ *uid = u;
+ *uid2 = u2;
+ *action = a;
+ return 0;
}
/* add or remove a ACL for a given uid from all matching devices */
static void apply_acl_to_devices(uid_t uid, int add)
{
- struct udev *udev;
- struct udev_enumerate *enumerate;
- struct udev_list_entry *list_entry;
-
- /* iterate over all devices tagged with ACL_SET */
- udev = udev_new();
- enumerate = udev_enumerate_new(udev);
- udev_enumerate_add_match_tag(enumerate, "udev-acl");
- udev_enumerate_scan_devices(enumerate);
- udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
- struct udev_device *device;
- const char *node;
-
- device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
- udev_list_entry_get_name(list_entry));
- if (device == NULL)
- continue;
- node = udev_device_get_devnode(device);
- if (node == NULL) {
- udev_device_unref(device);
- continue;
- }
- set_facl(node, uid, add);
- udev_device_unref(device);
- }
- udev_enumerate_unref(enumerate);
- udev_unref(udev);
+ struct udev *udev;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *list_entry;
+
+ /* iterate over all devices tagged with ACL_SET */
+ udev = udev_new();
+ enumerate = udev_enumerate_new(udev);
+ udev_enumerate_add_match_tag(enumerate, "udev-acl");
+ udev_enumerate_scan_devices(enumerate);
+ udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
+ struct udev_device *device;
+ const char *node;
+
+ device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
+ udev_list_entry_get_name(list_entry));
+ if (device == NULL)
+ continue;
+ node = udev_device_get_devnode(device);
+ if (node == NULL) {
+ udev_device_unref(device);
+ continue;
+ }
+ set_facl(node, uid, add);
+ udev_device_unref(device);
+ }
+ udev_enumerate_unref(enumerate);
+ udev_unref(udev);
}
static void
remove_uid (uid_t uid, const char *remove_session_id)
{
- /*
- * Remove ACL for given uid from all matching devices
- * when there is currently no local active session.
- */
- GSList *list;
-
- list = uids_with_local_active_session(remove_session_id);
- if (!uid_in_list(list, uid))
- apply_acl_to_devices(uid, 0);
- g_slist_free(list);
+ /*
+ * Remove ACL for given uid from all matching devices
+ * when there is currently no local active session.
+ */
+ GSList *list;
+
+ list = uids_with_local_active_session(remove_session_id);
+ if (!uid_in_list(list, uid))
+ apply_acl_to_devices(uid, 0);
+ g_slist_free(list);
}
int main (int argc, char* argv[])
{
- static const struct option options[] = {
- { "action", required_argument, NULL, 'a' },
- { "device", required_argument, NULL, 'D' },
- { "user", required_argument, NULL, 'u' },
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- {}
- };
- int action = -1;
- const char *device = NULL;
- bool uid_given = false;
- uid_t uid = 0;
- uid_t uid2 = 0;
- const char* remove_session_id = NULL;
- int rc = 0;
-
- /* valgrind is more important to us than a slice allocator */
- g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
-
- while (1) {
- int option;
-
- option = getopt_long(argc, argv, "+a:D:u:dh", options, NULL);
- if (option == -1)
- break;
-
- switch (option) {
- case 'a':
- if (strcmp(optarg, "remove") == 0)
- action = ACTION_REMOVE;
- else
- action = ACTION_ADD;
- break;
- case 'D':
- device = optarg;
- break;
- case 'u':
- uid_given = true;
- uid = strtoul(optarg, NULL, 10);
- break;
- case 'd':
- debug = 1;
- break;
- case 'h':
- printf("Usage: udev-acl --action=ACTION [--device=DEVICEFILE] [--user=UID]\n\n");
- goto out;
- }
- }
-
- if (action < 0 && device == NULL && !uid_given)
- if (!consolekit_called(argv[optind], &uid, &uid2, &remove_session_id, &action))
- uid_given = true;
-
- if (action < 0) {
- fprintf(stderr, "missing action\n\n");
- rc = 2;
- goto out;
- }
-
- if (device != NULL && uid_given) {
- fprintf(stderr, "only one option, --device=DEVICEFILE or --user=UID expected\n\n");
- rc = 3;
- goto out;
- }
-
- if (uid_given) {
- switch (action) {
- case ACTION_ADD:
- /* Add ACL for given uid to all matching devices. */
- apply_acl_to_devices(uid, 1);
- break;
- case ACTION_REMOVE:
- remove_uid(uid, remove_session_id);
- break;
- case ACTION_CHANGE:
- remove_uid(uid, remove_session_id);
- apply_acl_to_devices(uid2, 1);
- break;
- case ACTION_NONE:
- goto out;
- break;
- default:
- g_assert_not_reached();
- break;
- }
- } else if (device != NULL) {
- /*
- * Add ACLs for all current session uids to a given device.
- *
- * Or remove ACLs for uids which do not have any current local
- * active session. Remove is not really interesting, because in
- * most cases the device node is removed anyway.
- */
- GSList *list;
- GSList *l;
-
- list = uids_with_local_active_session(NULL);
- for (l = list; l != NULL; l = g_slist_next(l)) {
- uid_t u;
-
- u = GPOINTER_TO_UINT(l->data);
- if (action == ACTION_ADD || !uid_in_list(list, u))
- set_facl(device, u, action == ACTION_ADD);
- }
- g_slist_free(list);
- } else {
- fprintf(stderr, "--device=DEVICEFILE or --user=UID expected\n\n");
- rc = 3;
- }
+ static const struct option options[] = {
+ { "action", required_argument, NULL, 'a' },
+ { "device", required_argument, NULL, 'D' },
+ { "user", required_argument, NULL, 'u' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ {}
+ };
+ int action = -1;
+ const char *device = NULL;
+ bool uid_given = false;
+ uid_t uid = 0;
+ uid_t uid2 = 0;
+ const char* remove_session_id = NULL;
+ int rc = 0;
+
+ /* valgrind is more important to us than a slice allocator */
+ g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
+
+ while (1) {
+ int option;
+
+ option = getopt_long(argc, argv, "+a:D:u:dh", options, NULL);
+ if (option == -1)
+ break;
+
+ switch (option) {
+ case 'a':
+ if (strcmp(optarg, "remove") == 0)
+ action = ACTION_REMOVE;
+ else
+ action = ACTION_ADD;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'u':
+ uid_given = true;
+ uid = strtoul(optarg, NULL, 10);
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'h':
+ printf("Usage: udev-acl --action=ACTION [--device=DEVICEFILE] [--user=UID]\n\n");
+ goto out;
+ }
+ }
+
+ if (action < 0 && device == NULL && !uid_given)
+ if (!consolekit_called(argv[optind], &uid, &uid2, &remove_session_id, &action))
+ uid_given = true;
+
+ if (action < 0) {
+ fprintf(stderr, "missing action\n\n");
+ rc = 2;
+ goto out;
+ }
+
+ if (device != NULL && uid_given) {
+ fprintf(stderr, "only one option, --device=DEVICEFILE or --user=UID expected\n\n");
+ rc = 3;
+ goto out;
+ }
+
+ if (uid_given) {
+ switch (action) {
+ case ACTION_ADD:
+ /* Add ACL for given uid to all matching devices. */
+ apply_acl_to_devices(uid, 1);
+ break;
+ case ACTION_REMOVE:
+ remove_uid(uid, remove_session_id);
+ break;
+ case ACTION_CHANGE:
+ remove_uid(uid, remove_session_id);
+ apply_acl_to_devices(uid2, 1);
+ break;
+ case ACTION_NONE:
+ goto out;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ } else if (device != NULL) {
+ /*
+ * Add ACLs for all current session uids to a given device.
+ *
+ * Or remove ACLs for uids which do not have any current local
+ * active session. Remove is not really interesting, because in
+ * most cases the device node is removed anyway.
+ */
+ GSList *list;
+ GSList *l;
+
+ list = uids_with_local_active_session(NULL);
+ for (l = list; l != NULL; l = g_slist_next(l)) {
+ uid_t u;
+
+ u = GPOINTER_TO_UINT(l->data);
+ if (action == ACTION_ADD || !uid_in_list(list, u))
+ set_facl(device, u, action == ACTION_ADD);
+ }
+ g_slist_free(list);
+ } else {
+ fprintf(stderr, "--device=DEVICEFILE or --user=UID expected\n\n");
+ rc = 3;
+ }
out:
- return rc;
+ return rc;
}