def _auth_header(self): if not self.creds or self.creds.lifetime < 300: self.creds = self.init_creds() ctx = gssapi.SecurityContext(name=self.service_name, creds=self.creds) authtok = ctx.step() return {'Authorization': 'Negotiate %s' % b64encode( authtok).decode('ascii')}
def get_host_info(self, host): """ 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. """ (host, extra_headers, x509) = SSLTransport.get_host_info(self, host) if not isinstance(extra_headers, list): extra_headers = [] session_cookie = getattr(context, 'session_cookie', None) if session_cookie: extra_headers.append(('Cookie', session_cookie)) return (host, extra_headers, x509) # Set the remote host principal service = "HTTP@" + host.split(':')[0] try: name = gssapi.Name(service, gssapi.NameType.hostbased_service) self._sec_context = gssapi.SecurityContext(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(extra_headers, response) return (host, extra_headers, x509)
def process_gssapi_request(token): if current_app.config['KERBEROS_HTTP_HOST']: hostname = current_app.config['KERBEROS_HTTP_HOST'] else: hostname = gethostname() service_name = gssapi.Name("HTTP@%s" % hostname, gssapi.NameType.hostbased_service) try: stage = "initialize server context" sc = gssapi.SecurityContext(usage="accept") stage = "step context" token = sc.step(token if token != "" else None) token = token if token is not None else "" # The current architecture cannot support continuation here stage = "checking completion" if not sc.complete: current_app.logger.error( 'Multiple GSSAPI round trips not supported') raise Forbidden("Attempted multiple GSSAPI round trips") current_app.logger.debug('Completed GSSAPI negotiation') stage = "getting remote user" user = str(sc.initiator_name) return user, token except gssapi.exceptions.GSSError as e: current_app.logger.error('Unable to authenticate: failed to %s: %s' % (stage, e.gen_msg())) raise Forbidden("Authentication failed")
def get(self, path): """ Perform a GET request with GSSAPI authentication """ # Generate token service_name = gssapi.Name('HTTP@{0}'.format(self.url.netloc), gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(usage="initiate", name=service_name) data = b64encode(ctx.step()).decode() # Make the connection connection = httplib.HTTPSConnection(self.url.netloc, 443) log.debug("GET {0}".format(path)) connection.putrequest("GET", path) connection.putheader("Authorization", "Negotiate {0}".format(data)) connection.putheader("Referer", self.url_string) connection.endheaders() # Perform the request, convert response into lines response = connection.getresponse() if response.status != 200: raise ReportError( "Failed to fetch tickets: {0}".format(response.status)) lines = response.read().decode("utf8").strip().split("\n")[1:] log.debug("Tickets fetched:") log.debug(pretty(lines)) return lines
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 connect(self): """Connect and authenticate to the server.""" self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = (self.host, self.port) self.sock.connect(server_address) self.stream = self.sock.makefile(mode='rwb') service_name = gssapi.Name(self.service_name, name_type=gssapi.NameType.hostbased_service) self.ctx = gssapi.SecurityContext(name=service_name, usage='initiate') in_token = None while not self.ctx.complete: out_token = self.ctx.step(in_token) if out_token: out_encoded = base64.standard_b64encode(out_token) self._write_line(out_encoded) if self.ctx.complete: break in_encoded = self._read_line() in_token = base64.standard_b64decode(in_encoded) if not in_token: raise GSSError('No response from server.') _LOGGER.debug('Successfully authenticated.') return True
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 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 __gsshandler(self, token): if token == "": token = None try: if not self.gss_vc: name = gssapi.Name('imap@' + self.hostname, gssapi.NameType.hostbased_service) self.gss_vc = gssapi.SecurityContext(usage="initiate", name=name) if not self.gss_vc.complete: response = self.gss_vc.step(token) return response if response else "" # Don't bother checking qop because we're over a TLS channel # already. But hey, if some server started encrypting tomorrow, # we'd be ready since krb5 always requests integrity and # confidentiality support. response = self.gss_vc.unwrap(token) response = self.gss_vc.wrap(response.message, response.encrypted) return response.message if response.message else "" except gssapi.exceptions.GSSError as err: # GSSAPI errored out on us; respond with None to cancel the # authentication self.ui.debug('imap', err.gen_message()) return None
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 handle(self, src, addr): data = b'' while True: data += src.recv(1024) if b'\r\n\r\n' in data: break service = gssapi.Name('HTTP@%s' % self.upstream[0], gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(name=service, usage='initiate') token = ctx.step() b64token = base64.b64encode(token).encode('ascii') headers, data = data.split(b'\r\n\r\n', 1) headers = headers.split('\r\n') replaced = False for i, header in enumerate(headers): if header.startswith('Proxy-Authorization:'): headers[i] = b'Proxy-Authorization: Negotiate %s' % b64token replaced = True break if not replaced: headers.append(b'Proxy-Authorization: Negotiate %s' % b64token) dst = create_connection(self.upstream) dst.sendall(b'\r\n'.join(headers) + b'\r\n\r\n' + data) forwarders = (gevent.spawn(forward, src, dst), gevent.spawn(forward, dst, src)) gevent.joinall(forwarders)
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 init_cred(self, call, target="nfs@jupiter", source=None, oid=None): # STUB - need intelligent way to set defaults good_major = [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED] p = Packer() up = GSSUnpacker('') # Set target (of form nfs@SERVER) target = gssapi.Name(target, gssapi.NameType.hostbased_service) # Set source (of form USERNAME) if source is not None: source = gssapi.Name(source, gssapi.NT_USER_NAME) gss_cred = gssapi.Credential(gssapi.INITIATE, source.ptr) # XXX else: # Just use default cred gss_cred = None # RFC2203 5.2.2. Context Creation Requests # When GSS_Init_sec_context() is called, the parameters # replay_det_req_flag and sequence_req_flag must be turned off. # Note - by default, out_of_sequence_detection flag (sequence_req_flag) is used by gssapi.init_sec_context() # and we have 'An expected per-message token was not received' error (GSS_S_GAP_TOKEN). # To prevent this, we need to use default flags without out_of_sequence_detection bit. flags = gssapi.IntEnumFlagSet( gssapi.RequirementFlag, [gssapi.RequirementFlag.mutual_authentication]) context = gssapi.SecurityContext(name=target, creds=gss_cred, flags=flags) input_token = None handle = b'' proc = RPCSEC_GSS_INIT while not context.complete: # Call initSecContext. If it returns COMPLETE, we are done. # If it returns CONTINUE_NEEDED, we must send d['token'] # to the target, which will run it through acceptSecContext, # and give us back a token we need to send through initSecContext. # Repeat as necessary. output_token = context.step(input_token) if context.complete: # XXX if res.major == CONTINUE there is a bug in library code # STUB - now what? Just use context? # XXX need to use res.seq_window # XXX - what if handle still '' ? self._add_context(context, handle) break # Send token to target using protocol of RFC 2203 sect 5.2.2 credinfo = CredInfo(self, context=handle, gss_proc=proc) proc = RPCSEC_GSS_CONTINUE_INIT p.reset() p.pack_opaque(output_token) header, reply = call(p.get_buffer(), credinfo) up.reset(reply) res = up.unpack_rpc_gss_init_res() up.done() # res now holds relevent output from target's acceptSecContext call if res.gss_major not in good_major: raise GSSError(res.gss_major, res.gss_minor) handle = res.handle # Should not change between calls input_token = res.gss_token # This needs to be sent to SecurityContext.step() return CredInfo(self, context=handle)
def __init__(self, hostname, service="WSMAN"): spn=service+"/"+hostname gss_spn = gssapi.Name(spn, name_type=gssapi.NameType.kerberos_principal) self._ctx = gssapi.SecurityContext(name=gss_spn) self.token = "".join(base64.encodestring(self._ctx.step()).split("\n"))
def spnego(): service_name = gssapi.Name(k5realm.http_princ) service_name.canonicalize(gssapi.MechType.kerberos) # first attempt ctx = gssapi.SecurityContext(usage='initiate', name=service_name) return 'Negotiate %s' % base64.b64encode( ctx.step()).decode('ascii')
def _have_gssapi_ctx(self): assert (self.name is not None) if self.gctx is None: self.gctx = gssapi.SecurityContext(name=self.name, usage='initiate') assert (self.gctx is not None) self.gctx.__DEFER_STEP_ERRORS__ = False return self.gctx
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 netcat(host, port, proxy_host, proxy_port): request = [('CONNECT %s:%d HTTP/1.1' % (host, port)).encode('ascii')] request.append(('Host: %s:%d' % (host, port)).encode('ascii')) request.append(('Proxy-Connection: Keep-Alive').encode('ascii')) request.append(('\r\n').encode('ascii')) dst = create_connection((proxy_host, proxy_port)) dst.sendall(b'\r\n'.join(request)) data = b'' while True: data += dst.recv(1024) if b'\r\n\r\n' in data: break if b'200 Connection established' not in data and b'407' in data: if sys.platform == "win32": status, ctx = winkerberos.authGSSClientInit('HTTP/%s' % proxy_host, gssflags=0, mech_oid=winkerberos.GSS_MECH_OID_KRB5) status = winkerberos.authGSSClientStep(ctx, "") b64token = winkerberos.authGSSClientResponse(ctx) else: service = gssapi.Name('HTTP@%s' % proxy_host, gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(name=service, usage='initiate') token = ctx.step() b64token = base64.b64encode(token).encode('ascii') request[-1] = ('Proxy-Authorization: Negotiate %s' % b64token).encode('ascii') request.append(('\r\n').encode('ascii')) try: dst.sendall(b'\r\n'.join(request)) except: # if proxy does not support Keep-Alive dst.close() dst = create_connection((proxy_host, proxy_port)) dst.sendall(b'\r\n'.join(request)) data = b'' while True: data += dst.recv(1024) if b'\r\n\r\n' in data: break if b'200 Connection established' in data: sys.stderr.write('Proxy connection established\n') data = data.split(b'\r\n\r\n', 1)[1] if data: dst.sendall(data) forwarders = (gevent.spawn(forward_stdin, dst), gevent.spawn(forward_stdout, dst)) gevent.joinall(forwarders) elif b'407' in data: sys.stderr.write('Proxy authentication failed\n') else: version, status_code, status_message = data.split(b'\r\n', 1)[0].split(b' ', 2) sys.stderr.write('Proxy returned %s %s\n' % (status_code, status_message))
def getAuthToken(target): spnego_mech = gssapi.raw.OID.from_int_seq('1.3.6.1.5.5.2') name = gssapi.Name('HTTP@%s' % target, gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(name=name, mech=spnego_mech) token = ctx.step() return 'Negotiate %s' % b64encode(token).decode()
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 __init__(self, username, password, server): log.info("Setting up GSSAPI Security Context for Kerberos auth") self.creds = self._acquire_creds(username, password) server_spn = "cifs@%s" % server log.debug("GSSAPI Server SPN Target: %s" % server_spn) server_name = gssapi.Name(base=server_spn, name_type=gssapi.NameType.hostbased_service) self.context = gssapi.SecurityContext(name=server_name, creds=self.creds, usage='initiate')
async def login(self): if self._gssapi_client_ctx: return # already logged in server_name = gssapi.Name( f"HTTP@{urlparse(self._errata_url).hostname}", gssapi.NameType.hostbased_service) client_ctx = gssapi.SecurityContext(name=server_name, usage='initiate') out_token = client_ctx.step(b"") self._gssapi_client_ctx = client_ctx self._headers["Authorization"] = 'Negotiate ' + base64.b64encode( out_token).decode()
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_spnego_token(self): """ Obtain a SPNEGO token for the broker service and set the token to the 'authorization' metadata header. """ service_name_string = BROKER_USER service_name = gssapi.Name(service_name_string, gssapi.NameType.kerberos_principal) spnego_mech_oid = gssapi.raw.OID.from_int_seq('1.3.6.1.5.5.2') context = gssapi.SecurityContext( name=service_name, mech=spnego_mech_oid, usage='initiate', creds=self.credentials) response = context.step() spnego_token = b64encode(response).decode() return spnego_token
def get_host_info(self, host): host, extra_headers, x509 = Transport.get_host_info(self, host) # Set the remote host principal hostinfo = host.split(':') service = "HTTP@" + hostinfo[0] service_name = gssapi.Name(service, gssapi.NameType.hostbased_service) context = gssapi.SecurityContext(usage="initiate", name=service_name) token = context.step() token = b64encode(token).decode() extra_headers = [("Authorization", f"Negotiate {token}")] return host, extra_headers, x509
def negotiate(self): self.client_ctx = gssapi.SecurityContext(name=self.server_name, usage='initiate', flags=self.flags) token = b'' while not self.client_ctx.complete: log.debug('Doing step') token = self.client_ctx.step(token) self._inner.write(token) if not self.client_ctx.complete: token = self._inner.read() else: log.debug('GSSAPI Handshake done')
def init_sec_context(self): import gssapi # AUTHORIZATION MECHANISM gsi_mech = gssapi.raw.OID.from_int_seq(GSI_OID) # SERVER NAME server_name = gssapi.Name(self.account.server_dn) server_name.canonicalize(gsi_mech) # CLIENT CONTEXT self.client_ctx = gssapi.SecurityContext(name=server_name, mech=gsi_mech, flags=[2, 4], usage='initiate')
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! """ target_name = gssapi.Name('ldap@' + connection.server.host, gssapi.NameType.hostbased_service) ctx = gssapi.SecurityContext(name=target_name, mech=gssapi.MechType.kerberos) 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: # noinspection PyStatementEffect ctx.complete # This raises an exception if we haven't completed connecting. 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