Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store session cookie in a ccache option #546

Closed
wants to merge 1 commit into from

Conversation

simo5
Copy link
Contributor

@simo5 simo5 commented Mar 7, 2017

Instead of using the kernel keyring, store the session cookie within the
ccache. This way kdestroy will really wipe away all crededntials.

Ticket: https://pagure.io/freeipa/issue/6661

pass


PY3 = sys.version_info[0] == 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use six.PY3 instead to be consistent with other parts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

value = self.value
if value is None:
return None
elif not isinstance(value, str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably

elif isinstance(value, bytes):

might be better to handle Py2/Py3. Otherwise you must check Unicode too


class _krb5_context(ctypes.Structure): # noqa
"""krb5/krb5.h struct _krb5_context"""
__slots__ = ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why __slots__ are defined? Is it performance improvement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's defined empty, but I'll remove them altogether

def from_param(cls, value):
if value is None:
return None
if PY3 and isinstance(value, str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be this replaced with:

if not isinstance(value, bytes):
    return value.encode('utf-8')

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out I am not actually using c_text_p anywhere in the end, so I'm removing all of this

krb5_cc_get_config.retval = krb5_error
krb5_cc_get_config.errcheck = krb5_errcheck

class session_store:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be class session_store(object):

krb5_free_context(self.__context)
self.__context = None

def __del__(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't define __del__ method in python unless you have bulletproof evidence that it will work in your case.
https://docs.python.org/2/reference/datamodel.html#object.__del__

In python, if you want safely do cleanup, it must be done by contextmanager (what you have already implemented), don't use del method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

krb5_cc_get_config(self.__context, ccache, principal,
self._hidden_cred_name, ctypes.byref(data))

return str(data.data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is data.data type? If bytes this will return unexpected string in py3. .decode() should be used in case of bytes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is decalred as c_char_p

try:
LIBKRB5 = ctypes.CDLL('libkrb5.so.3')
except OSError as e: # pragma: no cover
LIBKRB5 = e
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we rather fail early and raise ImportError ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could

@MartinBasti
Copy link
Contributor

Pylint failed and I have a few inline comments

************* Module ipapython.ccache_storage
ipapython/ccache_storage.py:234: [C0305(trailing-newlines), ] Trailing newlines)
ipapython/ccache_storage.py:32: [W1612(unicode-builtin), c_text_p.from_param] unicode built-in referenced)
ipapython/ccache_storage.py:45: [E1101(no-member), c_text_p.text] Class 'value' has no 'decode' member)
ipapython/ccache_storage.py:128: [C1001(old-style-class), session_store] Old-style class defined.)
ipapython/ccache_storage.py:132: [E0710(raising-non-exception), session_store.__init__] Raising a new style class which doesn't inherit from BaseException)
ipapython/ccache_storage.py:6: [W0611(unused-import), ] Unused import os)

@rcritten
Copy link
Contributor

rcritten commented Mar 7, 2017

Should this patch not also remove the keyring code?

Unit tests should be provided.

@simo5
Copy link
Contributor Author

simo5 commented Mar 7, 2017

@rcritten the keyring stuff is still used for detection of keyring in other places, so I did not touch it as those uses are still vaild

@simo5
Copy link
Contributor Author

simo5 commented Mar 7, 2017

Not sure how to provide unit tests, these functions work only if you have a valid ccache in the name of the principal you are trying to store a session cookie for.

@simo5
Copy link
Contributor Author

simo5 commented Mar 7, 2017

Ok removed a bunch of code and made sure pylint passes.

@simo5
Copy link
Contributor Author

simo5 commented Mar 7, 2017

I also renamed the module and the class, makes more sense to me this way around.


class ccache_store(object):
def __init__(self, name='X-IPA-Session-Cookie'):
self.__context = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use single underscore here. Double underscore lead to name mangling, which makes debugging harder.

self._hidden_cred_name = name

def __enter__(self):
return self
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context should be initialized in __enter__, not in __init__

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually ccache_store is not used together with with statement, what is your goal @simo5?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied example code from krbproxy, I do not have any special goal.
I could even not carry a global context but crate and destroy contexts at each call
Whatever is preferred.

@simo5
Copy link
Contributor Author

simo5 commented Mar 9, 2017

Ok I decide to do away with the whole class stuff, given we never really keep a round the class object for more than one operation at a time in actual use.
As @rcritten requested I also added a test, and I am glad it was asked as I found a failure case we need to handle (see the exception handling in remove_data()

@simo5 simo5 dismissed MartinBasti’s stale review March 9, 2017 12:35

All requested changes have been applied

Test the `session_storage.py` module.
"""

from nose.tools import raises # pylint: disable=E0611
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is unused and instead of nose.raises please use pytest raises

@MartinBasti
Copy link
Contributor

************* Module ipapython.session_storage
ipapython/session_storage.py:187: [W1624(indexing-exception), remove_data] Indexing exceptions will not work on Python 3)
************* Module ipalib.rpc
ipalib/rpc.py:114: [E1120(no-value-for-parameter), read_persistent_client_session_data] No value for argument 'value' in function call)
************* Module ipatests.test_ipapython.test_session_storage
ipatests/test_ipapython/test_session_storage.py:39: [W0612(unused-variable), test_session_storage.test_03] Unused variable 'e')
ipatests/test_ipapython/test_session_storage.py:9: [W0611(unused-import), ] Unused raises imported from nose.tools)
ipatests/test_ipapython/test_session_storage.py:12: [W0611(unused-import), ] Unused import pytest)

Instead of using the kernel keyring, store the session cookie within the
ccache. This way kdestroy will really wipe away all credentials.

Ticket: https://pagure.io/freeipa/issue/6661

Signed-off-by: Simo Sorce <simo@redhat.com>
@simo5
Copy link
Contributor Author

simo5 commented Mar 9, 2017

Oops sorry, forgot to run make pylint on my last iteration, should be all fixed now

self.key = 'X-IPA-test-session-storage'
self.data = 'Test Data'

def test_01(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests has no description

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but they are somehow selfexplanatory

@MartinBasti MartinBasti added the ack Pull Request approved, can be merged label Mar 9, 2017
@MartinBasti
Copy link
Contributor

master:

  • 7cab959 Store session cookie in a ccache option

@MartinBasti MartinBasti added the pushed Pull Request has already been pushed label Mar 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ack Pull Request approved, can be merged pushed Pull Request has already been pushed
Projects
None yet
4 participants