Implements a state machine
        :return:

def _credssp_processor(self, context):
        """
        Implements a state machine
        :return:
        """
        http_response = (yield)
        credssp_context = self._get_credssp_header(http_response)

        if credssp_context is None:
            raise Exception('The remote host did not respond with a \'www-authenticate\' header containing '
                            '\'CredSSP\' as an available authentication mechanism')

        # 1. First, secure the channel with a TLS Handshake
        if not credssp_context:
            self.tls_connection = SSL.Connection(self.tls_context)
            self.tls_connection.set_connect_state()
            while True:
                try:
                    self.tls_connection.do_handshake()
                except SSL.WantReadError:
                    http_response = yield self._set_credssp_header(http_response.request, self.tls_connection.bio_read(4096))
                    credssp_context = self._get_credssp_header(http_response)
                    if credssp_context is None or not credssp_context:
                        raise Exception('The remote host rejected the CredSSP TLS handshake')
                    self.tls_connection.bio_write(credssp_context)
                else:
                    break

        # add logging to display the negotiated cipher (move to a function)
        openssl_lib = _util.binding.lib
        ffi = _util.binding.ffi
        cipher = openssl_lib.SSL_get_current_cipher(self.tls_connection._ssl)
        cipher_name = ffi.string( openssl_lib.SSL_CIPHER_get_name(cipher))
        log.debug("Negotiated TLS Cipher: %s", cipher_name)

        # 2. Send an TSRequest containing an NTLM Negotiate Request
        context_generator = context.initialize_security_context()
        negotiate_token = context_generator.send(None)
        log.debug("NTLM Type 1: %s", AsHex(negotiate_token))

        ts_request = TSRequest()
        ts_request['negoTokens'] = negotiate_token
        self.tls_connection.send(ts_request.getData())

        http_response = yield self._set_credssp_header(http_response.request, self.tls_connection.bio_read(4096))

        # Extract and decrypt the encoded TSRequest response struct from the Negotiate header
        authenticate_header = self._get_credssp_header(http_response)
        if not authenticate_header or authenticate_header is None:
            raise Exception("The remote host rejected the CredSSP negotiation token")
        self.tls_connection.bio_write(authenticate_header)

        # NTLM Challenge Response and Server Public Key Validation
        ts_request = TSRequest()
        ts_request.fromString(self.tls_connection.recv(8192))
        challenge_token = ts_request['negoTokens']
        log.debug("NTLM Type 2: %s", AsHex(challenge_token))
        server_cert = self.tls_connection.get_peer_certificate()

        # not using channel bindings
        #certificate_digest = base64.b16decode(server_cert.digest('SHA256').replace(':', ''))
        ## channel_binding_structure = gss_channel_bindings_struct()
        ## channel_binding_structure['application_data'] = "tls-server-end-point:" + certificate_digest
        public_key = HttpCredSSPAuth._get_rsa_public_key(server_cert)
        # The _RSAPublicKey must be 'wrapped' using the negotiated GSSAPI mechanism and send to the server along with
        # the final SPNEGO token. This step of the CredSSP protocol is designed to thwart 'man-in-the-middle' attacks

        # Build and encrypt the response to the server
        ts_request = TSRequest()
        type3= context_generator.send(challenge_token)
        log.debug("NTLM Type 3: %s", AsHex(type3))
        ts_request['negoTokens'] = type3
        public_key_encrypted, signature = context.wrap_message(public_key)
        ts_request['pubKeyAuth'] = signature + public_key_encrypted

        self.tls_connection.send(ts_request.getData())
        enc_type3 = self.tls_connection.bio_read(8192)
        http_response = yield self._set_credssp_header(http_response.request, enc_type3)

        # TLS decrypt the response, then ASN decode and check the error code
        auth_response = self._get_credssp_header(http_response)
        if not auth_response or auth_response is None:
            raise Exception("The remote host rejected the challenge response")

        self.tls_connection.bio_write(auth_response)
        ts_request = TSRequest()
        ts_request.fromString(self.tls_connection.recv(8192))
        # TODO: determine how to validate server certificate here
        #a = ts_request['pubKeyAuth']
        # print ":".join("{:02x}".format(ord(c)) for c in a)

        # 4. Send the Credentials to be delegated, these are encrypted with both NTLM v2 and then by TLS
        tsp = TSPasswordCreds()
        tsp['domain'] = self.password_authenticator.get_domain()
        tsp['username'] = self.password_authenticator.get_username()
        tsp['password'] = self.password_authenticator.get_password()

        tsc = TSCredentials()
        tsc['type'] = 1
        tsc['credentials'] = tsp.getData()

        ts_request = TSRequest()
        encrypted, signature = context.wrap_message(tsc.getData())
        ts_request['authInfo'] = signature + encrypted

        self.tls_connection.send(ts_request.getData())
        token = self.tls_connection.bio_read(8192)

        http_response.request.body = self.body
        http_response = yield self._set_credssp_header(self._encrypt(http_response.request, self.tls_connection), token)

        if http_response.status_code == 401:
            raise Exception('Authentication Failed')