gssapi/ctx.py
def step(self, input_token=None):
        """Performs a step to establish the context as an initiator.

        This method should be called in a loop and fed input tokens from the acceptor, and its
        output tokens should be sent to the acceptor, until this context's :attr:`established`
        attribute is True.

        :param input_token: The input token from the acceptor (omit this param or pass None on
            the first call).
        :type input_token: bytes
        :returns: either a byte string with the next token to send to the acceptor,
            or None if there is no further token to send to the acceptor.
        :raises: :exc:`~gssapi.error.GSSException` if there is an error establishing the context.
        """

        minor_status = ffi.new('OM_uint32[1]')

        if input_token:
            input_token_buffer = ffi.new('gss_buffer_desc[1]')
            input_token_buffer[0].length = len(input_token)
            c_str_input_token = ffi.new('char[]', input_token)
            input_token_buffer[0].value = c_str_input_token
        else:
            input_token_buffer = ffi.cast('gss_buffer_t', C.GSS_C_NO_BUFFER)

        if isinstance(self._desired_mech, OID):
            desired_mech = ffi.addressof(self._desired_mech._oid)
        else:
            desired_mech = ffi.cast('gss_OID', C.GSS_C_NO_OID)

        actual_mech = ffi.new('gss_OID[1]')
        output_token_buffer = ffi.new('gss_buffer_desc[1]')
        actual_flags = ffi.new('OM_uint32[1]')
        actual_time = ffi.new('OM_uint32[1]')

        if self._cred_object is not None:
            cred = self._cred_object._cred[0]
        else:
            cred = ffi.cast('gss_cred_id_t', C.GSS_C_NO_CREDENTIAL)

        retval = C.gss_init_sec_context(
            minor_status,
            cred,
            self._ctx,
            self.peer_name._name[0],
            desired_mech,
            self._req_flags,
            self._time_req,
            self._channel_bindings,
            input_token_buffer,
            actual_mech,
            output_token_buffer,
            actual_flags,
            actual_time
        )
        try:
            if output_token_buffer[0].length != 0:
                out_token = _buf_to_str(output_token_buffer[0])
            else:
                out_token = None

            if GSS_ERROR(retval):
                if minor_status[0] and actual_mech[0]:
                    raise _exception_for_status(retval, minor_status[0], actual_mech[0], out_token)
                else:
                    raise _exception_for_status(retval, minor_status[0], None, out_token)

            self.established = not (retval & C.GSS_S_CONTINUE_NEEDED)
            self.flags = actual_flags[0]

            if actual_mech[0]:
                self.mech_type = OID(actual_mech[0][0])

            return out_token
        except:
            if self._ctx[0]:
                C.gss_delete_sec_context(
                    minor_status,
                    self._ctx,
                    ffi.cast('gss_buffer_t', C.GSS_C_NO_BUFFER)
                )
                self._reset_flags()
            raise
        finally:
            if output_token_buffer[0].length != 0:
                C.gss_release_buffer(minor_status, output_token_buffer)
def step(self, input_token=None):
        """Performs a step to establish the context as an initiator.

        This method should be called in a loop and fed input tokens from the acceptor, and its
        output tokens should be sent to the acceptor, until this context's :attr:`established`
        attribute is True.

        :param input_token: The input token from the acceptor (omit this param or pass None on
            the first call).
        :type input_token: bytes
        :returns: either a byte string with the next token to send to the acceptor,
            or None if there is no further token to send to the acceptor.
        :raises: :exc:`~gssapi.error.GSSException` if there is an error establishing the context.
        """

        minor_status = ffi.new('OM_uint32[1]')

        if input_token:
            input_token_buffer = ffi.new('gss_buffer_desc[1]')
            input_token_buffer[0].length = len(input_token)
            c_str_input_token = ffi.new('char[]', input_token)
            input_token_buffer[0].value = c_str_input_token
        else:
            input_token_buffer = ffi.cast('gss_buffer_t', C.GSS_C_NO_BUFFER)

        if isinstance(self._desired_mech, OID):
            desired_mech = ffi.addressof(self._desired_mech._oid)
        else:
            desired_mech = ffi.cast('gss_OID', C.GSS_C_NO_OID)

        actual_mech = ffi.new('gss_OID[1]')
        output_token_buffer = ffi.new('gss_buffer_desc[1]')
        actual_flags = ffi.new('OM_uint32[1]')
        actual_time = ffi.new('OM_uint32[1]')

        if self._cred_object is not None:
            cred = self._cred_object._cred[0]
        else:
            cred = ffi.cast('gss_cred_id_t', C.GSS_C_NO_CREDENTIAL)

        retval = C.gss_init_sec_context(
            minor_status,
            cred,
            self._ctx,
            self.peer_name._name[0],
            desired_mech,
            self._req_flags,
            self._time_req,
            self._channel_bindings,
            input_token_buffer,
            actual_mech,
            output_token_buffer,
            actual_flags,
            actual_time
        )
        try:
            if output_token_buffer[0].length != 0:
                out_token = _buf_to_str(output_token_buffer[0])
            else:
                out_token = None

            if GSS_ERROR(retval):
                if minor_status[0] and actual_mech[0]:
                    raise _exception_for_status(retval, minor_status[0], actual_mech[0], out_token)
                else:
                    raise _exception_for_status(retval, minor_status[0], None, out_token)

            self.established = not (retval & C.GSS_S_CONTINUE_NEEDED)
            self.flags = actual_flags[0]

            if actual_mech[0]:
                self.mech_type = OID(actual_mech[0][0])

            return out_token
        except:
            if self._ctx[0]:
                C.gss_delete_sec_context(
                    minor_status,
                    self._ctx,
                    ffi.cast('gss_buffer_t', C.GSS_C_NO_BUFFER)
                )
                self._reset_flags()
            raise
        finally:
            if output_token_buffer[0].length != 0:
                C.gss_release_buffer(minor_status, output_token_buffer)
Performs a step to establish the context as an initiator.

        This method should be called in a loop and fed input tokens from the acceptor, and its
        output tokens should be sent to the acceptor, until this context's :attr:`established`
        attribute is True.

        :param input_token: The input token from the acceptor (omit this param or pass None on
            the first call).
        :type input_token: bytes
        :returns: either a byte string with the next token to send to the acceptor,
            or None if there is no further token to send to the acceptor.
        :raises: :exc:`~gssapi.error.GSSException` if there is an error establishing the context.