Exemple #1
0
 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')}
Exemple #2
0
    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)
Exemple #3
0
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")
Exemple #4
0
    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
Exemple #6
0
    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
Exemple #7
0
    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
Exemple #9
0
    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
Exemple #10
0
    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)
Exemple #12
0
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
Exemple #13
0
    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)
Exemple #14
0
  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"))
Exemple #15
0
        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')
Exemple #16
0
 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
Exemple #17
0
 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()
Exemple #20
0
    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))
Exemple #21
0
 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)
Exemple #22
0
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
Exemple #23
0
    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')
Exemple #24
0
 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()
Exemple #25
0
    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)
Exemple #26
0
 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
Exemple #27
0
    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