Skip to content

Instantly share code, notes, and snippets.

@ghoff
Last active August 29, 2015 14:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghoff/f0675b40b7f0d686a980 to your computer and use it in GitHub Desktop.
Save ghoff/f0675b40b7f0d686a980 to your computer and use it in GitHub Desktop.
/*
* u2f-detect
* read hid records looking for a usage page of 0xf1d0 and usage 1
* returns true, to be used for udev-rules to set permissions on hidraw
*
* Copyright (c) 2014 Geoff Hoff http://github.com/ghoff
* includes code from hidraw and based on code from lsusb
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* Hidraw Userspace Example
*
* Copyright (c) 2010 Alan Ott <alan@signal11.us>
* Copyright (c) 2010 Signal 11 Software
*
* The code may be used by anyone for any purpose,
* and can serve as a starting point for developing
* applications using hidraw.
*/
/*****************************************************************************/
/*
* lsusb.c -- lspci like utility for the USB bus
*
* Copyright (C) 1999-2001, 2003
* Thomas Sailer (t.sailer@alumni.ethz.ch)
* Copyright (C) 2003-2005 David Brownell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************/
/* Linux */
#include <linux/hidraw.h>
/* Unix */
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
/* C */
#include <stdio.h>
#include <string.h>
unsigned int report_desc(unsigned char *b, int *i,
unsigned int *btype, unsigned int *btag)
{
unsigned int j, bsize, data=0;
bsize = b[*i] & 0x03;
if (bsize == 3)
bsize = 4;
if (bsize > 0) {
for (j = 0; j < bsize; j++) {
data += (b[*i+1+j] << (8*j));
}
}
*btype = (b[*i] >> 2) & 0x03;
*btag = b[*i] & ~0x03; /* 2 LSB bits encode length */
*i += 1 + bsize;
return data;
}
#define TYPE_GLOBAL 1
#define TYPE_LOCAL 2
#define TAG_USAGE_PAGE 0x04
#define TAG_USAGE 0x08
static void dump_report_desc(unsigned char *b, int l)
{
unsigned int btype, btag, data;
int i, fido=0;
for (i = 0; i < l; ) {
data = report_desc(b, &i, &btype, &btag);
if (btype == TYPE_LOCAL && btag == TAG_USAGE && data == 1 && fido) {
printf("ID_SECURITY_TOKEN=1\n");
break;
}
fido=0;
if (btype == TYPE_GLOBAL && btag == TAG_USAGE_PAGE && data == 0xf1d0) {
fido=1;
}
}
}
int main(int argc, char **argv)
{
int fd;
int res, desc_size = 0;
struct hidraw_report_descriptor rpt_desc;
if (argc != 2) {
printf("Usage: %s <hidraw device>\n",argv[0]);
return 1;
}
/* Open the Device with non-blocking reads. */
fd = open(argv[1], O_RDONLY|O_NONBLOCK);
if (fd < 0) {
perror("Unable to open device");
return 1;
}
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
/* Get Report Descriptor Size */
res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
if (res < 0)
perror("HIDIOCGRDESCSIZE");
/* Get Report Descriptor */
rpt_desc.size = desc_size;
res = ioctl(fd, HIDIOCGRDESC, &rpt_desc);
if (res < 0) {
perror("HIDIOCGRDESC");
} else {
dump_report_desc(rpt_desc.value, rpt_desc.size);
}
close(fd);
return 0;
}
@ghoff
Copy link
Author

ghoff commented Dec 3, 2014

This program should universally support Fido u2f devices by reading the USB report usage pages and looking for the code 0xF1D0 and the usage of 0x01. If it is set, the program will print the variable ID_SECURITY_TOKEN=1 which udev will check for.

Compile
gcc -Wall -o u2f-detect u2f-detect.c
Copy u2f-detect to /lib/udev
Edit /lib/udev/rules.d/70-u2f.rules and add this line

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ENV{ID_SECURITY_TOKEN}!="?*", IMPORT{program}="u2f-detect $devnode"

The existing 70-uaccess.rules will grant file access to local user to devices with the ID_SECURITY_TOKEN environment variable set. This has been tested on Ubuntu..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment