1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 * Identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on the usage declared in their report
4 * descriptor and outputs suitable environment variables.
6 * Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c'
11 #include <linux/hid.h>
14 #include <sys/types.h>
17 #include "device-private.h"
18 #include "device-util.h"
20 #include "fido_id_desc.h"
23 #include "main-func.h"
24 #include "path-util.h"
25 #include "string-util.h"
26 #include "udev-util.h"
28 static int run(int argc
, char **argv
) {
29 _cleanup_(sd_device_unrefp
) struct sd_device
*device
= NULL
;
30 _cleanup_free_
char *desc_path
= NULL
;
31 _cleanup_close_
int fd
= -EBADF
;
33 struct sd_device
*hid_device
;
35 uint8_t desc
[HID_MAX_DESCRIPTOR_SIZE
];
40 log_set_target(LOG_TARGET_AUTO
);
42 log_parse_environment();
46 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Usage: %s [SYSFS_PATH]", program_invocation_short_name
);
49 r
= device_new_from_strv(&device
, environ
);
51 return log_error_errno(r
, "Failed to get current device from environment: %m");
53 r
= sd_device_new_from_syspath(&device
, argv
[1]);
55 return log_error_errno(r
, "Failed to get device from syspath: %m");
58 r
= sd_device_get_parent(device
, &hid_device
);
60 return log_device_error_errno(device
, r
, "Failed to get parent HID device: %m");
62 r
= sd_device_get_syspath(hid_device
, &sys_path
);
64 return log_device_error_errno(hid_device
, r
, "Failed to get syspath for HID device: %m");
66 desc_path
= path_join(sys_path
, "report_descriptor");
70 fd
= open(desc_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
| O_NOCTTY
);
72 return log_device_error_errno(hid_device
, errno
,
73 "Failed to open report descriptor at '%s': %m", desc_path
);
75 desc_len
= read(fd
, desc
, sizeof(desc
));
77 return log_device_error_errno(hid_device
, errno
,
78 "Failed to read report descriptor at '%s': %m", desc_path
);
80 return log_device_debug_errno(hid_device
, SYNTHETIC_ERRNO(EINVAL
),
81 "Empty report descriptor at '%s'.", desc_path
);
83 r
= is_fido_security_token_desc(desc
, desc_len
);
85 return log_device_debug_errno(hid_device
, r
,
86 "Failed to parse report descriptor at '%s'.", desc_path
);
88 printf("ID_FIDO_TOKEN=1\n");
89 printf("ID_SECURITY_TOKEN=1\n");
95 DEFINE_MAIN_FUNCTION(run
);