On Sat, 13 Jan 2024 11:26:50 +0100 Florian Schlichting
<f...@debian.org> wrote:
>
> [...]
> While it might be possible to patch py/yubikey.py to work with the
> interface changes in current python3-ykman, I doubt this is a
> sensible thing to do if upstream has decided to abandon
> the QT version.

in case you are interested, you can find the patch in attachement

br,
Sébastien
From 5660af2838fef22b53e9c7c47381755e96dcdc52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Noel?= <sebast...@twolife.be>
Date: Sat, 25 Feb 2023 17:59:48 +0100
Subject: [PATCH] Compatibility for ykman 5

---
 py/yubikey.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 84 insertions(+), 9 deletions(-)

diff --git a/py/yubikey.py b/py/yubikey.py
index 592f215..bfec19b 100644
--- a/py/yubikey.py
+++ b/py/yubikey.py
@@ -20,9 +20,7 @@
 
 from fido2.ctap import CtapError
 from fido2.ctap2 import Ctap2, ClientPin, FPBioEnrollment, CredentialManagement, CaptureError
-from ykman.device import scan_devices, list_all_devices, connect_to_device, get_name, read_info
 from ykman.pcsc import list_readers, list_devices as list_ccid
-from ykman.otp import PrepareUploadFailed, generate_static_pw, prepare_upload_key, time_challenge, format_oath_code
 from ykman.settings import AppData
 from ykman.oath import is_hidden, is_steam, calculate_steam
 from ykman.scancodes import KEYBOARD_LAYOUT, encode
@@ -44,6 +42,18 @@
 
 import pyotherside
 
+from ykman import __version__ as ykman_v
+
+if int(ykman_v.split(".")[0] ) > 4:
+    from yubikit.support import get_name, read_info
+    from ykman.device import list_all_devices, scan_devices
+    from ykman.otp import (
+    _PrepareUploadFailed as PrepareUploadFailed
+    , _prepare_upload_key as prepare_upload_key, generate_static_pw, time_challenge, format_oath_code)
+else:
+    from ykman.device import scan_devices, list_all_devices, get_name, read_info
+    from ykman.otp import PrepareUploadFailed, generate_static_pw, prepare_upload_key, time_challenge, format_oath_code
+
 
 logger = logging.getLogger(__name__)
 
@@ -193,7 +203,22 @@ def _open_device(self, connection_types=[SmartCardConnection, FidoConnection, Ot
                 return dev.open_connection(connection_types[0])
             else:
                 raise ValueError('no_device_custom_reader')
-        return connect_to_device(self._current_serial, connection_types=connection_types)[0]
+
+        if int(ykman_v.split(".")[0] ) > 4:
+            devs = list_all_devices(connection_types)
+            if len(devs) == 0:
+                raise Exception("No YubiKey connected")
+            elif len(devs) != 1:
+                raise Exception("More than one YubiKey connected")
+            dev, info2 = devs[0]
+
+            for conn_type in connection_types:
+                try:
+                    return dev.open_connection(conn_type)
+                except Exception:
+                    logger.debug(f"Failed connecting to the YubiKey over {conn_type}", exc_info=True)
+        else:
+            return connect_to_device(self._current_serial, connection_types=connection_types)[0]
 
     def _open_oath(self):
         if self._reader_filter:
@@ -203,7 +228,16 @@ def _open_oath(self):
             else:
                 raise ValueError('no_device_custom_reader')
 
-        return connect_to_device(self._current_serial, [SmartCardConnection])[0]
+        if int(ykman_v.split(".")[0] ) > 4:
+            devs = list_all_devices([SmartCardConnection])
+            if len(devs) == 0:
+                raise Exception("No YubiKey connected")
+            elif len(devs) != 1:
+                raise Exception("More than one YubiKey connected")
+            dev, info2 = devs[0]
+            return dev.open_connection(SmartCardConnection)
+        else:
+            return connect_to_device(self._current_serial, [SmartCardConnection])[0]
 
     def is_win_non_admin(self):
         return success({'winNonAdmin': self._win_non_admin})
@@ -284,7 +318,39 @@ def _get_version(dev):
         supported_interfaces = interfaces_from_capabilities(
                 info.supported_capabilities.get(TRANSPORT.USB))
 
-        return {
+        if int(ykman_v.split(".")[0] ) > 4:
+          return {
+            'name': get_name(info, dev.pid.yubikey_type),
+            'version': _get_version(info),
+            'serial': info.serial or '',
+            'usbAppEnabled': [
+                a.name for a in CAPABILITY
+                if a in info.config.enabled_capabilities.get(TRANSPORT.USB)],
+            'usbAppSupported': [
+                a.name for a in CAPABILITY
+                if a in info.supported_capabilities.get(TRANSPORT.USB)],
+            'nfcAppEnabled': [
+                a.name for a in CAPABILITY
+                if a in info.config.enabled_capabilities.get(TRANSPORT.NFC, [])],
+            'nfcAppSupported': [
+                a.name for a in CAPABILITY
+                if a in info.supported_capabilities.get(TRANSPORT.NFC, [])],
+            'usbInterfacesSupported': supported_interfaces,
+            'usbInterfacesEnabled': [
+                i.name for i in USB_INTERFACE
+                if i in dev.pid.usb_interfaces],
+            'canWriteConfig': info.version and info.version >= (5,0,0),
+            'configurationLocked': info.is_locked,
+            'formFactor': info.form_factor,
+            'hasPassword': dev.has_password if hasattr(dev, 'has_password') else False,
+            'ctapAvailable': ctap_available,
+            'fidoHasPin': fido_pin_list[0],
+            'fidoPinRetries': fido_pin_list[1],
+            'uvBlocked': fido_pin_list[2],
+            'isNfc': self._reader_filter and not self._reader_filter.lower().startswith("yubico yubikey"),
+          }
+        else:
+          return {
             'name': get_name(info, dev.pid.get_type()),
             'version': _get_version(info),
             'serial': info.serial or '',
@@ -313,7 +379,7 @@ def _get_version(dev):
             'fidoPinRetries': fido_pin_list[1],
             'uvBlocked': fido_pin_list[2],
             'isNfc': self._reader_filter and not self._reader_filter.lower().startswith("yubico yubikey"),
-       }
+          }
 
     def connect_custom_reader(self, reader_filter=None, otp_mode=False):
         def connect_custom_action(dev, event):
@@ -353,7 +419,11 @@ def load_devices_custom_reader(self, reader_filter=None, otp_mode=False):
             dev = self._get_dev_from_reader()
             if dev:
                 with dev.open_connection(SmartCardConnection) as conn:
-                    info = read_info(dev.pid, conn)
+                    if int(ykman_v.split(".")[0] ) > 4:
+                        info = read_info(conn, dev.pid)
+                    else:
+                        info = read_info(dev.pid, conn)
+
                     try:
                         oath = OathSession(conn)
                         has_password = oath.locked
@@ -415,7 +485,12 @@ def load_devices_usb(self, otp_mode=False):
         win_fido = False
         no_access = sum(self._devs.values()) > len(self._devices)
         if no_access:
-            if self._win_non_admin and \
+          if int(ykman_v.split(".")[0] ) > 4:
+              if self._win_non_admin and \
+                    any(pid.usb_interfaces == USB_INTERFACE.FIDO for pid in self._devs.keys()):
+                win_fido = True
+          else:
+              if self._win_non_admin and \
                     any(pid.get_interfaces() == USB_INTERFACE.FIDO for pid in self._devs.keys()):
                 win_fido = True
 
@@ -1069,7 +1144,7 @@ def enroll_action(conn, bio, event):
                 while not event.is_set():
                     try:
                         logger.debug("Place your finger against the sensor now...")
-                        template_id = enroller.capture(event)
+                        template_id = enroller.capture(event=event)
                         if template_id:
                             pyotherside.send("bio_enroll", True, enroller.remaining, template_id.hex())
                             break

Reply via email to