Esempio n. 1
0
 def auth_negotiate(self, auth_header, callback):
     """
     Perform Negotiate (GSSAPI/SSO) authentication via Kerberos.
     """
     auth_str = auth_header.split()[1]
     # Initialize Kerberos Context
     try:
         result, context = kerberos.authGSSServerInit(
             self.settings['sso_service'])
         if result != 1:
             raise tornado.web.HTTPError(500, _("Kerberos Init failed"))
         result = kerberos.authGSSServerStep(context, auth_str)
         if result == 1:
             gssstring = kerberos.authGSSServerResponse(context)
         else: # Fall back to Basic auth
             self.auth_basic(auth_header, callback)
         # NOTE: The user we get from Negotiate is a full UPN (user@REALM)
         user = kerberos.authGSSServerUserName(context)
     except kerberos.GSSError as e:
         logging.error(_("Kerberos Error: %s" % e))
         raise tornado.web.HTTPError(500, _("Kerberos Init failed"))
     finally:
         kerberos.authGSSServerClean(context)
     self.set_header('WWW-Authenticate', "Negotiate %s" % gssstring)
     callback(user)
Esempio n. 2
0
    def authorize(self, req, app, app_args, app_kwargs):
        """Perform a Kerberos authentication handshake with the KDC."""
        http_auth = req.environ.get(self.AUTH_HEADER)
        if not http_auth:
            log.info('kerberos: rejecting non-authed request from %s',
                     req.environ.get('REMOTE_ADDR'))
            return self.auth_fail()

        log.debug('kerberos: processing auth: %s', http_auth)
        auth_type, auth_key = self.parse_auth_header(http_auth)

        if auth_type == 'Negotiate':
            # Initialize a kerberos context.
            try:
                result, context = kerberos.authGSSServerInit(self._service)
                log.debug('kerberos: authGSSServerInit(%s) -> %s, %s',
                          self._service, result, context)
            except kerberos.GSSError as e:
                log.warning('kerberos: GSSError during init: %s', e)
                result, context = 0, None

            if not self.check_result(result):
                log.warning(
                    'kerberos: bad result from authGSSServerInit(%s): %s',
                    self._service, result)
                return self.auth_error()

            # Process the next challenge step and retrieve the response.
            gss_key = None
            try:
                result = kerberos.authGSSServerStep(context, auth_key)
                log.debug('kerberos: authGSSServerStep(%s, %s) -> %s', context,
                          auth_key, result)

                gss_key = kerberos.authGSSServerResponse(context)
                log.debug('kerberos: authGSSServerResponse(%s) -> %s', context,
                          gss_key)
            except kerberos.GSSError as e:
                log.warning('kerberos: GSSError(%s)', e)
                result = 0

            if not self.check_result(result):
                return self.auth_fail(gss_key)

            # Retrieve the user id and add it to the request environment.
            username = kerberos.authGSSServerUserName(context)
            req.environ['REMOTE_USER'] = username
            log.info('kerberos: authenticated user %s from %s', username,
                     req.environ.get('REMOTE_ADDR'))

            # Pass on the GSS response in the Bottle response.
            response.set_header('WWW-Authenticate',
                                'Negotiate ' + str(gss_key))

            # Clean up.
            kerberos.authGSSServerClean(context)

            return app(*app_args, **app_kwargs)
        else:
            return self.auth_fail()
Esempio n. 3
0
def get_kerberos_userid(request):
    if not request.authorization or request.authorization[0] != 'Negotiate':
        if 'challenge' in request.params:
            raise HTTPUnauthorized(headers={'WWW-Authenticate': 'Negotiate'})
        return None

    ticket = request.authorization[1]
    log.debug("Kerberos ticket received: %s" % ticket)

    service = 'HTTP@%s' % request.host.split(':')[0]
    result, context = kerberos.authGSSServerInit(service)
    if result != 1:
        log.error("Could not initialize Kerberos GSS service.")
        return None

    try:
        try:
            if not kerberos.authGSSServerStep(context, ticket) == 1:
                return None
        except kerberos.GSSError, e:
            log.warn("%s: GSSError %s\nTicket: %s" %
                     (request.remote_addr, e, ticket))
            return None

        principal = kerberos.authGSSServerUserName(context)
Esempio n. 4
0
    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 exc:
            LOG.error("Unhandled GSSError: %s", exc)
        finally:
            if state:
                kerberos.authGSSServerClean(state)
        return server_token, user
    def authenticate(self, handler, data):
        '''
            Performs GSSAPI Negotiate Authentication
            @param token: GSSAPI Authentication Token
            @type token: str
            @returns gssapi return code or None on failure
            @rtype: int or None
            '''
        state = None
        try:
            rc, state = kerberos.authGSSServerInit(self.service_name)
            self.log.info("kerberos.authGSSServerInit")
            if rc != kerberos.AUTH_GSS_COMPLETE:
                return None

            rc = kerberos.authGSSServerStep(state, data)
            self.log.info("kerberos.authGSSServerStep")
            if rc == kerberos.AUTH_GSS_COMPLETE:
                user = kerberos.authGSSServerUserName(state)
                self.log.info("Extracted User = "******"kerberos.AUTH_GSS_COMPLETE:" + user
            elif rc == kerberos.AUTH_GSS_CONTINUE:
                return "kerberos.AUTH_GSS_CONTINUE"
            else:
                self.log.info("return None")
                return None
        except kerberos.GSSError as err:
            self.log.info("kerberos.GSSError: {0}".format(err))
            return None
        finally:
            if state:
                kerberos.authGSSServerClean(state)
Esempio n. 6
0
    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:
            pass
        finally:
            if state:
                kerberos.authGSSServerClean(state)
        return server_token, user
Esempio n. 7
0
    def wrapped(resource, req, resp, *args, **kwargs):
        authorization = req.get_header("Authorization")

        if not authorization:
            resp.append_header("WWW-Authenticate", "Negotiate")
            raise falcon.HTTPUnauthorized("Unauthorized",
                                          "No Kerberos ticket offered?")

        token = ''.join(authorization.split()[1:])

        rc, context = kerberos.authGSSServerInit("HTTP@" + FQDN)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            raise falcon.HTTPForbidden("Forbidden", "Kerberos ticket expired?")

        rc = kerberos.authGSSServerStep(context, token)
        kerberos_user = kerberos.authGSSServerUserName(context).split("@")

        # References lost beyond this point! Results in
        # ValueError: PyCapsule_SetPointer called with null pointer
        kerberos.authGSSServerClean(context)

        if rc == kerberos.AUTH_GSS_COMPLETE:
            kwargs["user"] = kerberos_user
            return func(resource, req, resp, *args, **kwargs)
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            raise falcon.HTTPUnauthorized("Unauthorized", "Tried GSSAPI")
        else:
            raise falcon.HTTPForbidden("Forbidden", "Tried GSSAPI")
def _gssapi_authenticate(token):
    """
    Performs GSSAPI Negotiate Authentication

    On success also stashes the server response token for mutual authentication
    at the top of request context with the name kerberos_token, along with the
    authenticated user principal with the name kerberos_user.

    @param token: GSSAPI Authentication Token
    @type token: str
    @returns gssapi return code or None on failure
    @rtype: int or None
    """
    state = None
    # Should be a request local object
    ctx = request.ctx
    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            return None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 9
0
 def _doNegotiateAuth(self):
     _ignore_result, context = kerberos.authGSSServerInit("")
     try:
         self._getKerberosDetails()
         kerberos.authGSSServerStep(context, self.authToken)
         targetName = kerberos.authGSSServerTargetName(context)
         if targetName.lower() != self._kerberosPrincipal.lower():
             raise Exception(
                 "Target name did not match local principal - %s vs %s" %
                 (targetName, self._kerberosPrincipal))
         response = kerberos.authGSSServerResponse(context)
         principal = kerberos.authGSSServerUserName(context)
         (user, realm) = principal.split("@", 1)
         if realm.lower() != self._kerberosRealm.lower():
             raise Exception("Mismatched realms - %s vs %s" %
                             (realm, self._kerberosRealm))
         self.user = user
         self.page.responseHeaders.append(
             ("WWW-Authenticate", "Negotiate %s" % response))
         print "Did negotiate auth for %s" % self.user
     except:
         print "Failed negotiate auth"
         self.page.offerNegotiate = False
         raise
     finally:
         kerberos.authGSSServerClean(context)
Esempio n. 10
0
 def login_krb5(self, session, token):
     ctx = None
     if AuthenticationManager.has_krb5():
         import kerberos
         try:
             server_principal = "HTTP@" + self.function.server.instance_address
             (res, ctx) = kerberos.authGSSServerInit(server_principal)
             res = kerberos.authGSSServerStep(ctx, token)
             if res != kerberos.AUTH_GSS_COMPLETE:
                 raise exterror.ExtAccessDeniedError()
             
             authprinc = kerberos.authGSSServerUserName(ctx)
             if '@' in authprinc:
                 priminst, realm = authprinc.split('@')
                 if "/" in priminst:
                     primary, instance = priminst.split("/")
                 else:
                     primary, instance = priminst, ""
             else:
                 primary, instance, realm = authprinc, "", ""
 
             session.set("authuser", primary)
             session.set("authinst", instance)
             session.set("authrealm", realm)
         finally:
             if ctx:
                 kerberos.authGSSServerClean(ctx)
     else:
         raise exterror.ExtAuthenticationFailedError()
def get_kerberos_userid(request):
    if not request.authorization or request.authorization[0] != 'Negotiate':
        if 'challenge' in request.params:
            raise HTTPUnauthorized(headers={'WWW-Authenticate': 'Negotiate'})
        return None

    ticket = request.authorization[1]
    log.debug("Kerberos ticket received: %s" % ticket)

    service = 'HTTP@%s' % request.host.split(':')[0]
    result, context = kerberos.authGSSServerInit(service)
    if result != 1:
        log.error("Could not initialize Kerberos GSS service.")
        return None

    try:
        try:
            if not kerberos.authGSSServerStep(context,ticket) == 1:
                return None
        except kerberos.GSSError, e:
            log.warn("%s: GSSError %s\nTicket: %s" % (
                request.remote_addr, e, ticket))
            return None

        principal = kerberos.authGSSServerUserName(context)
Esempio n. 12
0
 def auth_negotiate(self, auth_header, callback):
     """
     Perform Negotiate (GSSAPI/SSO) authentication via Kerberos.
     """
     auth_str = auth_header.split()[1]
     # Initialize Kerberos Context
     context = None
     try:
         result, context = kerberos.authGSSServerInit(
             self.settings['sso_service'])
         if result != 1:
             raise tornado.web.HTTPError(500, _("Kerberos Init failed"))
         result = kerberos.authGSSServerStep(context, auth_str)
         if result == 1:
             gssstring = kerberos.authGSSServerResponse(context)
         else:  # Fall back to Basic auth
             self.auth_basic(auth_header, callback)
         # NOTE: The user we get from Negotiate is a full UPN (user@REALM)
         user = kerberos.authGSSServerUserName(context)
     except kerberos.GSSError as e:
         logging.error(_("Kerberos Error: %s" % e))
         raise tornado.web.HTTPError(500, _("Kerberos Init failed"))
     finally:
         if context:
             kerberos.authGSSServerClean(context)
     self.set_header('WWW-Authenticate', "Negotiate %s" % gssstring)
     callback(user)
Esempio n. 13
0
    def login_krb5(self, session, token):
        ctx = None
        if AuthenticationManager.has_krb5():
            import kerberos
            try:
                server_principal = "HTTP@" + self.function.server.instance_address
                (res, ctx) = kerberos.authGSSServerInit(server_principal)
                res = kerberos.authGSSServerStep(ctx, token)
                if res != kerberos.AUTH_GSS_COMPLETE:
                    raise exterror.ExtAccessDeniedError()

                authprinc = kerberos.authGSSServerUserName(ctx)
                if '@' in authprinc:
                    priminst, realm = authprinc.split('@')
                    if "/" in priminst:
                        primary, instance = priminst.split("/")
                    else:
                        primary, instance = priminst, ""
                else:
                    primary, instance, realm = authprinc, "", ""

                session.set("authuser", primary)
                session.set("authinst", instance)
                session.set("authrealm", realm)
            finally:
                if ctx:
                    kerberos.authGSSServerClean(ctx)
        else:
            raise exterror.ExtAuthenticationFailedError()
Esempio n. 14
0
 def authenticate(self, request, context):
     spnego_token = self._get_spnego_token(context)
     gcssapi_context = None
     try:
         # Initialize GSSAPI context
         result, gcssapi_context = kerberos.authGSSServerInit(
             f'{settings.BROKER_SERVICE_NAME}@{settings.BROKER_SERVICE_HOSTNAME}'
         )
         if result != kerberos.AUTH_GSS_COMPLETE:
             # The GSSAPI context initialization failed
             abort(grpc.StatusCode.PERMISSION_DENIED)
         # Process the client-supplied SPNEGO token
         result = kerberos.authGSSServerStep(gcssapi_context, spnego_token)
         if result == kerberos.AUTH_GSS_COMPLETE:
             # Authentication succeded. Return the authenticated principal's username.
             principal = kerberos.authGSSServerUserName(gcssapi_context)
             return principal
         else:
             # Authentication failed
             abort(grpc.StatusCode.PERMISSION_DENIED)
     except kerberos.GSSError:
         abort(grpc.StatusCode.PERMISSION_DENIED)
     finally:
         # Destroy the GSSAPI context
         if gcssapi_context:
             kerberos.authGSSServerClean(gcssapi_context)
Esempio n. 15
0
    def wrapped(resource, req, resp, *args, **kwargs):
        authorization = req.get_header("Authorization")

        if not authorization:
            resp.append_header("WWW-Authenticate", "Negotiate")
            raise falcon.HTTPUnauthorized("Unauthorized", "No Kerberos ticket offered?")

        token = ''.join(authorization.split()[1:])

        rc, context = kerberos.authGSSServerInit("HTTP@" + FQDN)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            raise falcon.HTTPForbidden("Forbidden", "Kerberos ticket expired?")

        rc = kerberos.authGSSServerStep(context, token)
        kerberos_user = kerberos.authGSSServerUserName(context).split("@")

        # References lost beyond this point! Results in
        # ValueError: PyCapsule_SetPointer called with null pointer
        kerberos.authGSSServerClean(context)

        if rc == kerberos.AUTH_GSS_COMPLETE:
            kwargs["user"] = kerberos_user
            return func(resource, req, resp, *args, **kwargs)
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            raise falcon.HTTPUnauthorized("Unauthorized", "Tried GSSAPI")
        else:
            raise falcon.HTTPForbidden("Forbidden", "Tried GSSAPI")
def _gssapi_authenticate(token):
    '''
    Performs GSSAPI Negotiate Authentication

    On success also stashes the server response token for mutual authentication
    at the top of request context with the name kerberos_token, along with the
    authenticated user principal with the name kerberos_user.

    @param token: GSSAPI Authentication Token
    @type token: str
    @returns gssapi return code or None on failure
    @rtype: int or None
    '''
    state = None
    # Should be a request local object
    ctx = request.ctx
    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            return None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 17
0
    def check_ticket(self, ticket):

        init_context_res = chech_ticket_res = -1
        principal = realm = orig_service = target_name = service = ''

        try:
            principal = kerberos.getServerPrincipalDetails(
                self._service_type, self._hostname)
            orig_service, realm = self._split_principal(principal)
            init_context_res, context = kerberos.authGSSServerInit('')
            chech_ticket_res = kerberos.authGSSServerStep(context, ticket)
            target_name = kerberos.authGSSServerTargetName(context)
            service, _ = self._split_principal(target_name)
            response = kerberos.authGSSServerResponse(context)
            principal = kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)

        except kerberos.GSSError:
            if init_context_res != 1:
                ERROR("Error init kerberos context")
            elif chech_ticket_res == -1:
                ERROR("Ticket is not correct:" + ticket)
            elif service.lower() != orig_service.lower():
                ERROR('Bad credentials: wrong target name ' + target_name)
            return '', '', ''

        except kerberos.KrbError:
            ERROR("Internal kerberos error")
            return '', '', ''

        # del kerberos
        username, realm = principal.split('@')
        return response, username, realm
Esempio n. 18
0
def _kerberos_auth(token):
    """
    Performs GSSAPI Negotiate Authentication

    Returns the retrun code and state so that token and user principle can be retrieved.

    @param token: GSSAPI Authentication Token
    @returns gssapi return and state
    @rtype: int or None, PyCObject
    """

    state = None
    rc = None
    context = stack.top
    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            return None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            context.kerberos_token = kerberos.authGSSServerResponse(state)
            context.kerberos_user = kerberos.authGSSServerUserName(state)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 19
0
    def get_current_user_kerberos(self):
        """Authenticate the current user using kerberos.

        Returns
        -------
        user : str
            The current user name.
        """
        import kerberos

        auth_header = self.request.headers.get("Authorization")
        if not auth_header:
            return self._raise_auth_required()

        auth_type, auth_key = auth_header.split(" ", 1)
        if auth_type != "Negotiate":
            return self._raise_auth_required()

        if _SERVICE_NAME is None:
            raise RuntimeError(
                "Kerberos not initialized, must call `init_kerberos` before "
                "serving requests")

        gss_context = None
        try:
            # Initialize kerberos context
            rc, gss_context = kerberos.authGSSServerInit(_SERVICE_NAME)

            # NOTE: Per the pykerberos documentation, the return code should be
            # checked after each step. However, after reading the pykerberos
            # code no method used here will ever return anything but
            # AUTH_GSS_COMPLETE (all other cases will raise an exception).  We
            # keep these checks in just in case pykerberos changes its behavior
            # to match its docs, but they likely never will trigger.

            if rc != kerberos.AUTH_GSS_COMPLETE:
                return self._raise_auth_error(
                    "GSS server init failed, return code = %r" % rc)

            # Challenge step
            rc = kerberos.authGSSServerStep(gss_context, auth_key)
            if rc != kerberos.AUTH_GSS_COMPLETE:
                return self._raise_auth_error(
                    "GSS server step failed, return code = %r" % rc)
            gss_key = kerberos.authGSSServerResponse(gss_context)

            # Retrieve user name
            fulluser = kerberos.authGSSServerUserName(gss_context)
            user = fulluser.split("@", 1)[0]

            # Complete the protocol by responding with the Negotiate header
            self.set_header("WWW-Authenticate", "Negotiate %s" % gss_key)
        except kerberos.GSSError as err:
            return self._raise_auth_error(err)
        finally:
            if gss_context is not None:
                kerberos.authGSSServerClean(gss_context)

        return user
    def authenticateCredentials(self, credentials):
        """ See IAuthenticationPlugin.

        o We expect the credentials to be those returned by
          ILoginPasswordExtractionPlugin.
        """
        # We only authenticate when our challenge mechanism extracted
        # the ticket
        if credentials.get('plugin') != self.getId():
            return None

        request = self.REQUEST
        response = request.RESPONSE
        remote_host = request.getClientAddr()

        # We are actually already authenticated... maybe we are in a subrequest
        if request.get('AUTHENTICATED_USER', None) is not None:
            username = request.AUTHENTICATED_USER.getName()
            return username, username

        ticket = credentials['ticket']

        if WINDOWS:
            sa = sspi.ServerAuth('Negotiate')
            sa.reset()
            data = ticket.decode('base64')
            err, sec_buffer = sa.authorize(data)

            if err == 0:
                username = sa.ctxt.QueryContextAttributes(
                    sspicon.SECPKG_ATTR_NAMES)
            else:
                raise Forbidden

        else:
            service = self.service
            if not service:
                service = "HTTP/" + urlparse.urlsplit(
                    request.SERVER_URL).netloc

            result, context = kerberos.authGSSServerInit(service)
            if result != 1:
                raise ValueError, "Kerberos authetication error"

            gssstring = ''
            try:
                r = kerberos.authGSSServerStep(context, ticket)
                if r == 1:
                    gssstring = kerberos.authGSSServerResponse(context)
                else:
                    raise Forbidden
            except GSSError, e:
                LOG('SPNEGO plugin', ERROR,
                    "%s: GSSError %s" % (remote_host, e))
                raise Forbidden

            username = kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)
Esempio n. 21
0
 def decode(self, base64data, request):
     
     # Init GSSAPI first - we won't specify the service now as we need to accept a target
     # name that is case-insenstive as some clients will use "http" instead of "HTTP"
     try:
         _ignore_result, context = kerberos.authGSSServerInit("");
     except kerberos.GSSError, ex:
         self.log_error("authGSSServerInit: %s(%s)" % (ex[0][0], ex[1][0],))
         raise error.LoginFailed('Authentication System Failure: %s(%s)' % (ex[0][0], ex[1][0],))
    def authenticateCredentials( self, credentials ):

        """ See IAuthenticationPlugin.

        o We expect the credentials to be those returned by
          ILoginPasswordExtractionPlugin.
        """
        # We only authenticate when our challenge mechanism extracted
        # the ticket
        if credentials.get('plugin') != self.getId():
            return None

        request = self.REQUEST
        response = request.RESPONSE
        remote_host = request.getClientAddr()

        # We are actually already authenticated... maybe we are in a subrequest
        if request.get('AUTHENTICATED_USER', None) is not None:
            username = request.AUTHENTICATED_USER.getName()
            return username, username

        ticket = credentials['ticket']

        if WINDOWS:
            sa = sspi.ServerAuth('Negotiate')
            sa.reset()
            data = ticket.decode('base64')
            err, sec_buffer = sa.authorize(data)
        
            if err == 0:
                username = sa.ctxt.QueryContextAttributes(
                    sspicon.SECPKG_ATTR_NAMES)		               
            else:
                raise Forbidden

        else:
            service = self.service
            if not service:
                service = "HTTP/" + urlparse.urlsplit(request.SERVER_URL).netloc
                
            result, context = kerberos.authGSSServerInit(service)
            if result != 1:
                raise ValueError, "Kerberos authetication error"

            gssstring=''
            try:
                r=kerberos.authGSSServerStep(context,ticket)
                if r == 1:
                    gssstring=kerberos.authGSSServerResponse(context)
                else:
                    raise Forbidden
            except GSSError, e:
                LOG('SPNEGO plugin', ERROR,  "%s: GSSError %s" % (remote_host, e))
                raise Forbidden

            username=kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)
Esempio n. 23
0
    def decode(self, base64data, request):

        # Init GSSAPI first - we won't specify the service now as we need to accept a target
        # name that is case-insenstive as some clients will use "http" instead of "HTTP"
        try:
            _ignore_result, context = kerberos.authGSSServerInit("")
        except kerberos.GSSError, ex:
            self.log.error("authGSSServerInit: {ex0}({ex1})", ex0=ex[0][0], ex1=ex[1][0])
            raise error.LoginFailed('Authentication System Failure: %s(%s)' % (ex[0][0], ex[1][0],))
Esempio n. 24
0
 def __enter__(self):
     try:
         res, self.context = kerberos.authGSSServerInit(self.serviceType)
     except kerberos.KrbError as e:
         msg = repr(e)
         log.msg(msg)
         raise LoginFailed(msg)
     
     if res < 0:
         raise LoginFailed()
     
     return self
Esempio n. 25
0
  def authorize(self, req, app, app_args, app_kwargs):
    """Perform a Kerberos authentication handshake with the KDC."""
    http_auth = req.environ.get(self.AUTH_HEADER)
    if not http_auth:
      log.info('kerberos: rejecting non-authed request from %s', req.environ.get('REMOTE_ADDR'))
      return self.auth_fail()

    log.debug('kerberos: processing auth: %s', http_auth)
    auth_type, auth_key = self.parse_auth_header(http_auth)

    if auth_type == 'Negotiate':
      # Initialize a kerberos context.
      try:
        result, context = kerberos.authGSSServerInit(self._service)
        log.debug('kerberos: authGSSServerInit(%s) -> %s, %s', self._service, result, context)
      except kerberos.GSSError as e:
        log.warning('kerberos: GSSError during init: %s', e)
        result, context = 0, None

      if not self.check_result(result):
        log.warning('kerberos: bad result from authGSSServerInit(%s): %s', self._service, result)
        return self.auth_error()

      # Process the next challenge step and retrieve the response.
      gss_key = None
      try:
        result = kerberos.authGSSServerStep(context, auth_key)
        log.debug('kerberos: authGSSServerStep(%s, %s) -> %s', context, auth_key, result)

        gss_key = kerberos.authGSSServerResponse(context)
        log.debug('kerberos: authGSSServerResponse(%s) -> %s', context, gss_key)
      except kerberos.GSSError as e:
        log.warning('kerberos: GSSError(%s)', e)
        result = 0

      if not self.check_result(result):
        return self.auth_fail(gss_key)

      # Retrieve the user id and add it to the request environment.
      username = kerberos.authGSSServerUserName(context)
      req.environ['REMOTE_USER'] = username
      log.info('kerberos: authenticated user %s from %s', username, req.environ.get('REMOTE_ADDR'))

      # Pass on the GSS response in the Bottle response.
      response.set_header('WWW-Authenticate', 'Negotiate ' + str(gss_key))

      # Clean up.
      kerberos.authGSSServerClean(context)

      return app(*app_args, **app_kwargs)
    else:
      return self.auth_fail()
Esempio n. 26
0
    def __call__(self, environ, start_response):
        def error():
            start_response('500 Error', [
                ('content-type', 'text/plain'),
            ])
            return ['Internal error']

        def noauth(msg=None):
            start_response('401 Unauthorized', [
                ('content-type', 'text/plain'),
                ('WWW-Authenticate', 'Negotiate'),
                ('WWW-Authenticate', 'Basic realm="Web Service for CloudLab"')
            ])
            if msg:
                return ['No auth. Error: %s' % msg]
            return ['No auth']

        if 'HTTP_AUTHORIZATION' not in environ:
            return noauth()

        type, authstr = environ['HTTP_AUTHORIZATION'].split(' ', 1)

        if type == 'Negotiate':
            result, context = kerberos.authGSSServerInit(self.service)
            if result != 1:
                return error()

            gssstring = ''
            r = kerberos.authGSSServerStep(context, authstr)
            if r == 1:
                gssstring = kerberos.authGSSServerResponse(context)
            else:
                return noauth()

            def new_start_response(status, headers):
                start_response(
                    status,
                    [('WWW-Authenticate', 'Negotiate %s' % gssstring)] +
                    headers)

            environ['REMOTE_USER'] = kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)
        elif type == 'Basic':
            username, password = b64decode(authstr).split(':', 1)
            try:
                kerberos.checkPassword(username, password, self.service,
                                       self.realm)
            except Exception, e:
                return noauth(e.message)
            new_start_response = start_response
            environ['REMOTE_USER'] = username
Esempio n. 27
0
    async def authenticate(self, handler, data):
        auth_header = handler.request.headers.get('Authorization')
        if not auth_header:  # pragma: nocover
            self.log.error("authenticate hit with no kerberos credentials, "
                           "this code path should never occur")
            return None

        auth_type, auth_key = auth_header.split(" ", 1)
        if auth_type != 'Negotiate':  # pragma: nocover
            self.log.error("authenticate hit with no kerberos credentials, "
                           "this code path should never occur")
            return None

        gss_context = None
        try:
            # Initialize kerberos context
            rc, gss_context = kerberos.authGSSServerInit(self.service_name)

            # NOTE: Per the pykerberos documentation, the return code should be
            # checked after each step. However, after reading the pykerberos
            # code no method used here will ever return anything but
            # AUTH_GSS_COMPLETE (all other cases will raise an exception).  We
            # keep these checks in just in case pykerberos changes its behavior
            # to match its docs, but they likely never will trigger.
            if rc != kerberos.AUTH_GSS_COMPLETE:  # pragma: nocover
                self.log.error("GSS server init failed, return code = %r", rc)
                return None

            # Challenge step
            rc = kerberos.authGSSServerStep(gss_context, auth_key)
            if rc != kerberos.AUTH_GSS_COMPLETE:  # pragma: nocover
                # Only warn here, since this happens for any user failing login
                self.log.warn("GSS server step failed, return code = %r", rc)
                return None
            gss_key = kerberos.authGSSServerResponse(gss_context)

            # Retrieve user name
            fulluser = kerberos.authGSSServerUserName(gss_context)
            user = fulluser.split("@", 1)[0]

            # Complete the protocol by responding with the Negotiate header
            handler.set_header('WWW-Authenticate', "Negotiate %s" % gss_key)
            return user
        except kerberos.GSSError as err:  # pragma: nocover
            self.log.error("Error occurred during kerberos authentication",
                           exc_info=err)
            return None
        finally:
            if gss_context is not None:
                kerberos.authGSSServerClean(gss_context)
Esempio n. 28
0
    def __call__(self, environ, start_response):
        def error():
            start_response('500 Error', [
                ('content-type', 'text/plain'),
            ])
            return ['Internal error']
        def noauth():
            start_response('401 Unauthorized', [
                ('content-type', 'text/plain'),
                ('WWW-Authenticate','Negotiate'),
                ('WWW-Authenticate','Basic realm="Secured area"')
            ])
            return ['No auth']


        if 'HTTP_AUTHORIZATION' not in environ:
            return noauth()

        type, authstr = environ['HTTP_AUTHORIZATION'].split(' ', 1)

        if type == 'Negotiate':
            result, context = kerberos.authGSSServerInit(self.service)
            if result != 1:
                return error()

            gssstring=''
            r=kerberos.authGSSServerStep(context,authstr)
            if r == 1:
                gssstring=kerberos.authGSSServerResponse(context)
            else:
                return noauth()
            def new_start_response(status, headers):
                start_response(
                    status,
                    [
                        ('WWW-Authenticate','Negotiate %s' % gssstring)
                    ]+headers
                )

            environ['REMOTE_USER']=kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)
        elif type == 'Basic':
            username, password = b64decode(authstr).split(':',1)
            try:
                kerberos.checkPassword(username, password, self.service, self.realm)
            except:
                return noauth()
            new_start_response=start_response
            environ['REMOTE_USER']=username
        return self.wrapped(environ, new_start_response)
Esempio n. 29
0
    def __call__(self, environ, start_response):
        def error():
            start_response("500 Error", [("content-type", "text/plain")])
            return ["Internal error"]

        def noauth(msg=None):
            start_response(
                "401 Unauthorized",
                [
                    ("content-type", "text/plain"),
                    ("WWW-Authenticate", "Negotiate"),
                    ("WWW-Authenticate", 'Basic realm="Web Service for CloudLab"'),
                ],
            )
            if msg:
                return ["No auth. Error: %s" % msg]
            return ["No auth"]

        if "HTTP_AUTHORIZATION" not in environ:
            return noauth()

        type, authstr = environ["HTTP_AUTHORIZATION"].split(" ", 1)

        if type == "Negotiate":
            result, context = kerberos.authGSSServerInit(self.service)
            if result != 1:
                return error()

            gssstring = ""
            r = kerberos.authGSSServerStep(context, authstr)
            if r == 1:
                gssstring = kerberos.authGSSServerResponse(context)
            else:
                return noauth()

            def new_start_response(status, headers):
                start_response(status, [("WWW-Authenticate", "Negotiate %s" % gssstring)] + headers)

            environ["REMOTE_USER"] = kerberos.authGSSServerUserName(context)
            kerberos.authGSSServerClean(context)
        elif type == "Basic":
            username, password = b64decode(authstr).split(":", 1)
            try:
                kerberos.checkPassword(username, password, self.service, self.realm)
            except Exception, e:
                return noauth(e.message)
            new_start_response = start_response
            environ["REMOTE_USER"] = username
Esempio n. 30
0
    def verify_token(self, logger, token):
        """ Method used to verify token against KDC
        :param token: Base64 encoded token (don't decoded it)
        :return If authentication succeed, dict with {'token_resp':the base64 encoded reponse from KDC, 'user':username of client}
        """
        # Initialize context with service
        res = dict()
        username = ""

        try:
            result, context = authGSSServerInit("HTTP@" + self.krb5_service)
            if result != 1:
                logger.error(
                    "KerberosClient::verify_token: authGSSServerInit(HTTP@{}) failed with status code : {}"
                    .format(str(self.krb5_service), str(result)))
                return res

            result = authGSSServerStep(context, token)
            if result != 1:
                logger.error(
                    "KerberosClient::verify_token: authGSSServerStep(token) failed with status code : {}"
                    .format(str(result)))
                return res
            # Retrieve username of authenticated user
            username = authGSSServerUserName(context)
            # Retrieve KDC response
            kdc_response = authGSSServerResponse(context)
            # Clean kerberos context
            authGSSServerClean(context)

        except Exception as e:
            logger.error(
                "KerberosClient::verify_token: Verify token against KDC failed : {}"
                .format(str(e)))
            return res

        logger.info(
            "KerberosClient::verify_token: Successfull authentication for username {}"
            .format(username))
        return {
            'dn': username,
            'user_phone': 'N/A',
            'user_email':
            username if '@' in username else username + '@' + self.realm,
            'password_expired': False,
            'account_locked': False,
            'token_resp': kdc_response
        }
Esempio n. 31
0
    async def authenticate(self, request):
        import kerberos

        auth_header = request.headers.get("Authorization")
        if not auth_header:
            raise unauthorized("Negotiate")

        auth_type, auth_key = auth_header.split(" ", 1)
        if auth_type != "Negotiate":
            raise unauthorized("Negotiate")

        gss_context = None
        try:
            # Initialize kerberos context
            rc, gss_context = kerberos.authGSSServerInit(self.service_name)

            # NOTE: Per the pykerberos documentation, the return code should be
            # checked after each step. However, after reading the pykerberos
            # code no method used here will ever return anything but
            # AUTH_GSS_COMPLETE (all other cases will raise an exception).  We
            # keep these checks in just in case pykerberos changes its behavior
            # to match its docs, but they likely never will trigger.

            if rc != kerberos.AUTH_GSS_COMPLETE:
                self.raise_auth_error(
                    "GSS server init failed, return code = %r" % rc)

            # Challenge step
            rc = kerberos.authGSSServerStep(gss_context, auth_key)
            if rc != kerberos.AUTH_GSS_COMPLETE:
                self.raise_auth_error(
                    "GSS server step failed, return code = %r" % rc)
            gss_key = kerberos.authGSSServerResponse(gss_context)

            # Retrieve user name
            fulluser = kerberos.authGSSServerUserName(gss_context)
            user = fulluser.split("@", 1)[0]
        except kerberos.GSSError as err:
            self.raise_auth_error(err)
        finally:
            if gss_context is not None:
                kerberos.authGSSServerClean(gss_context)

        return User(user), gss_key
Esempio n. 32
0
def testGSSAPI(service):
    def statusText(r):
        if r == 1:
            return "Complete"
        elif r == 0:
            return "Continue"
        else:
            return "Error"

    rc, vc = kerberos.authGSSClientInit(service)
    print("Status for authGSSClientInit = %s" % statusText(rc))
    if rc != 1:
        return

    rs, vs = kerberos.authGSSServerInit(service)
    print("Status for authGSSServerInit = %s" % statusText(rs))
    if rs != 1:
        return

    rc = kerberos.authGSSClientStep(vc, "")
    print("Status for authGSSClientStep = %s" % statusText(rc))
    if rc != 0:
        return

    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc))
    print("Status for authGSSServerStep = %s" % statusText(rs))
    if rs == -1:
        return

    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs))
    print("Status for authGSSClientStep = %s" % statusText(rc))
    if rc == -1:
        return

    print("Server user name: %s" % kerberos.authGSSServerUserName(vs))
    print("Server target name: %s" % kerberos.authGSSServerTargetName(vs))
    print("Client user name: %s" % kerberos.authGSSClientUserName(vc))

    rc = kerberos.authGSSClientClean(vc)
    print("Status for authGSSClientClean = %s" % statusText(rc))

    rs = kerberos.authGSSServerClean(vs)
    print("Status for authGSSServerClean = %s" % statusText(rs))
Esempio n. 33
0
 def auth_negotiate(self, auth_header, callback):
     """
     Perform Negotiate (GSSAPI/SSO) authentication via Kerberos.
     """
     auth_str = auth_header.split()[1]
     # Initialize Kerberos Context
     result, context = kerberos.authGSSServerInit(self.settings["sso_service"])
     if result != 1:
         raise tornado.web.HTTPError(500, "Kerberos Init failed")
     result = kerberos.authGSSServerStep(context, auth_str)
     if result == 1:
         gssstring = kerberos.authGSSServerResponse(context)
     else:  # Fall back to Basic auth
         self.auth_basic(auth_header, callback)
     # NOTE: The user we get from Negotiate is a full UPN (e.g. user@REALM)
     user = kerberos.authGSSServerUserName(context)
     self.set_header("WWW-Authenticate", "Negotiate %s" % gssstring)
     kerberos.authGSSServerClean(context)
     callback(user)
Esempio n. 34
0
def testGSSAPI(service):
    def statusText(r):
        if r == 1:
            return "Complete"
        elif r == 0:
            return "Continue"
        else:
            return "Error"

    rc, vc = kerberos.authGSSClientInit(service);
    print "Status for authGSSClientInit = %s" % statusText(rc);
    if rc != 1:
        return
    
    rs, vs = kerberos.authGSSServerInit(service);
    print "Status for authGSSServerInit = %s" % statusText(rs);
    if rs != 1:
        return
    
    rc = kerberos.authGSSClientStep(vc, "");
    print "Status for authGSSClientStep = %s" % statusText(rc);
    if rc != 0:
        return
    
    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc));
    print "Status for authGSSServerStep = %s" % statusText(rs);
    if rs == -1:
        return
    
    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs));
    print "Status for authGSSClientStep = %s" % statusText(rc);
    if rc == -1:
        return

    print "Server user name: %s" % kerberos.authGSSServerUserName(vs);
    print "Server target name: %s" % kerberos.authGSSServerTargetName(vs);
    print "Client user name: %s" % kerberos.authGSSClientUserName(vc);
    
    rc = kerberos.authGSSClientClean(vc);
    print "Status for authGSSClientClean = %s" % statusText(rc);
    
    rs = kerberos.authGSSServerClean(vs);
    print "Status for authGSSServerClean = %s" % statusText(rs);
Esempio n. 35
0
def get_kerberos_userid(request):
    if not request.authorization or request.authorization[0] != 'Negotiate':
        if 'challenge' in request.params:
            raise HTTPUnauthorized(headers={'WWW-Authenticate': 'Negotiate'})
        return None

    ticket = request.authorization[1]
    log.debug("Kerberos ticket received: %s" % ticket)

    result, context = kerberos.authGSSServerInit(SERVICE)
    if result != 1:
        log.error("Could not initialize Kerberos GSS service.")
        return None

    try:
        if not kerberos.authGSSServerStep(context,ticket) == 1:
            return None
    except kerberos.GSSError, e:
        log.error("%s: GSSError %s" % (request.remote_addr, e))
        return None
Esempio n. 36
0
def _gssapi_authenticate(token):
    state = None
    ctx = stack.top
    try:
        return_code, state = kerberos.authGSSServerInit(_KERBEROS_SERVICE.service_name)
        if return_code != kerberos.AUTH_GSS_COMPLETE:
            return None
        return_code = kerberos.authGSSServerStep(state, token)
        if return_code == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            return return_code
        if return_code == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 37
0
def get_kerberos_userid(request):
    if not request.authorization or request.authorization[0] != 'Negotiate':
        if 'challenge' in request.params:
            raise HTTPUnauthorized(headers={'WWW-Authenticate': 'Negotiate'})
        return None

    ticket = request.authorization[1]
    log.debug("Kerberos ticket received: %s" % ticket)

    result, context = kerberos.authGSSServerInit(SERVICE)
    if result != 1:
        log.error("Could not initialize Kerberos GSS service.")
        return None

    try:
        if not kerberos.authGSSServerStep(context, ticket) == 1:
            return None
    except kerberos.GSSError, e:
        log.error("%s: GSSError %s" % (request.remote_addr, e))
        return None
 def extractCredentials( self, request ):
  """ Extract credentials from 'request'.
  """
  creds = {}
  authorization = request._auth
  if authorization:
   try:
    result, context = kerberos.authGSSServerInit("HTTP")
    if result != 1:
     return creds
    gssstring=''
    authstr = authorization.split(" ")[1]
    r=kerberos.authGSSServerStep(context,authstr)   
    if r == 1:
     gssstring=kerberos.authGSSServerResponse(context)
    else:
     # Something went horribly wrong, challenge again!
     self.challenge(request, request.response)
    # Return the status to user's browser - this is like an ack message
    request.response.addHeader('WWW-Authenticate','Negotiate %s' % gssstring)
    username = kerberos.authGSSServerUserName(context)
    creds['login'] = self.deriveUserName(username)
    creds['remote_host'] = request.getClientAddr()
    creds['kerberos'] = True
    # For caching
    request.SESSION.set("__login",creds['login'])
    request.SESSION.set("__remote_host",creds['remote_host'])
    request.SESSION.set("__kerberos",creds['kerberos'])
    kerberos.authGSSServerClean(context)
   except GSSError as e:
    print "GSSAPI error in extractCredentials :"+str(e)
  else:
    # Let's attempt to cache this
    login = request.SESSION.get("__login")
    remote_host = request.SESSION.get("__remote_host")
    kerbeross = request.SESSION.get("__kerberos")
    if login and remote_host and kerbeross and request.getClientAddr() == remote_host:
     creds['login'] = login
     creds['remote_host'] = remote_host
     creds['kerberos'] = kerbeross
  return creds
Esempio n. 39
0
def _gssapi_authenticate(token):
    state = None
    ctx = stack.top
    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            return None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 40
0
def _gssapi_authenticate(token):
    state = None
    ctx = stack.top
    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            return None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            return None
    except kerberos.GSSError:
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 41
0
def _gssapi_authenticate(token, service_name):
    '''
    Performs GSSAPI Negotiate Authentication

    Parameters:
        token (str): GSSAPI Authentication Token
        service_name (str): GSSAPI service name

    Returns:
        tuple of
        (str | None) username
        (str | None) GSSAPI token
    '''
    state = None

    try:
        rc, state = kerberos.authGSSServerInit(service_name)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            log.warn('Unable to initialize server context')
            return None, None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            log.debug('Completed GSSAPI negotiation')
            return (
                kerberos.authGSSServerUserName(state),
                kerberos.authGSSServerResponse(state),
            )
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            log.debug('Continuing GSSAPI negotiation')
            return kerberos.AUTH_GSS_CONTINUE
        else:
            log.info('Unable to step server context')
            return None, None
    except kerberos.GSSError:
        log.info('Unable to authenticate', exc_info=True)
        return None, None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 42
0
def _gssapi_authenticate(token, service_name):
    '''
    Performs GSSAPI Negotiate Authentication

    Parameters:
        token (str): GSSAPI Authentication Token
        service_name (str): GSSAPI service name

    Returns:
        tuple of
        (str | None) username
        (str | None) GSSAPI token
    '''
    state = None

    try:
        rc, state = kerberos.authGSSServerInit(service_name)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            log.warn('Unable to initialize server context')
            return None, None
        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            log.debug('Completed GSSAPI negotiation')
            return (
                kerberos.authGSSServerUserName(state),
                kerberos.authGSSServerResponse(state),
            )
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            log.debug('Continuing GSSAPI negotiation')
            return kerberos.AUTH_GSS_CONTINUE
        else:
            log.info('Unable to step server context')
            return None, None
    except kerberos.GSSError:
        log.info('Unable to authenticate', exc_info=True)
        return None, None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 43
0
def _gssapi_authenticate(token):
    '''
    Performs GSSAPI Negotiate Authentication

    On success also stashes the server response token for mutual authentication
    at the top of request context with the name kerberos_token, along with the
    authenticated user principal with the name kerberos_user.

    @param token: GSSAPI Authentication Token
    @type token: str
    @returns gssapi return code or None on failure
    @rtype: int or None
    '''
    state = None
    ctx = stack.top

    try:
        rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
        if rc != kerberos.AUTH_GSS_COMPLETE:
            print("Authentication error. Could not init server. RC=%s" % rc)
            return None

        rc = kerberos.authGSSServerStep(state, token)
        if rc == kerberos.AUTH_GSS_COMPLETE:
            ctx.kerberos_token = kerberos.authGSSServerResponse(state)
            ctx.kerberos_user = kerberos.authGSSServerUserName(state)
            print("Authenticated user: %s" % ctx.kerberos_user)
            return rc
        elif rc == kerberos.AUTH_GSS_CONTINUE:
            return kerberos.AUTH_GSS_CONTINUE
        else:
            print("Authentication error. RC=%s" % rc)
            return None
    except kerberos.GSSError as exc:
        print("Authentication error: %s" % str(exc))
        return None
    finally:
        if state:
            kerberos.authGSSServerClean(state)
Esempio n. 44
0
 def _doNegotiateAuth(self):
     _ignore_result, context = kerberos.authGSSServerInit("")
     try:
         self._getKerberosDetails()
         kerberos.authGSSServerStep(context, self.authToken)
         targetName = kerberos.authGSSServerTargetName(context)
         if targetName.lower() != self._kerberosPrincipal.lower():
             raise Exception("Target name did not match local principal - %s vs %s" % (targetName, self._kerberosPrincipal))
         response = kerberos.authGSSServerResponse(context)
         principal = kerberos.authGSSServerUserName(context)
         (user, realm) = principal.split("@", 1)
         if realm.lower() != self._kerberosRealm.lower():
             raise Exception("Mismatched realms - %s vs %s" % (realm, self._kerberosRealm))
         self.user = user
         self.page.responseHeaders.append(("WWW-Authenticate", "Negotiate %s" % response))
         print "Did negotiate auth for %s" % self.user
     except:
         print "Failed negotiate auth"
         self.page.offerNegotiate = False
         raise
     finally:
         kerberos.authGSSServerClean(context)
Esempio n. 45
0
def test_gssapi():
    """
    Return Code Values
        0 = Continue
        1 = Complete
        Other = Error
    """
    service = "HTTP@%s" % hostname
    rc, vc = kerberos.authGSSClientInit(service)
    assert rc == 1, "authGSSClientInit = %d, expecting 1" % rc

    rs, vs = kerberos.authGSSServerInit(service)
    assert rs == 1, "authGSSServerInit = %d, expecting 1" % rs

    rc = kerberos.authGSSClientStep(vc, "")
    assert rc == 0, "authGSSClientStep = %d, expecting 0" % rc

    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc))
    assert rs != -1, "authGSSServerStep = %d, not expecting it to be -1" % rs

    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs))
    assert rc != -1, "authGSSClientStep = %d, not expecting it to be -1" % rc

    expected_username = "******" % (username, realm.upper())
    server_user_name = kerberos.authGSSServerUserName(vs)
    assert server_user_name == expected_username, "Invalid server username returned"

    client_user_name = kerberos.authGSSClientUserName(vc)
    assert client_user_name == expected_username, "Invalid client username returned"

    server_target_name = kerberos.authGSSServerTargetName(vs)
    assert server_target_name is None, "Server target name is not None"

    rc = kerberos.authGSSClientClean(vc)
    assert rc == 1, "authGSSClientClean = %d, expecting it to be 0" % rc

    rs = kerberos.authGSSServerClean(vs)
    assert rs == 1, "authGSSServerClean = %d, expecting it to be 0" % rs
Esempio n. 46
0
    def step(self, authorization, request):
        """
        Try to authenticate the client and if succesful authenticate
        ourself to the client.
        """
        user = None

        if not self.enabled():
            return (None, False)

        try:
            (neg, challenge) = authorization.split()
            if neg.lower().strip() != 'negotiate':
                return (None, False)

            self.log.debug("Negotiate header found, trying Kerberos")
            result, context = krb.authGSSServerInit(self.servicename)
            result = krb.authGSSServerStep(context, challenge)

            if result == -1:
                return (None, False)

            response = krb.authGSSServerResponse(context)
            # Client authenticated successfully, so authenticate to the client:
            request.queue_header("www-authenticate",
                                 "negotiate " + response)
            user = krb.authGSSServerUserName(context)

            self.log.debug("Negotiate: found user %s" % user)
            result = krb.authGSSServerClean(context)
            if result != 1:
                self.log.error("Failed to cleanup gss context")
            return (user, True)
        except krb.GSSError as err:
            self.log.error("gssapi error: %s", err)

        return None, False
Esempio n. 47
0
    def auth_negotiate(self, auth_header):
        """
        Manages the Negotiate authorization process with
        kerberos. Returns the gss server response after
        the kerberos negotiation is complete.
        """

        gssstring = None
        user = None
        context = None

        try:
            # Initialize the kerberos auth. This will
            # fail if the entries in the keytab are invalid.
            result, context = kerberos.authGSSServerInit('HTTP@{}'.format(
                settings.SPNEGO_HOSTNAME))
            if result != 1:
                logging.error('Kerberos init failed.')
                raise NotAuthorized

            result = kerberos.authGSSServerStep(context, auth_header)
            if result == 1:
                gssstring = kerberos.authGSSServerResponse(context)
            else:
                # There's something wrong with our session ticket
                # We should've already raised a GSSError
                raise NotAuthorized
            # This will give us the username in <user>@<realm> format
            user = kerberos.authGSSServerUserName(context)
        except kerberos.GSSError as e:
            logging.error("Kerberos error: %s", e)
            raise NotAuthorized
        finally:
            if context:
                kerberos.authGSSServerClean(context)
        return (gssstring, user)
Esempio n. 48
0
    def process_request(self, request):
        """
    The process_request() method needs to communicate some state to the
    process_response() method. The two options for this are to return an
    HttpResponse object or to modify the META headers in the request object. In
    order to ensure that all of the middleware is properly invoked, this code
    currently uses the later approach. The following headers are currently used:

    GSS-String:
      This means that GSS authentication was successful and that we need to pass
      this value for the WWW-Authenticate header in the response.

    Return-401:
      This means that the SPNEGO backend is in use, but we didn't get an
      AUTHORIZATION header from the client. The way that the protocol works
      (http://tools.ietf.org/html/rfc4559) is by having the first response to an
      un-authenticated request be a 401 with the WWW-Authenticate header set to
      Negotiate. This will cause the browser to re-try the request with the
      AUTHORIZATION header set.
    """
        # AuthenticationMiddleware is required so that request.user exists.
        if not hasattr(request, 'user'):
            raise ImproperlyConfigured(
                "The Django remote user auth middleware requires the"
                " authentication middleware to be installed.  Edit your"
                " MIDDLEWARE_CLASSES setting to insert"
                " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
                " before the SpnegoUserMiddleware class.")

        if 'HTTP_AUTHORIZATION' in request.META:
            type, authstr = request.META['HTTP_AUTHORIZATION'].split(' ', 1)

            if type == 'Negotiate':
                try:
                    result, context = kerberos.authGSSServerInit('HTTP')
                    if result != 1:
                        return

                    gssstring = ''
                    r = kerberos.authGSSServerStep(context, authstr)
                    if r == 1:
                        gssstring = kerberos.authGSSServerResponse(context)
                        request.META['GSS-String'] = 'Negotiate %s' % gssstring
                    else:
                        kerberos.authGSSServerClean(context)
                        return

                    username = kerberos.authGSSServerUserName(context)
                    kerberos.authGSSServerClean(context)

                    if request.user.is_authenticated():
                        if request.user.username == self.clean_username(
                                username, request):
                            return

                    user = authenticate(username=username)
                    if user:
                        request.user = user
                        login(request, user)
                    return
                except:
                    LOG.exception(
                        'Unexpected error when authenticating against KDC')
                    return
            else:
                request.META['Return-401'] = ''
                return
        else:
            if not request.user.is_authenticated():
                request.META['Return-401'] = ''
            return
Esempio n. 49
0
    def process_request(self, request):
        """
    The process_request() method needs to communicate some state to the
    process_response() method. The two options for this are to return an
    HttpResponse object or to modify the META headers in the request object. In
    order to ensure that all of the middleware is properly invoked, this code
    currently uses the later approach. The following headers are currently used:

    GSS-String:
      This means that GSS authentication was successful and that we need to pass
      this value for the WWW-Authenticate header in the response.

    Return-401:
      This means that the SPNEGO backend is in use, but we didn't get an
      AUTHORIZATION header from the client. The way that the protocol works
      (http://tools.ietf.org/html/rfc4559) is by having the first response to an
      un-authenticated request be a 401 with the WWW-Authenticate header set to
      Negotiate. This will cause the browser to re-try the request with the
      AUTHORIZATION header set.
    """
        view_func = resolve(request.path)[0]
        if view_func in DJANGO_VIEW_AUTH_WHITELIST:
            return

        # AuthenticationMiddleware is required so that request.user exists.
        if not hasattr(request, 'user'):
            raise exceptions.ImproperlyConfigured(
                "The Django remote user auth middleware requires the"
                " authentication middleware to be installed.  Edit your"
                " MIDDLEWARE_CLASSES setting to insert"
                " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
                " before the SpnegoUserMiddleware class.")

        if 'HTTP_AUTHORIZATION' in request.META:
            type, authstr = request.META['HTTP_AUTHORIZATION'].split(' ', 1)

            if type == 'Negotiate':
                try:
                    result, context = kerberos.authGSSServerInit('HTTP')
                    if result != 1:
                        return

                    gssstring = ''
                    r = kerberos.authGSSServerStep(context, authstr)
                    if r == 1:
                        gssstring = kerberos.authGSSServerResponse(context)
                        request.META['GSS-String'] = 'Negotiate %s' % gssstring
                    else:
                        kerberos.authGSSServerClean(context)
                        return

                    username = kerberos.authGSSServerUserName(context)
                    kerberos.authGSSServerClean(context)

                    # In Trusted knox proxy, Hue must expect following:
                    #   Trusted knox user: KNOX_PRINCIPAL
                    #   Trusted knox proxy host: KNOX_PROXYHOSTS
                    if 'desktop.auth.backend.KnoxSpnegoDjangoBackend' in AUTH.BACKEND.get(
                    ):
                        knox_verification = False
                        principals = self.clean_principal(
                            KNOX.KNOX_PRINCIPAL.get())
                        principal = self.clean_principal(username)
                        if principal.intersection(principals):
                            # This may contain chain of reverse proxies, e.g. knox proxy, hue load balancer
                            # Compare hostname on both HTTP_X_FORWARDED_HOST & KNOX_PROXYHOSTS.
                            # Both of these can be configured to use either hostname or IPs and we have to normalize to one or the other
                            req_hosts = self.clean_host(
                                request.META['HTTP_X_FORWARDED_HOST'])
                            knox_proxy = self.clean_host(
                                KNOX.KNOX_PROXYHOSTS.get())
                            if req_hosts.intersection(knox_proxy):
                                knox_verification = True
                            else:
                                access_warn(
                                    request,
                                    'Failed to verify provided host %s with %s '
                                    % (req_hosts, knox_proxy))
                        else:
                            access_warn(
                                request,
                                'Failed to verify provided username %s with %s '
                                % (principal, principals))
                        # If knox authentication failed then generate 401 (Unauthorized error)
                        if not knox_verification:
                            request.META['Return-401'] = ''
                            return

                    if request.user.is_authenticated:
                        if request.user.username == self.clean_username(
                                username, request):
                            return

                    user = authenticate(username=username, request=request)
                    if user:
                        request.user = user
                        login(request, user)
                        msg = 'Successful login for user: %s' % request.user.username
                    else:
                        msg = 'Failed login for user: %s' % request.user.username
                    request.audit = {
                        'operation': 'USER_LOGIN',
                        'username': request.user.username,
                        'operationText': msg
                    }
                    access_warn(request, msg)
                    return
                except:
                    LOG.exception(
                        'Unexpected error when authenticating against KDC')
                    return
            else:
                request.META['Return-401'] = ''
                return
        else:
            if not request.user.is_authenticated:
                request.META['Return-401'] = ''
            return
Esempio n. 50
0
        def kerberos_authenticate(resource, req, resp, *args, **kwargs):
            # Try pre-emptive authentication
            if not req.auth:
                if optional:
                    req.context["user"] = None
                    return func(resource, req, resp, *args, **kwargs)

                logger.debug(u"No Kerberos ticket offered while attempting to access %s from %s",
                    req.env["PATH_INFO"], req.context.get("remote_addr"))
                raise falcon.HTTPUnauthorized("Unauthorized",
                    "No Kerberos ticket offered, are you sure you've logged in with domain user account?",
                    ["Negotiate"])

            token = ''.join(req.auth.split()[1:])

            try:
                result, context = kerberos.authGSSServerInit("HTTP@" + const.FQDN)
            except kerberos.GSSError as ex:
                # TODO: logger.error
                raise falcon.HTTPForbidden("Forbidden",
                    "Authentication System Failure: %s(%s)" % (ex.args[0][0], ex.args[1][0],))

            try:
                result = kerberos.authGSSServerStep(context, token)
            except kerberos.GSSError as ex:
                kerberos.authGSSServerClean(context)
                logger.error(u"Kerberos authentication failed from %s. "
                    "GSSAPI error: %s (%d), perhaps the clock skew it too large?",
                    req.context.get("remote_addr"),
                    ex.args[0][0], ex.args[0][1])
                raise falcon.HTTPForbidden("Forbidden",
                    "GSSAPI error: %s (%d), perhaps the clock skew it too large?" % (ex.args[0][0], ex.args[0][1]))
            except kerberos.KrbError as ex:
                kerberos.authGSSServerClean(context)
                logger.error(u"Kerberos authentication failed from  %s. "
                    "Kerberos error: %s (%d)",
                    req.context.get("remote_addr"),
                    ex.args[0][0], ex.args[0][1])
                raise falcon.HTTPForbidden("Forbidden",
                    "Kerberos error: %s" % (ex.args[0],))

            user = kerberos.authGSSServerUserName(context)

            if "$@" in user and optional:
                # Extract machine hostname
                # TODO: Assert LDAP group membership
                req.context["machine"], _ = user.lower().split("$@", 1)
                req.context["user"] = None
            else:
                # Attempt to look up real user
                req.context["user"] = User.objects.get(user)

            try:
                kerberos.authGSSServerClean(context)
            except kerberos.GSSError as ex:
                logger.error(u"Kerberos authentication failed for user %s from  %s. "
                    "Authentication system failure: %s (%d)",
                    user, req.context.get("remote_addr"),
                    ex.args[0][0], ex.args[0][1])
                raise falcon.HTTPUnauthorized("Authentication System Failure %s (%s)" % (ex.args[0][0], ex.args[1][0]))

            if result == kerberos.AUTH_GSS_COMPLETE:
                logger.debug(u"Succesfully authenticated user %s for %s from %s",
                    req.context["user"], req.env["PATH_INFO"], req.context["remote_addr"])
                return func(resource, req, resp, *args, **kwargs)
            elif result == kerberos.AUTH_GSS_CONTINUE:
                logger.error(u"Kerberos authentication failed for user %s from  %s. "
                    "Unauthorized, tried GSSAPI.",
                    user, req.context.get("remote_addr"))
                raise falcon.HTTPUnauthorized("Unauthorized", "Tried GSSAPI")
            else:
                logger.error(u"Kerberos authentication failed for user %s from  %s. "
                    "Forbidden, tried GSSAPI.",
                    user, req.context.get("remote_addr"))
                raise falcon.HTTPForbidden("Forbidden", "Tried GSSAPI")
Esempio n. 51
0
  def process_request(self, request):
    """
    The process_request() method needs to communicate some state to the
    process_response() method. The two options for this are to return an
    HttpResponse object or to modify the META headers in the request object. In
    order to ensure that all of the middleware is properly invoked, this code
    currently uses the later approach. The following headers are currently used:

    GSS-String:
      This means that GSS authentication was successful and that we need to pass
      this value for the WWW-Authenticate header in the response.

    Return-401:
      This means that the SPNEGO backend is in use, but we didn't get an
      AUTHORIZATION header from the client. The way that the protocol works
      (http://tools.ietf.org/html/rfc4559) is by having the first response to an
      un-authenticated request be a 401 with the WWW-Authenticate header set to
      Negotiate. This will cause the browser to re-try the request with the
      AUTHORIZATION header set.
    """
    # AuthenticationMiddleware is required so that request.user exists.
    if not hasattr(request, 'user'):
      raise ImproperlyConfigured(
        "The Django remote user auth middleware requires the"
        " authentication middleware to be installed.  Edit your"
        " MIDDLEWARE_CLASSES setting to insert"
        " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
        " before the SpnegoUserMiddleware class.")

    if 'HTTP_AUTHORIZATION' in request.META:
      type, authstr = request.META['HTTP_AUTHORIZATION'].split(' ', 1)

      if type == 'Negotiate':
        try:
          result, context = kerberos.authGSSServerInit('HTTP')
          if result != 1:
            return

          gssstring=''
          r=kerberos.authGSSServerStep(context,authstr)
          if r == 1:
            gssstring=kerberos.authGSSServerResponse(context)
            request.META['GSS-String'] = 'Negotiate %s' % gssstring
          else:
            kerberos.authGSSServerClean(context)
            return

          username = kerberos.authGSSServerUserName(context)
          kerberos.authGSSServerClean(context)

          if request.user.is_authenticated():
            if request.user.username == self.clean_username(username, request):
              return

          user = authenticate(username=username)
          if user:
            request.user = user
            login(request, user)
          return
        except:
          LOG.exception('Unexpected error when authenticating against KDC')
          return
      else:
        request.META['Return-401'] = ''
        return
    else:
      if not request.user.is_authenticated():
        request.META['Return-401'] = ''
      return