/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on the usage declared in their report * descriptor and outputs suitable environment variables. * * Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' */ #include #include #include #include #include #include #include #include "device-private.h" #include "device-util.h" #include "fd-util.h" #include "fido_id_desc.h" #include "log.h" #include "macro.h" #include "main-func.h" #include "path-util.h" #include "string-util.h" #include "udev-util.h" static int run(int argc, char **argv) { _cleanup_(sd_device_unrefp) struct sd_device *device = NULL; _cleanup_free_ char *desc_path = NULL; _cleanup_close_ int fd = -1; struct sd_device *hid_device; const char *sys_path; uint8_t desc[HID_MAX_DESCRIPTOR_SIZE]; ssize_t desc_len; int r; log_set_target(LOG_TARGET_AUTO); udev_parse_config(); log_parse_environment(); log_open(); if (argc > 2) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Usage: %s [SYSFS_PATH]", program_invocation_short_name); if (argc == 1) { r = device_new_from_strv(&device, environ); if (r < 0) return log_error_errno(r, "Failed to get current device from environment: %m"); } else { r = sd_device_new_from_syspath(&device, argv[1]); if (r < 0) return log_error_errno(r, "Failed to get device from syspath: %m"); } r = sd_device_get_parent(device, &hid_device); if (r < 0) return log_device_error_errno(device, r, "Failed to get parent HID device: %m"); r = sd_device_get_syspath(hid_device, &sys_path); if (r < 0) return log_device_error_errno(hid_device, r, "Failed to get syspath for HID device: %m"); desc_path = path_join(sys_path, "report_descriptor"); if (!desc_path) return log_oom(); fd = open(desc_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY); if (fd < 0) return log_device_error_errno(hid_device, errno, "Failed to open report descriptor at '%s': %m", desc_path); desc_len = read(fd, desc, sizeof(desc)); if (desc_len < 0) return log_device_error_errno(hid_device, errno, "Failed to read report descriptor at '%s': %m", desc_path); if (desc_len == 0) return log_device_debug_errno(hid_device, SYNTHETIC_ERRNO(EINVAL), "Empty report descriptor at '%s'.", desc_path); r = is_fido_security_token_desc(desc, desc_len); if (r < 0) return log_device_debug_errno(hid_device, r, "Failed to parse report descriptor at '%s'.", desc_path); if (r > 0) { printf("ID_FIDO_TOKEN=1\n"); printf("ID_SECURITY_TOKEN=1\n"); } return 0; } DEFINE_MAIN_FUNCTION(run);