def memorise(self, value): assert len(value) < 16 * 1024, len(value) prevKeyId = self._keyId # Unfortunately, keyctl_update() loses the timeout associated # with the key, and in any case races any pre-existing timeout. # To avoid these complications always use add_key(). encrypted = self.__crypt.encrypt(value) keyId = keyutils.add_key(self.__keyName, encrypted, self._KeyRing.PROCESS) self._keyId = keyId keyutils.set_perm( keyId, keyutils.KEY_POS_ALL | keyutils.KEY_USR_VIEW | keyutils.KEY_USR_READ | keyutils.KEY_USR_SETATTR) self._touch() # Only add the key to the session keyring after it has # been constructed with the correct timeout to avoid # having the session keyring leak partially constructed # keys. keyutils.link(keyId, self._KeyRing.SESSION) if prevKeyId is not None: self._revoke(prevKeyId)
def _setupSession(): """ Link the user keyring into the session keyring. pam_keyinit.so normally does this by default, but do it again in case someone made a new session or the session was revoked. We want to add keys to the user keyring so that they are reachable across sessions, and continue to work after the session is revoked due to e.g. detaching from screen and closing SSH. But keys are created with permissions that require "possession" to read them, where possession means the key is reachable via the session keyring. If the session keyring is empty, adding a key to any other keyring means that key is not under possession and thus not readable even though we own it. The fix is to ensure the user keyring is always linked under the session keyring so that keys in the user keyring are reachable via the session keyring. """ global _keyring try: _keyutils.link(_keyutils.KEY_SPEC_USER_KEYRING, _keyutils.KEY_SPEC_SESSION_KEYRING) except AttributeError: # Old keyutils. Downgrade to just using the session keyring directly, # because there's no way to look in the user keyring. _keyring = _keyutils.KEY_SPEC_SESSION_KEYRING return except _keyutils.Error as err: if err.args[0] != _keyutils.EKEYREVOKED: raise # Session key was revoked. Make a new session and try again. _keyutils.join_session_keyring() _keyutils.link(_keyutils.KEY_SPEC_USER_KEYRING, _keyutils.KEY_SPEC_SESSION_KEYRING)
def testLink(self): desc = b"key1" child = keyutils.add_key(b"ring1", None, keyutils.KEY_SPEC_PROCESS_KEYRING, b"keyring") parent = keyutils.add_key(b"ring2", None, keyutils.KEY_SPEC_PROCESS_KEYRING, b"keyring") keyId = keyutils.add_key(desc, b"dummy", child) self.assertEqual(keyutils.search(child, desc), keyId) self.assertEqual(keyutils.search(parent, desc), None) keyutils.link(child, parent) self.assertEqual(keyutils.search(parent, desc), keyId)