def gssapi_login(self, user):
        # Try GSSAPI login first

        # Used FTP response codes:
        # 235 [ADAT=base64data] - indicates that the security data exchange
        #     completed successfully.
        # 334 [ADAT=base64data] - indicates that the requested security
        #     mechanism is ok, and includes security data to be used by the
        #     client to construct the next command.
        # 335 [ADAT=base64data] - indicates that the security data is
        #     acceptable, and more is required to complete the security
        #     data exchange.

        resp = self.sendcmd('AUTH GSSAPI')
        if resp.startswith('334 '):
            rc, self.vc = kerberos.authGSSClientInit("ftp@%s" % self.host)
            if kerberos.authGSSClientStep(self.vc, "") != 1:
                while resp[:4] in ('334 ', '335 '):
                    authdata = kerberos.authGSSClientResponse(self.vc)
                    resp = self.sendcmd('ADAT ' + authdata)
                    if resp[:9] in ('235 ADAT=', '335 ADAT='):
                        rc = kerberos.authGSSClientStep(self.vc, resp[9:])
                        if not ((resp.startswith('235 ') and rc == 1) or
                                (resp.startswith('335 ') and rc == 0)):
                            raise ftplib.error_reply, resp
            note(gettext("Authenticated as %s") %
                 kerberos.authGSSClientUserName(self.vc))

            # Monkey patch ftplib
            self.putcmd = self.mic_putcmd
            self.getline = self.mic_getline
            self.sendcmd('USER ' + user)
            return resp
        mutter("Unable to use GSSAPI authentication: %s", resp)
Exemple #2
0
    def gssapi_login(self, user):
        # Try GSSAPI login first

        # Used FTP response codes:
        # 235 [ADAT=base64data] - indicates that the security data exchange
        #     completed successfully.
        # 334 [ADAT=base64data] - indicates that the requested security
        #     mechanism is ok, and includes security data to be used by the
        #     client to construct the next command.
        # 335 [ADAT=base64data] - indicates that the security data is
        #     acceptable, and more is required to complete the security
        #     data exchange.

        resp = self.sendcmd('AUTH GSSAPI')
        if resp.startswith('334 '):
            rc, self.vc = kerberos.authGSSClientInit("ftp@%s" % self.host)
            if kerberos.authGSSClientStep(self.vc, "") != 1:
                while resp[:4] in ('334 ', '335 '):
                    authdata = kerberos.authGSSClientResponse(self.vc)
                    resp = self.sendcmd('ADAT ' + authdata)
                    if resp[:9] in ('235 ADAT=', '335 ADAT='):
                        rc = kerberos.authGSSClientStep(self.vc, resp[9:])
                        if not ((resp.startswith('235 ') and rc == 1) or
                                (resp.startswith('335 ') and rc == 0)):
                            raise ftplib.error_reply, resp
            note(
                gettext("Authenticated as %s") %
                kerberos.authGSSClientUserName(self.vc))

            # Monkey patch ftplib
            self.putcmd = self.mic_putcmd
            self.getline = self.mic_getline
            self.sendcmd('USER ' + user)
            return resp
        mutter("Unable to use GSSAPI authentication: %s", resp)
Exemple #3
0
    def __init__(self, endpoint, auth=None, capath=True):
        logger.debug("Initializing service (endpoint: %s, auth: %s", endpoint,
                     auth)
        self._endpoint = endpoint

        if auth == 'kerberos':
            # This step has been extended to work around issue #942 in the
            # kerberos library where the default principal cannot be
            # derived without raising an error. An explicit principal has
            # to be provided.
            #
            # This is ignored if PyKerberos is used.
            from urllib.parse import urlparse
            import kerberos

            if 'authGSSClientInquireCred' in dir(kerberos):
                parse = urlparse(endpoint)
                kerb_spn = "{0}@{1}".format("HTTP", parse.netloc)
                _, krb_context = kerberos.authGSSClientInit(kerb_spn)
                kerberos.authGSSClientInquireCred(krb_context)
                principal = kerberos.authGSSClientUserName(krb_context)
                # kerberos.authGSSClientClean(krb_context)
                auth = HTTPKerberosAuth(principal=principal)
            else:
                auth = HTTPKerberosAuth()

        self._auth = auth
        self._capath = capath
    def __request_authenticate(self, method, url, body, extra_hdrs):
        self.__probe_mechanisms()

        try:
            result, gssctx = kerberos.authGSSClientInit(self.__spn, principal=self.__upn)
        except kerberos.GSSError as ex:
            raise Krb5Error('%s (%s)' % (ex[0][0], ex[1][0]))
            
        response = None
        blob = ''

        while True:
            try:
                result, blob = self.__challenge(gssctx, blob)
            except Krb5Error as ex:
                kerberos.authGSSClientClean(gssctx)
                raise ex

            if result:
                self.__upn = kerberos.authGSSClientUserName(gssctx)
                break

            self.close()
            extra_hdrs['Authorization'] = 'Negotiate %s' % (blob, )
            response =  davlib.DAV._request(self, method, url, body, extra_hdrs)

            self.__store_cookies(response)
            authstr = response.getheader('www-authenticate')
            (mech, blob) = authstr.split(' ')

            persistauth = response.getheader('persistent-auth')
            self.__persistauth = persistauth == 'true'

        kerberos.authGSSClientClean(gssctx)
        return response
Exemple #5
0
    def process(self, challenge=None):
        if not self._have_negotiated_details:
            kerberos.authGSSClientStep(self.context, '')
            _negotiated_details = kerberos.authGSSClientResponse(self.context)
            self._have_negotiated_details = True
            return base64.b64decode(_negotiated_details)

        challenge = base64.b64encode(challenge).decode(
            'ascii')  # kerberos methods expect strings, not bytes
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return b''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = b''
            return response

        kerberos.authGSSClientUnwrap(self.context, challenge)
        data = kerberos.authGSSClientResponse(self.context)
        plaintext_data = base64.b64decode(data)
        if len(plaintext_data) != 4:
            raise SASLProtocolException(
                "Bad response from server")  # todo: better message

        word, = struct.unpack('!I', plaintext_data)
        qop_bits = word >> 24
        max_length = word & 0xffffff
        server_offered_qops = QOP.names_from_bitmask(qop_bits)
        self._pick_qop(server_offered_qops)

        self.max_buffer = min(self.sasl.max_buffer, max_length)
        """
        byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
        byte 1-3: the max length for any buffer sent back and forth on
            this connection. (big endian)
        the rest of the buffer: the authorization user name in UTF-8 -
            not null terminated.
        """
        auth_id = self.sasl.authorization_id or self.user
        l = len(auth_id)
        fmt = '!I' + str(l) + 's'
        word = QOP.flag_from_name(self.qop) << 24 | self.max_buffer
        out = struct.pack(
            fmt,
            word,
            _b(auth_id),
        )

        encoded = base64.b64encode(out).decode('ascii')

        kerberos.authGSSClientWrap(self.context, encoded)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)
Exemple #6
0
    def process(self, challenge=None):
        if not self._have_negotiated_details:
            kerberos.authGSSClientStep(self.context, '')
            _negotiated_details = kerberos.authGSSClientResponse(self.context)
            self._have_negotiated_details = True
            return base64.b64decode(_negotiated_details)

        challenge = base64.b64encode(challenge).decode('ascii')  # kerberos methods expect strings, not bytes
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return b''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = b''
            return response

        kerberos.authGSSClientUnwrap(self.context, challenge)
        data = kerberos.authGSSClientResponse(self.context)
        plaintext_data = base64.b64decode(data)
        if len(plaintext_data) != 4:
            raise SASLProtocolException("Bad response from server")  # todo: better message

        word, = struct.unpack('!I', plaintext_data)
        qop_bits = word >> 24
        max_length = word & 0xffffff
        server_offered_qops = QOP.names_from_bitmask(qop_bits)
        self._pick_qop(server_offered_qops)

        self.max_buffer = min(self.sasl.max_buffer, max_length)

        """
        byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
        byte 1-3: the max length for any buffer sent back and forth on
            this connection. (big endian)
        the rest of the buffer: the authorization user name in UTF-8 -
            not null terminated.
        """
        auth_id = self.sasl.authorization_id or self.user
        l = len(auth_id)
        fmt = '!I' + str(l) + 's'
        word = QOP.flag_from_name(self.qop) << 24 | self.max_buffer
        out = struct.pack(fmt, word, _b(auth_id),)

        encoded = base64.b64encode(out).decode('ascii')

        kerberos.authGSSClientWrap(self.context, encoded)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)
Exemple #7
0
    def _kerberos_received(self, message):
        # Inspired by: https://github.com/thobbs/pure-sasl/blob/0.6.2/puresasl/mechanisms.py
        #              https://github.com/thobbs/pure-sasl/blob/0.6.2/LICENSE
        try:
            import kerberos
        except ImportError:
            raise ImportError('Please install gremlinpython[kerberos].')

        # First pass: get service granting ticket and return it to gremlin-server
        if not self._kerberos_context:
            try:
                _, kerberos_context = kerberos.authGSSClientInit(
                    self._kerberized_service, gssflags=kerberos.GSS_C_MUTUAL_FLAG)
                kerberos.authGSSClientStep(kerberos_context, '')
                auth = kerberos.authGSSClientResponse(kerberos_context)
                self._kerberos_context = kerberos_context
            except kerberos.KrbError as e:
                raise ConfigurationError(
                    'Kerberos authentication requires a valid service name in DriverRemoteConnection, '
                    'as well as a valid tgt (export KRB5CCNAME) or keytab (export KRB5_KTNAME): ' + str(e))
            return request.RequestMessage('', 'authentication', {'sasl': auth})

        # Second pass: completion of authentication
        sasl_response = message['status']['attributes']['sasl']
        if not self._username:
            result_code = kerberos.authGSSClientStep(self._kerberos_context, sasl_response)
            if result_code == kerberos.AUTH_GSS_COMPLETE:
                self._username = kerberos.authGSSClientUserName(self._kerberos_context)
            return request.RequestMessage('', 'authentication', {'sasl': ''})

        # Third pass: sasl quality of protection (qop) handshake

        # Gremlin-server Krb5Authenticator only supports qop=QOP_AUTH; use ssl for confidentiality.
        # Handshake content format:
        # byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
        # byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian)
        # the rest of the buffer: the authorization user name in UTF-8 - not null terminated.
        kerberos.authGSSClientUnwrap(self._kerberos_context, sasl_response)
        data = kerberos.authGSSClientResponse(self._kerberos_context)
        plaintext_data = base64.b64decode(data)
        assert len(plaintext_data) == 4, "Unexpected response from gremlin server sasl handshake"
        word, = struct.unpack('!I', plaintext_data)
        qop_bits = word >> 24
        assert self.QOP_AUTH_BIT & qop_bits, "Unexpected sasl qop level received from gremlin server"

        name_length = len(self._username)
        fmt = '!I' + str(name_length) + 's'
        word = self.QOP_AUTH_BIT << 24 | self.MAX_CONTENT_LENGTH
        out = struct.pack(fmt, word, self._username.encode("utf-8"),)
        encoded = base64.b64encode(out).decode('ascii')
        kerberos.authGSSClientWrap(self._kerberos_context, encoded)
        auth = kerberos.authGSSClientResponse(self._kerberos_context)
        return request.RequestMessage('', 'authentication', {'sasl': auth})
Exemple #8
0
    def get_username(self, challenge):
        """
        Get the user name of the principal authenticated via the now complete
        GSSAPI client-side operations.

        @param challenge: a string containing the base64-encoded server data
        @return:          a string containing the user name.
        """
        result_code = yield self._step(challenge)
        if result_code != kerberos.AUTH_GSS_COMPLETE:
            raise Exception('kerberos authGSSClientStep failed ({0}). '
                            'challenge={1}'.format(result_code, challenge))
        defer.returnValue(kerberos.authGSSClientUserName(self._context))
Exemple #9
0
def get_current_principal():
    try:
        import kerberos
        rc, vc = kerberos.authGSSClientInit("notempty")
        rc = kerberos.authGSSClientInquireCred(vc)
        username = kerberos.authGSSClientUserName(vc)
        kerberos.authGSSClientClean(vc)
        return unicode(username)
    except ImportError:
        raise RuntimeError('python-kerberos is not available.')
    except kerberos.GSSError, e:
        #TODO: do a kinit?
        raise errors.CCacheError()
Exemple #10
0
def get_current_principal():
    try:
        import kerberos
        rc, vc = kerberos.authGSSClientInit("notempty")
        rc = kerberos.authGSSClientInquireCred(vc)
        username = kerberos.authGSSClientUserName(vc)
        kerberos.authGSSClientClean(vc)
        return unicode(username)
    except ImportError:
        raise RuntimeError('python-kerberos is not available.')
    except kerberos.GSSError, e:
        #TODO: do a kinit?
        raise errors.CCacheError()
Exemple #11
0
def noImpersonationCalls(args):
   """
   A non impersonated call using the kerberos package.
   """
   
   import kerberos
   _ignore, ctx = kerberos.authGSSClientInit(args.servicename)

   h = getConn(args.host, args.port)
   callserver(h, args.path, ctx, kerberos.authGSSClientStep, kerberos.authGSSClientResponse)

   callserver(h, args.path, ctx, kerberos.authGSSClientStep, kerberos.authGSSClientResponse)
   print "username", kerberos.authGSSClientUserName(ctx)
   kerberos.authGSSClientClean(ctx) # clean up
Exemple #12
0
    def get_username(self, challenge):
        """
        Get the user name of the principal authenticated via the now complete
        GSSAPI client-side operations.

        @param challenge: a string containing the base64-encoded server data
        @return:          a string containing the user name.
        """
        result_code = self._step(challenge)
        if result_code != kerberos.AUTH_GSS_COMPLETE:
            raise Exception('kerberos authGSSClientStep failed ({0}). '
                            'challenge={1}'
                            .format(result_code, challenge))
        return kerberos.authGSSClientUserName(self._context)
Exemple #13
0
    def do_collect(self, conn_info, enum_infos):
        """
        conn_info has the following attributes
            hostname
            auth_type: basic or kerberos
            username
            password
            scheme: http (https coming soon)
            port: int
        """
        client = EnumerateClient(conn_info)
        items = {}
        for enum_info in enum_infos:
            try:
                items[enum_info] = yield client.enumerate(
                    enum_info.wql, enum_info.resource_uri)
            except (UnauthorizedError, ForbiddenError):
                # Fail the collection for general errors.
                raise
            except RequestError:
                # Store empty results for other query-specific errors.
                continue

        try:
            assert(conn_info.username.lower() == authGSSClientUserName(
                client.session()._gssclient._context).lower())
        except Exception:
            print 'ERROR: Expected and Actual usernames do not match for host'\
                  ' {}'.format(conn_info.hostname)
            print 'Expected username: {}, Actual username {}'.format(
                conn_info.username,
                authGSSClientUserName(client.session()._gssclient._context))
        else:
            print 'Expected and Actual usernames match for host {}: {}'\
                .format(conn_info.hostname, conn_info.username)
        defer.returnValue(None)
Exemple #14
0
    def do_collect(self, conn_info, enum_infos):
        """
        conn_info has the following attributes
            hostname
            auth_type: basic or kerberos
            username
            password
            scheme: http (https coming soon)
            port: int
        """
        client = EnumerateClient(conn_info)
        items = {}
        for enum_info in enum_infos:
            try:
                items[enum_info] = yield client.enumerate(
                    enum_info.wql, enum_info.resource_uri)
            except (UnauthorizedError, ForbiddenError):
                # Fail the collection for general errors.
                raise
            except RequestError:
                # Store empty results for other query-specific errors.
                continue

        try:
            assert (conn_info.username.lower() == authGSSClientUserName(
                client._connection._gssclient._context).lower())
        except Exception:
            print 'ERROR: Expected and Actual usernames do not match for host'\
                  ' {}'.format(conn_info.hostname)
            print 'Expected username: {}, Actual username {}'.format(
                conn_info.username,
                authGSSClientUserName(client._connection._gssclient._context))
        else:
            print 'Expected and Actual usernames match for host {}: {}'\
                .format(conn_info.hostname, conn_info.username)
        defer.returnValue(None)
Exemple #15
0
def noImpersonationCalls(args):
    """
   A non impersonated call using the kerberos package.
   """

    import kerberos
    _ignore, ctx = kerberos.authGSSClientInit(args.servicename)

    h = getConn(args.host, args.port)
    callserver(h, args.path, ctx, kerberos.authGSSClientStep,
               kerberos.authGSSClientResponse)

    callserver(h, args.path, ctx, kerberos.authGSSClientStep,
               kerberos.authGSSClientResponse)
    print "username", kerberos.authGSSClientUserName(ctx)
    kerberos.authGSSClientClean(ctx)  # clean up
Exemple #16
0
 def _set_username(self, **kwargs):
     if self._username is not None:
         return
     try:
         (ret, ctx) = kerberos.authGSSClientInit('*****@*****.**')
         assert (ret == kerberos.AUTH_GSS_COMPLETE)
         ret = kerberos.authGSSClientInquireCred(ctx)
         assert (ret == kerberos.AUTH_GSS_COMPLETE)
         # XXX What if you have >1 ticket?
         ret = kerberos.authGSSClientUserName(ctx)
         if '@' in ret:
             self._username = ret.split('@')[0]
         else:
             self._username = ret
     except AssertionError:
         raise ErrataException('Pigeon crap. Did it forget to run kinit?')
Exemple #17
0
 def _set_username(self, **kwargs):
     if self._username is not None:
         return
     try:
         (ret, ctx) = kerberos.authGSSClientInit('*****@*****.**')
         assert (ret == kerberos.AUTH_GSS_COMPLETE)
         ret = kerberos.authGSSClientInquireCred(ctx)
         assert (ret == kerberos.AUTH_GSS_COMPLETE)
         # XXX What if you have >1 ticket?
         ret = kerberos.authGSSClientUserName(ctx)
         if '@' in ret:
             self._username = ret.split('@')[0]
         else:
             self._username = ret
     except AssertionError:
         raise ErrataException('Pigeon crap. Did it forget to run kinit?')
Exemple #18
0
   def _PassthroughLoginGSSAPI(self, host, sessionMgr, passthroughAuthPackage):
      """ Passthrough Authentication """

      userSession = None
      try:
         import kerberos
      except ImportError as err:
         LogException(err)
         return userSession

      context = None
      service = "host@%s" % host
      try:
         result, context = kerberos.authGSSClientInit(service, 0)
         challenge = ""
         while True:
            # Call GSS step
            result = kerberos.authGSSClientStep(context, challenge)
            if result < 0:
               logging.error("authGSSClientStep failed for %s" % service)
               break
            secToken = kerberos.authGSSClientResponse(context)
            try:
               userSession = sessionMgr.LoginBySSPI(secToken)
               # No exception => logged in
               userName = kerberos.authGSSClientUserName(context)
               logging.info("Passthru authentication: Logged in %s as %s" % \
                                                            service, userName)
               del secToken
               break
            except vim.fault.SSPIChallenge as err:
               # Continue gssapi challenges
               challenge = err.base64Token

         del challenge
      except Exception as err:
         LogException(err)
         logging.error("Login failed for %s" % service)

      if context:
         try:
            kerberos.authGSSClientClean(context)
         except Exception as err:
            LogException(err)

      return userSession
Exemple #19
0
def testGSSAPI(service):
    def statusText(r):
        if r == 1:
            return "Complete"
        elif r == 0:
            return "Continue"
        else:
            return "Error"

    rc, vc = kerberos.authGSSClientInit(service)
    print("Status for authGSSClientInit = %s" % statusText(rc))
    if rc != 1:
        return

    rs, vs = kerberos.authGSSServerInit(service)
    print("Status for authGSSServerInit = %s" % statusText(rs))
    if rs != 1:
        return

    rc = kerberos.authGSSClientStep(vc, "")
    print("Status for authGSSClientStep = %s" % statusText(rc))
    if rc != 0:
        return

    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc))
    print("Status for authGSSServerStep = %s" % statusText(rs))
    if rs == -1:
        return

    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs))
    print("Status for authGSSClientStep = %s" % statusText(rc))
    if rc == -1:
        return

    print("Server user name: %s" % kerberos.authGSSServerUserName(vs))
    print("Server target name: %s" % kerberos.authGSSServerTargetName(vs))
    print("Client user name: %s" % kerberos.authGSSClientUserName(vc))

    rc = kerberos.authGSSClientClean(vc)
    print("Status for authGSSClientClean = %s" % statusText(rc))

    rs = kerberos.authGSSServerClean(vs)
    print("Status for authGSSServerClean = %s" % statusText(rs))
Exemple #20
0
def testGSSAPI(service):
    def statusText(r):
        if r == 1:
            return "Complete"
        elif r == 0:
            return "Continue"
        else:
            return "Error"

    rc, vc = kerberos.authGSSClientInit(service);
    print "Status for authGSSClientInit = %s" % statusText(rc);
    if rc != 1:
        return
    
    rs, vs = kerberos.authGSSServerInit(service);
    print "Status for authGSSServerInit = %s" % statusText(rs);
    if rs != 1:
        return
    
    rc = kerberos.authGSSClientStep(vc, "");
    print "Status for authGSSClientStep = %s" % statusText(rc);
    if rc != 0:
        return
    
    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc));
    print "Status for authGSSServerStep = %s" % statusText(rs);
    if rs == -1:
        return
    
    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs));
    print "Status for authGSSClientStep = %s" % statusText(rc);
    if rc == -1:
        return

    print "Server user name: %s" % kerberos.authGSSServerUserName(vs);
    print "Server target name: %s" % kerberos.authGSSServerTargetName(vs);
    print "Client user name: %s" % kerberos.authGSSClientUserName(vc);
    
    rc = kerberos.authGSSClientClean(vc);
    print "Status for authGSSClientClean = %s" % statusText(rc);
    
    rs = kerberos.authGSSServerClean(vs);
    print "Status for authGSSServerClean = %s" % statusText(rs);
Exemple #21
0
 def verify_response(self, auth_header):
     # Handle comma-separated lists of authentication fields
     for field in auth_header.split(','):
         kind, ignored_space, details = field.strip().partition(' ')
         if kind.lower() == 'negotiate':
             auth_details = details.strip()
             break
     else:
         raise ValueError('Negotiate not found in {0}'.format(auth_header))
         # Finish the Kerberos handshake
     krb_context = self._krb_context
     if krb_context is None:
         raise RuntimeError('Ticket already used for verification')
     self._krb_context = None
     kerberos.authGSSClientStep(krb_context, auth_details)
     print(
         'User {0} authenticated successfully using Kerberos authentication'
         .format(kerberos.authGSSClientUserName(krb_context)))
     kerberos.authGSSClientClean(krb_context)
Exemple #22
0
def test_gssapi():
    """
    Return Code Values
        0 = Continue
        1 = Complete
        Other = Error
    """
    service = "HTTP@%s" % hostname
    rc, vc = kerberos.authGSSClientInit(service)
    assert rc == 1, "authGSSClientInit = %d, expecting 1" % rc

    rs, vs = kerberos.authGSSServerInit(service)
    assert rs == 1, "authGSSServerInit = %d, expecting 1" % rs

    rc = kerberos.authGSSClientStep(vc, "")
    assert rc == 0, "authGSSClientStep = %d, expecting 0" % rc

    rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc))
    assert rs != -1, "authGSSServerStep = %d, not expecting it to be -1" % rs

    rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs))
    assert rc != -1, "authGSSClientStep = %d, not expecting it to be -1" % rc

    expected_username = "******" % (username, realm.upper())
    server_user_name = kerberos.authGSSServerUserName(vs)
    assert server_user_name == expected_username, "Invalid server username returned"

    client_user_name = kerberos.authGSSClientUserName(vc)
    assert client_user_name == expected_username, "Invalid client username returned"

    server_target_name = kerberos.authGSSServerTargetName(vs)
    assert server_target_name is None, "Server target name is not None"

    rc = kerberos.authGSSClientClean(vc)
    assert rc == 1, "authGSSClientClean = %d, expecting it to be 0" % rc

    rs = kerberos.authGSSServerClean(vs)
    assert rs == 1, "authGSSServerClean = %d, expecting it to be 0" % rs
Exemple #23
0
    def __request_authenticate(self, method, url, body, extra_hdrs):
        self.__probe_mechanisms()

        try:
            result, gssctx = kerberos.authGSSClientInit(self.__spn,
                                                        principal=self.__upn)
        except kerberos.GSSError as ex:
            raise Krb5Error('%s (%s)' % (ex[0][0], ex[1][0]))

        response = None
        blob = ''

        while True:
            try:
                result, blob = self.__challenge(gssctx, blob)
            except Krb5Error as ex:
                kerberos.authGSSClientClean(gssctx)
                raise ex

            if result:
                self.__upn = kerberos.authGSSClientUserName(gssctx)
                break

            self.close()
            extra_hdrs['Authorization'] = 'Negotiate %s' % (blob, )
            response = davlib.DAV._request(self, method, url, body, extra_hdrs)

            self.__store_cookies(response)
            authstr = response.getheader('www-authenticate')
            (mech, blob) = authstr.split(' ')

            persistauth = response.getheader('persistent-auth')
            self.__persistauth = persistauth == 'true'

        kerberos.authGSSClientClean(gssctx)
        return response
 def finish(self, data):
     self.username = kerberos.authGSSClientUserName(self._gss)
     logger.debug("Authenticated as {0!r}".format(
                                 kerberos.authGSSClientUserName(self._gss)))
     return Success({"username": self.username, "authzid": self.authzid})
Exemple #25
0
    def process(self, challenge=None):
        if not self._have_negotiated_details:
            kerberos.authGSSClientStep(self.context, '')
            _negotiated_details = kerberos.authGSSClientResponse(self.context)
            self._have_negotiated_details = True
            return base64.b64decode(_negotiated_details)

        challenge = base64.b64encode(challenge)
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return ''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = ''
            return response

        kerberos.authGSSClientUnwrap(self.context, challenge)
        data = kerberos.authGSSClientResponse(self.context)
        plaintext_data = base64.b64decode(data)
        if len(plaintext_data) != 4:
            raise SASLProtocolException(
                "Bad response from server")  # todo: better message

        layers_supported, = struct.unpack('B', plaintext_data[0])
        server_offered_qops = []
        if 0x01 & layers_supported:
            server_offered_qops.append('auth')
        if 0x02 & layers_supported:
            server_offered_qops.append('auth-int')
        if 0x04 & layers_supported:
            server_offered_qops.append('auth-conf')

        self._pick_qop(server_offered_qops)

        max_length, = struct.unpack('!i', '\x00' + plaintext_data[1:])
        self.max_buffer = min(self.sasl.max_buffer, max_length)
        """
        Construct the reply.

        byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
        byte 1-3: the max length for any buffer sent back and forth on
            this connection. (big endian)
        the rest of the buffer: the authorization user name in UTF-8 -
            not null terminated.

        So, we write the max length and authorization user name first, then
        overwrite the first byte of the buffer with the qop.  This is ok since
        the max length is writen out in big endian.
        """
        i = len(self.user)
        fmt = '!I' + str(i) + 's'
        outdata = create_string_buffer(4 + i)
        struct.pack_into(fmt, outdata, 0, self.max_buffer, self.user)

        qop = 1
        if self.qop == 'auth-int':
            qop = 2
        elif self.qop == 'auth-conf':
            qop = 4
        struct.pack_into('!B', outdata, 0, qop)

        encodeddata = base64.b64encode(outdata)

        kerberos.authGSSClientWrap(self.context, encodeddata)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)
Exemple #26
0
 def username(self):
     return kerberos.authGSSClientUserName(self.context)
Exemple #27
0
    def process(self, challenge=None):
        if not self._have_negotiated_details:
            kerberos.authGSSClientStep(self.context, '')
            _negotiated_details = kerberos.authGSSClientResponse(self.context)
            self._have_negotiated_details = True
            return base64.b64decode(_negotiated_details)

        challenge = base64.b64encode(challenge)
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return ''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = ''
            return response

        ret = kerberos.authGSSClientUnwrap(self.context, challenge)
        data = kerberos.authGSSClientResponse(self.context)
        plaintext_data = base64.b64decode(data)
        if len(plaintext_data) != 4:
            raise SASLProtocolException("Bad response from server")  # todo: better message

        layers_supported, = struct.unpack('B', plaintext_data[0])
        server_offered_qops = []
        if 0x01 & layers_supported:
            server_offered_qops.append('auth')
        if 0x02 & layers_supported:
            server_offered_qops.append('auth-int')
        if 0x04 & layers_supported:
            server_offered_qops.append('auth-conf')

        self._pick_qop(server_offered_qops)

        max_length, = struct.unpack('!i', '\x00' + plaintext_data[1:])
        self.max_buffer = min(self.sasl.max_buffer, max_length)

        """
        Construct the reply.

        byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
        byte 1-3: the max length for any buffer sent back and forth on
            this connection. (big endian)
        the rest of the buffer: the authorization user name in UTF-8 -
            not null terminated.

        So, we write the max length and authorization user name first, then
        overwrite the first byte of the buffer with the qop.  This is ok since
        the max length is writen out in big endian.
        """
        i = len(self.user)
        fmt = '!I' + str(i) + 's'
        outdata = create_string_buffer(4 + i)
        struct.pack_into(fmt, outdata, 0, self.max_buffer, self.user)

        qop = 1
        if self.qop == 'auth-int':
            qop = 2
        elif self.qop == 'auth-conf':
            qop = 4
        struct.pack_into('!B', outdata, 0, qop)

        encodeddata = base64.b64encode(outdata)

        ret = kerberos.authGSSClientWrap(self.context, data)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)
Exemple #28
0
# set up headers
url = "http://{k_hostname}:5985/wsman".format(k_hostname=k_hostname)
k_headers = _ENCRYPTED_CONTENT_TYPE

kerbkey = 'Kerberos {0}'.format(base64_client_data)

i_headers = _CONTENT_TYPE
i_headers['Authorization'] = kerbkey
s.headers.update({'Accept-Encoding': '*'})
resp = s.request('POST', url, headers=i_headers)

kind, challenge = resp.headers['www-authenticate'].strip().split(' ', 1)
rc = kerberos.authGSSClientStep(context, challenge)
if rc == kerberos.AUTH_GSS_COMPLETE:
    print("Authenticated {0}".format(kerberos.authGSSClientUserName(context)))

# load request template and create payload
path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                    'enumerate.xml')
with open(path) as f:
    request_template = _XML_WHITESPACE_PATTERN.sub('><', f.read()).strip()

payload = request_template.format(resource_uri=DEFAULT_RESOURCE_URI, wql=query)
payload_xml = xml.dom.minidom.parseString(payload)
pretty_xml_as_string = payload_xml.toprettyxml(indent="  ")
print(
    "Enumeration payload before encryption:\n{0}".format(pretty_xml_as_string))
req = bytes(payload)

orig_len = len(payload)
Exemple #29
0
    def _get_token_with_kerberos(self):
        """Authenticate with a Kerberos ticket."""
        if kerberos is None:
            raise RuntimeError("Kerberos package not found.  Run 'pip "
                               "install sasctl[kerberos]' to install.")

        user = self._settings.get('username')
        # realm = user.rsplit('@', maxsplit=1)[-1] if '@' in user else None
        client_id = 'sas.tkmtrb'
        flags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG
        service = 'HTTP@%s' % self._settings['domain']

        logger.info('Attempting Kerberos authentication to %s as %s' %
                    (service, user))

        url = self._build_url(
            '/SASLogon/oauth/authorize?client_id=%s&response_type=token' %
            client_id)

        # Get Kerberos challenge
        r = self.get(url, allow_redirects=False, verify=self.verify)

        if r.status_code != 401:
            raise ValueError('Kerberos challenge response not received.  '
                             'Expected HTTP 401 but received %s' %
                             r.status_code)

        if 'www-authenticate' not in r.headers:
            raise ValueError("Kerberos challenge response not received.  "
                             "'WWW-Authenticate' header not received.")

        if 'Negotiate' not in r.headers['www-authenticate']:
            raise ValueError("Kerberos challenge response not received.  "
                             "'WWW-Authenticate' header contained '%s', "
                             "expected 'Negotiate'." %
                             r.headers['www-authenticate'])

        # Initialize a request to KDC for a ticket to access the service.
        _, context = kerberos.authGSSClientInit(service,
                                                principal=user,
                                                gssflags=flags)

        # Send the request.
        # NOTE: empty-string parameter required for initial call.
        kerberos.authGSSClientStep(context, '')

        # Get the KDC response
        auth_header = 'Negotiate %s' % kerberos.authGSSClientResponse(context)

        # Get the user that was used for authentication
        username = kerberos.authGSSClientUserName(context)
        logger.info('Authenticated as %s' % username)

        # Drop @REALM from username and store
        if username is not None:
            self._settings['username'] = username.rsplit('@', maxsplit=1)[0]

        # Response to Kerberos challenge with ticket
        r = self.get(url,
                     headers={'Authorization': auth_header},
                     allow_redirects=False,
                     verify=self.verify)

        if 'Location' not in r.headers:
            raise ValueError("Invalid authentication response."
                             "'Location' header not received.")

        match = re.search('(?<=access_token=)[^&]*', r.headers['Location'])

        if match is None:
            raise ValueError("Invalid authentication response.  'Location' "
                             "header does not contain an access token.")

        return match.group(0)
Exemple #30
0
 def username(self):
     return kerberos.authGSSClientUserName(self.context)
Exemple #31
0
 def finish(self, data):
     self.username = kerberos.authGSSClientUserName(self._gss)
     self.__logger.debug("Authenticated as %s" % kerberos.authGSSClientUserName(self._gss))
     return Success(self.username,None,self.authzid)
 def finish(self, data):
     self.username = kerberos.authGSSClientUserName(self._gss)
     logger.debug("Authenticated as {0!r}".format(
         kerberos.authGSSClientUserName(self._gss)))
     return Success(self.username, None, self.authzid)
Exemple #33
0
 def verify_response(self, auth_header):
     # Handle comma-separated lists of authentication fields
     for field in auth_header.split(','):
         kind, ignored_space, details = field.strip().partition(' ')
         if kind.lower() == 'negotiate':
             auth_details = details.strip()
             break
     else:
         raise ValueError('Negotiate not found in {0}'.format(auth_header))
         # Finish the Kerberos handshake
     krb_context = self._krb_context
     if krb_context is None:
         raise RuntimeError('Ticket already used for verification')
     self._krb_context = None
     kerberos.authGSSClientStep(krb_context, auth_details)
     print('User {0} authenticated successfully using Kerberos authentication'.format(kerberos.authGSSClientUserName(krb_context)))
     kerberos.authGSSClientClean(krb_context)
Exemple #34
0
# set up headers
url = "http://{k_hostname}:5985/wsman".format(k_hostname=k_hostname)
k_headers = _ENCRYPTED_CONTENT_TYPE

kerbkey = 'Kerberos {0}'.format(base64_client_data)

i_headers = _CONTENT_TYPE
i_headers['Authorization'] = kerbkey
s.headers.update({'Accept-Encoding': '*'})
resp = s.request('POST', url, headers=i_headers)

kind, challenge = resp.headers['www-authenticate'].strip().split(' ',1)
rc = kerberos.authGSSClientStep(context,challenge)
if rc == kerberos.AUTH_GSS_COMPLETE:
    print("Authenticated {0}".format(kerberos.authGSSClientUserName(context)))

# load request template and create payload
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'enumerate.xml')
with open(path) as f:
    request_template = _XML_WHITESPACE_PATTERN.sub('><', f.read()).strip()

payload = request_template.format(resource_uri=DEFAULT_RESOURCE_URI,wql=query)
payload_xml = xml.dom.minidom.parseString(payload)
pretty_xml_as_string = payload_xml.toprettyxml(indent="  ")
print("Enumeration payload before encryption:\n{0}".format(pretty_xml_as_string))
req = bytes(payload)

orig_len = len(payload)
ereq = base64.b64encode(payload)
rc,pad_len = kerberos.authGSSClientWrapIov(context,ereq,1)