Example #1
0
    def test_authenticate(self):
        res, ctx = kerberos.authGSSClientInit(_SPN, None,
                                              kerberos.GSS_C_MUTUAL_FLAG,
                                              _USER, _DOMAIN, _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        res = kerberos.authGSSClientStep(ctx, "")
        self.assertEqual(res, kerberos.AUTH_GSS_CONTINUE)

        payload = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(payload, str)

        response = self.db.command('saslStart',
                                   mechanism='GSSAPI',
                                   payload=payload)
        while res == kerberos.AUTH_GSS_CONTINUE:
            res = kerberos.authGSSClientStep(ctx, response['payload'])
            payload = kerberos.authGSSClientResponse(ctx) or ''
            response = self.db.command(
                'saslContinue',
                conversationId=response['conversationId'],
                payload=payload)

        res = kerberos.authGSSClientUnwrap(ctx, response['payload'])
        self.assertEqual(res, 1)

        unwrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(unwrapped, str)
        self.assertIsInstance(kerberos.authGSSClientResponseConf(ctx), int)

        # RFC-4752
        challenge_bytes = base64.standard_b64decode(unwrapped)
        self.assertEqual(4, len(challenge_bytes))

        # Manually create an authorization message and encrypt it. This
        # is the "no security layer" message as detailed in RFC-4752,
        # section 3.1, final paragraph. This is also the message created
        # by calling authGSSClientWrap with the "user" option.
        msg = base64.standard_b64encode(b"\x01\x00\x00\x00" +
                                        _UPN.encode("utf8")).decode("utf8")
        res = kerberos.authGSSClientWrap(ctx, msg)
        self.assertEqual(res, 1)

        custom = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(custom, str)

        # Wrap using unwrapped and user principal.
        res = kerberos.authGSSClientWrap(ctx, unwrapped, _UPN)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        # Actually complete authentication, using our custom message.
        response = self.db.command('saslContinue',
                                   conversationId=response['conversationId'],
                                   payload=custom)
        self.assertTrue(response['done'])

        self.assertIsInstance(kerberos.authGSSClientUsername(ctx), str)
    def retry_http_krb_sspi_auth(self, host, req):
        url = req.full_url
        scheme, _, host, path = url.split('/', 3)

        h = HTTPConnection(host) if scheme == 'http:' else HTTPSConnection(
            host)
        headers = dict(req.unredirected_hdrs)
        headers.update(
            dict((k, v) for k, v in req.headers.items() if k not in headers))

        try:
            __, krb_context = kerberos.authGSSClientInit("HTTP@" + host)
            kerberos.authGSSClientStep(krb_context, "")

            negotiate_details = kerberos.authGSSClientResponse(krb_context)

            headers["Connection"] = "Keep-Alive"
            headers["Authorization"] = "Negotiate " + negotiate_details
            h.request(req.get_method(), req.selector, req.data, headers)
            response = h.getresponse()
            return addinfourl(response, response.msg, req.get_full_url(),
                              response.status)
        except:
            # e = sys.exc_info()[0]
            # _log.warning(str(e))
            # _log.warning('Failed Kerberos authentication')
            return None
 def authenticate(self,
                  service=_SPN,
                  principal=None,
                  flags=kerberos.GSS_C_MUTUAL_FLAG,
                  user=_USER,
                  domain=_DOMAIN,
                  password=_PASSWORD,
                  mech_oid=kerberos.GSS_MECH_OID_KRB5,
                  upn=_UPN,
                  protect=0):
         res, ctx = kerberos.authGSSClientInit(
             service, principal, flags, user, domain, password, mech_oid)
         res = kerberos.authGSSClientStep(ctx, "")
         payload = kerberos.authGSSClientResponse(ctx)
         response = self.db.command(
             'saslStart', mechanism='GSSAPI', payload=payload)
         while res == kerberos.AUTH_GSS_CONTINUE:
             res = kerberos.authGSSClientStep(ctx, response['payload'])
             payload = kerberos.authGSSClientResponse(ctx) or ''
             response = self.db.command(
                'saslContinue',
                conversationId=response['conversationId'],
                payload=payload)
         kerberos.authGSSClientUnwrap(ctx, response['payload'])
         kerberos.authGSSClientWrap(ctx,
                                    kerberos.authGSSClientResponse(ctx),
                                    upn,
                                    protect)
         response = self.db.command(
            'saslContinue',
            conversationId=response['conversationId'],
            payload=kerberos.authGSSClientResponse(ctx))
         self.assertTrue(response['done'])
Example #4
0
 def authenticate(self,
                  service=_SPN,
                  principal=None,
                  flags=kerberos.GSS_C_MUTUAL_FLAG,
                  user=_USER,
                  domain=_DOMAIN,
                  password=_PASSWORD,
                  mech_oid=kerberos.GSS_MECH_OID_KRB5,
                  upn=_UPN,
                  protect=0):
     res, ctx = kerberos.authGSSClientInit(service, principal, flags, user,
                                           domain, password, mech_oid)
     res = kerberos.authGSSClientStep(ctx, "")
     payload = kerberos.authGSSClientResponse(ctx)
     response = self.db.command('saslStart',
                                mechanism='GSSAPI',
                                payload=payload)
     while res == kerberos.AUTH_GSS_CONTINUE:
         res = kerberos.authGSSClientStep(ctx, response['payload'])
         payload = kerberos.authGSSClientResponse(ctx) or ''
         response = self.db.command(
             'saslContinue',
             conversationId=response['conversationId'],
             payload=payload)
     kerberos.authGSSClientUnwrap(ctx, response['payload'])
     kerberos.authGSSClientWrap(ctx, kerberos.authGSSClientResponse(ctx),
                                upn, protect)
     response = self.db.command('saslContinue',
                                conversationId=response['conversationId'],
                                payload=kerberos.authGSSClientResponse(ctx))
     self.assertTrue(response['done'])
Example #5
0
 def __init__(self):
     if "winkerberos" in sys.modules:
         status, self.ctx = winkerberos.authGSSClientInit("NTLM", gssflags=0, mech_oid=winkerberos.GSS_MECH_OID_SPNEGO)
         self.get_response = self.get_response_wkb
     else:
         self.sspi_client = sspi.ClientAuth("NTLM", os.environ.get("USERNAME"), scflags=0)
         self.get_response = self.get_response_sspi
Example #6
0
File: px.py Project: y-cann/px
 def __init__(self, proxy_type):
     if proxy_type == "NTLM":
         self.ctx = sspi.ClientAuth("NTLM", os.environ.get("USERNAME"), scflags=0)
         self.get_response = self.get_response_sspi
     else:
         _, self.ctx = winkerberos.authGSSClientInit("HTTP@" + State.proxy_server[0][0],
             gssflags=0, mech_oid=winkerberos.GSS_MECH_OID_SPNEGO)
         self.get_response = self.get_response_wkb
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))
Example #8
0
    def process_challenge_kerberos(self, packet):
        digest = packet[3]
        if not digest.startswith(b"kerberos:"):
            authlog("%s is not a kerberos challenge", digest)
            #not a kerberos challenge
            return False
        try:
            if WIN32:
                import winkerberos as kerberos
            else:
                import kerberos
        except ImportError as e:
            authlog("import (win)kerberos", exc_info=True)
            if first_time("no-kerberos"):
                authlog.warn(
                    "Warning: kerberos challenge handler is not supported:")
                authlog.warn(" %s", e)
            return False
        service = bytestostr(digest.split(b":", 1)[1])
        if service not in KERBEROS_SERVICES and "*" not in KERBEROS_SERVICES:
            authlog.warn("Warning: invalid kerberos request for service '%s'",
                         service)
            authlog.warn(" services supported: %s", csv(KERBEROS_SERVICES))
            return False
        authlog("kerberos service=%s", service)

        def log_kerberos_exception(e):
            try:
                for x in e.args:
                    if isinstance(x, (list, tuple)):
                        try:
                            log.error(" %s", csv(x))
                            continue
                        except:
                            pass
                    authlog.error(" %s", x)
            except Exception:
                authlog.error(" %s", e)

        try:
            r, ctx = kerberos.authGSSClientInit(service)
            assert r == 1, "return code %s" % r
        except Exception as e:
            authlog("kerberos.authGSSClientInit(%s)", service, exc_info=True)
            authlog.error("Error: cannot initialize kerberos client:")
            log_kerberos_exception(e)
            return False
        try:
            kerberos.authGSSClientStep(ctx, "")
        except Exception as e:
            authlog("kerberos.authGSSClientStep", exc_info=True)
            authlog.error("Error: kerberos client authentication failure:")
            log_kerberos_exception(e)
            return False
        token = kerberos.authGSSClientResponse(ctx)
        authlog("kerberos token=%s", token)
        self.send_challenge_reply(packet, token)
        return True
Example #9
0
    def test_uninitialized_context(self):
        res, ctx = kerberos.authGSSClientInit(_SPN, None,
                                              kerberos.GSS_C_MUTUAL_FLAG,
                                              _USER, _DOMAIN, _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        self.assertIsNone(kerberos.authGSSClientResponse(ctx))
        self.assertIsNone(kerberos.authGSSClientUsername(ctx))
        self.assertRaises(kerberos.GSSError, kerberos.authGSSClientUnwrap, ctx,
                          "foobar")
        self.assertRaises(kerberos.GSSError, kerberos.authGSSClientWrap, ctx,
                          "foobar")
Example #10
0
    def test_authenticate(self):
        res, ctx = kerberos.authGSSClientInit(
            _SPN,
            _PRINCIPAL,
            kerberos.GSS_C_MUTUAL_FLAG,
            _USER,
            _DOMAIN,
            _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        res = kerberos.authGSSClientStep(ctx, "")
        self.assertEqual(res, kerberos.AUTH_GSS_CONTINUE)

        payload = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(payload, str)

        response = self.db.command(
            'saslStart', mechanism='GSSAPI', payload=payload)
        while res == kerberos.AUTH_GSS_CONTINUE:
            res = kerberos.authGSSClientStep(ctx, response['payload'])
            payload = kerberos.authGSSClientResponse(ctx) or ''
            response = self.db.command(
               'saslContinue',
               conversationId=response['conversationId'],
               payload=payload)

        res = kerberos.authGSSClientUnwrap(ctx, response['payload'])
        self.assertEqual(res, 1)

        unwrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(unwrapped, str)

        # Try just rewrapping (no user)
        res = kerberos.authGSSClientWrap(ctx, unwrapped)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        # Actually complete authentication
        res = kerberos.authGSSClientWrap(ctx, unwrapped, _UPN)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        response = self.db.command(
           'saslContinue',
           conversationId=response['conversationId'],
           payload=wrapped)
        self.assertTrue(response['done'])

        self.assertIsInstance(kerberos.authGSSClientUsername(ctx), str)
Example #11
0
def _windows_sasl_gssapi(connection, controls):
    """ Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism
    from RFC 4752 using the winkerberos package that works natively on most
    windows operating systems.
    """
    target_name = _common_determine_target_name(connection)
    # initiation happens before beginning the SASL bind when using windows kerberos
    authz_id, _ = _common_determine_authz_id_and_creds(connection)
    gssflags = (winkerberos.GSS_C_MUTUAL_FLAG | winkerberos.GSS_C_SEQUENCE_FLAG
                | winkerberos.GSS_C_INTEG_FLAG | winkerberos.GSS_C_CONF_FLAG)
    _, ctx = winkerberos.authGSSClientInit(target_name, gssflags=gssflags)

    in_token = b''
    try:
        negotiation_complete = False
        while not negotiation_complete:
            # GSSAPI is a "client goes first" SASL mechanism. Send the first "response" to the server and
            # recieve its first challenge.
            # Despite this, we can get channel binding, which includes CBTs for windows environments computed from
            # the peer certificate, before starting.
            status = winkerberos.authGSSClientStep(
                ctx,
                base64.b64encode(in_token).decode('utf-8'),
                channel_bindings=get_channel_bindings(connection.socket))
            # figure out if we're done with our sasl negotiation
            negotiation_complete = (status == winkerberos.AUTH_GSS_COMPLETE)
            out_token = winkerberos.authGSSClientResponse(ctx) or ''
            out_token_bytes = base64.b64decode(out_token)
            result = send_sasl_negotiation(connection, controls,
                                           out_token_bytes)
            in_token = result['saslCreds'] or b''

        winkerberos.authGSSClientUnwrap(
            ctx,
            base64.b64encode(in_token).decode('utf-8'))
        negotiated_token = ''
        if winkerberos.authGSSClientResponse(ctx):
            negotiated_token = base64.standard_b64decode(
                winkerberos.authGSSClientResponse(ctx))
        client_security_layers = _common_process_end_token_get_security_layers(
            negotiated_token)
        # manually construct a message indicating use of authorization-only layer
        # see winkerberos example: https://github.com/mongodb/winkerberos/blob/master/test/test_winkerberos.py
        authz_only_msg = base64.b64encode(
            bytes(client_security_layers) + authz_id).decode('utf-8')
        winkerberos.authGSSClientWrap(ctx, authz_only_msg)
        out_token = winkerberos.authGSSClientResponse(ctx) or ''

        return send_sasl_negotiation(connection, controls,
                                     base64.b64decode(out_token))
    except (winkerberos.GSSError, LDAPCommunicationError):
        abort_sasl_negotiation(connection, controls)
        raise
Example #12
0
    def test_authenticate(self):
        res, ctx = kerberos.authGSSClientInit(_SPN, _PRINCIPAL,
                                              kerberos.GSS_C_MUTUAL_FLAG,
                                              _USER, _DOMAIN, _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        res = kerberos.authGSSClientStep(ctx, "")
        self.assertEqual(res, kerberos.AUTH_GSS_CONTINUE)

        payload = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(payload, str)

        response = self.db.command('saslStart',
                                   mechanism='GSSAPI',
                                   payload=payload)
        while res == kerberos.AUTH_GSS_CONTINUE:
            res = kerberos.authGSSClientStep(ctx, response['payload'])
            payload = kerberos.authGSSClientResponse(ctx) or ''
            response = self.db.command(
                'saslContinue',
                conversationId=response['conversationId'],
                payload=payload)

        res = kerberos.authGSSClientUnwrap(ctx, response['payload'])
        self.assertEqual(res, 1)

        unwrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(unwrapped, str)

        # Try just rewrapping (no user)
        res = kerberos.authGSSClientWrap(ctx, unwrapped)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        # Actually complete authentication
        res = kerberos.authGSSClientWrap(ctx, unwrapped, _UPN)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        response = self.db.command('saslContinue',
                                   conversationId=response['conversationId'],
                                   payload=wrapped)
        self.assertTrue(response['done'])

        self.assertIsInstance(kerberos.authGSSClientUsername(ctx), str)
Example #13
0
    def init(self):
        if self._ctx:
            return self._ctx

        if __debug__:
            logger.debug('Initialize security context: %s', self)

        args = [self.name, self.creds.name if self.creds else None]

        kwargs = {'gssflags': self.flags, 'mech_oid': self.mech}

        need_inquire_creds = True

        if self.creds and self.creds.password:
            kwargs['password'] = self.creds.password,

            try:
                result, self._ctx = krb.authGSSClientInit(*args, **kwargs)

                logger.debug('GSSApiExt: password ok')
                need_inquire_creds = False
            except TypeError:
                logger.debug('GSSApiExt: password is not supported')
                del kwargs['password']

        if not self._ctx:
            result, self._ctx = krb.authGSSClientInit(*args, **kwargs)

        if result < 0:
            raise GSSAPIAdapterException(result)

        if need_inquire_creds and have_inquire_creds:
            logger.debug('GSSApiExt: inquire credentials')
            result = krb.authGSSClientInquireCred(self._ctx)
            if result < 0:
                raise GSSAPIAdapterException(result)
    def test_uninitialized_context(self):
        res, ctx = kerberos.authGSSClientInit(
            _SPN,
            None,
            kerberos.GSS_C_MUTUAL_FLAG,
            _USER,
            _DOMAIN,
            _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        self.assertIsNone(kerberos.authGSSClientResponse(ctx))
        self.assertIsNone(kerberos.authGSSClientUserName(ctx))
        self.assertRaises(
            kerberos.GSSError, kerberos.authGSSClientUnwrap, ctx, "foobar")
        self.assertRaises(
            kerberos.GSSError, kerberos.authGSSClientWrap, ctx, "foobar")
Example #15
0
 def handle(self, packet):
     digest = bytestostr(packet[3])
     if not digest.startswith("kerberos:"):
         log("%s is not a kerberos challenge", digest)
         #not a kerberos challenge
         return False
     try:
         if WIN32:
             import winkerberos as kerberos
         else:
             import kerberos  #@UnresolvedImport
     except ImportError as e:
         log.warn("Warning: cannot use kerberos authentication handler")
         log.warn(" %s", e)
         return False
     service = digest.split(":", 1)[1]
     if service not in self.services and "*" not in self.services:
         log.warn("Warning: invalid kerberos request for service '%s'",
                  service)
         log.warn(" services supported: %s", csv(self.services))
         return False
     log("kerberos service=%s", service)
     try:
         r, ctx = kerberos.authGSSClientInit(service)
         assert r == 1, "return code %s" % r
     except Exception as e:
         log("kerberos.authGSSClientInit(%s)", service, exc_info=True)
         log.error("Error: cannot initialize kerberos client:")
         log_kerberos_exception(e)
         return False
     try:
         kerberos.authGSSClientStep(ctx, "")
     except Exception as e:
         log("kerberos.authGSSClientStep", exc_info=True)
         log.error("Error: kerberos client authentication failure:")
         log_kerberos_exception(e)
         return False
     token = kerberos.authGSSClientResponse(ctx)
     log("kerberos token=%s", token)
     self.client.send_challenge_reply(packet, token)
     return True
Example #16
0
    def handle(self, src, addr):
        data = b''
        while True:
            data += src.recv(1024)
            if b'\r\n\r\n' in data:
                break
                
        if sys.platform == "win32":
            status, ctx = winkerberos.authGSSClientInit('HTTP/%s' % self.upstream[0], gssflags=0, mech_oid=winkerberos.GSS_MECH_OID_KRB5)
            status = winkerberos.authGSSClientStep(ctx, "")
            b64token = winkerberos.authGSSClientResponse(ctx)
        else:
            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 test_authenticate(self):
        res, ctx = kerberos.authGSSClientInit(
            _SPN,
            None,
            kerberos.GSS_C_MUTUAL_FLAG,
            _USER,
            _DOMAIN,
            _PASSWORD)
        self.assertEqual(res, kerberos.AUTH_GSS_COMPLETE)

        res = kerberos.authGSSClientStep(ctx, "")
        self.assertEqual(res, kerberos.AUTH_GSS_CONTINUE)

        payload = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(payload, str)

        response = self.db.command(
            'saslStart', mechanism='GSSAPI', payload=payload)
        while res == kerberos.AUTH_GSS_CONTINUE:
            res = kerberos.authGSSClientStep(ctx, response['payload'])
            payload = kerberos.authGSSClientResponse(ctx) or ''
            response = self.db.command(
               'saslContinue',
               conversationId=response['conversationId'],
               payload=payload)

        res = kerberos.authGSSClientUnwrap(ctx, response['payload'])
        self.assertEqual(res, 1)

        unwrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(unwrapped, str)
        self.assertIsInstance(kerberos.authGSSClientResponseConf(ctx), int)

        # RFC-4752
        challenge_bytes = base64.standard_b64decode(unwrapped)
        self.assertEqual(4, len(challenge_bytes))

        # Manually create an authorization message and encrypt it. This
        # is the "no security layer" message as detailed in RFC-4752,
        # section 3.1, final paragraph. This is also the message created
        # by calling authGSSClientWrap with the "user" option.
        msg = base64.standard_b64encode(
            b"\x01\x00\x00\x00" + _UPN.encode("utf8")).decode("utf8")
        res = kerberos.authGSSClientWrap(ctx, msg)
        self.assertEqual(res, 1)

        custom = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(custom, str)

        # Wrap using unwrapped and user principal.
        res = kerberos.authGSSClientWrap(ctx, unwrapped, _UPN)
        self.assertEqual(res, 1)

        wrapped = kerberos.authGSSClientResponse(ctx)
        self.assertIsInstance(wrapped, str)

        # Actually complete authentication, using our custom message.
        response = self.db.command(
           'saslContinue',
           conversationId=response['conversationId'],
           payload=custom)
        self.assertTrue(response['done'])

        self.assertIsInstance(kerberos.authGSSClientUserName(ctx), str)
Example #18
0
 def __init__(self):
     status, self.ctx = winkerberos.authGSSClientInit(
         "HTTP@" + State.proxy_server[0][0],
         gssflags=0,
         mech_oid=winkerberos.GSS_MECH_OID_SPNEGO)
Example #19
0
def _authenticate_gssapi(credentials, sock_info):
    """Authenticate using GSSAPI.
    """
    if not HAVE_KERBEROS:
        raise ConfigurationError('The "kerberos" module must be '
                                 'installed to use GSSAPI authentication.')

    try:
        username = credentials.username
        password = credentials.password
        props = credentials.mechanism_properties
        # Starting here and continuing through the while loop below - establish
        # the security context. See RFC 4752, Section 3.1, first paragraph.
        host = sock_info.address[0]
        if props.canonicalize_host_name:
            host = socket.getfqdn(host)
        service = props.service_name + '@' + host
        if props.service_realm is not None:
            service = service + '@' + props.service_realm

        if password is not None:
            if _USE_PRINCIPAL:
                # Note that, though we use unquote_plus for unquoting URI
                # options, we use quote here. Microsoft's UrlUnescape (used
                # by WinKerberos) doesn't support +.
                principal = ":".join((quote(username), quote(password)))
                result, ctx = kerberos.authGSSClientInit(
                    service, principal, gssflags=kerberos.GSS_C_MUTUAL_FLAG)
            else:
                if '@' in username:
                    user, domain = username.split('@', 1)
                else:
                    user, domain = username, None
                result, ctx = kerberos.authGSSClientInit(
                    service, gssflags=kerberos.GSS_C_MUTUAL_FLAG,
                    user=user, domain=domain, password=password)
        else:
            result, ctx = kerberos.authGSSClientInit(
                service, gssflags=kerberos.GSS_C_MUTUAL_FLAG)

        if result != kerberos.AUTH_GSS_COMPLETE:
            raise OperationFailure('Kerberos context failed to initialize.')

        try:
            # pykerberos uses a weird mix of exceptions and return values
            # to indicate errors.
            # 0 == continue, 1 == complete, -1 == error
            # Only authGSSClientStep can return 0.
            if kerberos.authGSSClientStep(ctx, '') != 0:
                raise OperationFailure('Unknown kerberos '
                                       'failure in step function.')

            # Start a SASL conversation with mongod/s
            # Note: pykerberos deals with base64 encoded byte strings.
            # Since mongo accepts base64 strings as the payload we don't
            # have to use bson.binary.Binary.
            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslStart', 1),
                       ('mechanism', 'GSSAPI'),
                       ('payload', payload),
                       ('autoAuthorize', 1)])
            response = sock_info.command('$external', cmd)

            # Limit how many times we loop to catch protocol / library issues
            for _ in range(10):
                result = kerberos.authGSSClientStep(ctx,
                                                    str(response['payload']))
                if result == -1:
                    raise OperationFailure('Unknown kerberos '
                                           'failure in step function.')

                payload = kerberos.authGSSClientResponse(ctx) or ''

                cmd = SON([('saslContinue', 1),
                           ('conversationId', response['conversationId']),
                           ('payload', payload)])
                response = sock_info.command('$external', cmd)

                if result == kerberos.AUTH_GSS_COMPLETE:
                    break
            else:
                raise OperationFailure('Kerberos '
                                       'authentication failed to complete.')

            # Once the security context is established actually authenticate.
            # See RFC 4752, Section 3.1, last two paragraphs.
            if kerberos.authGSSClientUnwrap(ctx,
                                            str(response['payload'])) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Unwrap step.')

            if kerberos.authGSSClientWrap(ctx,
                                          kerberos.authGSSClientResponse(ctx),
                                          username) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Wrap step.')

            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslContinue', 1),
                       ('conversationId', response['conversationId']),
                       ('payload', payload)])
            sock_info.command('$external', cmd)

        finally:
            kerberos.authGSSClientClean(ctx)

    except kerberos.KrbError as exc:
        raise OperationFailure(str(exc))
 def __init__(self, user=None):
     status, self.ctx = kerberos.authGSSClientInit(
         "NTLM", gssflags=0, mech_oid=kerberos.GSS_MECH_OID_SPNEGO)
Example #21
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 tuple with one or two elements.
    The first element determines which service principal to request a ticket
    for and can be one of the following:
    - None or False, to use the hostname from the Server object
    - True to perform a reverse DNS lookup to retrieve the canonical hostname
      for the hosts IP address
    - A string containing the hostname
    The optional second element is what authorization ID to request.
    - If omitted or None, the authentication ID is used as the authorization ID
    - If a string, the authorization ID to use. Should start with "dn:" or
      "user:"******"""
    # pylint: disable=too-many-branches
    target_name = None
    authz_id = b''
    if connection.sasl_credentials:
        if (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 = 'ldap@' + hostname

            else:
                target_name = 'ldap@' + connection.sasl_credentials[0]
        if (len(connection.sasl_credentials) >= 2
                and connection.sasl_credentials[1]):
            authz_id = connection.sasl_credentials[1].encode("utf-8")
    if target_name is None:
        target_name = 'ldap@' + connection.server.host

    gssflags = (kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG
                | kerberos.GSS_C_INTEG_FLAG | kerberos.GSS_C_CONF_FLAG)
    channel_bindings = get_channel_bindings(connection.socket)
    _, ctx = kerberos.authGSSClientInit(target_name, gssflags=gssflags)

    in_token = b''
    try:
        while True:
            if channel_bindings:
                status = kerberos.authGSSClientStep(
                    ctx,
                    base64.b64encode(in_token).decode('ascii'),
                    channel_bindings=channel_bindings)
            else:
                status = kerberos.authGSSClientStep(
                    ctx,
                    base64.b64encode(in_token).decode('ascii'))
            out_token = kerberos.authGSSClientResponse(ctx) or ''
            result = send_sasl_negotiation(connection, controls,
                                           base64.b64decode(out_token))
            in_token = result['saslCreds'] or b''
            if status == kerberos.AUTH_GSS_COMPLETE:
                break

        kerberos.authGSSClientUnwrap(
            ctx,
            base64.b64encode(in_token).decode('ascii'))
        unwrapped_token = base64.b64decode(
            kerberos.authGSSClientResponse(ctx) or '')

        if len(unwrapped_token) != 4:
            raise LDAPCommunicationError('Incorrect response from server')

        server_security_layers = unwrapped_token[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])
        kerberos.authGSSClientWrap(
            ctx,
            base64.b64encode(bytes(client_security_layers) +
                             authz_id).decode('ascii'))
        out_token = kerberos.authGSSClientResponse(ctx) or ''

        return send_sasl_negotiation(connection, controls,
                                     base64.b64decode(out_token))
    except (kerberos.GSSError, LDAPCommunicationError):
        abort_sasl_negotiation(connection, controls)
        raise