Snippets

Ilnur Ibragimov DjangoKerberosMiddleWare

Created by Ilnur Ibragimov last modified
# -*- 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
1
2
3
4
5
6
7
8
MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'training_site.django_kerberos.DjangoKerberosAuthMiddleware',
    ...
]

KERBEROS_HTTP_HOST = 'my.example.com'  # principal HOSTNAME

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.