Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Sep 2019 15:09:16 +0000 (UTC)
From:      Michael Gmelin <grembo@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r512019 - in head/security/py-fido2: . files
Message-ID:  <201909141509.x8EF9G4b094082@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grembo
Date: Sat Sep 14 15:09:16 2019
New Revision: 512019
URL: https://svnweb.freebsd.org/changeset/ports/512019

Log:
  Add fido/u2f support for FreeBSD.
  
  Also adds test target.
  
  This was merged upstream, so patches can be removed from files/
  on the next release of python-fido2.
  
  See:
  https://github.com/Yubico/python-fido2/pull/64
  https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
  
  PR:		240476
  Approved by:	koobs (python: maintainer)

Added:
  head/security/py-fido2/files/
  head/security/py-fido2/files/patch-README.adoc   (contents, props changed)
  head/security/py-fido2/files/patch-fido2___pyu2f_____init____.py   (contents, props changed)
  head/security/py-fido2/files/patch-fido2___pyu2f_freebsd.py   (contents, props changed)
  head/security/py-fido2/files/patch-setup.py   (contents, props changed)
  head/security/py-fido2/files/patch-test___pyu2f_freebsd__test.py   (contents, props changed)
  head/security/py-fido2/files/patch-test___pyu2f_linux__test.py   (contents, props changed)
  head/security/py-fido2/files/patch-test___pyu2f_macos__test.py   (contents, props changed)
Modified:
  head/security/py-fido2/Makefile

Modified: head/security/py-fido2/Makefile
==============================================================================
--- head/security/py-fido2/Makefile	Sat Sep 14 14:45:49 2019	(r512018)
+++ head/security/py-fido2/Makefile	Sat Sep 14 15:09:16 2019	(r512019)
@@ -2,6 +2,7 @@
 
 PORTNAME=	fido2
 PORTVERSION=	0.7.0
+PORTREVISION=	1
 CATEGORIES=	security python
 MASTER_SITES=	CHEESESHOP
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
@@ -14,11 +15,17 @@ LICENSE_FILE=	${WRKSRC}/COPYING
 
 RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}cryptography>=1.5:security/py-cryptography@${PY_FLAVOR} \
 		${PY_ENUM34} \
-		${PYTHON_PKGNAMEPREFIX}six>=0:devel/py-six@${PY_FLAVOR}
+		${PYTHON_PKGNAMEPREFIX}six>=0:devel/py-six@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}uhid-freebsd>=1.2.1:devel/py-uhid-freebsd@${PY_FLAVOR}
+TEST_DEPENDS=	${PYTHON_PKGNAMEPREFIX}mock>0:devel/py-mock@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pycodestyle>0:devel/py-pycodestyle@${PY_FLAVOR}
 
 USES=		python
 USE_PYTHON=	autoplist distutils
 
 NO_ARCH=	yes
+
+do-test:
+	@cd ${WRKSRC} && ${PYTHON_CMD} ${PYDISTUTILS_SETUP} test
 
 .include <bsd.port.mk>

Added: head/security/py-fido2/files/patch-README.adoc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-README.adoc	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,25 @@
+This was part of a pull request that has been merged uptream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- README.adoc.orig	2019-06-17 12:31:00 UTC
++++ README.adoc
+@@ -64,10 +64,15 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", \
+   MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1050"
+ ----
+ 
++Under FreeBSD you will either need to run as root or add rules for your device
++to /etc/devd.conf, which can be automated by installing security/u2f-devd:
+ 
++  # pkg install u2f-devd
++
++
+ === Dependencies
+ fido2 is compatible with CPython 2.7 (2.7.6 and up), 3.4 onwards, and is tested
+-on Windows, MacOS, and Linux.
++on Windows, MacOS, FreeBSD, and Linux.
+ 
+ This project depends on Cryptography. For instructions on installing this
+ dependency, see https://cryptography.io/en/latest/installation/.

Added: head/security/py-fido2/files/patch-fido2___pyu2f_____init____.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-fido2___pyu2f_____init____.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,18 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- fido2/_pyu2f/__init__.py.orig	2019-09-10 15:15:37 UTC
++++ fido2/_pyu2f/__init__.py
+@@ -47,6 +47,9 @@ def InternalPlatformSwitch(funcname, *args, **kwargs):
+   elif sys.platform.startswith('darwin'):
+     from . import macos
+     clz = macos.MacOsHidDevice
++  elif sys.platform.startswith('freebsd'):
++    from . import freebsd
++    clz = freebsd.FreeBSDHidDevice
+ 
+   if not clz:
+     raise Exception('Unsupported platform: ' + sys.platform)

Added: head/security/py-fido2/files/patch-fido2___pyu2f_freebsd.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-fido2___pyu2f_freebsd.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,63 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- fido2/_pyu2f/freebsd.py.orig	2019-09-12 11:35:02 UTC
++++ fido2/_pyu2f/freebsd.py
+@@ -0,0 +1,54 @@
++# Copyright 2016 Google Inc. All Rights Reserved.
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++#    http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++"""Implements raw HID interface on FreeBSD using sysctl and device files."""
++
++from __future__ import absolute_import
++
++import os
++import uhid_freebsd
++
++from . import linux
++
++
++class FreeBSDHidDevice(linux.LinuxHidDevice):
++    """Implementation of HID device for FreeBSD.
++    """
++
++    @staticmethod
++    def Enumerate():
++        for dev in uhid_freebsd.enumerate():
++            desc = linux.base.DeviceDescriptor()
++            desc.path = dev["path"]
++            desc.vendor_id = dev["vendor_id"]
++            desc.product_id = dev["product_id"]
++            desc.product_string = dev["product_desc"]
++            fd = os.open(desc.path, os.O_RDONLY)
++            linux.ParseReportDescriptor(
++                uhid_freebsd.get_report_data(fd, 3), desc)
++            os.close(fd)
++            yield desc.ToPublicDict()
++
++    def __init__(self, path):
++        linux.base.HidDevice.__init__(self, path)
++        self.dev = os.open(path, os.O_RDWR)
++        self.desc = linux.base.DeviceDescriptor()
++        self.desc.path = path
++        linux.ParseReportDescriptor(
++            uhid_freebsd.get_report_data(self.dev, 3), self.desc)
++
++    def Write(self, packet):
++        """See base class."""
++        out = bytes(bytearray([0]*64 + packet))  # 64 zero bytes (report ID)
++        os.write(self.dev, out)

Added: head/security/py-fido2/files/patch-setup.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-setup.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,24 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- setup.py.orig	2019-06-17 10:59:34 UTC
++++ setup.py
+@@ -48,13 +48,14 @@ setup(
+     install_requires=[
+         'six',
+         'cryptography>=1.5',
++        'uhid-freebsd>=1.2.1;platform_system=="FreeBSD"',
+     ],
+     extras_require={
+         ':python_version < "3.4"': ['enum34'],
+         'pcsc': ['pyscard']
+     },
+     test_suite='test',
+-    tests_require=['mock>=1.0.1', 'pyfakefs>=3.4'],
++    tests_require=['mock>=1.0.1', 'pyfakefs>=3.4;platform_system=="Linux"'],
+     classifiers=[
+         'License :: OSI Approved :: BSD License',
+         'License :: OSI Approved :: Apache Software License',

Added: head/security/py-fido2/files/patch-test___pyu2f_freebsd__test.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-test___pyu2f_freebsd__test.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,131 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- test/_pyu2f/freebsd_test.py.orig	2019-09-13 11:01:05 UTC
++++ test/_pyu2f/freebsd_test.py
+@@ -0,0 +1,122 @@
++# Copyright 2016 Google Inc. All Rights Reserved.
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++#    http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++"""Tests for _pyu2f.hid.freebsd."""
++
++import base64
++import os
++import sys
++
++import six
++from six.moves import builtins
++from mock import patch
++
++if sys.platform.startswith('freebsd'):
++    from fido2._pyu2f import freebsd
++
++if sys.version_info[:2] < (2, 7):
++    import unittest2 as unittest  # pylint: disable=g-import-not-at-top
++else:
++    import unittest  # pylint: disable=g-import-not-at-top
++
++
++# These are base64 encoded report descriptors of a Yubico token
++# and a Logitech keyboard.
++YUBICO_RD = 'BtDxCQGhAQkgFQAm/wB1CJVAgQIJIRUAJv8AdQiVQJECwA=='
++KEYBOARD_RD = (
++    'BQEJAqEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVAXUDgQEFAQkwCTEJOBWBJX91CJUDgQbAwA==')
++
++
++class FakeUhidFreeBSDModule():
++    def enumerate(self):
++        return [{'device': 'uhid0',
++                 'path': '/dev/uhid0',
++                 'vendor_id': 0x046d,
++                 'product_id': 0xc31c,
++                 'product_desc': 'Logitech Keyboard'},
++                {'device': 'uhid1',
++                 'path': '/dev/uhid1',
++                 'vendor_id': 0x1050,
++                 'product_id': 0x0407,
++                 'product_desc': 'Yubico U2F'}]
++
++    def get_report_data(self, fd, unused_report_id):
++        if fd:
++            return base64.b64decode(YUBICO_RD)
++        else:
++            return base64.b64decode(KEYBOARD_RD)
++
++
++class FakeOsModule():
++    O_RDONLY = os.O_RDONLY
++    O_RDWR = os.O_RDWR
++    path = os.path
++
++    data_written = None
++    data_to_return = None
++
++    def open(self, path, unused_opts):  # pylint: disable=invalid-name
++        if path.find('uhid1') >= 0:
++            return 1  # fd == 1 => magic number to return Yubikey RD below
++        else:
++            return 0
++
++    def write(self, unused_dev, data):  # pylint: disable=invalid-name
++        self.data_written = data
++
++    def read(self, unused_dev, unused_length):  # pylint: disable=invalid-name
++        return self.data_to_return
++
++    def close(self, unused_dev):  # pylint: disable=invalid-name
++        pass
++
++
++@unittest.skipIf(not sys.platform.startswith('freebsd'),
++                 'FreeBSD specific test case')
++class FreeBSDTest(unittest.TestCase):
++    @patch('fido2._pyu2f.freebsd.os', FakeOsModule())
++    @patch('fido2._pyu2f.freebsd.uhid_freebsd', FakeUhidFreeBSDModule())
++    def testCallEnumerate(self):
++        devs = list(freebsd.FreeBSDHidDevice.Enumerate())
++        devs = sorted(devs, key=lambda k: k['vendor_id'])
++
++        self.assertEqual(len(devs), 2)
++        self.assertEqual(devs[0]['vendor_id'], 0x046d)
++        self.assertEqual(devs[0]['product_id'], 0xc31c)
++        self.assertEqual(devs[1]['vendor_id'], 0x1050)
++        self.assertEqual(devs[1]['product_id'], 0x0407)
++        self.assertEqual(devs[1]['usage_page'], 0xf1d0)
++        self.assertEqual(devs[1]['usage'], 1)
++
++    @patch('fido2._pyu2f.freebsd.uhid_freebsd', FakeUhidFreeBSDModule())
++    def testCallOpen(self):
++        fake_os = FakeOsModule()
++        with patch('fido2._pyu2f.linux.os', fake_os):
++            with patch('fido2._pyu2f.freebsd.os', fake_os):
++                dev = freebsd.FreeBSDHidDevice('/dev/uhid1')
++                self.assertEqual(dev.GetInReportDataLength(), 64)
++                self.assertEqual(dev.GetOutReportDataLength(), 64)
++
++                dev.Write(list(range(0, 64)))
++                # The HidDevice implementation prepends one zero-byte-packet
++                # (64 bytes) representing the report ID + padding
++                self.assertEqual(list(six.iterbytes(fake_os.data_written)),
++                                 [0]*64 + list(range(0, 64)))
++
++                fake_os.data_to_return = b'x' * 64
++                self.assertEqual(dev.Read(), [120] * 64)  # chr(120) = 'x'
++
++
++if __name__ == '__main__':
++    unittest.main()

Added: head/security/py-fido2/files/patch-test___pyu2f_linux__test.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-test___pyu2f_linux__test.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,30 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- test/_pyu2f/linux_test.py.orig	2019-09-13 11:17:23 UTC
++++ test/_pyu2f/linux_test.py
+@@ -27,7 +27,11 @@ from fido2._pyu2f import linux
+ try:
+   from pyfakefs import fake_filesystem  # pylint: disable=g-import-not-at-top
+ except ImportError:
+-  from fakefs import fake_filesystem  # pylint: disable=g-import-not-at-top
++  try:
++    from fakefs import fake_filesystem  # pylint: disable=g-import-not-at-top
++  except ImportError:
++    if sys.platform.startswith('linux'):
++      raise
+ 
+ if sys.version_info[:2] < (2, 7):
+   import unittest2 as unittest  # pylint: disable=g-import-not-at-top
+@@ -71,6 +75,8 @@ class FakeDeviceOsModule(object):
+     return self.data_to_return
+ 
+ 
++@unittest.skipIf(not sys.platform.startswith('linux'),
++                 'Linux specific test case')
+ class LinuxTest(unittest.TestCase):
+   def setUp(self):
+     self.fs = fake_filesystem.FakeFilesystem()

Added: head/security/py-fido2/files/patch-test___pyu2f_macos__test.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/py-fido2/files/patch-test___pyu2f_macos__test.py	Sat Sep 14 15:09:16 2019	(r512019)
@@ -0,0 +1,17 @@
+This was part of a pull request that has been merged upstream. Most likely
+this patch can be removed on the next release of python-fido2.
+
+See https://github.com/Yubico/python-fido2/pull/64 and
+https://github.com/Yubico/python-fido2/commit/19c86d5459931b8a76d1adc76420a8a1e0c0cf2e
+
+--- test/_pyu2f/macos_test.py.orig	2018-07-04 13:27:36 UTC
++++ test/_pyu2f/macos_test.py
+@@ -44,6 +44,8 @@ def init_mock_get_int_property(mock_get_int_property):
+   mock_get_int_property.return_value = 64
+ 
+ 
++@unittest.skipIf(not sys.platform.startswith('darwin'),
++                 'MacOS specific test case')
+ class MacOsTest(unittest.TestCase):
+ 
+   @classmethod



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909141509.x8EF9G4b094082>