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
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)
Exemple #3
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 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)
Exemple #5
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()
Exemple #6
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)
    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)
Exemple #8
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()
Exemple #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)
Exemple #10
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)
Exemple #11
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
Exemple #12
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))
Exemple #13
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)
Exemple #14
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
Exemple #16
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:
        if not kerberos.authGSSServerStep(context, ticket) == 1:
            return None
    except kerberos.GSSError, e:
        log.error("%s: GSSError %s" % (request.remote_addr, e))
        return None
Exemple #17
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)
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)
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)
Exemple #20
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)
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)
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)
Exemple #23
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
Exemple #24
0
    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).split("@")[0]
                self.log.info("Extracted User = "******"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)
Exemple #25
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
Exemple #26
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:
            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)
Exemple #27
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)
Exemple #28
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"))
     self.set_header('WWW-Authenticate', "Negotiate %s" % gssstring)
     kerberos.authGSSServerClean(context)
     callback(user)
Exemple #29
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
Exemple #30
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")
Exemple #31
0
 def step(self, challenge):
     return kerberos.authGSSServerStep(self.context, challenge)
Exemple #32
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
Exemple #33
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