def test_key_create_or_update_user_type_empty_payload(self): """Creating a user key with an empty payload yields to EINVAL""" # whether an empty payload is supported or not depends on the key type # (hence, we cannot check this at the python level) with self.assertRaises(OSError) as expected: Key.create_or_update('user', 'foo', '', session_keyring) self.assertEqual(errno.EINVAL, expected.exception.errno)
def test_key_update_user_key_type(self): """Create two keys with the same description""" description = 'a simple description' key = Key.create_or_update('user', description, 'xxx', session_keyring) self.assertEqual(b'xxx', key.payload()) key2 = Key.create_or_update('user', description, 'yyy', session_keyring) self.assertEqual(b'yyy', key2.payload()) # this is an implementation detail of a user key, which supports an # update self.assertEqual(b'yyy', key.payload()) self.assertEqual(key.serial, key2.serial)
def test_key_payload_zappable(self): """Ensure that the object returned by Key.payload(...) can be zapped""" key = Key.create_or_update('user', 'descr', b'x\xdc\x00', session_keyring) payload = key.payload() self.assertEqual(b'x\xdc\x00', payload) payload[0] = 0 payload[1] = 0 self.assertEqual(b'\x00\x00\x00', payload)
def test_key_revoke(self): """Revoke a key""" key = Key.create_or_update('user', 'foo', 'bar', session_keyring) key.revoke() with self.assertRaises(OSError) as expected: key.revoke() # depending on /proc/sys/kernel/keys/gc_delay, the key might have # been subject to garbage collection, hence, check for errno.ENOKEY expected_errnos = (errno.EKEYREVOKED, errno.ENOKEY) self.assertIn(expected.exception.errno, expected_errnos) with self.assertRaises(OSError) as expected: key.payload() self.assertIn(expected.exception.errno, expected_errnos)
def test_key_create_or_update_arg_types(self): """Mix str and bytes arguments (also illegal ones)""" key = Key.create_or_update('user', b'description', 'payl\0oad', session_keyring) key2 = Key.create_or_update(b'user', b'description', b'payl\0oad', session_keyring) self.assertEqual(key.serial, key2.serial) self.assertEqual(b'payl\0oad', key.payload()) with self.assertRaises(ValueError): Key.create_or_update('user\0', b'description', b'payload', session_keyring) with self.assertRaises(ValueError): Key.create_or_update('user', b'descri\0ption', b'payload', session_keyring)
def test_key_invalidate(self): """Invalidate a key""" key = Key.create_or_update('user', 'description', 'abcd', session_keyring) key.invalidate() with self.assertRaises(OSError) as expected: key.invalidate() self.assertEqual(errno.ENOKEY, expected.exception.errno) with self.assertRaises(OSError) as expected: key.payload() expected_errnos = (errno.ENOKEY, errno.EPERM) # Invalidating a key kicks the garbage collection. It is possible # that we still find the key via lookup_user_key, but we do not possess # the key anymore. Hence, the subsequent permission check in # keyctl_read_key yields -EACCES; Note: the previous key.invalidate() # directly yields ENOKEY because keyctl_invalidate_key passes a # non-zero permission to lookup_user_key => wait_for_key_construction # returns -ENOKEY (as in the key.payload() case) but this time it is # not ignored (because a non-zero permission was used) # Long story short: check for ENOKEY or EACCES expected_errnos = (errno.ENOKEY, errno.EACCES) with self.assertRaises(OSError) as expected: key.payload() self.assertIn(expected.exception.errno, expected_errnos)
def test_key_creation(self): """Create a key and read its payload""" key = Key.create_or_update('user', 'some description', 'my payload', session_keyring) self.assertTrue(key.serial >= 0) self.assertEqual(b'my payload', key.payload())