Esempio n. 1
0
    def connect_to_exchange_as_current_user(self, smtp):
        # Send the SMTP EHLO command
        code, response = smtp.ehlo()
        if code != self._config.SMTP_EHLO_OKAY:
            raise SMTPException(
                "Server did not respond as expected to EHLO command")

        sspiclient = sspi.ClientAuth('NTLM')

        # Generate the NTLM Type 1 message
        sec_buffer = None
        err, sec_buffer = sspiclient.authorize(sec_buffer)
        ntlm_message = self.asbase64(sec_buffer[0].Buffer)

        # Send the NTLM Type 1 message -- Authentication Request
        code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)

        # Verify the NTLM Type 2 response -- Challenge Message
        if code != self._config.SMTP_AUTH_CHALLENGE:
            raise SMTPException(
                "Server did not respond as expected to NTLM negotiate message")

        # Generate the NTLM Type 3 message
        err, sec_buffer = sspiclient.authorize(base64.decodestring(response))
        ntlm_message = self.asbase64(sec_buffer[0].Buffer)

        # Send the NTLM Type 3 message -- Response Message
        #code, response = smtp.docmd("", ntlm_message)
        code, response = smtp.docmd(ntlm_message)
        if code != self._config.SMTP_AUTH_OKAY:
            raise SMTPAuthenticationError(code, response)
Esempio n. 2
0
    def _connect_to_exchange(self, smtp):
        code, response = smtp.ehlo()
        if code != SMTP_EHLO_OKAY:
            logging.error("Server did not respond as expected to EHLO command")
            raise smtplib.SMTPException(
                "Server did not respond as expected to EHLO command")
        sspiclient = sspi.ClientAuth('NTLM')

        # Generate the NTLM Type 1 message
        sec_buffer = None
        err, sec_buffer = sspiclient.authorize(sec_buffer)
        ntlm_message = asbase64(sec_buffer[0].Buffer)

        # Send the NTLM Type 1 message -- Authentication Request
        code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)

        # Verify the NTLM Type 2 response -- Challenge Message
        if code != SMTP_AUTH_CHALLENGE:
            logging.error(
                "Server did not respond as expected to NTLM negotiate message")
            raise smtplib.SMTPException(
                "Server did not respond as expected to NTLM negotiate message")

        # Generate the NTLM Type 3 message
        err, sec_buffer = sspiclient.authorize(base64.decodebytes(response))
        ntlm_message = asbase64(sec_buffer[0].Buffer)

        # Send the NTLM Type 3 message -- Response Message
        code, response = smtp.docmd("", ntlm_message)
        if code != SMTP_AUTH_OKAY:
            logging.error("SMTPAuthenticationError")
            raise smtplib.SMTPAuthenticationError(code, response)
        # if this part is reached, the authentication was succesfull and emails can be sent.
        pass
Esempio n. 3
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
Esempio n. 4
0
def connect_to_exchange_as_current_user(smtp):
    """Example:
 >>> import smtplib
 >>> smtp = smtplib.SMTP("mail.huajingsec.com")
 >>> connect_to_exchange_as_current_user(smtp)
 """
    # Send the SMTP EHLO command
    code, response = smtp.ehlo()
    if code != SMTP_EHLO_OKAY:
        raise SMTPException(
            "Server did not respond as expected to EHLO command")
    sspiclient = sspi.ClientAuth('NTLM')
    # Generate the NTLM Type 1 message
    sec_buffer = None
    err, sec_buffer = sspiclient.authorize(sec_buffer)
    print(sec_buffer)
    ntlm_message = asbase64(sec_buffer[0].Buffer)
    # Send the NTLM Type 1 message -- Authentication Request
    code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)
    # Verify the NTLM Type 2 response -- Challenge Message
    if code != SMTP_AUTH_CHALLENGE:
        raise SMTPException(
            "Server did not respond as expected to NTLM negotiate message")
    # Generate the NTLM Type 3 message
    err, sec_buffer = sspiclient.authorize(
        base64.b64decode(response.encode(encoding='utf-8')))
    ntlm_message = asbase64(sec_buffer[0].Buffer)
    # Send the NTLM Type 3 message -- Response Message
    code, response = smtp.docmd(ntlm_message)
    # code, response = smtp.docmd("", ntlm_message)
    if code != SMTP_AUTH_OKAY:
        raise SMTPAuthenticationError(code, response)
Esempio n. 5
0
File: px.py Progetto: 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
Esempio n. 6
0
 def _create_sspi_authenticator(self, auth_info, targetspn, scflags):
     # Use the Negotiate package which means we'll use Kerberos if it's
     # supported/available and fall back to NTLM otherwise.
     ca = sspi.ClientAuth("Negotiate",
                          auth_info=auth_info,
                          targetspn=targetspn,
                          scflags=scflags)
     return ca
Esempio n. 7
0
 def _create_sspi_authenticator(self, auth_info, targetspn, scflags):
     # explicitly specifying 'Kerberos' or 'NTLM' will also work
     # here, but technically if we say the SASL type is GSS-SPNEGO,
     # we're supposed to use 'Negotiate'
     ca = sspi.ClientAuth('Negotiate',
                          auth_info=auth_info,
                          targetspn=targetspn,
                          scflags=scflags)
     return ca
    def do_ntlm_auth(self, resp_auth_hdr, req_auth_hdr, resp, kwargs):
        if hasattr(resp.request.body, "seek"):
            content_length = int(
                resp.request.headers.get("Content-Length", "0"))
            if content_length > 0:
                resp.request.body.seek(-content_length, 1)
            else:
                resp.request.body.seek(0, 0)

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        resp.content
        resp.raw.release_conn()
        new_req = resp.request.copy()

        # Prepare authorization header for the new request.
        ca = sspi.ClientAuth("NTLM",
                             auth_info=(self.username, self.domain,
                                        self.password))
        _, data = ca.authorize(None)
        new_req.headers[req_auth_hdr] = "NTLM %s" % base64.b64encode(
            data[0].Buffer)

        # A streaming response breaks authentication.
        #
        # This can be fixed by not streaming this request, which is safe
        # because the returned resp3 will still have stream=True set if
        # specified in kwargs. In addition, we expect this request to give us a
        # challenge and not the real content, so the content will be short
        # anyway.
        kwargs_nostream = dict(kwargs, stream=False)
        resp2 = resp.connection.send(new_req, **kwargs_nostream)

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        resp2.content
        resp2.raw.release_conn()
        new_req = resp2.request.copy()

        challenge = resp2.headers[resp_auth_hdr]
        challenge = filter(lambda s: s.startswith("NTLM "),
                           challenge.split(","))[0].strip().split()[1]
        challenge = base64.b64decode(challenge)

        # Build response of challenge
        _, data = ca.authorize(challenge)
        new_req.headers[req_auth_hdr] = "NTLM %s" % base64.b64encode(
            data[0].Buffer)

        resp3 = resp2.connection.send(new_req, **kwargs)

        # Update the history
        resp3.history.append(resp)
        resp3.history.append(resp2)

        return resp3
Esempio n. 9
0
    def _doAuth(self, pkg_name):
        sspiclient = sspi.ClientAuth(pkg_name, targetspn=win32api.GetUserName())
        sspiserver = sspi.ServerAuth(pkg_name)

        sec_buffer = None
        err = 1
        while err != 0:
            err, sec_buffer = sspiclient.authorize(sec_buffer)
            err, sec_buffer = sspiserver.authorize(sec_buffer)
        return sspiclient, sspiserver
Esempio n. 10
0
    def ssh_init_sec_context(self,
                             target,
                             desired_mech=None,
                             username=None,
                             recv_token=None):
        """
        Initialize a SSPI context.

        :param str username: The name of the user who attempts to login
        :param str target: The FQDN of the target to connect to
        :param str desired_mech: The negotiated SSPI mechanism
                                 ("pseudo negotiated" mechanism, because we
                                 support just the krb5 mechanism :-))
        :param recv_token: The SSPI token received from the Server
        :raises:
            `.SSHException` -- Is raised if the desired mechanism of the client
            is not supported
        :return: A ``String`` if the SSPI has returned a token or ``None`` if
                 no token was returned
        """
        from pyasn1.codec.der import decoder

        self._username = username
        self._gss_host = target
        error = 0
        targ_name = "host/" + self._gss_host
        if desired_mech is not None:
            mech, __ = decoder.decode(desired_mech)
            if mech.__str__() != self._krb5_mech:
                raise SSHException("Unsupported mechanism OID.")
        try:
            if recv_token is None:
                self._gss_ctxt = sspi.ClientAuth("Kerberos",
                                                 scflags=self._gss_flags,
                                                 targetspn=targ_name)
            error, token = self._gss_ctxt.authorize(recv_token)
            token = token[0].Buffer
        except pywintypes.error as e:
            e.strerror += ", Target: {}".format(e, self._gss_host)
            raise

        if error == 0:
            """
            if the status is GSS_COMPLETE (error = 0) the context is fully
            established an we can set _gss_ctxt_status to True.
            """
            self._gss_ctxt_status = True
            token = None
            """
            You won't get another token if the context is fully established,
            so i set token to None instead of ""
            """
        return token
Esempio n. 11
0
    def init_context(self):
        flags = sspicon.ISC_REQ_INTEGRITY | \
                sspicon.ISC_REQ_CONFIDENTIALITY | \
                sspicon.ISC_REQ_REPLAY_DETECT | \
                sspicon.ISC_REQ_SEQUENCE_DETECT | \
                sspicon.ISC_REQ_MUTUAL_AUTH

        self._context = sspi.ClientAuth(pkg_name=self.auth_provider,
                                        auth_info=(self.username, self.domain,
                                                   self.password),
                                        targetspn=self._target_spn,
                                        scflags=flags)
Esempio n. 12
0
 def fixup(self):
     try:
         fullName = self.context.getFullname()
         xml = self.getXml()
         firstFullName = str(
             xml.xpath(self.firstSend)[0].get("fullName"))
         firstFullName = firstFullName[firstFullName.index('.') + 1:]
         if fullName.find(
                 firstFullName
         ) > -1 and SspiAuthenticationFixup._firstObj != self.context:
             #scflags = sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|\
             #	sspicon.ISC_REQ_REPLAY_DETECT|sspicon.ISC_REQ_CONFIDENTIALITY
             scflags = sspicon.ISC_REQ_INTEGRITY | sspicon.ISC_REQ_SEQUENCE_DETECT | \
                       sspicon.ISC_REQ_REPLAY_DETECT
             SspiAuthenticationFixup._firstObj = self.context
             SspiAuthenticationFixup._sspi = sspi.ClientAuth(
                 "Negotiate",
                 "",  # client_name
                 (self.username, self.workgroup,
                  self.password),  # auth_info
                 None,  # targetsn (target security context provider)
                 scflags,  #scflags	# None,	# security context flags
             )
             (done,
              data) = SspiAuthenticationFixup._sspi.authorize(None)
             data = data[0].Buffer
             SspiAuthenticationFixup._data = data
             return data
         if fullName.find(firstFullName) > -1:
             return SspiAuthenticationFixup._data
         secondFullName = str(
             xml.xpath(self.secondSend)[0].get("fullName"))
         secondFullName = secondFullName[secondFullName.index('.') + 1:]
         if fullName.find(
                 secondFullName
         ) > -1 and SspiAuthenticationFixup._secondObj != self.context:
             inputData = self.context.getInternalValue()
             if len(inputData) < 5:
                 return None
             (done,
              data) = SspiAuthenticationFixup._sspi.authorize(inputData)
             data = data[0].Buffer
             SspiAuthenticationFixup._secondObj = self.context
             SspiAuthenticationFixup._data = data
             return data
         if fullName.find(secondFullName) > -1:
             return SspiAuthenticationFixup._data
     except:
         print("!!! EXCEPTION !!!")
         print(repr(sys.exc_info()))
         pass
Esempio n. 13
0
def connectMSExchange(server):
    """
    Creates a connection for the inputted server to a Microsoft Exchange server.

    :param      server | <smtplib.SMTP>
    
    :usage      |>>> import smtplib
                |>>> import projex.notify
                |>>> smtp = smtplib.SMTP('mail.server.com')
                |>>> projex.notify.connectMSExchange(smtp)
    
    :return     (<bool> success, <str> reason)
    """
    if not sspi:
        return False, 'No sspi module found.'

    # send the SMTP EHLO command
    code, response = server.ehlo()
    if code != SMTP_EHLO_OKAY:
        return False, 'Server did not respond to EHLO command.'

    sspi_client = sspi.ClientAuth('NTLM')

    # generate NTLM Type 1 message
    sec_buffer = None
    err, sec_buffer = sspi_client.authorize(sec_buffer)
    # noinspection PyShadowingBuiltins
    buffer = sec_buffer[0].Buffer
    ntlm_message = base64.encodestring(buffer).replace('\n', '')

    # send NTLM Type 1 message -- Authentication Request
    code, response = server.docmd('AUTH', 'NTLM ' + ntlm_message)

    # verify the NTLM Type 2 response -- Challenge Message
    if code != SMTP_AUTH_CHALLENGE:
        msg = 'Server did not respond as expected to NTLM negotiate message'
        return False, msg

    # generate NTLM Type 3 message
    err, sec_buffer = sspi_client.authorize(base64.decodestring(response))
    # noinspection PyShadowingBuiltins
    buffer = sec_buffer[0].Buffer
    ntlm_message = base64.encodestring(buffer).replace('\n', '')

    # send the NTLM Type 3 message -- Response Message
    code, response = server.docmd('', ntlm_message)
    if code != SMTP_AUTH_OKAY:
        return False, response

    return True, ''
Esempio n. 14
0
    def __init__(self, pkgName):
        PI.IClientAuthenticationPlugin.__init__(self)
        flags = sspicon.ISC_REQ_INTEGRITY       | \
                sspicon.ISC_REQ_SEQUENCE_DETECT | \
                sspicon.ISC_REQ_REPLAY_DETECT   | \
                sspicon.ISC_REQ_CONFIDENTIALITY | \
                sspicon.ISC_REQ_DELEGATE
        #ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
        #ISC_REQ_MUTUAL_AUTH |ISC_REQ_REPLAY_DETECT |
        #ISC_REQ_SEQUENCE_DETECT |ISC_REQ_CONFIDENTIALITY |
        #ISC_REQ_CONNECTION

        self.mClient = sspi.ClientAuth(pkgName, scflags=flags)
        self.mAvatar = None
        self.mAuthenticationDeferred = twisted.internet.defer.Deferred()
Esempio n. 15
0
    def __connect_to_exchange(self, smtp):
        '''
        Connects to an exchange server for SMTP authentication.  This uses NTLM
        method which attempts to authenticate as the currently logged in user.

        This means whatever account is used to run this process must have
        access to the exchange server for sending email.

        Example:
        >>> import smtplib
        >>> smtp = smtplib.SMTP("my.smtp.server")
        >>> __connect_to_exchange(smtp)
        '''
        # NTLM Guide -- http://curl.haxx.se/rfc/ntlm.html

        # Send the SMTP EHLO command
        code, response = smtp.ehlo()
        if code != SMTP_EHLO_OKAY:
            raise SMTPException(
                "Server did not respond as expected to EHLO command")

        sspiclient = sspi.ClientAuth('NTLM')  # login as current user

        # Generate the NTLM Type 1 message
        sec_buffer = None
        err, sec_buffer = sspiclient.authorize(sec_buffer)
        ntlm_message = self.__asbase64(sec_buffer[0].Buffer)

        # Send the NTLM Type 1 message -- Authentication Request
        code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)

        # Verify the NTLM Type 2 response -- Challenge Message
        if code != SMTP_AUTH_CHALLENGE:
            raise SMTPException(
                "Server did not respond as expected to NTLM negotiate message")

        # Generate the NTLM Type 3 message
        err, sec_buffer = sspiclient.authorize(base64.decodestring(response))
        ntlm_message = self.__asbase64(sec_buffer[0].Buffer)

        if err:
            self.__root_logger.warning(('Error while authenticating to '
                                        'exchange server'))

        # Send the NTLM Type 3 message -- Response Message
        code, response = smtp.docmd("", ntlm_message)
        if code != SMTP_AUTH_OKAY:
            raise SMTPAuthenticationError(code, response)
Esempio n. 16
0
def get_krb_http_auth(host):
    hostname = host.split(':')[0] # remove port
    if os.name == 'nt':
        s = sspi.ClientAuth('Kerberos', targetspn="HTTP/" + hostname)
        a,b = s.authorize(None)
        auth = encodestring(b[0].Buffer).replace("\012", "")
    else:
        # On Linux need kerberos.so. Getting kerberos.so:
        # git clone https://github.com/apple/ccs-pykerberos.git
        # cd ccs-pykerberos.git
        # python setup.py build
        # --> kerberos.so in build/libxxx/ --> copy to same dir as python code
        __, krb_context = kerberos.authGSSClientInit("HTTP@" + hostname)
        kerberos.authGSSClientStep(krb_context, "")
        auth = kerberos.authGSSClientResponse(krb_context)
    return auth
    def __init__(self, username, password, server):
        log.info("Setting up SSPI Security Context for Windows auth")
        self._call_counter = 0

        flags = sspicon.ISC_REQ_INTEGRITY | \
            sspicon.ISC_REQ_CONFIDENTIALITY | \
            sspicon.ISC_REQ_REPLAY_DETECT | \
            sspicon.ISC_REQ_SEQUENCE_DETECT | \
            sspicon.ISC_REQ_MUTUAL_AUTH

        domain, username = _split_username_and_domain(username)
        # We could use the MECH to derive the package name but we are just
        # better off using Negotiate and lettings Windows do all the heavy
        # lifting.
        self._context = sspi.ClientAuth(pkg_name='Negotiate',
                                        auth_info=(username, domain, password),
                                        targetspn="cifs/%s" % server,
                                        scflags=flags)
Esempio n. 18
0
def sspi_client():
    c = http.client.HTTPConnection("localhost", options.port)
    c.connect()
    # Do the auth dance.
    ca = sspi.ClientAuth(options.package, targetspn=options.target_spn)
    data = None
    while 1:
        err, out_buf = ca.authorize(data)
        _send_msg(c.sock, out_buf[0].Buffer)
        if err == 0:
            break
        data = _get_msg(c.sock)
    print("Auth dance complete - sending a few encryted messages")
    # Assume out data is sensitive - encrypt the message.
    for data in "Hello from the client".split():
        blob, key = ca.encrypt(data)
        _send_msg(c.sock, blob)
        _send_msg(c.sock, key)
    c.sock.close()
    print("Client completed.")
Esempio n. 19
0
   def _PassthroughLoginSSPI(self, host, sessionMgr, passthroughAuthPackage):
      """ Passthrough Authentication """
      userSession = None

      try:
         from base64 import b64encode, b64decode
         import sspi
      except ImportError as err:
         LogException(err)
         return userSession

      try:
         # Create client authorization
         clientAuth = sspi.ClientAuth(passthroughAuthPackage)
         secBufDesc = None
         outSecBufDesc = None
         err = True
         while err:
            # Call authorization API
            err, outSecBufDesc = clientAuth.authorize(secBufDesc)
            # LoginBySSPI requires token to be base64 encoded
            secToken = b64encode(outSecBufDesc[0].Buffer)
            try:
               userSession = sessionMgr.LoginBySSPI(secToken)
               # No exception => logged in
               del secToken
               break
            except vim.fault.SSPIChallenge as err:
               # Continue sspi challenges
               # Decode token back to native format
               outSecBufDesc[0].Buffer = b64decode(err.base64Token)
               secBufDesc = outSecBufDesc

         # Cleanup
         del clientAuth
         del outSecBufDesc
      except sspi.error as err:
         logging.error(err.message)

      return userSession
Esempio n. 20
0
 def __init__(self, user=None):
     if not user:
         user = win32api.GetUserName()
     self.sspi_client = sspi.ClientAuth("NTLM", user, scflags=0)
Esempio n. 21
0
    def _gssapi_sspi_test(self):
        """
        Test the used methods of python-gssapi or sspi, sspicon from pywin32.
        """
        try:
            import gssapi

            if (
                hasattr(gssapi, "__title__")
                and gssapi.__title__ == "python-gssapi"
            ):
                _API = "PYTHON-GSSAPI-OLD"
            else:
                _API = "PYTHON-GSSAPI-NEW"
        except ImportError:
            import sspicon
            import sspi

            _API = "SSPI"

        c_token = None
        gss_ctxt_status = False
        mic_msg = b"G'day Mate!"

        if _API == "PYTHON-GSSAPI-OLD":
            if self.server_mode:
                gss_flags = (
                    gssapi.C_PROT_READY_FLAG,
                    gssapi.C_INTEG_FLAG,
                    gssapi.C_MUTUAL_FLAG,
                    gssapi.C_DELEG_FLAG,
                )
            else:
                gss_flags = (
                    gssapi.C_PROT_READY_FLAG,
                    gssapi.C_INTEG_FLAG,
                    gssapi.C_DELEG_FLAG,
                )
            # Initialize a GSS-API context.
            ctx = gssapi.Context()
            ctx.flags = gss_flags
            krb5_oid = gssapi.OID.mech_from_string(self.krb5_mech)
            target_name = gssapi.Name(
                "host@" + self.targ_name, gssapi.C_NT_HOSTBASED_SERVICE
            )
            gss_ctxt = gssapi.InitContext(
                peer_name=target_name, mech_type=krb5_oid, req_flags=ctx.flags
            )
            if self.server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.established
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.AcceptContext()
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.established
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.established:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_mic(mic_msg)

            if self.server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_mic(mic_msg, mic_token)
                self.assertEquals(0, status)
        elif _API == "PYTHON-GSSAPI-NEW":
            if self.server_mode:
                gss_flags = (
                    gssapi.RequirementFlag.protection_ready,
                    gssapi.RequirementFlag.integrity,
                    gssapi.RequirementFlag.mutual_authentication,
                    gssapi.RequirementFlag.delegate_to_peer,
                )
            else:
                gss_flags = (
                    gssapi.RequirementFlag.protection_ready,
                    gssapi.RequirementFlag.integrity,
                    gssapi.RequirementFlag.delegate_to_peer,
                )
            # Initialize a GSS-API context.
            krb5_oid = gssapi.MechType.kerberos
            target_name = gssapi.Name(
                "host@" + self.targ_name,
                name_type=gssapi.NameType.hostbased_service,
            )
            gss_ctxt = gssapi.SecurityContext(
                name=target_name,
                flags=gss_flags,
                mech=krb5_oid,
                usage="initiate",
            )
            if self.server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.complete
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.SecurityContext(usage="accept")
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.complete
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.complete:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_signature(mic_msg)

            if self.server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_signature(mic_msg, mic_token)
                self.assertEquals(0, status)
        else:
            gss_flags = (
                sspicon.ISC_REQ_INTEGRITY
                | sspicon.ISC_REQ_MUTUAL_AUTH
                | sspicon.ISC_REQ_DELEGATE
            )
            # Initialize a GSS-API context.
            target_name = "host/" + socket.getfqdn(self.targ_name)
            gss_ctxt = sspi.ClientAuth(
                "Kerberos", scflags=gss_flags, targetspn=target_name
            )
            if self.server_mode:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertEquals(0, error)
                # Accept a GSS-API context.
                gss_srv_ctxt = sspi.ServerAuth("Kerberos", spn=target_name)
                error, token = gss_srv_ctxt.authorize(c_token)
                s_token = token[0].Buffer
                # Establish the context.
                error, token = gss_ctxt.authorize(s_token)
                c_token = token[0].Buffer
                self.assertEquals(None, c_token)
                self.assertEquals(0, error)
                # Build MIC
                mic_token = gss_ctxt.sign(mic_msg)
                # Check MIC
                gss_srv_ctxt.verify(mic_msg, mic_token)
            else:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertNotEquals(0, error)
Esempio n. 22
0
    def test_2_gssapi_sspi(self):
        """
        Test the used methods of python-gssapi or sspi, sspicon from pywin32.
        """
        _API = "MIT"
        try:
            import gssapi
        except ImportError:
            import sspicon
            import sspi
            _API = "SSPI"

        c_token = None
        gss_ctxt_status = False
        mic_msg = b"G'day Mate!"

        if _API == "MIT":
            if server_mode:
                gss_flags = (gssapi.C_PROT_READY_FLAG, gssapi.C_INTEG_FLAG,
                             gssapi.C_MUTUAL_FLAG, gssapi.C_DELEG_FLAG)
            else:
                gss_flags = (gssapi.C_PROT_READY_FLAG, gssapi.C_INTEG_FLAG,
                             gssapi.C_DELEG_FLAG)
            # Initialize a GSS-API context.
            ctx = gssapi.Context()
            ctx.flags = gss_flags
            krb5_oid = gssapi.OID.mech_from_string(krb5_mech)
            target_name = gssapi.Name("host@" + targ_name,
                                      gssapi.C_NT_HOSTBASED_SERVICE)
            gss_ctxt = gssapi.InitContext(peer_name=target_name,
                                          mech_type=krb5_oid,
                                          req_flags=ctx.flags)
            if server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.established
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.AcceptContext()
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.established
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.established:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_mic(mic_msg)

            if server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_mic(mic_msg, mic_token)
                self.assertEquals(0, status)
        else:
            gss_flags = (sspicon.ISC_REQ_INTEGRITY
                         | sspicon.ISC_REQ_MUTUAL_AUTH
                         | sspicon.ISC_REQ_DELEGATE)
            # Initialize a GSS-API context.
            target_name = "host/" + socket.getfqdn(targ_name)
            gss_ctxt = sspi.ClientAuth("Kerberos",
                                       scflags=gss_flags,
                                       targetspn=target_name)
            if server_mode:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertEquals(0, error)
                # Accept a GSS-API context.
                gss_srv_ctxt = sspi.ServerAuth("Kerberos", spn=target_name)
                error, token = gss_srv_ctxt.authorize(c_token)
                s_token = token[0].Buffer
                # Establish the context.
                error, token = gss_ctxt.authorize(s_token)
                c_token = token[0].Buffer
                self.assertEquals(None, c_token)
                self.assertEquals(0, error)
                # Build MIC
                mic_token = gss_ctxt.sign(mic_msg)
                # Check MIC
                gss_srv_ctxt.verify(mic_msg, mic_token)
            else:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertNotEquals(0, error)
Esempio n. 23
0
    def _retry_using_http_Negotiate_auth(self, response, scheme, args):
        if 'Authorization' in response.request.headers:
            return response

        if self._host is None:
            targeturl = urlparse(response.request.url)
            self._host = targeturl.hostname
            try:
                self._host = socket.getaddrinfo(self._host, None, 0, 0, 0,
                                                socket.AI_CANONNAME)[0][3]
            except socket.gaierror as e:
                _logger.info(
                    'Skipping canonicalization of name %s due to error: %s',
                    self._host, e)

        targetspn = '{}/{}'.format(self._service, self._host)

        # Set up SSPI connection structure
        pkg_info = win32security.QuerySecurityPackageInfo(scheme)
        clientauth = sspi.ClientAuth(scheme,
                                     targetspn=targetspn,
                                     auth_info=self._auth_info)
        sec_buffer = win32security.PySecBufferDescType()

        # Channel Binding Hash (aka Extended Protection for Authentication)
        # If this is a SSL connection, we need to hash the peer certificate, prepend the RFC5929 channel binding type,
        # and stuff it into a SEC_CHANNEL_BINDINGS structure.
        # This should be sent along in the initial handshake or Kerberos auth will fail.
        if hasattr(response, 'peercert') and response.peercert is not None:
            md = hashlib.sha256()
            md.update(response.peercert)
            appdata = 'tls-server-end-point:'.encode('ASCII') + md.digest()
            cbtbuf = win32security.PySecBufferType(
                pkg_info['MaxToken'], sspicon.SECBUFFER_CHANNEL_BINDINGS)
            cbtbuf.Buffer = struct.pack('LLLLLLLL{}s'.format(len(appdata)), 0,
                                        0, 0, 0, 0, 0, len(appdata), 32,
                                        appdata)
            sec_buffer.append(cbtbuf)

        content_length = int(response.request.headers.get(
            'Content-Length', '0'),
                             base=10)

        if hasattr(response.request.body, 'seek'):
            if content_length > 0:
                response.request.body.seek(-content_length, 1)
            else:
                response.request.body.seek(0, 0)

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response.content
        response.raw.release_conn()
        request = response.request.copy()

        # this is important for some web applications that store
        # authentication-related info in cookies
        if response.headers.get('set-cookie'):
            request.headers['Cookie'] = response.headers.get('set-cookie')

        # Send initial challenge auth header
        try:
            error, auth = clientauth.authorize(sec_buffer)
            request.headers['Authorization'] = '{} {}'.format(
                scheme,
                base64.b64encode(auth[0].Buffer).decode('ASCII'))
            _logger.debug(
                'Sending Initial Context Token - error={} authenticated={}'.
                format(error, clientauth.authenticated))
        except pywintypes.error as e:
            _logger.error('Error calling {}: {}'.format(e[1], e[2]),
                          exc_info=e)
            return response

        # A streaming response breaks authentication.
        # This can be fixed by not streaming this request, which is safe
        # because the returned response3 will still have stream=True set if
        # specified in args. In addition, we expect this request to give us a
        # challenge and not the real content, so the content will be short
        # anyway.
        args_nostream = dict(args, stream=False)
        response2 = response.connection.send(request, **args_nostream)

        # Should get another 401 if we are doing challenge-response (NTLM)
        if response2.status_code != 401:
            if response2.status_code == 200:
                # Kerberos may have succeeded; if so, finalize our auth context
                final = response2.headers.get('WWW-Authenticate')
                if final is not None:
                    try:
                        # Sometimes Windows seems to forget to prepend 'Negotiate' to the success response,
                        # and we get just a bare chunk of base64 token. Not sure why.
                        final = final.replace(scheme, '', 1).lstrip()
                        tokenbuf = win32security.PySecBufferType(
                            pkg_info['MaxToken'], sspicon.SECBUFFER_TOKEN)
                        tokenbuf.Buffer = base64.b64decode(final)
                        sec_buffer.append(tokenbuf)
                        error, auth = clientauth.authorize(sec_buffer)
                        _logger.debug(
                            'Kerberos Authentication succeeded - error={} authenticated={}'
                            .format(error, clientauth.authenticated))
                    except TypeError:
                        pass

            # Regardless of whether or not we finalized our auth context,
            # without a 401 we've got nothing to do. Update the history and return.
            response2.history.append(response)
            return response2

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response2.content
        response2.raw.release_conn()
        request = response2.request.copy()

        # Keep passing the cookies along
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # Extract challenge message from server
        challenge = [
            val[len(scheme) + 1:] for val in response2.headers.get(
                'WWW-Authenticate', '').split(', ') if scheme in val
        ]
        if len(challenge) != 1:
            raise HTTPError(
                'Did not get exactly one {} challenge from server.'.format(
                    scheme))

        # Add challenge to security buffer
        tokenbuf = win32security.PySecBufferType(pkg_info['MaxToken'],
                                                 sspicon.SECBUFFER_TOKEN)
        tokenbuf.Buffer = base64.b64decode(challenge[0])
        sec_buffer.append(tokenbuf)
        _logger.debug('Got Challenge Token (NTLM)')

        # Perform next authorization step
        error, auth = clientauth.authorize(sec_buffer)
        request.headers['Authorization'] = '{} {}'.format(
            scheme,
            base64.b64encode(auth[0].Buffer).decode('ASCII'))
        _logger.debug('Sending Response - error={} authenticated={}'.format(
            error, clientauth.authenticated))

        response3 = response2.connection.send(request, **args)

        # Update the history and return
        response3.history.append(response)
        response3.history.append(response2)

        return response3
Esempio n. 24
0
    def _gssapi_sspi_test(self):
        try:
            import gssapi
            _API = "MIT-NEW"
        except ImportError:
            import sspicon
            import sspi
            _API = "SSPI"

        c_token = None
        gss_ctxt_status = False
        mic_msg = b"G'day Mate!"

        if _API == "MIT-NEW":
            if self.server_mode:
                gss_flags = (gssapi.RequirementFlag.protection_ready,
                             gssapi.RequirementFlag.integrity,
                             gssapi.RequirementFlag.mutual_authentication,
                             gssapi.RequirementFlag.delegate_to_peer)
            else:
                gss_flags = (gssapi.RequirementFlag.protection_ready,
                             gssapi.RequirementFlag.integrity,
                             gssapi.RequirementFlag.delegate_to_peer)
            # Initialize a GSS-API context.
            krb5_oid = gssapi.MechType.kerberos
            target_name = gssapi.Name(
                "host@" + self.targ_name,
                name_type=gssapi.NameType.hostbased_service)
            gss_ctxt = gssapi.SecurityContext(name=target_name,
                                              flags=gss_flags,
                                              mech=krb5_oid,
                                              usage='initiate')
            if self.server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.complete
                self.assertEqual(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.SecurityContext(usage='accept')
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.complete
                self.assertNotEqual(None, s_token)
                self.assertEqual(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEqual(None, c_token)
            else:
                while not gss_ctxt.complete:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEqual(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_signature(mic_msg)

            if self.server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_signature(mic_msg, mic_token)
                self.assertEqual(0, status)

        else:
            gss_flags = (sspicon.ISC_REQ_INTEGRITY
                         | sspicon.ISC_REQ_MUTUAL_AUTH
                         | sspicon.ISC_REQ_DELEGATE)
            # Initialize a GSS-API context.
            target_name = "host/" + socket.getfqdn(self.targ_name)
            gss_ctxt = sspi.ClientAuth("Kerberos",
                                       scflags=gss_flags,
                                       targetspn=target_name)
            if self.server_mode:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertEqual(0, error)
                # Accept a GSS-API context.
                gss_srv_ctxt = sspi.ServerAuth("Kerberos", spn=target_name)
                error, token = gss_srv_ctxt.authorize(c_token)
                s_token = token[0].Buffer
                # Establish the context.
                error, token = gss_ctxt.authorize(s_token)
                c_token = token[0].Buffer
                self.assertEqual(None, c_token)
                self.assertEqual(0, error)
                # Build MIC
                mic_token = gss_ctxt.sign(mic_msg)
                # Check MIC
                gss_srv_ctxt.verify(mic_msg, mic_token)
            else:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertNotEqual(0, error)
Esempio n. 25
0

"""
pkg_name='Kerberos'
sspiclient=SSPIClient(pkg_name, win32api.GetUserName(),  ## target spn is ourself
    None, None,   ## use none for client name and authentication information for current context
    ## u'username', (u'username',u'domain.com',u'passwd'),
    sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|sspicon.ISC_REQ_REPLAY_DETECT| sspicon.ISC_REQ_DELEGATE|sspicon.ISC_REQ_CONFIDENTIALITY|sspicon.ISC_REQ_USE_SESSION_KEY)
sspiserver=SSPIServer(pkg_name, None,
    sspicon.ASC_REQ_INTEGRITY|sspicon.ASC_REQ_SEQUENCE_DETECT|sspicon.ASC_REQ_REPLAY_DETECT| sspicon.ASC_REQ_DELEGATE|sspicon.ASC_REQ_CONFIDENTIALITY|sspicon.ASC_REQ_STREAM|sspicon.ASC_REQ_USE_SESSION_KEY)
"""

pkg_name = 'NTLM'

# Setup the 2 contexts.
sspiclient = sspi.ClientAuth(pkg_name)
sspiserver = sspi.ServerAuth(pkg_name)

# Perform the authentication dance, each loop exchanging more information
# on the way to completing authentication.
sec_buffer = None
while 1:
    err, sec_buffer = sspiclient.authorize(sec_buffer)
    err, sec_buffer = sspiserver.authorize(sec_buffer)
    if err == 0:
        break

# The server can now impersonate the client.  In this demo the 2 users will
# always be the same.
sspiserver.ctxt.ImpersonateSecurityContext()
print('Impersonated user: ',
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, auth_type, args):
        """Attempt to authenticate using HTTP NTLM challenge/response."""
        if auth_header in response.request.headers:
            return response

        content_length = int(response.request.headers.get(
            'Content-Length', '0'),
                             base=10)
        if hasattr(response.request.body, 'seek'):
            if content_length > 0:
                response.request.body.seek(-content_length, 1)
            else:
                response.request.body.seek(0, 0)

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response.content
        response.raw.release_conn()
        request = response.request.copy()

        # initial auth header with username. will result in challenge
        if self._use_default_credentials:
            pkg_info = win32security.QuerySecurityPackageInfo(_package)
            clientauth = sspi.ClientAuth(_package)
            sec_buffer = win32security.PySecBufferDescType()
            error, auth = clientauth.authorize(sec_buffer)
            request.headers[auth_header] = '{} {}'.format(
                _package,
                b64encode(auth[0].Buffer).decode('ascii'))
        else:
            msg = "%s\\%s" % (self.domain,
                              self.username) if self.domain else self.username

            # ntlm returns the headers as a base64 encoded bytestring. Convert to
            # a string.
            auth = '%s %s' % (auth_type, ntlm.create_NTLM_NEGOTIATE_MESSAGE(
                msg).decode('ascii'))
            request.headers[auth_header] = auth

        # A streaming response breaks authentication.
        # This can be fixed by not streaming this request, which is safe
        # because the returned response3 will still have stream=True set if
        # specified in args. In addition, we expect this request to give us a
        # challenge and not the real content, so the content will be short
        # anyway.
        args_nostream = dict(args, stream=False)
        response2 = response.connection.send(request, **args_nostream)

        # needed to make NTLM auth compatible with requests-2.3.0

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response2.content
        response2.raw.release_conn()
        request = response2.request.copy()

        # this is important for some web applications that store
        # authentication-related info in cookies (it took a long time to
        # figure out)
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]

        auth_strip = auth_type + ' '

        ntlm_header_value = next(
            s for s in (val.lstrip() for val in auth_header_value.split(','))
            if s.startswith(auth_strip)).strip()

        challenge_value = ntlm_header_value[len(auth_strip):]

        # build response
        if self._use_default_credentials:
            # Add challenge to security buffer
            tokenbuf = win32security.PySecBufferType(pkg_info['MaxToken'],
                                                     sspicon.SECBUFFER_TOKEN)
            tokenbuf.Buffer = b64decode(challenge_value)
            sec_buffer.append(tokenbuf)

            # Perform next authorization step
            error, auth = clientauth.authorize(sec_buffer)
            request.headers[auth_header] = '{} {}'.format(
                _package,
                b64encode(auth[0].Buffer).decode('ascii'))
        else:
            ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                challenge_value)
            # ntlm returns the headers as a base64 encoded bytestring. Convert to a
            # string.
            auth = '%s %s' % (auth_type,
                              ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                                  ServerChallenge, self.username, self.domain,
                                  self.password,
                                  NegotiateFlags).decode('ascii'))
            request.headers[auth_header] = auth

        response3 = response2.connection.send(request, **args)

        # Update the history.
        response3.history.append(response)
        response3.history.append(response2)

        return response3