django-cas-server/cas_server/auth.py

177 lines
5.5 KiB
Python
Raw Normal View History

2015-05-17 21:24:41 +00:00
# ⁻*- coding: utf-8 -*-
2015-05-27 20:10:06 +00:00
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
# more details.
#
# You should have received a copy of the GNU General Public License version 3
# along with this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# (c) 2015 Valentin Samir
2015-05-27 19:56:39 +00:00
"""Some authentication classes for the CAS"""
2015-05-17 21:24:41 +00:00
from django.conf import settings
2015-12-12 16:26:19 +00:00
from django.contrib.auth import get_user_model
2016-06-17 17:28:49 +00:00
from django.utils import timezone
from datetime import timedelta
2016-06-26 13:34:26 +00:00
try: # pragma: no cover
2015-05-17 21:24:41 +00:00
import MySQLdb
import MySQLdb.cursors
from utils import check_password
2015-05-17 21:24:41 +00:00
except ImportError:
MySQLdb = None
2015-05-27 19:56:39 +00:00
2016-06-17 17:28:49 +00:00
from .models import FederatedUser
2015-06-12 16:10:52 +00:00
2015-12-12 16:26:19 +00:00
class AuthUser(object):
def __init__(self, username):
self.username = username
def test_password(self, password):
"""test `password` agains the user"""
2016-06-26 09:16:41 +00:00
raise NotImplementedError()
2015-12-12 16:26:19 +00:00
def attributs(self):
"""return a dict of user attributes"""
2016-06-26 09:16:41 +00:00
raise NotImplementedError()
2015-12-12 16:26:19 +00:00
2016-06-26 13:34:26 +00:00
class DummyAuthUser(AuthUser): # pragma: no cover
2015-05-27 19:56:39 +00:00
"""A Dummy authentication class"""
2015-06-12 16:10:52 +00:00
2015-05-17 21:24:41 +00:00
def __init__(self, username):
2015-12-12 16:26:19 +00:00
super(DummyAuthUser, self).__init__(username)
2015-05-17 21:24:41 +00:00
def test_password(self, password):
2015-05-27 19:56:39 +00:00
"""test `password` agains the user"""
2015-05-17 21:24:41 +00:00
return False
def attributs(self):
2015-05-27 19:56:39 +00:00
"""return a dict of user attributes"""
2015-05-17 21:24:41 +00:00
return {}
2015-12-12 16:26:19 +00:00
class TestAuthUser(AuthUser):
2015-05-27 19:56:39 +00:00
"""A test authentication class with one user test having
alose test as password and some attributes"""
2015-06-12 16:10:52 +00:00
2015-05-17 21:24:41 +00:00
def __init__(self, username):
2015-05-27 19:56:39 +00:00
super(TestAuthUser, self).__init__(username)
2015-05-17 21:24:41 +00:00
def test_password(self, password):
2015-05-27 19:56:39 +00:00
"""test `password` agains the user"""
return self.username == settings.CAS_TEST_USER and password == settings.CAS_TEST_PASSWORD
2015-05-17 21:24:41 +00:00
def attributs(self):
2015-05-27 19:56:39 +00:00
"""return a dict of user attributes"""
return settings.CAS_TEST_ATTRIBUTES
2015-05-17 21:24:41 +00:00
2016-06-26 13:34:26 +00:00
class MysqlAuthUser(AuthUser): # pragma: no cover
2015-05-27 19:56:39 +00:00
"""A mysql auth class: authentication user agains a mysql database"""
2015-05-17 21:24:41 +00:00
user = None
2015-06-12 16:10:52 +00:00
2015-05-17 21:24:41 +00:00
def __init__(self, username):
mysql_config = {
2015-05-27 19:56:39 +00:00
"user": settings.CAS_SQL_USERNAME,
"passwd": settings.CAS_SQL_PASSWORD,
"db": settings.CAS_SQL_DBNAME,
"host": settings.CAS_SQL_HOST,
2015-06-12 16:10:52 +00:00
"charset": settings.CAS_SQL_DBCHARSET,
"cursorclass": MySQLdb.cursors.DictCursor
2015-05-17 21:24:41 +00:00
}
if not MySQLdb:
raise RuntimeError("Please install MySQLdb before using the MysqlAuthUser backend")
conn = MySQLdb.connect(**mysql_config)
curs = conn.cursor()
if curs.execute(settings.CAS_SQL_USER_QUERY, (username,)) == 1:
self.user = curs.fetchone()
super(MysqlAuthUser, self).__init__(self.user['username'])
else:
super(MysqlAuthUser, self).__init__(username)
2015-05-17 21:24:41 +00:00
def test_password(self, password):
2015-05-27 19:56:39 +00:00
"""test `password` agains the user"""
2016-06-26 13:34:26 +00:00
if self.user:
2016-06-27 12:01:39 +00:00
return check_password(
settings.CAS_SQL_PASSWORD_CHECK,
password,
self.user["password"],
settings.CAS_SQL_DBCHARSET
)
2015-05-17 21:24:41 +00:00
else:
2016-06-26 13:34:26 +00:00
return False
2015-05-17 21:24:41 +00:00
def attributs(self):
2015-05-27 19:56:39 +00:00
"""return a dict of user attributes"""
2016-06-26 13:34:26 +00:00
if self.user:
2015-05-17 21:24:41 +00:00
return self.user
2016-06-26 13:34:26 +00:00
else:
return {}
2015-05-17 21:24:41 +00:00
2015-06-12 16:10:52 +00:00
2016-06-26 13:34:26 +00:00
class DjangoAuthUser(AuthUser): # pragma: no cover
2015-05-27 19:56:39 +00:00
"""A django auth class: authenticate user agains django internal users"""
2015-05-17 21:24:41 +00:00
user = None
2015-06-12 16:10:52 +00:00
2015-05-17 21:24:41 +00:00
def __init__(self, username):
2015-12-12 16:26:19 +00:00
User = get_user_model()
2015-05-17 21:24:41 +00:00
try:
self.user = User.objects.get(username=username)
except User.DoesNotExist:
pass
super(DjangoAuthUser, self).__init__(username)
def test_password(self, password):
2015-05-27 19:56:39 +00:00
"""test `password` agains the user"""
2016-06-26 13:34:26 +00:00
if self.user:
2015-05-17 21:24:41 +00:00
return self.user.check_password(password)
2016-06-26 13:34:26 +00:00
else:
return False
2015-05-17 21:24:41 +00:00
def attributs(self):
2015-05-27 19:56:39 +00:00
"""return a dict of user attributes"""
2016-06-26 13:34:26 +00:00
if self.user:
2015-05-17 21:24:41 +00:00
attr = {}
for field in self.user._meta.fields:
2015-05-27 19:56:39 +00:00
attr[field.attname] = getattr(self.user, field.attname)
2015-05-17 21:24:41 +00:00
return attr
2016-06-26 13:34:26 +00:00
else:
return {}
2016-06-17 17:28:49 +00:00
2016-06-17 17:28:49 +00:00
class CASFederateAuth(AuthUser):
user = None
def __init__(self, username):
component = username.split('@')
username = '@'.join(component[:-1])
provider = component[-1]
try:
self.user = FederatedUser.objects.get(username=username, provider=provider)
super(CASFederateAuth, self).__init__(
"%s@%s" % (self.user.username, self.user.provider)
)
except FederatedUser.DoesNotExist:
super(CASFederateAuth, self).__init__("%s@%s" % (username, provider))
def test_password(self, ticket):
"""test `password` agains the user"""
if not self.user or not self.user.ticket:
return False
else:
return (
ticket == self.user.ticket and
self.user.last_update >
(timezone.now() - timedelta(seconds=settings.CAS_TICKET_VALIDITY))
)
def attributs(self):
"""return a dict of user attributes"""
if not self.user:
return {}
else:
return self.user.attributs