Skip to content
This repository has been archived by the owner on May 13, 2020. It is now read-only.

Commit

Permalink
Fix unpickling errors in MemCache.
Browse files Browse the repository at this point in the history
  • Loading branch information
mgedmin committed Oct 11, 2012
1 parent fb0c5a1 commit 7a2347e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGES.txt
Expand Up @@ -12,6 +12,12 @@ CHANGES
using their own passwords -- but the first user could now use her password
to log in as anyone else.

+ Do not store custom classes in memcached so we don't get unpickling
errors caused by the special execution environment set up by
pam_python.so. Previously the cached value was a subclass of tuple,
now it's a plain tuple, so old caches will continue to work with the
new code.

- FileCache reliability fixes:

+ Avoid incorrect cache lookups (or invalidations) when a username is a
Expand Down
7 changes: 5 additions & 2 deletions src/cipher/googlepam/pam_google.py
Expand Up @@ -144,12 +144,15 @@ def _get_key(self, username):
return self.pam.config.get(self.SECTION_NAME, 'key-prefix') + username

def _get_user_info(self, username):
return self._client.get(self._get_key(username))
cached = self._client.get(self._get_key(username))
if cached is None:
return None
return UserInfo(*cached)

def _add_user_info(self, username, password):
self._client.set(
self._get_key(username),
UserInfo(time.time(), bcrypt.hashpw(password, bcrypt.gensalt())))
(time.time(), bcrypt.hashpw(password, bcrypt.gensalt())))

def _del_user_info(self, username):
self._client.delete(self._get_key(username))
Expand Down
18 changes: 17 additions & 1 deletion src/cipher/googlepam/tests/test_doc.py
Expand Up @@ -14,6 +14,7 @@
"""Google PAM Tests
"""
import doctest
import sys
import os
import tempfile
import ConfigParser
Expand Down Expand Up @@ -452,12 +453,27 @@ def doctest_FileCache_del_user_info_prefix_safety():
def doctest_MemcacheCache():
"""class MemcacheCache
This is a bit tricky: when pam_python.so loads the module, its name
ends up being simply 'pam_google' instead of 'cipher.googlepam.pam_google'.
This can break unpickling of classes defined in that module, since
pam_python.so doesn't add the directory containing pam_google.py to
sys.path, and it doesn't add pam_google itself to sys.modules.
>>> sys.path.insert(0, os.path.dirname(pam_google.__file__))
>>> import pam_google
>>> pam_google.__name__
'pam_google'
>>> del sys.path[0]
>>> del sys.modules['pam_google']
Now that we have an approximation of that environment, let's go on
>>> pam = pam_google.GooglePAM(
... FakePamHandle(), 0,
... ['script', '-c', os.path.join(HERE, 'mem-cache.conf')])
>>> pam._cache
<cipher.googlepam.pam_google.MemcacheCache object at ...>
<pam_google.MemcacheCache object at ...>
>>> pam._cache.authenticate('user', 'pwd')
Expand Down

0 comments on commit 7a2347e

Please sign in to comment.