Commit 0f0cda76 by Bach Dániel

add copypasted code

parent 855dcbb6
......@@ -227,6 +227,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'voms.auth.VomsMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
########## END MIDDLEWARE CONFIGURATION
......@@ -279,6 +280,7 @@ LOCAL_APPS = (
'manager',
'acl',
'monitor',
'voms',
)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
......@@ -360,6 +362,10 @@ CACHES = {
}
}
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'voms.auth.VomsBackend',
)
if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE':
try:
......@@ -371,8 +377,7 @@ if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE':
INSTALLED_APPS += (
'djangosaml2',
)
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
AUTHENTICATION_BACKENDS += (
'djangosaml2.backends.Saml2Backend',
)
......
from __future__ import absolute_import
from hashlib import sha1
import logging
import M2Crypto
from django.contrib.auth import login, authenticate
from django.contrib.auth.models import User
from dashboard.models import Profile
from .voms_helper import VOMS
logger = logging.getLogger(__name__)
# https://github.com/IFCA/keystone-voms/blob/stable/icehouse/keystone_voms/core.py
# TODO
class VomsError(Exception):
"""Voms credential management error"""
errors = {
0: ('none', None),
1: ('nosocket', 'Socket problem'),
2: ('noident', 'Cannot identify itself (certificate problem)'),
3: ('comm', 'Server problem'),
4: ('param', 'Wrong parameters'),
5: ('noext', 'VOMS extension missing'),
6: ('noinit', 'Initialization error'),
7: ('time', 'Error in time checking'),
8: ('idcheck', 'User data in extension different from the real'),
9: ('extrainfo', 'VO name and URI missing'),
10: ('format', 'Wrong data format'),
11: ('nodata', 'Empty extension'),
12: ('parse', 'Parse error'),
13: ('dir', 'Directory error'),
14: ('sign', 'Signature error'),
15: ('server', 'Unidentifiable VOMS server'),
16: ('mem', 'Memory problems'),
17: ('verify', 'Generic verification error'),
18: ('type', 'Returned data of unknown type'),
19: ('order', 'Ordering different than required'),
20: ('servercode', 'Error from the server'),
21: ('notavail', 'Method not available'),
}
def __init__(self, value):
self.code, self.message = self.errors.get(
value, ('oops', 'Unknown error %d' % value))
def __str__(self):
return self.message
class VomsBackend(object):
# https://github.com/IFCA/keystone-voms/blob/stable/icehouse
# /keystone_voms/core.py
# TODO
@staticmethod
def _get_cert_chain(cert, chain):
"""Return certificate and chain from the ssl info in M2Crypto format"""
cert_out = M2Crypto.X509.load_cert_string(cert)
chain_out = M2Crypto.X509.X509_Stack()
for c in chain:
aux = M2Crypto.X509.load_cert_string(c)
if aux.check_ca():
continue # Don't include CA certs
chain_out.push(aux)
return cert_out, chain_out
# https://github.com/IFCA/keystone-voms/blob/stable/icehouse
# /keystone_voms/core.py
# TODO
def _get_voms_info(self, cert, chain):
"""Extract voms info from ssl_info and return dict with it."""
try:
cert, chain = self._get_cert_chain(cert, chain)
except M2Crypto.X509.X509Error:
raise
with VOMS('/etc/grid-security/vomsdir/',
'/etc/grid-security/certificates/',
'libvomsapi.so.1') as v:
voms_data = v.retrieve(cert, chain)
if not voms_data:
raise VomsError(v.error.value)
d = {}
for attr in ('user', 'userca', 'server', 'serverca',
'voname', 'uri', 'version', 'serial',
('not_before', 'date1'), ('not_after', 'date2')):
if isinstance(attr, basestring):
d[attr] = getattr(voms_data, attr)
else:
d[attr[0]] = getattr(voms_data, attr[1])
d["fqans"] = []
for fqan in iter(voms_data.fqan):
if fqan is None:
break
d["fqans"].append(fqan)
return d
def authenticate(self, request):
cert = request.environ.get('SSL_CLIENT_CERT')
chain = []
for k, v in request.environ.iteritems():
if k.startswith('SSL_CLIENT_CERT_CHAIN_'):
chain.append(v)
if not cert or not chain:
logger.debug('missing cert(%s) or chain(%s)', cert, chain)
return None
cert = cert.replace('\t', '\n')
try:
voms_info = self._get_voms_info(cert, chain)
except VomsError as e:
logger.info('VomsError: %s', str(e))
return None
except:
logger.exception('Unhandled error: ')
return None
dn = voms_info['user']
username = sha1(dn).hexdigest()[:30]
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
cn = dn.split('/')[-1].lstrip('CN=')
first_name, last_name = cn.split(' ', 2)
user = User(username=username, password='',
first_name=first_name, last_name=last_name)
user.save()
profile, created = Profile.objects.get_or_create(user=user)
profile.org_id = dn
profile.save()
logger.info(u'new voms user: %s (%s)', user, dn)
return user
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
# https://github.com/kimvais/django-ssl-client-auth/blob/master/django_ssl_auth/base.py
class VomsMiddleware(object):
def process_request(self, request):
if not hasattr(request, 'user') or request.user.is_authenticated():
return
user = authenticate(request=request)
if user is None or not user.is_authenticated():
return
logger.info("VomsMiddleware login: %s", repr(user))
login(request, user)
# Copyright 2012 Spanish National Research Council
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import ctypes
class _voms(ctypes.Structure):
_fields_ = [
("siglen", ctypes.c_int32),
("signature", ctypes.c_char_p),
("user", ctypes.c_char_p),
("userca", ctypes.c_char_p),
("server", ctypes.c_char_p),
("serverca", ctypes.c_char_p),
("voname", ctypes.c_char_p),
("uri", ctypes.c_char_p),
("date1", ctypes.c_char_p),
("date2", ctypes.c_char_p),
("type", ctypes.c_int32),
("std", ctypes.c_void_p),
("custom", ctypes.c_char_p),
("datalen", ctypes.c_int32),
("version", ctypes.c_int32),
("fqan", ctypes.POINTER(ctypes.c_char_p)),
("serial", ctypes.c_char_p),
("ac", ctypes.c_void_p),
("holder", ctypes.c_void_p),
]
class _vomsdata(ctypes.Structure):
_fields_ = [
("cdir", ctypes.c_char_p),
("vdir", ctypes.c_char_p),
("data", ctypes.POINTER(ctypes.POINTER(_voms))),
("workvo", ctypes.c_char_p),
("extra_data", ctypes.c_char_p),
("volen", ctypes.c_int32),
("extralen", ctypes.c_int32),
("real", ctypes.c_void_p),
]
class VOMS(object):
"""Context Manager for VOMS handling"""
def __init__(self, vomsdir_path, ca_path, vomsapi_lib):
self.VOMSApi = ctypes.CDLL(vomsapi_lib)
self.VOMSApi.VOMS_Init.restype = ctypes.POINTER(_vomsdata)
self.VOMSDIR = vomsdir_path
self.CADIR = ca_path
self.vd = None
def __enter__(self):
self.vd = self.VOMSApi.VOMS_Init(self.VOMSDIR, self.CADIR).contents
return self
def set_no_verify(self):
"""Skip verification of AC.
This method skips the AC signature verification, this it should
only be used for debugging and tests.
"""
error = ctypes.c_int32(0)
self.VOMSApi.VOMS_SetVerificationType(0x040,
ctypes.byref(self.vd),
ctypes.byref(error))
def retrieve(self, cert, chain):
"""Retrieve VOMS credentials from a certificate and chain."""
self.error = ctypes.c_int32(0)
cert_ptr = ctypes.cast(long(cert._ptr()), ctypes.c_void_p)
chain_ptr = ctypes.cast(long(chain._ptr()), ctypes.c_void_p)
res = self.VOMSApi.VOMS_Retrieve(cert_ptr,
chain_ptr,
0,
ctypes.byref(self.vd),
ctypes.byref(self.error))
if res == 0:
msg = ctypes.create_string_buffer(1000)
self.VOMSApi.VOMS_ErrorMessage(
ctypes.byref(self.vd), self.error, ctypes.byref(msg),
ctypes.sizeof(msg))
print msg.raw
return None
else:
return self.vd.data.contents.contents
def __exit__(self, type, value, tb):
self.VOMSApi.VOMS_Destroy(ctypes.byref(self.vd))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment