FreeBSD: remove dependency on uhid-freebsd.

This commit is contained in:
Enrik Berkhan 2021-03-18 20:25:27 +01:00
parent 142587b3e6
commit bd36cbcf35
2 changed files with 92 additions and 9 deletions

View File

@ -18,8 +18,10 @@
from __future__ import absolute_import
from ctypes.util import find_library
import ctypes
import re
import os
import uhid_freebsd
from .base import HidDescriptor, parse_report_descriptor, FileCtapHidConnection
@ -28,20 +30,105 @@ import logging
logger = logging.getLogger(__name__)
devdir = "/dev/"
device_re = re.compile("^uhid([0-9]+)$")
vendor_re = re.compile("vendor=(0x[0-9a-fA-F]+)")
product_re = re.compile("product=(0x[0-9a-fA-F]+)")
sernum_re = re.compile('sernum="([^"]+)')
libc = ctypes.CDLL(find_library("c"))
USB_GET_REPORT_DESC = 0xC0205515
class usb_gen_descriptor(ctypes.Structure):
_fields_ = [
(
"ugd_data",
ctypes.c_void_p,
), # TODO: check what COMPAT_32BIT in C header means
("ugd_lang_id", ctypes.c_uint16),
("ugd_maxlen", ctypes.c_uint16),
("ugd_actlen", ctypes.c_uint16),
("ugd_offset", ctypes.c_uint16),
("ugd_config_index", ctypes.c_uint8),
("ugd_string_index", ctypes.c_uint8),
("ugd_iface_index", ctypes.c_uint8),
("ugd_altif_index", ctypes.c_uint8),
("ugd_endpt_index", ctypes.c_uint8),
("ugd_report_type", ctypes.c_uint8),
("reserved", ctypes.c_uint8 * 8),
]
def open_connection(descriptor):
return FileCtapHidConnection(descriptor)
def _get_report_data(fd, report_type):
data = ctypes.create_string_buffer(b"\000" * 4096)
desc = usb_gen_descriptor(
ugd_data=ctypes.addressof(data),
ugd_maxlen=ctypes.sizeof(data),
report_type=report_type,
)
ret = libc.ioctl(fd, USB_GET_REPORT_DESC, ctypes.byref(desc))
if ret != 0:
raise ValueError("ioctl failed")
return data.raw[: desc.ugd_actlen]
def _read_descriptor(vid, pid, name, serial, path):
fd = os.open(path, os.O_RDONLY)
data = uhid_freebsd.get_report_data(fd, 3)
data = _get_report_data(fd, 3)
os.close(fd)
max_in_size, max_out_size = parse_report_descriptor(data)
return HidDescriptor(path, vid, pid, max_in_size, max_out_size, name, serial)
def _enumerate():
for uhid in os.listdir(devdir):
m = device_re.search(uhid)
if m is None:
continue
index = m.group(1)
pnpinfo = ("dev.uhid." + index + ".%pnpinfo").encode()
desc = ("dev.uhid." + index + ".%desc").encode()
ovalue = ctypes.create_string_buffer(b"\000" * 1024)
olen = ctypes.c_size_t(ctypes.sizeof(ovalue))
key = ctypes.c_char_p(pnpinfo)
retval = libc.sysctlbyname(key, ovalue, ctypes.byref(olen), None, None)
if retval != 0:
continue
dev = {}
dev["name"] = uhid
dev["path"] = devdir + uhid
value = ovalue.value.decode()
m = vendor_re.search(value)
dev["vendor_id"] = m.group(1) if m else None
m = product_re.search(value)
dev["product_id"] = m.group(1) if m else None
m = sernum_re.search(value)
dev["serial_number"] = m.group(1) if m else None
key = ctypes.c_char_p(desc)
retval = libc.sysctlbyname(key, ovalue, ctypes.byref(olen), None, None)
if retval == 0:
dev["product_desc"] = ovalue.value.decode() or None
yield dev
def get_descriptor(path):
for dev in uhid_freebsd.enumerate():
for dev in _enumerate():
if dev["path"] == path:
vid = dev["vendor_id"]
pid = dev["product_id"]
@ -53,7 +140,7 @@ def get_descriptor(path):
def list_descriptors():
descriptors = []
for dev in uhid_freebsd.enumerate():
for dev in _enumerate():
try:
name = dev["product_desc"] or None
serial = (dev["serial_number"] if "serial_number" in dev else None) or None

View File

@ -53,11 +53,7 @@ setup(
description="Python based FIDO 2.0 library",
url="https://github.com/Yubico/python-fido2",
python_requires=">=2.7.6,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
install_requires=[
"six",
"cryptography>=1.5",
'uhid-freebsd>=1.2.1;platform_system=="FreeBSD"',
],
install_requires=["six", "cryptography>=1.5"],
extras_require={':python_version < "3.4"': ["enum34"], "pcsc": ["pyscard"]},
classifiers=[
"License :: OSI Approved :: BSD License",