def _acquire_creds(self, username, password): # 3 use cases with Kerberos Auth # 1. Both the user and pass is supplied so we want to create a new # ticket with the pass # 2. Only the user is supplied so we will attempt to get the cred # from the existing store # 3. The user is not supplied so we will attempt to get the default # cred from the existing store log.info("GSSAPI: Acquiring credentials handle") if username and password: log.debug("GSSAPI: Acquiring credentials handle for user %s with " "password" % username) user = gssapi.Name(base=username, name_type=gssapi.NameType.user) bpass = password.encode('utf-8') try: creds = gssapi.raw.acquire_cred_with_password(user, bpass, usage='initiate') except AttributeError: raise SMBAuthenticationError("Cannot get GSSAPI credential " "with password as the necessary " "GSSAPI extensions are not " "available") except gssapi.exceptions.GSSError as er: raise SMBAuthenticationError("Failed to acquire GSSAPI " "credential with password: %s" % str(er)) # acquire_cred_with_password returns a wrapper, we want the creds # object inside this wrapper creds = creds.creds elif username: log.debug("GSSAPI: Acquiring credentials handle for user %s from " "existing cache" % username) user = gssapi.Name(base=username, name_type=gssapi.NameType.user) try: creds = gssapi.Credentials(name=user, usage='initiate') except gssapi.exceptions.MissingCredentialsError as er: raise SMBAuthenticationError("Failed to acquire GSSAPI " "credential for user %s from the " "exisiting cache: %s" % (str(user), str(er))) else: log.debug("GSSAPI: Acquiring credentials handle for default user " "in cache") try: creds = gssapi.Credentials(name=None, usage='initiate') except gssapi.exceptions.GSSError as er: raise SMBAuthenticationError("Failed to acquire default " "GSSAPI credential from the " "existing cache: %s" % str(er)) user = creds.name log.info("GSSAPI: Acquired credentials for user %s" % str(user)) return creds
def _gssapi_check(self): environ = request.environ if environ["wsgi.multithread"]: abort( 400, "GSSAPI is not compatible with multi-threaded WSGI servers.", ) ccache = environ.get("KRB5CCNAME") if not ccache: abort(400, "KRB5CCNAME missing.") raise ValueError("KRB5CCNAME missing") principal = environ.get("GSS_NAME") if not principal: abort(400, "GSS_NAME missing.") gss_name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) try: creds = gssapi.Credentials(usage="initiate", name=gss_name, store={"ccache": ccache}) except gssapi.exceptions.GSSError as e: abort(403, f"Invalid credentials {e}") else: if creds.lifetime <= 0: abort(401, "Credential lifetime has expired.")
def get_auth_info(self, use_cookie=True): """ Two things can happen here. If we have a session we will add a cookie for that. If not we will set an Authorization header. """ if not isinstance(self._extra_headers, list): self._extra_headers = [] # Remove any existing Cookie first self._remove_extra_header('Cookie') if use_cookie: session_cookie = getattr(context, 'session_cookie', None) if session_cookie: self._extra_headers.append(('Cookie', session_cookie)) return # Set the remote host principal host = self._get_host() service = self.service + "@" + host.split(':')[0] try: creds = None if self.ccache: creds = gssapi.Credentials(usage='initiate', store={'ccache': self.ccache}) name = gssapi.Name(service, gssapi.NameType.hostbased_service) self._sec_context = gssapi.SecurityContext(creds=creds, name=name, flags=self.flags) response = self._sec_context.step() except gssapi.exceptions.GSSError as e: self._handle_exception(e, service=service) self._set_auth_header(response)
def start(self): response = self.strategy.html('Authorization Required') response.status_code = 401 response['WWW-Authenticate'] = 'Negotiate' # browser didn't send negotiation token if 'HTTP_AUTHORIZATION' not in self.strategy.request.META: # this will keep a reference to the current user b/c # kerberos auth is a stateful protocol while HTTP is stateless. context_id = "%d@%d" % (hash(repr( self.strategy.request.META)), id(self.strategy.request)) self.strategy.request.session['_krb5'] = context_id self._krb5[context_id] = None return response token = self.strategy.request.META['HTTP_AUTHORIZATION'] token = token.split('Negotiate')[-1].strip() token = base64.b64decode(token) context_id = self.strategy.request.session.get('_krb5', None) if self._krb5[context_id] is None: keytab_path = self.strategy.setting('SOCIAL_AUTH_KRB5_KEYTAB') creds = gssapi.Credentials(usage='accept', store={'keytab': keytab_path}) self._krb5[context_id] = gssapi.SecurityContext(creds=creds) server_token = self._krb5[context_id].step(token) response = self.strategy.redirect(self.redirect_uri) if server_token is not None: server_token_hex = base64.b64encode(server_token).decode() response['WWW-Authenticate'] = 'Negotiate %s' % server_token_hex return response
def init_creds(self): name = gssapi.Name(self.client_service, gssapi.NameType.hostbased_service) store = {'client_keytab': self.keytab, 'ccache': 'MEMORY:Custodia_%s' % b64encode( os.urandom(8)).decode('ascii')} return gssapi.Credentials(name=name, store=store, usage='initiate')
def negotiate(request, name=None, store=None): '''Try to authenticate the user using SPNEGO and Kerberos''' if name: logger.debug(u'GSSAPI negotiate using name %s', name) try: server_creds = gssapi.Credentials(usage='accept', name=name, store=store) except gssapi.exceptions.GSSError as e: logging.debug('GSSAPI credentials failure: %s', e) return None, None if not request.META.get('HTTP_AUTHORIZATION', '').startswith('Negotiate '): return None, None authstr = request.META['HTTP_AUTHORIZATION'][10:] try: in_token = base64.b64decode(authstr) except (TypeError, ValueError): return None, None server_ctx = gssapi.SecurityContext(creds=server_creds, usage='accept') try: out_token = server_ctx.step(in_token) except gssapi.exceptions.GSSError as e: logging.debug('GSSAPI security context failure: %s', e) return None, None if not server_ctx.complete: raise NegotiateContinue(out_token) return server_ctx.initiator_name, out_token
def generate_request_header(self, response, host, is_preemptive=False): # This method needs to be shimmed because `host` isn't exposed to # __init__() and we need to derive things from it. Also, __init__() # can't fail, in the strictest compatability sense. try: if self.principal is not None: gss_stage = "acquiring credentials" name = gssapi.Name(self.principal, gssapi.NameType.hostbased_service) self.creds = gssapi.Credentials(name=name, usage="initiate") # contexts still need to be stored by host, but hostname_override # allows use of an arbitrary hostname for the GSSAPI exchange (eg, # in cases of aliased hosts, internal vs external, CNAMEs w/ # name-based HTTP hosting) if self.service is not None: gss_stage = "initiating context" kerb_host = host if self.hostname_override: kerb_host = self.hostname_override kerb_spn = "{0}@{1}".format(self.service, kerb_host) self.target_name = gssapi.Name( kerb_spn, gssapi.NameType.hostbased_service) return HTTPSPNEGOAuth.generate_request_header( self, response, host, is_preemptive) except gssapi.exceptions.GSSError as error: msg = error.gen_message() log.exception( "generate_request_header(): {0} failed:".format(gss_stage)) log.exception(msg) raise SPNEGOExchangeError("%s failed: %s" % (gss_stage, msg))
def authenticate(self, request): if request.method == 'OPTIONS': return authorization = request.META.get('HTTP_AUTHORIZATION', '') if authorization.startswith('Negotiate '): host = socket.gethostbyaddr(request.META['SERVER_ADDR'])[0] service_name = 'HTTP/{}'.format(host) service_name = gssapi.Name(service_name) # The browser is authenticating using GSSAPI, trim off 'Negotiate ' and decode: in_token = base64.b64decode(authorization[10:]) server_creds = gssapi.Credentials(name=service_name, usage='accept') ctx = gssapi.SecurityContext(creds=server_creds) # Feed the input token to the context, and get an output token in return out_token = ctx.step(in_token) if out_token: request.negotiate_token = base64.b64encode(out_token).decode() if ctx.complete: name = str(ctx.initiator_name) User = get_user_model() user = User.objects.get(**{self.principal_name_field: name}) return user, None else: raise HTTPUnauthorized
def __init__(self, app, ccname): self.app = app self.ccname = ccname self.creds = gssapi.Credentials( usage='initiate', store={'ccache': ccname} )
def test_explicit_creds(patched_creds, patched_ctx): response = null_response(headers=neg_token) creds = gssapi.Credentials() auth = httpx_gssapi.HTTPSPNEGOAuth(creds=creds) auth.generate_request_header(response.url.host, response) check_init(creds=b"fake creds") fake_resp.assert_called_with(b"token")
def get_credentials(name=None, ccache_name=None): ''' Obtains GSSAPI credentials with given principal name from ccache. When no principal name specified, it retrieves the default one for given credentials cache. :parameters: name gssapi.Name object specifying principal or None for the default ccache_name string specifying Kerberos credentials cache name or None for the default :returns: gssapi.Credentials object ''' store = None if ccache_name: store = {'ccache': ccache_name} try: return gssapi.Credentials(usage='initiate', name=name, store=store) except gssapi.exceptions.GSSError as e: if e.min_code in ( # pylint: disable=no-member KRB5_FCC_NOFILE, GSSPROXY_KRB5_FCC_NOFILE, KRB5_CC_NOTFOUND, ): raise ValueError('"%s", ccache="%s"' % (e, ccache_name)) raise
def use_api_as_principal(principal, keytab): with ipautil.private_ccache() as ccache_file: try: old_principal = getattr(context, "principal", None) name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {"ccache": ccache_file, "client_keytab": keytab} gssapi.Credentials(name=name, usage="initiate", store=store) # Finalize API when TGT obtained using host keytab exists if not api.isdone("finalize"): api.finalize() # Now we have a TGT, connect to IPA try: if api.Backend.rpcclient.isconnected(): api.Backend.rpcclient.disconnect() api.Backend.rpcclient.connect() yield except gssapi.exceptions.GSSError as e: raise Exception( "Unable to bind to IPA server. Error initializing " "principal %s in %s: %s" % (principal, keytab, str(e))) finally: if api.Backend.rpcclient.isconnected(): api.Backend.rpcclient.disconnect() setattr(context, "principal", old_principal)
def _get_security_context(name_type, mech, spn, username, password, delegate, wrap_required, channel_bindings=None): if username is not None: username = gssapi.Name(base=username, name_type=name_type) server_name = gssapi.Name(spn, name_type=gssapi.NameType.hostbased_service) # first try and get the cred from the existing cache, if that fails # then get a new ticket with the password (if specified). The cache # can only be used for Kerberos, NTLM/SPNEGO must have acquire the # cred with a pass cred = None kerb_oid = GSSAPIContext._AUTH_PROVIDERS['kerberos'] kerb_mech = gssapi.OID.from_int_seq(kerb_oid) if mech == kerb_mech: try: cred = gssapi.Credentials(name=username, usage='initiate', mechs=[mech]) except gssapi.exceptions.GSSError as err: # we can't acquire the cred if no password was supplied if password is None: raise err pass elif username is None or password is None: raise ValueError("Can only use implicit credentials with kerberos " "authentication") if cred is None: # error when trying to access the existing cache, get our own # credentials with the password specified b_password = to_bytes(password) cred = gssapi.raw.acquire_cred_with_password(username, b_password, usage='initiate', mechs=[mech]) cred = cred.creds flags = gssapi.RequirementFlag.mutual_authentication | \ gssapi.RequirementFlag.out_of_sequence_detection if delegate: flags |= gssapi.RequirementFlag.delegate_to_peer if wrap_required: flags |= gssapi.RequirementFlag.confidentiality context = gssapi.SecurityContext(name=server_name, creds=cred, usage='initiate', mech=mech, flags=flags, channel_bindings=channel_bindings) return context
def initiate_security_context(self): log.debug('Initialize security context for %s', self.canonical_name) credentials = gssapi.Credentials(name=self.name, usage='initiate', store=self.store) return gssapi.SecurityContext(name=self.name, usage='initiate', creds=credentials)
def _login_gssapi(self): """Login using kerberos credentials (uses gssapi).""" login_url = urlparse.urljoin(self._hub_url, "auth/krb5login/") # read default values from settings principal = self._conf.get("KRB_PRINCIPAL") keytab = self._conf.get("KRB_KEYTAB") service = self._conf.get("KRB_SERVICE") realm = self._conf.get("KRB_REALM") ccache = self._conf.get("KRB_CCACHE") import requests import gssapi import requests_gssapi request_args = {} # NOTE behavior difference from hub proxy overall: # HubProxy by default DOES NOT verify https connections :( # See the constructor. It could be repeated here by defaulting verify to False, # but let's not do that, instead you must have an unbroken SSL setup to # use this auth method. if self._conf.get("CA_CERT"): request_args["verify"] = self._conf["CA_CERT"] server_name = self.get_server_principal(service=service, realm=realm) server_name = gssapi.Name(server_name, gssapi.NameType.kerberos_principal) auth_args = { "target_name": server_name, } if principal is not None: if keytab is None: raise ImproperlyConfigured( "Cannot specify a principal without a keytab") name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {"client_keytab": keytab} if ccache is not None: store["ccache"] = "FILE:" + ccache auth_args["creds"] = gssapi.Credentials(name=name, store=store, usage="initiate") # We only do one request, but a Session is used to allow requests to write # the new session ID into the cookiejar. with requests.Session() as s: s.cookies = self._transport.cookiejar response = s.get(login_url, auth=requests_gssapi.HTTPSPNEGOAuth(**auth_args), allow_redirects=False, **request_args) self._logger and self._logger.debug("Login response: %s %s", response, response.headers) response.raise_for_status()
def _get_kerberos_principal(): """ Use gssapi to get the current kerberos principal. This will be used as the requester for some tools when creating tickets. :return: The kerberos principal. """ try: return str(gssapi.Credentials(usage='initiate').name).lower() except gssapi.raw.misc.GSSError: return None
def get_user_from_credentials(): """Get user from credentials without realm.""" try: creds = gssapi.Credentials(usage="initiate") user = str(creds.name) if user.find("@") != -1: user, _ = user.split("@", 1) return user except gssapi.raw.misc.GSSError as err: return getpass.getuser()
def generate_request_header(self, response, host, is_preemptive=False): """ Generates the GSSAPI authentication token with kerberos. If any GSSAPI step fails, raise KerberosExchangeError with failure detail. """ gssflags = [ gssapi.RequirementFlag.mutual_authentication, gssapi.RequirementFlag.out_of_sequence_detection ] if self.delegate: gssflags.append(gssapi.RequirementFlag.delegate_to_peer) try: # contexts still need to be stored by host, but hostname_override # allows use of an arbitrary hostname for the GSSAPI exchange # (eg, in cases of aliased hosts, internal vs external, CNAMEs # w/ name-based HTTP hosting) kerb_host = host if self.hostname_override: kerb_host = self.hostname_override kerb_spn = "{0}@{1}".format(self.service, kerb_host) creds = None if self.principal: gss_stage = "acquiring credentials" creds = gssapi.Credentials(name=gssapi.Name(self.principal), usage="initiate") gss_stage = "initiating context" self.context[host] = gssapi.SecurityContext( usage="initiate", flags=gssflags, name=gssapi.Name(kerb_spn), creds=creds) gss_stage = "stepping context" if is_preemptive: gss_response = self.context[host].step() else: gss_response = self.context[host].step( _negotiate_value(response)) return "Negotiate {0}".format(gss_response) except gssapi.exceptions.GSSError as error: msg = error.gen_message() log.exception( "generate_request_header(): {0} failed:".format(gss_stage)) log.exception(msg) raise KerberosExchangeError("%s failed: %s" % (gss_stage, msg))
def get_context(self, host): service_name = gssapi.Name(self.service_name or '{0}@{1}'.format(self.service, host), gssapi.NameType.hostbased_service) logging.debug("get_context(): service name={0}".format(service_name)) if self.negotiate_client_name: creds = gssapi.Credentials(name=gssapi.Name(self.negotiate_client_name), usage='initiate') else: creds = None return gssapi.SecurityContext(name=service_name, creds=creds)
def sasl_gssapi(connection, controls): """ Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism from RFC 4752. Does not support any security layers, only authentication! sasl_credentials can be empty or a 1-element tuple with the requested target_name or the True value to request the target_name from DNS """ if connection.sasl_credentials and len(connection.sasl_credentials) == 1 and connection.sasl_credentials[0]: if connection.sasl_credentials[0] is True: hostname = socket.gethostbyaddr(connection.socket.getpeername()[0])[0] target_name = gssapi.Name('ldap@' + hostname, gssapi.NameType.hostbased_service) else: target_name = gssapi.Name('ldap@' + connection.sasl_credentials[0], gssapi.NameType.hostbased_service) else: target_name = gssapi.Name('ldap@' + connection.server.host, gssapi.NameType.hostbased_service) creds = gssapi.Credentials(name=gssapi.Name(connection.user), usage='initiate') if connection.user else None ctx = gssapi.SecurityContext(name=target_name, mech=gssapi.MechType.kerberos, creds=creds) in_token = None try: while True: out_token = ctx.step(in_token) if out_token is None: out_token = '' result = send_sasl_negotiation(connection, controls, out_token) in_token = result['saslCreds'] try: # This raised an exception in gssapi<1.1.2 if the context was # incomplete, but was fixed in # https://github.com/pythongssapi/python-gssapi/pull/70 if ctx.complete: break except gssapi.exceptions.MissingContextError: pass unwrapped_token = ctx.unwrap(in_token) if len(unwrapped_token.message) != 4: raise LDAPCommunicationError("Incorrect response from server") server_security_layers = unwrapped_token.message[0] if not isinstance(server_security_layers, int): server_security_layers = ord(server_security_layers) if server_security_layers in (0, NO_SECURITY_LAYER): if unwrapped_token.message[1:] != '\x00\x00\x00': raise LDAPCommunicationError("Server max buffer size must be 0 if no security layer") if not (server_security_layers & NO_SECURITY_LAYER): raise LDAPCommunicationError("Server requires a security layer, but this is not implemented") client_security_layers = bytearray([NO_SECURITY_LAYER, 0, 0, 0]) out_token = ctx.wrap(bytes(client_security_layers), False) return send_sasl_negotiation(connection, controls, out_token.message) except (gssapi.exceptions.GSSError, LDAPCommunicationError): abort_sasl_negotiation(connection, controls) raise
def initial_step(self, request, response=None): if self.context is None: store = {'ccache': self.ccache_name} creds = gssapi.Credentials(usage='initiate', store=store) name = gssapi.Name('HTTP@{0}'.format(self.target_host), name_type=gssapi.NameType.hostbased_service) self.context = gssapi.SecurityContext(creds=creds, name=name, usage='initiate') in_token = self._get_negotiate_token(response) out_token = self.context.step(in_token) self._set_authz_header(request, out_token)
def _get_creds(self): if self.principal is None: return None name = gssapi.Name(self.principal, gssapi.NameType.kerberos_principal) try: creds = gssapi.Credentials(name=name, usage="initiate") except gssapi.exceptions.GSSError as e: raise ClientError("Authentication failed", errno.EPROTO, data={"exc": e}) if creds.lifetime <= 0: raise ClientError("Authentication expired", errno.EPROTO) return creds
def _common_determine_authz_id_and_creds(connection): """ Given our connection, figure out the authorization id (i.e. the kerberos principal) and kerberos credentials being used for our SASL bind. On posix systems, we can actively negotiate with raw credentials and receive a kerberos client ticket during our SASL bind. So credentials can be specified. However, on windows systems, winkerberos expects to use the credentials cached by the system because windows machines are generally domain-joined. So no initiation is supported, as the TGT must already be valid prior to beginning the SASL bind, and the windows system credentials will be used as needed with that. """ authz_id = b"" creds = None # the default value for credentials is only something we should instantiate on systems using the # posix GSSAPI, as windows kerberos expects that a tgt already exists (i.e. the machine is domain-joined) # and does not support initiation from raw credentials if not posix_gssapi_unavailable: creds = gssapi.Credentials( name=gssapi.Name(connection.user), usage='initiate', store=connection.cred_store) if connection.user else None if connection.sasl_credentials: if len(connection.sasl_credentials ) >= 2 and connection.sasl_credentials[1]: authz_id = connection.sasl_credentials[1].encode("utf-8") if len(connection.sasl_credentials ) >= 3 and connection.sasl_credentials[2]: if posix_gssapi_unavailable: raise LDAPPackageUnavailableError( 'The winkerberos package does not support specifying raw credentials' 'to initiate GSSAPI Kerberos communication. A ticket granting ticket ' 'must have already been obtained for the user before beginning a ' 'SASL bind.') raw_creds = connection.sasl_credentials[2] creds = gssapi.Credentials(base=raw_creds, usage='initiate', store=connection.cred_store) return authz_id, creds
def test_explicit_creds(self): with patch.multiple("gssapi.Credentials", __new__=fake_creds), \ patch.multiple("gssapi.SecurityContext", __init__=fake_init, step=fake_resp): response = requests.Response() response.url = "http://www.example.org/" response.headers = {'www-authenticate': b64_negotiate_token} host = urlparse(response.url).hostname creds = gssapi.Credentials() auth = requests_gssapi.HTTPSPNEGOAuth(creds=creds) auth.generate_request_header(response, host) fake_init.assert_called_with( name=gssapi_name("*****@*****.**"), usage="initiate", flags=gssflags, creds=b"fake creds") fake_resp.assert_called_with(b"token")
def kerberos_validate_ticket(): """ Return the kerberos ticket lifetime left after getting the ticket from the credential cache """ import gssapi try: del_creds = gssapi.Credentials(store={'ccache': session['KRB5CCNAME']}) creds = del_creds.acquire(store={'ccache': session['KRB5CCNAME']}) except Exception as e: current_app.logger.exception(e) return internal_server_error(errormsg=str(e)) return make_json_response(data={'ticket_lifetime': creds.lifetime}, status=200)
def init_app(self, app): """ Initialises the Negotiate extension for the given application. """ if not hasattr(app, 'extensions'): app.extensions = {} service_name = app.config.get('GSSAPI_SERVICE_NAME', 'HTTP') name = app.config.get('GSSAPI_HOSTNAME', socket.getfqdn()) if name is not None: principal = '{}@{}'.format(service_name, name) name = gssapi.Name(principal, gssapi.NameType.hostbased_service) app.extensions['gssapi'] = { 'creds': gssapi.Credentials(name=name, usage='accept'), }
def start(self, connection): try: if self.client_name: creds = gssapi.Credentials( name=gssapi.Name(self.client_name)) else: creds = None hostname = self.get_hostname(connection) name = gssapi.Name(b'@'.join([self.service, hostname]), gssapi.NameType.hostbased_service) context = gssapi.SecurityContext(name=name, creds=creds) return context.step(None) except gssapi.raw.misc.GSSError: if self.fail_soft: return NotImplemented else: raise
def kinit_keytab(principal, keytab, ccache_name, config): """ Perform kinit using principal/keytab, with the specified config file and store the TGT in ccache_name. """ old_config = os.environ.get('KRB5_CONFIG') os.environ['KRB5_CONFIG'] = config try: name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {'ccache': ccache_name, 'client_keytab': keytab} cred = gssapi.Credentials(name=name, store=store, usage='initiate') return cred finally: if old_config is not None: os.environ['KRB5_CONFIG'] = old_config else: os.environ.pop('KRB5_CONFIG', None)
def use_keytab(principal, keytab): try: tmpdir = tempfile.mkdtemp(prefix = "tmp-") ccache_file = 'FILE:%s/ccache' % tmpdir name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {'ccache': ccache_file, 'client_keytab': keytab} os.environ['KRB5CCNAME'] = ccache_file gssapi.Credentials(name=name, usage='initiate', store=store) conn = ldap2(api) conn.connect(autobind=ipaldap.AUTOBIND_DISABLED) conn.disconnect() except gssapi.exceptions.GSSError as e: raise Exception('Unable to bind to LDAP. Error initializing principal %s in %s: %s' % (principal, keytab, str(e))) finally: os.environ.pop('KRB5CCNAME', None) if tmpdir: shutil.rmtree(tmpdir)
def use_keytab(principal, keytab): with private_ccache() as ccache_file: try: old_principal = getattr(context, 'principal', None) name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {'ccache': ccache_file, 'client_keytab': keytab} gssapi.Credentials(name=name, usage='initiate', store=store) conn = ldap2(api) conn.connect(ccache=ccache_file, autobind=ipaldap.AUTOBIND_DISABLED) yield conn conn.disconnect() except gssapi.exceptions.GSSError as e: raise Exception('Unable to bind to LDAP. Error initializing ' 'principal %s in %s: %s' % (principal, keytab, str(e))) finally: setattr(context, 'principal', old_principal)