Example #1
0
    def testAuthenticateAllKeysInvalid(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = errors.InvalidKeyHandleError
        mock_sk.CmdVersion.return_value = b'U2F_V2'

        u2f_api = u2f.U2FInterface(mock_sk)
        with self.assertRaises(errors.U2FError) as cm:
            u2f_api.Authenticate(
                'testapp', b'ABCD',
                [model.RegisteredKey('khA'),
                 model.RegisteredKey('khB')])
        self.assertEquals(cm.exception.code, errors.U2FError.DEVICE_INELIGIBLE)

        u2f_api = u2f.U2FInterface(mock_sk)
Example #2
0
    def InternalObtainCredentials(self, metadata):
        sk = metadata['securityKey']
        challenges = sk['challenges']
        app_id = sk['applicationId']

        challenge_data = []
        for c in challenges:
            kh = c['keyHandle'].encode('ascii')
            key = model.RegisteredKey(bytearray(base64.urlsafe_b64decode(kh)))
            challenge = c['challenge'].encode('ascii')
            challenge = base64.urlsafe_b64decode(challenge)
            challenge_data.append({'key': key, 'challenge': challenge})

        try:
            api = authenticator.CreateCompositeAuthenticator(REAUTH_ORIGIN)
            response = api.Authenticate(app_id,
                                        challenge_data,
                                        print_callback=GetPrintCallback())
            return {'securityKey': response}
        except u2ferrors.U2FError as e:
            if e.code == u2ferrors.U2FError.DEVICE_INELIGIBLE:
                GetPrintCallback()('Ineligible security key.\n')
            elif e.code == u2ferrors.U2FError.TIMEOUT:
                GetPrintCallback()(
                    'Timed out while waiting for security key touch.\n')
            else:
                raise e
        except u2ferrors.NoDeviceFoundError:
            GetPrintCallback()('No security key found.\n')
        return None
Example #3
0
 def handle(self, packet) -> bool:
     digest = bytestostr(packet[3])
     if not digest.startswith("u2f:"):
         log("%s is not a u2f challenge", digest)
         return False
     try:
         from pyu2f import model                     #@UnresolvedImport
         from pyu2f.u2f import GetLocalU2FInterface  #@UnresolvedImport
     except ImportError as e:
         log.warn("Warning: cannot use u2f authentication handler")
         log.warn(" %s", e)
         return False
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle = self.get_key_handle()
     if not key_handle:
         return False
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     log.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     log("process_challenge_u2f client data=%s, signature=%s", client_data, binascii.hexlify(sig))
     self.client.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
Example #4
0
    def testAuthenticateSuccessSkipInvalidVersion(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.return_value = 'signature'
        mock_sk.CmdVersion.return_value = b'U2F_V2'

        u2f_api = u2f.U2FInterface(mock_sk)

        resp = u2f_api.Authenticate('testapp', b'ABCD', [
            model.RegisteredKey('khA', version='U2F_V3'),
            model.RegisteredKey('khB')
        ])
        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 1)
        self.assertEquals(mock_sk.CmdWink.call_count, 0)
        self.assertEquals(resp.key_handle, 'khB')
        self.assertEquals(resp.client_data.raw_server_challenge, b'ABCD')
        self.assertEquals(resp.client_data.typ, 'navigator.id.getAssertion')
        self.assertEquals(resp.signature_data, 'signature')
Example #5
0
    def testAuthenticateTimeout(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = errors.TUPRequiredError
        mock_sk.CmdVersion.return_value = b'U2F_V2'
        u2f_api = u2f.U2FInterface(mock_sk)

        # Speed up the test by mocking out sleep to do nothing
        with mock.patch.object(u2f, 'time') as _:
            with self.assertRaises(errors.U2FError) as cm:
                u2f_api.Authenticate('testapp', b'ABCD',
                                     [model.RegisteredKey('khA')])
        self.assertEquals(cm.exception.code, errors.U2FError.TIMEOUT)
        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 30)
        self.assertEquals(mock_sk.CmdWink.call_count, 30)
Example #6
0
 def process_challenge_u2f(self, packet):
     digest = packet[3]
     if not digest.startswith(b"u2f:"):
         authlog("%s is not a u2f challenge", digest)
         return False
     import binascii
     import logging
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     from pyu2f import model
     from pyu2f.u2f import GetLocalU2FInterface
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle_str = os.environ.get("XPRA_U2F_KEY_HANDLE")
     authlog("process_challenge_u2f XPRA_U2F_KEY_HANDLE=%s", key_handle_str)
     if not key_handle_str:
         #try to load the key handle from the user conf dir(s):
         from xpra.platform.paths import get_user_conf_dirs
         info = self._protocol.get_info(False)
         key_handle_filenames = []
         for hostinfo in ("-%s" % info.get("host", ""), ""):
             key_handle_filenames += [
                 os.path.join(d, "u2f-keyhandle%s.hex" % hostinfo)
                 for d in get_user_conf_dirs()
             ]
         for filename in key_handle_filenames:
             p = osexpand(filename)
             key_handle_str = load_binary_file(p)
             authlog("key_handle_str(%s)=%s", p, key_handle_str)
             if key_handle_str:
                 key_handle_str = key_handle_str.rstrip(b" \n\r")
                 break
         if not key_handle_str:
             authlog.warn("Warning: no U2F key handle found")
             return False
     authlog("process_challenge_u2f key_handle=%s", key_handle_str)
     key_handle = binascii.unhexlify(key_handle_str)
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     authlog.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     authlog("process_challenge_u2f client data=%s, signature=%s",
             client_data, binascii.hexlify(sig))
     self.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
Example #7
0
    def testAuthenticateError(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = errors.ApduError(0xff, 0xff)
        mock_sk.CmdVersion.return_value = b'U2F_V2'
        u2f_api = u2f.U2FInterface(mock_sk)

        with self.assertRaises(errors.U2FError) as cm:
            u2f_api.Authenticate('testapp', b'ABCD',
                                 [model.RegisteredKey('khA')])
        self.assertEquals(cm.exception.code, errors.U2FError.BAD_REQUEST)
        self.assertEquals(cm.exception.cause.sw1, 0xff)
        self.assertEquals(cm.exception.cause.sw2, 0xff)

        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 1)
        self.assertEquals(mock_sk.CmdWink.call_count, 0)
Example #8
0
    def testRegisterFailAlreadyRegistered(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = errors.TUPRequiredError
        mock_sk.CmdVersion.return_value = b'U2F_V2'

        u2f_api = u2f.U2FInterface(mock_sk)

        with self.assertRaises(errors.U2FError) as cm:
            u2f_api.Register('testapp', b'ABCD', [model.RegisteredKey('khA')])
        self.assertEquals(cm.exception.code, errors.U2FError.DEVICE_INELIGIBLE)

        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 1)
        # Should be "Check only"
        self.assertTrue(mock_sk.CmdAuthenticate.call_args[0][3])

        self.assertEquals(mock_sk.CmdRegister.call_count, 0)
        self.assertEquals(mock_sk.CmdWink.call_count, 0)
Example #9
0
    def testAuthenticateSuccessWithTUP(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = [
            errors.TUPRequiredError, 'signature'
        ]
        mock_sk.CmdVersion.return_value = b'U2F_V2'

        u2f_api = u2f.U2FInterface(mock_sk)

        resp = u2f_api.Authenticate('testapp', b'ABCD',
                                    [model.RegisteredKey('khA')])
        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 2)
        self.assertEquals(mock_sk.CmdWink.call_count, 1)
        self.assertEquals(resp.key_handle, 'khA')
        self.assertEquals(resp.client_data.raw_server_challenge, b'ABCD')
        self.assertEquals(resp.client_data.typ, 'navigator.id.getAssertion')
        self.assertEquals(resp.signature_data, 'signature')
Example #10
0
    def testRegisterSuccessWithPreviousKeys(self):
        mock_sk = mock.MagicMock()
        mock_sk.CmdAuthenticate.side_effect = errors.InvalidKeyHandleError
        mock_sk.CmdRegister.side_effect = [errors.TUPRequiredError, 'regdata']
        mock_sk.CmdVersion.return_value = b'U2F_V2'

        u2f_api = u2f.U2FInterface(mock_sk)

        resp = u2f_api.Register('testapp', b'ABCD',
                                [model.RegisteredKey('khA')])
        self.assertEquals(mock_sk.CmdAuthenticate.call_count, 1)
        # Should be "Check only"
        self.assertTrue(mock_sk.CmdAuthenticate.call_args[0][3])

        self.assertEquals(mock_sk.CmdRegister.call_count, 2)
        self.assertEquals(mock_sk.CmdWink.call_count, 1)
        self.assertEquals(resp.client_data.raw_server_challenge, b'ABCD')
        self.assertEquals(resp.client_data.typ,
                          'navigator.id.finishEnrollment')
        self.assertEquals(resp.registration_data, 'regdata')
Example #11
0
    'key_handle_encoded':
    ('iBbl9-VYt-XSdWeHVNX-gfQcXGzlrAQ7BcngVNUxWijIQQlnZEI'
     '4Vb0Bp2ydBCbIQu_5rNlKqPH6NK1TtnM7fA'),
    'origin':
    'test_origin',
    'signature_data_encoded': ('AQAAAI8wRQIhALlIPo6Hg8HwzELdYRIXnAnpsiHYCSXHex'
                               'CS34eiS2ixAiBt3TRmKE1A9WyMjc3JGrGI7gSPg-QzDSNL'
                               'aIj7JwcCTA'),
    'client_data_encoded': ('eyJjaGFsbGVuZ2UiOiAiWVhOa1ptRnpaR1kiLCAib3JpZ2luI'
                            'jogInRlc3Rfb3JpZ2luIiwgInR5cCI6ICJuYXZpZ2F0b3IuaW'
                            'QuZ2V0QXNzZXJ0aW9uIn0'),
    'u2f_version':
    'U2F_V2',
    'registered_key':
    model.RegisteredKey(
        base64.urlsafe_b64decode(
            'iBbl9-VYt-XSdWeHVNX-gfQcXGzlrAQ7BcngVNUxWijIQQlnZEI4Vb0Bp2ydBCbIQu'
            '_5rNlKqPH6NK1TtnM7fA=='))
}


@mock.patch.object(sys, 'stderr', new=mock.MagicMock())
class CustomAuthenticatorTest(unittest.TestCase):
    @mock.patch.object(customauthenticator.os.environ,
                       'get',
                       return_value=None)
    def testEnvVarNotSet(self, os_get_method):
        authenticator = customauthenticator.CustomAuthenticator('testorigin')

        self.assertFalse(authenticator.IsAvailable(),
                         'Should return false when no env var is present')
    'qhJtbTQvsU0BmLLpDWes-3zFGbegR2wp1mv5BJ2BwC0=',
    'key_handle_encoded':
    ('iBbl9-VYt-XSdWeHVNX-gfQcXGzlrAQ7BcngVNUxWijIQQlnZEI'
     '4Vb0Bp2ydBCbIQu_5rNlKqPH6NK1TtnM7fA=='),
    'origin':
    'test_origin',
    'signature_data_encoded': ('AQAAAI8wRQIhALlIPo6Hg8HwzELdYRIXnAnpsiHYCSXHex'
                               'CS34eiS2ixAiBt3TRmKE1A9WyMjc3JGrGI7gSPg-QzDSNL'
                               'aIj7JwcCTA=='),
    'client_data_encoded': ('eyJjaGFsbGVuZ2UiOiAiWVhOa1ptRnpaR1kiLCAib3JpZ2luI'
                            'jogInRlc3Rfb3JpZ2luIiwgInR5cCI6ICJuYXZpZ2F0b3IuaW'
                            'QuZ2V0QXNzZXJ0aW9uIn0='),
    'u2f_version':
    'U2F_V2'
}
SIGN_SUCCESS['registered_key'] = model.RegisteredKey(
    base64.urlsafe_b64decode(SIGN_SUCCESS['key_handle_encoded']))
SIGN_SUCCESS['client_data'] = model.ClientData(
    model.ClientData.TYP_AUTHENTICATION, SIGN_SUCCESS['challenge'],
    SIGN_SUCCESS['origin'])


@mock.patch.object(sys, 'stderr', new=mock.MagicMock())
class LocalAuthenticatorTest(unittest.TestCase):
    @mock.patch.object(localauthenticator.u2f, 'GetLocalU2FInterface')
    def testSignSuccess(self, mock_get_u2f_method):
        """Test successful signing with a valid key."""
        # Prepare u2f mocks
        mock_u2f = mock.MagicMock()
        mock_get_u2f_method.return_value = mock_u2f

        mock_authenticate = mock.MagicMock()