Snippets
Created by
Ilnur Ibragimov
last modified
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | # -*- coding: utf-8 -*-
import os
import socket
import logging
import kerberos
from django.http import HttpResponse
from django.core.exceptions import MiddlewareNotUsed
LOG = logging.getLogger('django-kerberos')
class DjangoKerberosAuthMiddleware(object):
"""
Middleware that sets sets REMOTE_USER using kerberos.
"""
def __init__(self):
from django.conf import settings
if hasattr(settings, 'KERBEROS_HTTP_HOST'):
hostname = settings.KERBEROS_HTTP_HOST
else:
hostname = socket.gethostname()
self.service = 'HTTP@%s' % hostname # GSS Service
if 'KRB5_KTNAME' in os.environ:
try:
principal = kerberos.getServerPrincipalDetails('HTTP',
hostname)
except kerberos.KrbError as exc:
LOG.warn('KerberosAuthMiddleware: %s', exc)
raise MiddlewareNotUsed()
else:
LOG.debug('KerberosAuthMiddleware is identifying as %s' %
principal)
else:
LOG.warn('KerberosAuthMiddleware: set KRB5_KTNAME to your keytab '
'file')
raise MiddlewareNotUsed()
def process_request(self, request):
if request.session.get('KRB_REMOTE_USER'):
request.META['REMOTE_USER'] = request.session.get('KRB_REMOTE_USER')
return None
authorization = request.META.get('HTTP_AUTHORIZATION')
# If we have no 'Authorization' header, return a 401.
if authorization is None:
response = HttpResponse('Unauthorized')
response.status_code = 401
response['WWW-Authenticate'] = 'Negotiate'
return response
# If we have an 'Authorization' header, extract the client's token and
# attempt to authenticate with it.
client_token = ''.join(authorization.split()[1:])
server_token, user = self._authenticate(client_token)
if user:
# Add the user to the environment for the application to use it,
# call the application, add the token to the response, and return
# it
# remove realm
user = user.split("@")[0]
request.META['REMOTE_USER'] = user
request.META['KRB_REMOTE_USER'] = user
request.session['KRB_REMOTE_USER'] = user
if server_token:
request.META['KRB_SERVER_TOKEN'] = server_token
def process_response(self, request, response):
if request.META.get('KRB_SERVER_TOKEN'):
server_token = request.META['KRB_SERVER_TOKEN']
response['WWW-Authenticate'] = 'negotiate %s' % server_token
if hasattr(request, 'user') and request.user.is_authenticated():
request.session['KRB_REMOTE_USER'] = request.user.username
return response
def _authenticate(self, client_token):
'''
Validate the client token
Return the authenticated users principal and a token suitable to
provide mutual authentication to the client.
'''
state = None
server_token = None
user = None
try:
rc, state = kerberos.authGSSServerInit(self.service)
if rc == kerberos.AUTH_GSS_COMPLETE:
rc = kerberos.authGSSServerStep(state, client_token)
if rc == kerberos.AUTH_GSS_COMPLETE:
server_token = kerberos.authGSSServerResponse(state)
user = kerberos.authGSSServerUserName(state)
elif rc == kerberos.AUTH_GSS_CONTINUE:
server_token = kerberos.authGSSServerResponse(state)
except kerberos.GSSError as e:
LOG.error('ERROR IN KERBEROS: %s', e)
finally:
if state:
kerberos.authGSSServerClean(state)
return server_token, user
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.