File 0001-bugfix-cve-2021-23192.patch of Package samba

From 32d79612d6547c9a76fe675d55849ce98bf458cc Mon Sep 17 00:00:00 2001
From: miaokaibo <miaokaibo@xfusion.com>
Date: Mon, 21 Mar 2022 18:45:27 +0800
Subject: [PATCH] bugfix cve-2021-23192

---
 libcli/auth/wscript_build                   |    2 +-
 librpc/rpc/dcerpc_pkt_auth.c                |  498 +++
 librpc/rpc/dcerpc_pkt_auth.h                |   59 +
 librpc/rpc/dcerpc_util.c                    |  336 +--
 librpc/rpc/dcerpc_util.h                    |   85 +
 librpc/rpc/dcesrv_auth.c                    |  691 +++++
 librpc/rpc/dcesrv_core.c                    | 3012 +++++++++++++++++++
 librpc/rpc/dcesrv_reply.c                   |    1 +
 librpc/rpc/rpc_common.h                     |   73 -
 librpc/wscript_build                        |    7 +-
 python/samba/tests/dcerpc/raw_protocol.py   | 1563 +++++++++-
 python/samba/tests/dcerpc/raw_testcase.py   |   56 +-
 source3/librpc/rpc/dcerpc_helpers.c         |    1 +
 source3/rpc_client/cli_pipe.c               |    1 +
 source3/rpc_client/rpc_transport_np.c       |    1 +
 source3/rpc_server/rpc_ncacn_np.c           |    1 +
 source3/rpc_server/rpc_server.c             |    1 +
 source3/rpc_server/srv_pipe.c               |    1 +
 source3/wscript_build                       |    3 +-
 source4/librpc/rpc/dcerpc.c                 |    3 +
 source4/librpc/rpc/dcerpc_roh_channel_out.c |    1 +
 source4/librpc/wscript_build                |    2 +-
 source4/rpc_server/dcerpc_server.c          |    1 +
 source4/rpc_server/dcesrv_auth.c            |    9 +
 24 files changed, 5826 insertions(+), 582 deletions(-)
 create mode 100644 librpc/rpc/dcerpc_pkt_auth.c
 create mode 100644 librpc/rpc/dcerpc_pkt_auth.h
 create mode 100644 librpc/rpc/dcerpc_util.h
 create mode 100644 librpc/rpc/dcesrv_auth.c
 create mode 100644 librpc/rpc/dcesrv_core.c
 create mode 100644 librpc/rpc/dcesrv_reply.c

diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build
index 6f7d9a7..34a3f04 100644
--- a/libcli/auth/wscript_build
+++ b/libcli/auth/wscript_build
@@ -30,7 +30,7 @@ bld.SAMBA_SUBSYSTEM('COMMON_SCHANNEL',
 
 bld.SAMBA_SUBSYSTEM('NETLOGON_CREDS_CLI',
         source='netlogon_creds_cli.c',
-        deps='dbwrap util_tdb tevent-util samba-hostconfig RPC_NDR_NETLOGON NDR_NETLOGON'
+        deps='dbwrap util_tdb tevent-util samba-hostconfig gensec RPC_NDR_NETLOGON NDR_NETLOGON'
         )
 
 bld.SAMBA_SUBSYSTEM('PAM_ERRORS',
diff --git a/librpc/rpc/dcerpc_pkt_auth.c b/librpc/rpc/dcerpc_pkt_auth.c
new file mode 100644
index 0000000..29b495b
--- /dev/null
+++ b/librpc/rpc/dcerpc_pkt_auth.c
@@ -0,0 +1,498 @@
+/*
+   Unix SMB/CIFS implementation.
+   raw dcerpc operations
+
+   Copyright (C) Andrew Tridgell 2003-2005
+   Copyright (C) Jelmer Vernooij 2004-2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+#include <tevent.h>
+#include "lib/util/talloc_stack.h"
+#include "lib/util/debug.h"
+#include "lib/util/byteorder.h"
+#include "lib/util/samba_util.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_util.h"
+#include "librpc/rpc/dcerpc_pkt_auth.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "rpc_common.h"
+#include "lib/util/bitmap.h"
+#include "auth/gensec/gensec.h"
+#include "lib/util/mkdir_p.h"
+#include "lib/crypto/gnutls_helpers.h"
+#include <gnutls/crypto.h>
+
+NTSTATUS dcerpc_ncacn_pull_pkt_auth(const struct dcerpc_auth *auth_state,
+				    struct gensec_security *gensec,
+				    bool check_pkt_auth_fields,
+				    TALLOC_CTX *mem_ctx,
+				    enum dcerpc_pkt_type ptype,
+				    uint8_t required_flags,
+				    uint8_t optional_flags,
+				    uint8_t payload_offset,
+				    DATA_BLOB *payload_and_verifier,
+				    DATA_BLOB *raw_packet,
+				    const struct ncacn_packet *pkt)
+{
+	NTSTATUS status;
+	struct dcerpc_auth auth;
+	uint32_t auth_length;
+
+	if (auth_state == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(pkt, ptype,
+					payload_and_verifier->length,
+					required_flags, optional_flags);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	switch (auth_state->auth_level) {
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PACKET:
+		break;
+
+	case DCERPC_AUTH_LEVEL_CONNECT:
+		if (pkt->auth_length != 0) {
+			break;
+		}
+		return NT_STATUS_OK;
+	case DCERPC_AUTH_LEVEL_NONE:
+		if (pkt->auth_length != 0) {
+			return NT_STATUS_ACCESS_DENIED;
+		}
+		return NT_STATUS_OK;
+
+	default:
+		return NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL;
+	}
+
+	if (pkt->auth_length == 0) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (gensec == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
+					  payload_and_verifier,
+					  &auth, &auth_length, false);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (payload_and_verifier->length < auth_length) {
+		/*
+		 * should be checked in dcerpc_pull_auth_trailer()
+		 */
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	payload_and_verifier->length -= auth_length;
+
+	if (payload_and_verifier->length < auth.auth_pad_length) {
+		/*
+		 * should be checked in dcerpc_pull_auth_trailer()
+		 */
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (auth.auth_type != auth_state->auth_type) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	if (auth.auth_level != auth_state->auth_level) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	if (auth.auth_context_id != auth_state->auth_context_id) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	/* check signature or unseal the packet */
+	switch (auth_state->auth_level) {
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		status = gensec_unseal_packet(gensec,
+					      raw_packet->data + payload_offset,
+					      payload_and_verifier->length,
+					      raw_packet->data,
+					      raw_packet->length -
+					      auth.credentials.length,
+					      &auth.credentials);
+		if (!NT_STATUS_IS_OK(status)) {
+			return NT_STATUS_RPC_SEC_PKG_ERROR;
+		}
+		memcpy(payload_and_verifier->data,
+		       raw_packet->data + payload_offset,
+		       payload_and_verifier->length);
+		break;
+
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PACKET:
+		status = gensec_check_packet(gensec,
+					     payload_and_verifier->data,
+					     payload_and_verifier->length,
+					     raw_packet->data,
+					     raw_packet->length -
+					     auth.credentials.length,
+					     &auth.credentials);
+		if (!NT_STATUS_IS_OK(status)) {
+			return NT_STATUS_RPC_SEC_PKG_ERROR;
+		}
+		break;
+
+	case DCERPC_AUTH_LEVEL_CONNECT:
+		/* for now we ignore possible signatures here */
+		break;
+
+	default:
+		return NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL;
+	}
+
+	/*
+	 * remove the indicated amount of padding
+	 *
+	 * A possible overflow is checked above.
+	 */
+	payload_and_verifier->length -= auth.auth_pad_length;
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS dcerpc_ncacn_push_pkt_auth(const struct dcerpc_auth *auth_state,
+				    struct gensec_security *gensec,
+				    TALLOC_CTX *mem_ctx,
+				    DATA_BLOB *raw_packet,
+				    size_t sig_size,
+				    uint8_t payload_offset,
+				    const DATA_BLOB *payload,
+				    const struct ncacn_packet *pkt)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	NTSTATUS status;
+	enum ndr_err_code ndr_err;
+	struct ndr_push *ndr = NULL;
+	uint32_t payload_length;
+	uint32_t whole_length;
+	DATA_BLOB blob = data_blob_null;
+	DATA_BLOB sig = data_blob_null;
+	struct dcerpc_auth _out_auth_info;
+	struct dcerpc_auth *out_auth_info = NULL;
+
+	*raw_packet = data_blob_null;
+
+	if (auth_state == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	switch (auth_state->auth_level) {
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PACKET:
+		if (sig_size == 0) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+
+		if (gensec == NULL) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+
+		_out_auth_info = (struct dcerpc_auth) {
+			.auth_type = auth_state->auth_type,
+			.auth_level = auth_state->auth_level,
+			.auth_context_id = auth_state->auth_context_id,
+		};
+		out_auth_info = &_out_auth_info;
+		break;
+
+	case DCERPC_AUTH_LEVEL_CONNECT:
+		/*
+		 * TODO: let the gensec mech decide if it wants to generate a
+		 *       signature that might be needed for schannel...
+		 */
+		if (sig_size != 0) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+
+		if (gensec == NULL) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+		break;
+
+	case DCERPC_AUTH_LEVEL_NONE:
+		if (sig_size != 0) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+		break;
+
+	default:
+		TALLOC_FREE(frame);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	ndr = ndr_push_init_ctx(frame);
+	if (ndr == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		TALLOC_FREE(frame);
+		return ndr_map_error2ntstatus(ndr_err);
+	}
+
+	if (out_auth_info != NULL) {
+		/*
+		 * pad to 16 byte multiple in the payload portion of the
+		 * packet. This matches what w2k3 does. Note that we can't use
+		 * ndr_push_align() as that is relative to the start of the
+		 * whole packet, whereas w2k8 wants it relative to the start
+		 * of the stub.
+		 */
+		out_auth_info->auth_pad_length =
+			DCERPC_AUTH_PAD_LENGTH(payload->length);
+		ndr_err = ndr_push_zero(ndr, out_auth_info->auth_pad_length);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			TALLOC_FREE(frame);
+			return ndr_map_error2ntstatus(ndr_err);
+		}
+
+		payload_length = payload->length +
+			out_auth_info->auth_pad_length;
+
+		ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,
+					       out_auth_info);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			TALLOC_FREE(frame);
+			return ndr_map_error2ntstatus(ndr_err);
+		}
+
+		whole_length = ndr->offset;
+
+		ndr_err = ndr_push_zero(ndr, sig_size);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			TALLOC_FREE(frame);
+			return ndr_map_error2ntstatus(ndr_err);
+		}
+	} else {
+		payload_length = payload->length;
+		whole_length = ndr->offset;
+	}
+
+	/* extract the whole packet as a blob */
+	blob = ndr_push_blob(ndr);
+
+	/*
+	 * Setup the frag and auth length in the packet buffer.
+	 * This is needed if the GENSEC mech does AEAD signing
+	 * of the packet headers. The signature itself will be
+	 * appended later.
+	 */
+	dcerpc_set_frag_length(&blob, blob.length);
+	dcerpc_set_auth_length(&blob, sig_size);
+
+	/* sign or seal the packet */
+	switch (auth_state->auth_level) {
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		status = gensec_seal_packet(gensec,
+					    frame,
+					    blob.data + payload_offset,
+					    payload_length,
+					    blob.data,
+					    whole_length,
+					    &sig);
+		if (!NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(frame);
+			return status;
+		}
+		break;
+
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PACKET:
+		status = gensec_sign_packet(gensec,
+					    frame,
+					    blob.data + payload_offset,
+					    payload_length,
+					    blob.data,
+					    whole_length,
+					    &sig);
+		if (!NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(frame);
+			return status;
+		}
+		break;
+
+	case DCERPC_AUTH_LEVEL_CONNECT:
+	case DCERPC_AUTH_LEVEL_NONE:
+		break;
+
+	default:
+		TALLOC_FREE(frame);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (sig.length != sig_size) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_RPC_SEC_PKG_ERROR;
+	}
+
+	if (sig_size != 0) {
+		memcpy(blob.data + whole_length, sig.data, sig_size);
+	}
+
+	*raw_packet = blob;
+	talloc_steal(mem_ctx, raw_packet->data);
+	TALLOC_FREE(frame);
+	return NT_STATUS_OK;
+}
+
+#ifdef DEVELOPER
+
+/*
+ * Save valid, well-formed DCE/RPC stubs to use as a seed for
+ * ndr_fuzz_X
+ */
+void dcerpc_save_ndr_fuzz_seed(TALLOC_CTX *mem_ctx,
+			       DATA_BLOB raw_blob,
+			       const char *dump_dir,
+			       const char *iface_name,
+			       int flags,
+			       int opnum,
+			       bool ndr64)
+{
+	char *fname = NULL;
+	const char *sub_dir = NULL;
+	TALLOC_CTX *temp_ctx = talloc_new(mem_ctx);
+	DATA_BLOB blob;
+	int ret, rc;
+	uint8_t digest[20];
+	DATA_BLOB digest_blob;
+	char *digest_hex;
+	uint16_t fuzz_flags = 0;
+
+	/*
+	 * We want to save the 'stub' in a per-pipe subdirectory, with
+	 * the ndr_fuzz_X header 4 byte header. For the sake of
+	 * convenience (this is a developer only function), we mkdir
+	 * -p the sub-directories when they are needed.
+	 */
+
+	if (dump_dir == NULL) {
+		return;
+	}
+
+	temp_ctx = talloc_stackframe();
+
+	sub_dir = talloc_asprintf(temp_ctx, "%s/%s",
+				  dump_dir,
+				  iface_name);
+	if (sub_dir == NULL) {
+		talloc_free(temp_ctx);
+		return;
+	}
+	ret = mkdir_p(sub_dir, 0755);
+	if (ret && errno != EEXIST) {
+		DBG_ERR("could not create %s\n", sub_dir);
+		talloc_free(temp_ctx);
+		return;
+	}
+
+	blob.length = raw_blob.length + 4;
+	blob.data = talloc_array(sub_dir,
+				 uint8_t,
+				 blob.length);
+	if (blob.data == NULL) {
+		DBG_ERR("could not allocate for fuzz seeds! (%s)\n",
+			iface_name);
+		talloc_free(temp_ctx);
+		return;
+	}
+
+	if (ndr64) {
+		fuzz_flags = 4;
+	}
+	if (flags & NDR_IN) {
+		fuzz_flags |= 1;
+	} else if (flags & NDR_OUT) {
+		fuzz_flags |= 2;
+	}
+
+	SSVAL(blob.data, 0, fuzz_flags);
+	SSVAL(blob.data, 2, opnum);
+
+	memcpy(&blob.data[4],
+	       raw_blob.data,
+	       raw_blob.length);
+
+	/*
+	 * This matches how oss-fuzz names the corpus input files, due
+	 * to a preference from libFuzzer
+	 */
+	rc = gnutls_hash_fast(GNUTLS_DIG_SHA1,
+			      blob.data,
+			      blob.length,
+			      digest);
+	if (rc < 0) {
+		/*
+		 * This prints a better error message, eg if SHA1 is
+		 * disabled
+		 */
+		NTSTATUS status = gnutls_error_to_ntstatus(rc,
+						  NT_STATUS_HASH_NOT_SUPPORTED);
+		DBG_ERR("Failed to generate SHA1 to save fuzz seed: %s",
+			nt_errstr(status));
+		talloc_free(temp_ctx);
+		return;
+	}
+
+	digest_blob.data = digest;
+	digest_blob.length = sizeof(digest);
+	digest_hex = data_blob_hex_string_lower(temp_ctx, &digest_blob);
+
+	fname = talloc_asprintf(temp_ctx, "%s/%s",
+				sub_dir,
+				digest_hex);
+	if (fname == NULL) {
+		talloc_free(temp_ctx);
+		return;
+	}
+
+	/*
+	 * If this fails, it is most likely because that file already
+	 * exists.  This is fine, it means we already have this
+	 * sample
+	 */
+	file_save(fname,
+		  blob.data,
+		  blob.length);
+
+	talloc_free(temp_ctx);
+}
+
+#endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
diff --git a/librpc/rpc/dcerpc_pkt_auth.h b/librpc/rpc/dcerpc_pkt_auth.h
new file mode 100644
index 0000000..1dcee12
--- /dev/null
+++ b/librpc/rpc/dcerpc_pkt_auth.h
@@ -0,0 +1,59 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) Stefan Metzmacher 2010-2011
+   Copyright (C) Andrew Tridgell 2010-2011
+   Copyright (C) Simo Sorce 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LIBRPC_RPC_DCERPC_PKT_AUTH_H__
+#define __LIBRPC_RPC_DCERPC_PKT_AUTH_H__
+
+#include "replace.h"
+#include <talloc.h>
+#include "lib/util/data_blob.h"
+#include "libcli/util/ntstatus.h"
+#include "librpc/rpc/rpc_common.h"
+#include "librpc/gen_ndr/dcerpc.h"
+
+NTSTATUS dcerpc_ncacn_pull_pkt_auth(const struct dcerpc_auth *auth_state,
+				    struct gensec_security *gensec,
+				    bool check_pkt_auth_fields,
+				    TALLOC_CTX *mem_ctx,
+				    enum dcerpc_pkt_type ptype,
+				    uint8_t required_flags,
+				    uint8_t optional_flags,
+				    uint8_t payload_offset,
+				    DATA_BLOB *payload_and_verifier,
+				    DATA_BLOB *raw_packet,
+				    const struct ncacn_packet *pkt);
+NTSTATUS dcerpc_ncacn_push_pkt_auth(const struct dcerpc_auth *auth_state,
+				    struct gensec_security *gensec,
+				    TALLOC_CTX *mem_ctx,
+				    DATA_BLOB *raw_packet,
+				    size_t sig_size,
+				    uint8_t payload_offset,
+				    const DATA_BLOB *payload,
+				    const struct ncacn_packet *pkt);
+struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 struct tstream_context *stream);
+NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
+				       TALLOC_CTX *mem_ctx,
+				       struct ncacn_packet **pkt,
+				       DATA_BLOB *buffer);
+
+#endif
diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c
index 6bc97f7..235984d 100644
--- a/librpc/rpc/dcerpc_util.c
+++ b/librpc/rpc/dcerpc_util.c
@@ -25,10 +25,11 @@
 #include "lib/tsocket/tsocket.h"
 #include "lib/util/tevent_ntstatus.h"
 #include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "rpc_common.h"
 #include "lib/util/bitmap.h"
-#include "auth/gensec/gensec.h"
+
 
 /* we need to be able to get/set the fragment length without doing a full
    decode */
@@ -459,339 +460,6 @@ NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
 	return NT_STATUS_OK;
 }
 
-NTSTATUS dcerpc_ncacn_pull_pkt_auth(const struct dcerpc_auth *auth_state,
-				    struct gensec_security *gensec,
-				    TALLOC_CTX *mem_ctx,
-				    enum dcerpc_pkt_type ptype,
-				    uint8_t required_flags,
-				    uint8_t optional_flags,
-				    uint8_t payload_offset,
-				    DATA_BLOB *payload_and_verifier,
-				    DATA_BLOB *raw_packet,
-				    const struct ncacn_packet *pkt)
-{
-	NTSTATUS status;
-	struct dcerpc_auth auth;
-	uint32_t auth_length;
-
-	if (auth_state == NULL) {
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	status = dcerpc_verify_ncacn_packet_header(pkt, ptype,
-					payload_and_verifier->length,
-					required_flags, optional_flags);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
-	switch (auth_state->auth_level) {
-	case DCERPC_AUTH_LEVEL_PRIVACY:
-	case DCERPC_AUTH_LEVEL_INTEGRITY:
-	case DCERPC_AUTH_LEVEL_PACKET:
-		break;
-
-	case DCERPC_AUTH_LEVEL_CONNECT:
-		if (pkt->auth_length != 0) {
-			break;
-		}
-		return NT_STATUS_OK;
-	case DCERPC_AUTH_LEVEL_NONE:
-		if (pkt->auth_length != 0) {
-			return NT_STATUS_ACCESS_DENIED;
-		}
-		return NT_STATUS_OK;
-
-	default:
-		return NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL;
-	}
-
-	if (pkt->auth_length == 0) {
-		return NT_STATUS_RPC_PROTOCOL_ERROR;
-	}
-
-	if (gensec == NULL) {
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
-					  payload_and_verifier,
-					  &auth, &auth_length, false);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
-	if (payload_and_verifier->length < auth_length) {
-		/*
-		 * should be checked in dcerpc_pull_auth_trailer()
-		 */
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	payload_and_verifier->length -= auth_length;
-
-	if (payload_and_verifier->length < auth.auth_pad_length) {
-		/*
-		 * should be checked in dcerpc_pull_auth_trailer()
-		 */
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	if (auth.auth_type != auth_state->auth_type) {
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
-	if (auth.auth_level != auth_state->auth_level) {
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
-	if (auth.auth_context_id != auth_state->auth_context_id) {
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
-	/* check signature or unseal the packet */
-	switch (auth_state->auth_level) {
-	case DCERPC_AUTH_LEVEL_PRIVACY:
-		status = gensec_unseal_packet(gensec,
-					      raw_packet->data + payload_offset,
-					      payload_and_verifier->length,
-					      raw_packet->data,
-					      raw_packet->length -
-					      auth.credentials.length,
-					      &auth.credentials);
-		if (!NT_STATUS_IS_OK(status)) {
-			return NT_STATUS_RPC_SEC_PKG_ERROR;
-		}
-		memcpy(payload_and_verifier->data,
-		       raw_packet->data + payload_offset,
-		       payload_and_verifier->length);
-		break;
-
-	case DCERPC_AUTH_LEVEL_INTEGRITY:
-	case DCERPC_AUTH_LEVEL_PACKET:
-		status = gensec_check_packet(gensec,
-					     payload_and_verifier->data,
-					     payload_and_verifier->length,
-					     raw_packet->data,
-					     raw_packet->length -
-					     auth.credentials.length,
-					     &auth.credentials);
-		if (!NT_STATUS_IS_OK(status)) {
-			return NT_STATUS_RPC_SEC_PKG_ERROR;
-		}
-		break;
-
-	case DCERPC_AUTH_LEVEL_CONNECT:
-		/* for now we ignore possible signatures here */
-		break;
-
-	default:
-		return NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL;
-	}
-
-	/*
-	 * remove the indicated amount of padding
-	 *
-	 * A possible overflow is checked above.
-	 */
-	payload_and_verifier->length -= auth.auth_pad_length;
-
-	return NT_STATUS_OK;
-}
-
-NTSTATUS dcerpc_ncacn_push_pkt_auth(const struct dcerpc_auth *auth_state,
-				    struct gensec_security *gensec,
-				    TALLOC_CTX *mem_ctx,
-				    DATA_BLOB *raw_packet,
-				    size_t sig_size,
-				    uint8_t payload_offset,
-				    const DATA_BLOB *payload,
-				    const struct ncacn_packet *pkt)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	NTSTATUS status;
-	enum ndr_err_code ndr_err;
-	struct ndr_push *ndr = NULL;
-	uint32_t payload_length;
-	uint32_t whole_length;
-	DATA_BLOB blob = data_blob_null;
-	DATA_BLOB sig = data_blob_null;
-	struct dcerpc_auth _out_auth_info;
-	struct dcerpc_auth *out_auth_info = NULL;
-
-	*raw_packet = data_blob_null;
-
-	if (auth_state == NULL) {
-		TALLOC_FREE(frame);
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	switch (auth_state->auth_level) {
-	case DCERPC_AUTH_LEVEL_PRIVACY:
-	case DCERPC_AUTH_LEVEL_INTEGRITY:
-	case DCERPC_AUTH_LEVEL_PACKET:
-		if (sig_size == 0) {
-			TALLOC_FREE(frame);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-
-		if (gensec == NULL) {
-			TALLOC_FREE(frame);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-
-		_out_auth_info = (struct dcerpc_auth) {
-			.auth_type = auth_state->auth_type,
-			.auth_level = auth_state->auth_level,
-			.auth_context_id = auth_state->auth_context_id,
-		};
-		out_auth_info = &_out_auth_info;
-		break;
-
-	case DCERPC_AUTH_LEVEL_CONNECT:
-		/*
-		 * TODO: let the gensec mech decide if it wants to generate a
-		 *       signature that might be needed for schannel...
-		 */
-		if (sig_size != 0) {
-			TALLOC_FREE(frame);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-
-		if (gensec == NULL) {
-			TALLOC_FREE(frame);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-		break;
-
-	case DCERPC_AUTH_LEVEL_NONE:
-		if (sig_size != 0) {
-			TALLOC_FREE(frame);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-		break;
-
-	default:
-		TALLOC_FREE(frame);
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	ndr = ndr_push_init_ctx(frame);
-	if (ndr == NULL) {
-		TALLOC_FREE(frame);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		TALLOC_FREE(frame);
-		return ndr_map_error2ntstatus(ndr_err);
-	}
-
-	if (out_auth_info != NULL) {
-		/*
-		 * pad to 16 byte multiple in the payload portion of the
-		 * packet. This matches what w2k3 does. Note that we can't use
-		 * ndr_push_align() as that is relative to the start of the
-		 * whole packet, whereas w2k8 wants it relative to the start
-		 * of the stub.
-		 */
-		out_auth_info->auth_pad_length =
-			DCERPC_AUTH_PAD_LENGTH(payload->length);
-		ndr_err = ndr_push_zero(ndr, out_auth_info->auth_pad_length);
-		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-			TALLOC_FREE(frame);
-			return ndr_map_error2ntstatus(ndr_err);
-		}
-
-		payload_length = payload->length +
-			out_auth_info->auth_pad_length;
-
-		ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,
-					       out_auth_info);
-		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-			TALLOC_FREE(frame);
-			return ndr_map_error2ntstatus(ndr_err);
-		}
-
-		whole_length = ndr->offset;
-
-		ndr_err = ndr_push_zero(ndr, sig_size);
-		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-			TALLOC_FREE(frame);
-			return ndr_map_error2ntstatus(ndr_err);
-		}
-	} else {
-		payload_length = payload->length;
-		whole_length = ndr->offset;
-	}
-
-	/* extract the whole packet as a blob */
-	blob = ndr_push_blob(ndr);
-
-	/*
-	 * Setup the frag and auth length in the packet buffer.
-	 * This is needed if the GENSEC mech does AEAD signing
-	 * of the packet headers. The signature itself will be
-	 * appended later.
-	 */
-	dcerpc_set_frag_length(&blob, blob.length);
-	dcerpc_set_auth_length(&blob, sig_size);
-
-	/* sign or seal the packet */
-	switch (auth_state->auth_level) {
-	case DCERPC_AUTH_LEVEL_PRIVACY:
-		status = gensec_seal_packet(gensec,
-					    frame,
-					    blob.data + payload_offset,
-					    payload_length,
-					    blob.data,
-					    whole_length,
-					    &sig);
-		if (!NT_STATUS_IS_OK(status)) {
-			TALLOC_FREE(frame);
-			return status;
-		}
-		break;
-
-	case DCERPC_AUTH_LEVEL_INTEGRITY:
-	case DCERPC_AUTH_LEVEL_PACKET:
-		status = gensec_sign_packet(gensec,
-					    frame,
-					    blob.data + payload_offset,
-					    payload_length,
-					    blob.data,
-					    whole_length,
-					    &sig);
-		if (!NT_STATUS_IS_OK(status)) {
-			TALLOC_FREE(frame);
-			return status;
-		}
-		break;
-
-	case DCERPC_AUTH_LEVEL_CONNECT:
-	case DCERPC_AUTH_LEVEL_NONE:
-		break;
-
-	default:
-		TALLOC_FREE(frame);
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	if (sig.length != sig_size) {
-		TALLOC_FREE(frame);
-		return NT_STATUS_RPC_SEC_PKG_ERROR;
-	}
-
-	if (sig_size != 0) {
-		memcpy(blob.data + whole_length, sig.data, sig_size);
-	}
-
-	*raw_packet = blob;
-	talloc_steal(mem_ctx, raw_packet->data);
-	TALLOC_FREE(frame);
-	return NT_STATUS_OK;
-}
 
 struct dcerpc_read_ncacn_packet_state {
 #if 0
diff --git a/librpc/rpc/dcerpc_util.h b/librpc/rpc/dcerpc_util.h
new file mode 100644
index 0000000..a9bc7bd
--- /dev/null
+++ b/librpc/rpc/dcerpc_util.h
@@ -0,0 +1,85 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) Stefan Metzmacher 2010-2011
+   Copyright (C) Andrew Tridgell 2010-2011
+   Copyright (C) Simo Sorce 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LIBRPC_RPC_DCERPC_UTIL_H__
+#define __LIBRPC_RPC_DCERPC_UTIL_H__
+
+#include "replace.h"
+#include <talloc.h>
+#include "lib/util/data_blob.h"
+#include "librpc/rpc/rpc_common.h"
+#include "librpc/gen_ndr/dcerpc.h"
+
+void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v);
+uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob);
+void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v);
+uint16_t dcerpc_get_auth_length(const DATA_BLOB *blob);
+uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob);
+uint8_t dcerpc_get_auth_type(const DATA_BLOB *blob);
+uint8_t dcerpc_get_auth_level(const DATA_BLOB *blob);
+uint32_t dcerpc_get_auth_context_id(const DATA_BLOB *blob);
+const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx,
+					      enum dcerpc_transport_t transport,
+					      const struct ndr_interface_table *table);
+
+NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
+				  const DATA_BLOB *blob,
+				  struct ncacn_packet *r);
+
+/**
+* @brief	Pull a dcerpc_auth structure, taking account of any auth
+*		padding in the blob. For request/response packets we pass
+*		the whole data blob, so auth_data_only must be set to false
+*		as the blob contains data+pad+auth and no just pad+auth.
+*
+* @param pkt		- The ncacn_packet strcuture
+* @param mem_ctx	- The mem_ctx used to allocate dcerpc_auth elements
+* @param pkt_trailer	- The packet trailer data, usually the trailing
+*			  auth_info blob, but in the request/response case
+*			  this is the stub_and_verifier blob.
+* @param auth		- A preallocated dcerpc_auth *empty* structure
+* @param auth_length	- The length of the auth trail, sum of auth header
+*			  lenght and pkt->auth_length
+* @param auth_data_only	- Whether the pkt_trailer includes only the auth_blob
+*			  (+ padding) or also other data.
+*
+* @return		- A NTSTATUS error code.
+*/
+NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
+				  TALLOC_CTX *mem_ctx,
+				  const DATA_BLOB *pkt_trailer,
+				  struct dcerpc_auth *auth,
+				  uint32_t *auth_length,
+				  bool auth_data_only);
+NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
+					   enum dcerpc_pkt_type ptype,
+					   size_t max_auth_info,
+					   uint8_t required_flags,
+					   uint8_t optional_flags);
+struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 struct tstream_context *stream);
+NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
+				       TALLOC_CTX *mem_ctx,
+				       struct ncacn_packet **pkt,
+				       DATA_BLOB *buffer);
+
+#endif
diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c
new file mode 100644
index 0000000..f403d1e
--- /dev/null
+++ b/librpc/rpc/dcesrv_auth.c
@@ -0,0 +1,691 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   server side dcerpc authentication code
+
+   Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Stefan (metze) Metzmacher 2004
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "librpc/rpc/dcesrv_core.h"
+#include "librpc/rpc/dcesrv_core_proto.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "auth/auth.h"
+#include "param/param.h"
+
+static NTSTATUS dcesrv_auth_negotiate_hdr_signing(struct dcesrv_call_state *call,
+						  struct ncacn_packet *pkt)
+{
+	struct dcesrv_connection *dce_conn = call->conn;
+	struct dcesrv_auth *a = NULL;
+
+	if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
+		return NT_STATUS_OK;
+	}
+
+	if (dce_conn->client_hdr_signing) {
+		if (dce_conn->negotiated_hdr_signing && pkt != NULL) {
+			pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
+		}
+		return NT_STATUS_OK;
+	}
+
+	dce_conn->client_hdr_signing = true;
+	dce_conn->negotiated_hdr_signing = dce_conn->support_hdr_signing;
+
+	if (!dce_conn->negotiated_hdr_signing) {
+		return NT_STATUS_OK;
+	}
+
+	if (pkt != NULL) {
+		pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
+	}
+
+	a = call->conn->default_auth_state;
+	if (a->gensec_security != NULL) {
+		gensec_want_feature(a->gensec_security,
+				    GENSEC_FEATURE_SIGN_PKT_HEADER);
+	}
+
+	for (a = call->conn->auth_states; a != NULL; a = a->next) {
+		if (a->gensec_security == NULL) {
+			continue;
+		}
+
+		gensec_want_feature(a->gensec_security,
+				    GENSEC_FEATURE_SIGN_PKT_HEADER);
+	}
+
+	return NT_STATUS_OK;
+}
+
+static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
+{
+	struct dcesrv_connection *dce_conn = call->conn;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	if (auth->auth_started) {
+		return false;
+	}
+
+	auth->auth_started = true;
+
+	if (auth->auth_invalid) {
+		return false;
+	}
+
+	if (auth->auth_finished) {
+		return false;
+	}
+
+	if (auth->gensec_security != NULL) {
+		return false;
+	}
+
+	switch (call->in_auth_info.auth_level) {
+	case DCERPC_AUTH_LEVEL_CONNECT:
+	case DCERPC_AUTH_LEVEL_CALL:
+	case DCERPC_AUTH_LEVEL_PACKET:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		/*
+		 * We evaluate auth_type only if auth_level was valid
+		 */
+		break;
+	default:
+		/*
+		 * Setting DCERPC_AUTH_LEVEL_NONE,
+		 * gives the caller the reject_reason
+		 * as auth_context_id.
+		 *
+		 * Note: DCERPC_AUTH_LEVEL_NONE == 1
+		 */
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		auth->auth_context_id = DCERPC_BIND_NAK_REASON_NOT_SPECIFIED;
+		return false;
+	}
+
+	auth->auth_type = call->in_auth_info.auth_type;
+	auth->auth_level = call->in_auth_info.auth_level;
+	auth->auth_context_id = call->in_auth_info.auth_context_id;
+
+	status = call->conn->dce_ctx->callbacks.auth.gensec_prepare(auth,
+						call,
+						&auth->gensec_security);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
+			  nt_errstr(status)));
+		return false;
+	}
+
+	/*
+	 * We have to call this because we set the target_service for
+	 * Kerberos to NULL above, and in any case we wish to log a
+	 * more specific service target.
+	 *
+	 */
+	status = gensec_set_target_service_description(auth->gensec_security,
+						       "DCE/RPC");
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to call gensec_set_target_service_description %s\n",
+			  nt_errstr(status)));
+		return false;
+	}
+
+	if (call->conn->remote_address != NULL) {
+		status = gensec_set_remote_address(auth->gensec_security,
+						call->conn->remote_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(1, ("Failed to call gensec_set_remote_address() %s\n",
+				  nt_errstr(status)));
+			return false;
+		}
+	}
+
+	if (call->conn->local_address != NULL) {
+		status = gensec_set_local_address(auth->gensec_security,
+						  call->conn->local_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(1, ("Failed to call gensec_set_local_address() %s\n",
+				  nt_errstr(status)));
+			return false;
+		}
+	}
+
+	status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
+					       auth->auth_level);
+	if (!NT_STATUS_IS_OK(status)) {
+		const char *backend_name =
+			gensec_get_name_by_authtype(auth->gensec_security,
+						    auth->auth_type);
+
+		DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: "
+			  "auth_type=%d (%s), auth_level=%d: %s\n",
+			  (int)auth->auth_type, backend_name,
+			  (int)auth->auth_level,
+			  nt_errstr(status)));
+
+		/*
+		 * Setting DCERPC_AUTH_LEVEL_NONE,
+		 * gives the caller the reject_reason
+		 * as auth_context_id.
+		 *
+		 * Note: DCERPC_AUTH_LEVEL_NONE == 1
+		 */
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		if (backend_name != NULL) {
+			auth->auth_context_id =
+				DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM;
+		} else {
+			auth->auth_context_id =
+				DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE;
+		}
+		return false;
+	}
+
+	if (dce_conn->negotiated_hdr_signing) {
+		gensec_want_feature(auth->gensec_security,
+				    GENSEC_FEATURE_SIGN_PKT_HEADER);
+	}
+
+	return true;
+}
+
+static void dcesrv_default_auth_state_finish_bind(struct dcesrv_call_state *call)
+{
+	SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_BIND);
+
+	if (call->auth_state == call->conn->default_auth_state) {
+		return;
+	}
+
+	if (call->conn->default_auth_state->auth_started) {
+		return;
+	}
+
+	if (call->conn->default_auth_state->auth_invalid) {
+		return;
+	}
+
+	call->conn->default_auth_state->auth_type = DCERPC_AUTH_TYPE_NONE;
+	call->conn->default_auth_state->auth_level = DCERPC_AUTH_LEVEL_NONE;
+	call->conn->default_auth_state->auth_context_id = 0;
+	call->conn->default_auth_state->auth_started = true;
+	call->conn->default_auth_state->auth_finished = true;
+
+	/*
+	 *
+	 * We defer log_successful_dcesrv_authz_event()
+	 * to dcesrv_default_auth_state_prepare_request()
+	 *
+	 * As we don't want to trigger authz_events
+	 * just for alter_context requests without authentication
+	 */
+}
+
+void dcesrv_default_auth_state_prepare_request(struct dcesrv_call_state *call)
+{
+	struct dcesrv_connection *dce_conn = call->conn;
+	struct dcesrv_auth *auth = call->auth_state;
+
+	if (auth->auth_audited) {
+		return;
+	}
+
+	if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
+		return;
+	}
+
+	if (auth != dce_conn->default_auth_state) {
+		return;
+	}
+
+	if (auth->auth_invalid) {
+		return;
+	}
+
+	if (!auth->auth_finished) {
+		return;
+	}
+
+	if (!call->conn->dce_ctx->callbacks.log.successful_authz) {
+		return;
+	}
+
+	call->conn->dce_ctx->callbacks.log.successful_authz(call);
+}
+
+/*
+  parse any auth information from a dcerpc bind request
+  return false if we can't handle the auth request for some
+  reason (in which case we send a bind_nak)
+*/
+bool dcesrv_auth_bind(struct dcesrv_call_state *call)
+{
+	struct ncacn_packet *pkt = &call->pkt;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	if (pkt->auth_length == 0) {
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		auth->auth_context_id = 0;
+		auth->auth_started = true;
+
+		if (call->conn->dce_ctx->callbacks.log.successful_authz) {
+			call->conn->dce_ctx->callbacks.log.successful_authz(call);
+		}
+
+		return true;
+	}
+
+	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
+					  &call->in_auth_info,
+					  NULL, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * Setting DCERPC_AUTH_LEVEL_NONE,
+		 * gives the caller the reject_reason
+		 * as auth_context_id.
+		 *
+		 * Note: DCERPC_AUTH_LEVEL_NONE == 1
+		 */
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		auth->auth_context_id =
+			DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED;
+		return false;
+	}
+
+	return dcesrv_auth_prepare_gensec(call);
+}
+
+NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
+{
+	struct dcesrv_auth *auth = call->auth_state;
+	const char *pdu = "<unknown>";
+
+	switch (call->pkt.ptype) {
+	case DCERPC_PKT_BIND:
+		pdu = "BIND";
+		break;
+	case DCERPC_PKT_ALTER:
+		pdu = "ALTER";
+		break;
+	case DCERPC_PKT_AUTH3:
+		pdu = "AUTH3";
+		if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+			DEBUG(4, ("GENSEC not finished at at %s\n", pdu));
+			return NT_STATUS_RPC_SEC_PKG_ERROR;
+		}
+		break;
+	default:
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		return NT_STATUS_OK;
+	}
+
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(4, ("GENSEC mech rejected the incoming authentication "
+			  "at %s: %s\n", pdu, nt_errstr(status)));
+		return status;
+	}
+
+	status = gensec_session_info(auth->gensec_security,
+				     auth,
+				     &auth->session_info);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to establish session_info: %s\n",
+			  nt_errstr(status)));
+		return status;
+	}
+	auth->auth_finished = true;
+
+	if (auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT &&
+	    !call->conn->got_explicit_auth_level_connect)
+	{
+		call->conn->default_auth_level_connect = auth;
+	}
+
+	if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
+		return NT_STATUS_OK;
+	}
+
+	if (call->out_auth_info->credentials.length != 0) {
+		DEBUG(4, ("GENSEC produced output token (len=%zu) at %s\n",
+			  call->out_auth_info->credentials.length, pdu));
+		return NT_STATUS_RPC_SEC_PKG_ERROR;
+	}
+
+	return NT_STATUS_OK;
+}
+
+/*
+  add any auth information needed in a bind ack, and process the authentication
+  information found in the bind.
+*/
+NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+{
+	struct dcesrv_connection *dce_conn = call->conn;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	dce_conn->allow_alter = true;
+	dcesrv_default_auth_state_finish_bind(call);
+
+	if (call->pkt.auth_length == 0) {
+		auth->auth_finished = true;
+		return NT_STATUS_OK;
+	}
+
+	/* We can't work without an existing gensec state */
+	if (auth->gensec_security == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = auth->auth_type,
+		.auth_level = auth->auth_level,
+		.auth_context_id = auth->auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
+	return NT_STATUS_OK;
+}
+
+/*
+  process the final stage of a auth request
+*/
+bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
+{
+	struct ncacn_packet *pkt = &call->pkt;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	if (pkt->auth_length == 0) {
+		return false;
+	}
+
+	if (auth->auth_finished) {
+		return false;
+	}
+
+	if (auth->auth_invalid) {
+		return false;
+	}
+
+	/* We can't work without an existing gensec state */
+	if (auth->gensec_security == NULL) {
+		return false;
+	}
+
+	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
+					  &call->in_auth_info, NULL, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * Windows returns DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY
+		 * instead of DCERPC_NCA_S_PROTO_ERROR.
+		 */
+		call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY;
+		return false;
+	}
+
+	if (call->in_auth_info.auth_type != auth->auth_type) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_level != auth->auth_level) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
+		return false;
+	}
+
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = auth->auth_type,
+		.auth_level = auth->auth_level,
+		.auth_context_id = auth->auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
+	return true;
+}
+
+/*
+  parse any auth information from a dcerpc alter request
+  return false if we can't handle the auth request for some
+  reason (in which case we send a bind_nak (is this true for here?))
+*/
+bool dcesrv_auth_alter(struct dcesrv_call_state *call)
+{
+	struct ncacn_packet *pkt = &call->pkt;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	/* on a pure interface change there is no auth blob */
+	if (pkt->auth_length == 0) {
+		if (!auth->auth_finished) {
+			return false;
+		}
+		return true;
+	}
+
+	if (auth->auth_finished) {
+		call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+		return false;
+	}
+
+	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
+					  &call->in_auth_info, NULL, true);
+	if (!NT_STATUS_IS_OK(status)) {
+		call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
+		return false;
+	}
+
+	if (!auth->auth_started) {
+		bool ok;
+
+		ok = dcesrv_auth_prepare_gensec(call);
+		if (!ok) {
+			call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+			return false;
+		}
+
+		return true;
+	}
+
+	if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
+		call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+		return false;
+	}
+
+	if (auth->auth_invalid) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_type != auth->auth_type) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_level != auth->auth_level) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
+		return false;
+	}
+
+	return true;
+}
+
+/*
+  add any auth information needed in a alter ack, and process the authentication
+  information found in the alter.
+*/
+NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+{
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	/* on a pure interface change there is no auth_info structure
+	   setup */
+	if (call->pkt.auth_length == 0) {
+		return NT_STATUS_OK;
+	}
+
+	if (auth->gensec_security == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = auth->auth_type,
+		.auth_level = auth->auth_level,
+		.auth_context_id = auth->auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
+	return NT_STATUS_OK;
+}
+
+/*
+  check credentials on a packet
+*/
+bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
+			  DATA_BLOB *full_packet,
+			  uint8_t required_flags,
+			  uint8_t optional_flags,
+			  uint8_t payload_offset,
+			  DATA_BLOB *payload_and_verifier)
+{
+	struct ncacn_packet *pkt = &call->pkt;
+	struct dcesrv_auth *auth = call->auth_state;
+	const struct dcerpc_auth tmp_auth = {
+		.auth_type = auth->auth_type,
+		.auth_level = auth->auth_level,
+		.auth_context_id = auth->auth_context_id,
+	};
+	bool check_pkt_auth_fields;
+	NTSTATUS status;
+
+	if (!auth->auth_started) {
+		return false;
+	}
+
+	if (!auth->auth_finished) {
+		call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
+		return false;
+	}
+
+	if (auth->auth_invalid) {
+		return false;
+	}
+
+	if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+		/*
+		 * The caller most likely checked this
+		 * already, but we better double check
+		 */
+		check_pkt_auth_fields = true;
+	} else {
+		/*
+		 * The caller already found first fragment
+		 * and is passing the auth_state of it.
+		 * A server is supposed to use the
+		 * setting of the first fragment and
+		 * completely ignore the values
+		 * on the remaining fragments
+		 */
+		check_pkt_auth_fields = false;
+	}
+
+	status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
+					    auth->gensec_security,
+					    check_pkt_auth_fields,
+					    call,
+					    pkt->ptype,
+					    required_flags,
+					    optional_flags,
+					    payload_offset,
+					    payload_and_verifier,
+					    full_packet,
+					    pkt);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+		call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
+		return false;
+	}
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL)) {
+		call->fault_code = DCERPC_NCA_S_UNSUPPORTED_AUTHN_LEVEL;
+		return false;
+	}
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+		call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
+		return false;
+	}
+	if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+		return false;
+	}
+	if (!NT_STATUS_IS_OK(status)) {
+		return false;
+	}
+
+	return true;
+}
+
+/*
+   push a signed or sealed dcerpc request packet into a blob
+*/
+bool dcesrv_auth_pkt_push(struct dcesrv_call_state *call,
+			  DATA_BLOB *blob, size_t sig_size,
+			  uint8_t payload_offset,
+			  const DATA_BLOB *payload,
+			  const struct ncacn_packet *pkt)
+{
+	struct dcesrv_auth *auth = call->auth_state;
+	const struct dcerpc_auth tmp_auth = {
+		.auth_type = auth->auth_type,
+		.auth_level = auth->auth_level,
+		.auth_context_id = auth->auth_context_id,
+	};
+	NTSTATUS status;
+
+	status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
+					    auth->gensec_security,
+					    call, blob, sig_size,
+					    payload_offset,
+					    payload,
+					    pkt);
+	return NT_STATUS_IS_OK(status);
+}
diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c
new file mode 100644
index 0000000..892ff7e
--- /dev/null
+++ b/librpc/rpc/dcesrv_core.c
@@ -0,0 +1,3012 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   server side dcerpc core code
+
+   Copyright (C) Andrew Tridgell 2003-2005
+   Copyright (C) Stefan (metze) Metzmacher 2004-2005
+   Copyright (C) Samuel Cabrero <scabrero@samba.org> 2019
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "librpc/rpc/dcesrv_core.h"
+#include "librpc/rpc/dcesrv_core_proto.h"
+#include "librpc/gen_ndr/auth.h"
+#include "auth/gensec/gensec.h"
+#include "lib/util/dlinklist.h"
+#include "libcli/security/security.h"
+#include "param/param.h"
+#include "lib/tsocket/tsocket.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "lib/util/tevent_ntstatus.h"
+
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
+				const struct dcerpc_bind *b,
+				struct dcerpc_ack_ctx *ack_ctx_list);
+
+/*
+  see if two endpoints match
+*/
+static bool endpoints_match(const struct dcerpc_binding *ep1,
+			    const struct dcerpc_binding *ep2)
+{
+	enum dcerpc_transport_t t1;
+	enum dcerpc_transport_t t2;
+	const char *e1;
+	const char *e2;
+
+	t1 = dcerpc_binding_get_transport(ep1);
+	t2 = dcerpc_binding_get_transport(ep2);
+
+	e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
+	e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
+
+	if (t1 != t2) {
+		return false;
+	}
+
+	if (!e1 || !e2) {
+		return e1 == e2;
+	}
+
+	if (strcasecmp(e1, e2) != 0) {
+		return false;
+	}
+
+	return true;
+}
+
+/*
+  find an endpoint in the dcesrv_context
+*/
+_PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
+				const struct dcerpc_binding *ep_description,
+				struct dcesrv_endpoint **_out)
+{
+	struct dcesrv_endpoint *ep = NULL;
+	for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
+		if (endpoints_match(ep->ep_description, ep_description)) {
+			*_out = ep;
+			return NT_STATUS_OK;
+		}
+	}
+	return NT_STATUS_NOT_FOUND;
+}
+
+/*
+  find a registered context_id from a bind or alter_context
+*/
+static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
+							     uint16_t context_id)
+{
+	struct dcesrv_connection_context *c;
+	for (c=conn->contexts;c;c=c->next) {
+		if (c->context_id == context_id) return c;
+	}
+	return NULL;
+}
+
+/*
+  see if a uuid and if_version match to an interface
+*/
+static bool interface_match(const struct dcesrv_interface *if1,
+							const struct dcesrv_interface *if2)
+{
+	return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
+			GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
+}
+
+/*
+  find the interface operations on any endpoint with this binding
+*/
+static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
+								struct dcerpc_binding *binding,
+								const struct dcesrv_interface *iface)
+{
+	struct dcesrv_endpoint *ep;
+	for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
+		if (endpoints_match(ep->ep_description, binding)) {
+			struct dcesrv_if_list *ifl;
+			for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
+				if (interface_match(ifl->iface, iface)) {
+					return ifl->iface;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+/*
+  see if a uuid and if_version match to an interface
+*/
+static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
+				    const struct GUID *uuid, uint32_t if_version)
+{
+	return (iface->syntax_id.if_version == if_version &&
+			GUID_equal(&iface->syntax_id.uuid, uuid));
+}
+
+/*
+  find the interface operations on an endpoint by uuid
+*/
+_PUBLIC_ const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
+						      const struct GUID *uuid, uint32_t if_version)
+{
+	struct dcesrv_if_list *ifl;
+	for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
+		if (interface_match_by_uuid(ifl->iface, uuid, if_version)) {
+			return ifl->iface;
+		}
+	}
+	return NULL;
+}
+
+/*
+  find the earlier parts of a fragmented call awaiting reassembily
+*/
+static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
+{
+	struct dcesrv_call_state *c;
+	for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
+		if (c->pkt.call_id == call_id) {
+			return c;
+		}
+	}
+	return NULL;
+}
+
+/*
+  register an interface on an endpoint
+
+  An endpoint is one unix domain socket (for ncalrpc), one TCP port
+  (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
+
+  Each endpoint can have many interfaces such as netlogon, lsa or
+  samr.  Some have essentially the full set.
+
+  This is driven from the set of interfaces listed in each IDL file
+  via the PIDL generated *__op_init_server() functions.
+*/
+_PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
+				   const char *ep_name,
+				   const char *ncacn_np_secondary_endpoint,
+				   const struct dcesrv_interface *iface,
+				   const struct security_descriptor *sd)
+{
+	struct dcesrv_endpoint *ep;
+	struct dcesrv_if_list *ifl;
+	struct dcerpc_binding *binding;
+	struct dcerpc_binding *binding2 = NULL;
+	bool add_ep = false;
+	NTSTATUS status;
+	enum dcerpc_transport_t transport;
+	char *ep_string = NULL;
+	bool use_single_process = true;
+	const char *ep_process_string;
+
+	/*
+	 * If we are not using handles, there is no need for force
+	 * this service into using a single process.
+	 *
+	 * However, due to the way we listen for RPC packets, we can
+	 * only do this if we have a single service per pipe or TCP
+	 * port, so we still force a single combined process for
+	 * ncalrpc.
+	 */
+	if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
+		use_single_process = false;
+	}
+
+	status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
+
+	if (NT_STATUS_IS_ERR(status)) {
+		DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
+		return status;
+	}
+
+	transport = dcerpc_binding_get_transport(binding);
+	if (transport == NCACN_IP_TCP) {
+		int port;
+		char port_str[6];
+
+		/*
+		 * First check if there is already a port specified, eg
+		 * for epmapper on ncacn_ip_tcp:[135]
+		 */
+		const char *endpoint
+			= dcerpc_binding_get_string_option(binding,
+							   "endpoint");
+		if (endpoint == NULL) {
+			port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
+					      "rpc server port", iface->name, 0);
+
+			/*
+			 * For RPC services that are not set to use a single
+			 * process, we do not default to using the 'rpc server
+			 * port' because that would cause a double-bind on
+			 * that port.
+			 */
+			if (port == 0 && !use_single_process) {
+				port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
+			}
+			if (port != 0) {
+				snprintf(port_str, sizeof(port_str), "%u", port);
+				status = dcerpc_binding_set_string_option(binding,
+									  "endpoint",
+									  port_str);
+				if (!NT_STATUS_IS_OK(status)) {
+					return status;
+				}
+			}
+		}
+	}
+
+	if (transport == NCACN_NP && ncacn_np_secondary_endpoint != NULL) {
+		enum dcerpc_transport_t transport2;
+
+		status = dcerpc_parse_binding(dce_ctx,
+					      ncacn_np_secondary_endpoint,
+					      &binding2);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
+				  ncacn_np_secondary_endpoint));
+			return status;
+		}
+
+		transport2 = dcerpc_binding_get_transport(binding2);
+		SMB_ASSERT(transport2 == transport);
+	}
+
+	/* see if the interface is already registered on the endpoint */
+	if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
+		DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
+			 iface->name, ep_name));
+		return NT_STATUS_OBJECT_NAME_COLLISION;
+	}
+
+	/* check if this endpoint exists
+	 */
+	status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
+	if (NT_STATUS_IS_OK(status)) {
+		/*
+		 * We want a new port on ncacn_ip_tcp for NETLOGON, so
+		 * it can be multi-process.  Other processes can also
+		 * listen on distinct ports, if they have one forced
+		 * in the code above with eg 'rpc server port:drsuapi = 1027'
+		 *
+		 * If we have mulitiple endpoints on port 0, they each
+		 * get an epemeral port (currently by walking up from
+		 * 1024).
+		 *
+		 * Because one endpoint can only have one process
+		 * model, we add a new IP_TCP endpoint for each model.
+		 *
+		 * This works in conjunction with the forced overwrite
+		 * of ep->use_single_process below.
+		 */
+		if (ep->use_single_process != use_single_process
+		    && transport == NCACN_IP_TCP) {
+			add_ep = true;
+		}
+	}
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
+		ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
+		if (!ep) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		ZERO_STRUCTP(ep);
+		ep->ep_description = talloc_move(ep, &binding);
+		ep->ep_2nd_description = talloc_move(ep, &binding2);
+		add_ep = true;
+
+		/* add mgmt interface */
+		ifl = talloc_zero(ep, struct dcesrv_if_list);
+		if (!ifl) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		ifl->iface = talloc_memdup(ifl,
+					   dcesrv_get_mgmt_interface(),
+					   sizeof(struct dcesrv_interface));
+		if (ifl->iface == NULL) {
+			talloc_free(ep);
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		DLIST_ADD(ep->interface_list, ifl);
+	} else if (!NT_STATUS_IS_OK(status)) {
+		DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
+		return status;
+	}
+
+	/*
+	 * By default don't force into a single process, but if any
+	 * interface on this endpoint on this service uses handles
+	 * (most do), then we must force into single process mode
+	 *
+	 * By overwriting this each time a new interface is added to
+	 * this endpoint, we end up with the most restrictive setting.
+	 */
+	if (use_single_process) {
+		ep->use_single_process = true;
+	}
+
+	/* talloc a new interface list element */
+	ifl = talloc_zero(ep, struct dcesrv_if_list);
+	if (!ifl) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* copy the given interface struct to the one on the endpoints interface list */
+	ifl->iface = talloc_memdup(ifl,
+				   iface,
+				   sizeof(struct dcesrv_interface));
+	if (ifl->iface == NULL) {
+		talloc_free(ep);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* if we have a security descriptor given,
+	 * we should see if we can set it up on the endpoint
+	 */
+	if (sd != NULL) {
+		/* if there's currently no security descriptor given on the endpoint
+		 * we try to set it
+		 */
+		if (ep->sd == NULL) {
+			ep->sd = security_descriptor_copy(ep, sd);
+		}
+
+		/* if now there's no security descriptor given on the endpoint
+		 * something goes wrong, either we failed to copy the security descriptor
+		 * or there was already one on the endpoint
+		 */
+		if (ep->sd != NULL) {
+			DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
+			         "                           on endpoint '%s'\n",
+				iface->name, ep_name));
+			if (add_ep) free(ep);
+			free(ifl);
+			return NT_STATUS_OBJECT_NAME_COLLISION;
+		}
+	}
+
+	/* finally add the interface on the endpoint */
+	DLIST_ADD(ep->interface_list, ifl);
+
+	/* if it's a new endpoint add it to the dcesrv_context */
+	if (add_ep) {
+		DLIST_ADD(dce_ctx->endpoint_list, ep);
+	}
+
+	/* Re-get the string as we may have set a port */
+	ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
+
+	if (use_single_process) {
+		ep_process_string = "single process required";
+	} else {
+		ep_process_string = "multi process compatible";
+	}
+
+	DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
+		 iface->name, ep_string, ep_process_string);
+	TALLOC_FREE(ep_string);
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
+						DATA_BLOB *session_key)
+{
+	if (auth->session_info == NULL) {
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
+	if (auth->session_info->session_key.length == 0) {
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
+	*session_key = auth->session_info->session_key;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
+					  DATA_BLOB *session_key)
+{
+	if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
+	return dcesrv_session_info_session_key(auth, session_key);
+}
+
+static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
+					       DATA_BLOB *session_key)
+{
+	return dcerpc_generic_session_key(session_key);
+}
+
+/*
+ * Fetch the authentication session key if available.
+ *
+ * This is the key generated by a gensec authentication.
+ *
+ */
+_PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
+					  DATA_BLOB *session_key)
+{
+	struct dcesrv_auth *auth = call->auth_state;
+	SMB_ASSERT(auth->auth_finished);
+	return dcesrv_session_info_session_key(auth, session_key);
+}
+
+/*
+ * Fetch the transport session key if available.
+ * Typically this is the SMB session key
+ * or a fixed key for local transports.
+ *
+ * The key is always truncated to 16 bytes.
+*/
+_PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
+					       DATA_BLOB *session_key)
+{
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	SMB_ASSERT(auth->auth_finished);
+
+	if (auth->session_key_fn == NULL) {
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
+	status = auth->session_key_fn(auth, session_key);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	session_key->length = MIN(session_key->length, 16);
+
+	return NT_STATUS_OK;
+}
+
+static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
+{
+	const struct dcesrv_endpoint *ep = conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(ep->ep_description);
+	struct dcesrv_auth *auth = NULL;
+
+	auth = talloc_zero(conn, struct dcesrv_auth);
+	if (auth == NULL) {
+		return NULL;
+	}
+
+	switch (transport) {
+	case NCACN_NP:
+		auth->session_key_fn = dcesrv_remote_session_key;
+		break;
+	case NCALRPC:
+	case NCACN_UNIX_STREAM:
+		auth->session_key_fn = dcesrv_local_fixed_session_key;
+		break;
+	default:
+		/*
+		 * All other's get a NULL pointer, which
+		 * results in NT_STATUS_NO_USER_SESSION_KEY
+		 */
+		break;
+	}
+
+	return auth;
+}
+
+/*
+  connect to a dcerpc endpoint
+*/
+_PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
+				TALLOC_CTX *mem_ctx,
+				const struct dcesrv_endpoint *ep,
+				struct auth_session_info *session_info,
+				struct tevent_context *event_ctx,
+				uint32_t state_flags,
+				struct dcesrv_connection **_p)
+{
+	struct dcesrv_auth *auth = NULL;
+	struct dcesrv_connection *p;
+
+	if (!session_info) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	p = talloc_zero(mem_ctx, struct dcesrv_connection);
+	NT_STATUS_HAVE_NO_MEMORY(p);
+
+	p->dce_ctx = dce_ctx;
+	p->endpoint = ep;
+	p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
+					      NULL,
+					      "dcesrv",
+					      "stubs directory");
+	p->event_ctx = event_ctx;
+	p->state_flags = state_flags;
+	p->allow_bind = true;
+	p->max_recv_frag = 5840;
+	p->max_xmit_frag = 5840;
+	p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
+
+	p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
+						 NULL,
+						 "dcesrv",
+						 "header signing",
+						 true);
+	p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
+					      NULL,
+					      "dcesrv",
+					      "max auth states",
+					      2049);
+
+	auth = dcesrv_auth_create(p);
+	if (auth == NULL) {
+		talloc_free(p);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	auth->session_info = talloc_reference(auth, session_info);
+	if (auth->session_info == NULL) {
+		talloc_free(p);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	p->default_auth_state = auth;
+
+	/*
+	 * For now we only support NDR32.
+	 */
+	p->preferred_transfer = &ndr_transfer_syntax_ndr;
+
+	*_p = p;
+	return NT_STATUS_OK;
+}
+
+/*
+  move a call from an existing linked list to the specified list. This
+  prevents bugs where we forget to remove the call from a previous
+  list when moving it.
+ */
+static void dcesrv_call_set_list(struct dcesrv_call_state *call,
+				 enum dcesrv_call_list list)
+{
+	switch (call->list) {
+	case DCESRV_LIST_NONE:
+		break;
+	case DCESRV_LIST_CALL_LIST:
+		DLIST_REMOVE(call->conn->call_list, call);
+		break;
+	case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+		DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
+		break;
+	case DCESRV_LIST_PENDING_CALL_LIST:
+		DLIST_REMOVE(call->conn->pending_call_list, call);
+		break;
+	}
+	call->list = list;
+	switch (list) {
+	case DCESRV_LIST_NONE:
+		break;
+	case DCESRV_LIST_CALL_LIST:
+		DLIST_ADD_END(call->conn->call_list, call);
+		break;
+	case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+		DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
+		break;
+	case DCESRV_LIST_PENDING_CALL_LIST:
+		DLIST_ADD_END(call->conn->pending_call_list, call);
+		break;
+	}
+}
+
+static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
+					 const char *reason)
+{
+	struct dcesrv_auth *a = NULL;
+
+	if (call->conn->terminate != NULL) {
+		return;
+	}
+
+	call->conn->allow_bind = false;
+	call->conn->allow_alter = false;
+
+	call->conn->default_auth_state->auth_invalid = true;
+
+	for (a = call->conn->auth_states; a != NULL; a = a->next) {
+		a->auth_invalid = true;
+	}
+
+	call->terminate_reason = talloc_strdup(call, reason);
+	if (call->terminate_reason == NULL) {
+		call->terminate_reason = __location__;
+	}
+}
+
+/*
+  return a dcerpc bind_nak
+*/
+static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
+{
+	struct ncacn_packet pkt;
+	struct dcerpc_bind_nak_version version;
+	struct data_blob_list_item *rep;
+	NTSTATUS status;
+	static const uint8_t _pad[3] = { 0, };
+
+	/*
+	 * We add the call to the pending_call_list
+	 * in order to defer the termination.
+	 */
+	dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
+
+	/* setup a bind_nak */
+	dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+	pkt.auth_length = 0;
+	pkt.call_id = call->pkt.call_id;
+	pkt.ptype = DCERPC_PKT_BIND_NAK;
+	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+	pkt.u.bind_nak.reject_reason = reason;
+	version.rpc_vers = 5;
+	version.rpc_vers_minor = 0;
+	pkt.u.bind_nak.num_versions = 1;
+	pkt.u.bind_nak.versions = &version;
+	pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
+
+	rep = talloc_zero(call, struct data_blob_list_item);
+	if (!rep) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	dcerpc_set_frag_length(&rep->blob, rep->blob.length);
+
+	DLIST_ADD_END(call->replies, rep);
+	dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
+
+	if (call->conn->call_list && call->conn->call_list->replies) {
+		if (call->conn->transport.report_output_data) {
+			call->conn->transport.report_output_data(call->conn);
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
++static NTSTATUS _dcesrv_fault_disconnect_flags(struct dcesrv_call_state *call,
+		uint32_t fault_code,
+		uint8_t extra_flags,
+		const char *func,
+		const char *location)
+{
+	const char *reason = NULL;
+	reason = talloc_asprintf(call, "%s:%s: fault=%u (%s) flags=0x%x",
+			func, location,
+			fault_code,
+			dcerpc_errstr(call, fault_code),
+			extra_flags);
+	if (reason == NULL) {
+		reason = location;
+	}
+	dcesrv_call_disconnect_after(call, reason);
+	return dcesrv_fault_with_flags(call, fault_code, extra_flags);
+}
+
+#define dcesrv_fault_disconnect(call, fault_code) \
+	_dcesrv_fault_disconnect_flags(call, fault_code, \
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE, \
+			__func__, __location__)
+#define dcesrv_fault_disconnect0(call, fault_code) \
+	_dcesrv_fault_disconnect_flags(call, fault_code, 0, \
+			__func__, __location__)
+
+static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
+{
+	DLIST_REMOVE(c->conn->contexts, c);
+
+	if (c->iface && c->iface->unbind) {
+		c->iface->unbind(c, c->iface);
+		c->iface = NULL;
+	}
+
+	return 0;
+}
+
+static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+	struct dcesrv_connection_context *context = dce_call->context;
+	const struct dcesrv_interface *iface = context->iface;
+
+	context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+}
+
+NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
+						 const struct dcesrv_interface *iface)
+{
+	/*
+	 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
+	 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
+	 */
+	context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
+	return NT_STATUS_OK;
+}
+
+NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
+					       const struct dcesrv_interface *iface)
+{
+	context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
+						       const struct dcesrv_interface *iface)
+{
+	struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = false;
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
+						      const struct dcesrv_interface *iface)
+{
+	struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = true;
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+	return NT_STATUS_OK;
+}
+
+struct dcesrv_conn_auth_wait_context {
+	struct tevent_req *req;
+	bool done;
+	NTSTATUS status;
+};
+
+struct dcesrv_conn_auth_wait_state {
+	uint8_t dummy;
+};
+
+static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
+						     struct tevent_context *ev,
+						     void *private_data)
+{
+	struct dcesrv_conn_auth_wait_context *auth_wait =
+		talloc_get_type_abort(private_data,
+		struct dcesrv_conn_auth_wait_context);
+	struct tevent_req *req = NULL;
+	struct dcesrv_conn_auth_wait_state *state = NULL;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct dcesrv_conn_auth_wait_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	auth_wait->req = req;
+
+	tevent_req_defer_callback(req, ev);
+
+	if (!auth_wait->done) {
+		return req;
+	}
+
+	if (tevent_req_nterror(req, auth_wait->status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
+static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
+{
+	struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
+
+	if (conn->wait_send != NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
+	if (auth_wait == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	conn->wait_private = auth_wait;
+	conn->wait_send = dcesrv_conn_auth_wait_send;
+	conn->wait_recv = dcesrv_conn_auth_wait_recv;
+	return NT_STATUS_OK;
+}
+
+static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
+					   NTSTATUS status)
+{
+	struct dcesrv_conn_auth_wait_context *auth_wait =
+		talloc_get_type_abort(conn->wait_private,
+		struct dcesrv_conn_auth_wait_context);
+
+	auth_wait->done = true;
+	auth_wait->status = status;
+
+	if (auth_wait->req == NULL) {
+		return;
+	}
+
+	if (tevent_req_nterror(auth_wait->req, status)) {
+		return;
+	}
+
+	tevent_req_done(auth_wait->req);
+}
+
+static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
+
+static void dcesrv_bind_done(struct tevent_req *subreq);
+
+/*
+  handle a bind request
+*/
+static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
+{
+	struct dcesrv_connection *conn = call->conn;
+	struct ncacn_packet *pkt = &call->ack_pkt;
+	NTSTATUS status;
+	uint32_t extra_flags = 0;
+	uint16_t max_req = 0;
+	uint16_t max_rep = 0;
+	struct dcerpc_binding *ep_2nd_description = NULL;
+	const char *endpoint = NULL;
+	struct dcesrv_auth *auth = call->auth_state;
+	struct dcerpc_ack_ctx *ack_ctx_list = NULL;
+	struct dcerpc_ack_ctx *ack_features = NULL;
+	struct tevent_req *subreq = NULL;
+	size_t i;
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_BIND,
+			call->pkt.u.bind.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_bind_nak(call,
+			DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
+	}
+
+	/* max_recv_frag and max_xmit_frag result always in the same value! */
+	max_req = MIN(call->pkt.u.bind.max_xmit_frag,
+		      call->pkt.u.bind.max_recv_frag);
+	/*
+	 * The values are between 2048 and 5840 tested against Windows 2012R2
+	 * via ncacn_ip_tcp on port 135.
+	 */
+	max_req = MAX(2048, max_req);
+	max_rep = MIN(max_req, call->conn->max_recv_frag);
+	/* They are truncated to an 8 byte boundary. */
+	max_rep &= 0xFFF8;
+
+	/* max_recv_frag and max_xmit_frag result always in the same value! */
+	call->conn->max_recv_frag = max_rep;
+	call->conn->max_xmit_frag = max_rep;
+
+	status = call->conn->dce_ctx->callbacks.assoc_group.find(call);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
+			   call->pkt.u.bind.assoc_group_id, nt_errstr(status));
+		return dcesrv_bind_nak(call, 0);
+	}
+
+	if (call->pkt.u.bind.num_contexts < 1) {
+		return dcesrv_bind_nak(call, 0);
+	}
+
+	ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
+					 call->pkt.u.bind.num_contexts);
+	if (ack_ctx_list == NULL) {
+		return dcesrv_bind_nak(call, 0);
+	}
+
+	/*
+	 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
+	 * dcesrv_check_or_create_context()) and do some protocol validation
+	 * and set sane defaults.
+	 */
+	for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
+		const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
+		struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
+		bool is_feature = false;
+		uint64_t features = 0;
+
+		if (c->num_transfer_syntaxes == 0) {
+			return dcesrv_bind_nak(call, 0);
+		}
+
+		a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
+		a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
+
+		/*
+		 * It's only treated as bind time feature request, if the first
+		 * transfer_syntax matches, all others are ignored.
+		 */
+		is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
+							       &features);
+		if (!is_feature) {
+			continue;
+		}
+
+		if (ack_features != NULL) {
+			/*
+			 * Only one bind time feature context is allowed.
+			 */
+			return dcesrv_bind_nak(call, 0);
+		}
+		ack_features = a;
+
+		a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
+		a->reason.negotiate = 0;
+		if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
+			if (call->conn->max_auth_states != 0) {
+				a->reason.negotiate |=
+				DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
+			}
+		}
+		if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
+			a->reason.negotiate |=
+				DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
+		}
+
+		call->conn->assoc_group->bind_time_features = a->reason.negotiate;
+	}
+
+	/*
+	 * Try to negotiate one new presentation context.
+	 *
+	 * Deep in here we locate the iface (by uuid) that the client
+	 * requested, from the list of interfaces on the
+	 * call->conn->endpoint, and call iface->bind() on that iface.
+	 *
+	 * call->conn was set up at the accept() of the socket, and
+	 * call->conn->endpoint has a list of interfaces restricted to
+	 * this port or pipe.
+	 */
+	status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+		return dcesrv_bind_nak(call, 0);
+	}
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	/*
+	 * At this point we still don't know which interface (eg
+	 * netlogon, lsa, drsuapi) the caller requested in this bind!
+	 * The most recently added context is available as the first
+	 * element in the linked list at call->conn->contexts, that is
+	 * call->conn->contexts->iface, but they may not have
+	 * requested one at all!
+	 */
+
+	if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
+	    (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+		call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
+		extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
+	}
+
+	if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
+		call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
+	}
+
+	/*
+	 * After finding the interface and setting up the NDR
+	 * transport negotiation etc, handle any authentication that
+	 * is being requested.
+	 */
+	if (!dcesrv_auth_bind(call)) {
+
+		if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
+			/*
+			 * With DCERPC_AUTH_LEVEL_NONE, we get the
+			 * reject_reason in auth->auth_context_id.
+			 */
+			return dcesrv_bind_nak(call, auth->auth_context_id);
+		}
+
+		/*
+		 * This must a be a temporary failure e.g. talloc or invalid
+		 * configuration, e.g. no machine account.
+		 */
+		return dcesrv_bind_nak(call,
+				DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
+	}
+
+	/* setup a bind_ack */
+	dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+	pkt->auth_length = 0;
+	pkt->call_id = call->pkt.call_id;
+	pkt->ptype = DCERPC_PKT_BIND_ACK;
+	pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+	pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
+	pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
+	pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
+
+	ep_2nd_description = call->conn->endpoint->ep_2nd_description;
+	if (ep_2nd_description == NULL) {
+		ep_2nd_description = call->conn->endpoint->ep_description;
+	}
+
+	endpoint = dcerpc_binding_get_string_option(
+				ep_2nd_description,
+				"endpoint");
+	if (endpoint == NULL) {
+		endpoint = "";
+	}
+
+	pkt->u.bind_ack.secondary_address = endpoint;
+	pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
+	pkt->u.bind_ack.ctx_list = ack_ctx_list;
+	pkt->u.bind_ack.auth_info = data_blob_null;
+
+	status = dcesrv_auth_prepare_bind_ack(call, pkt);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_bind_nak(call, 0);
+	}
+
+	if (auth->auth_finished) {
+		return dcesrv_auth_reply(call);
+	}
+
+	subreq = gensec_update_send(call, call->event_ctx,
+				    auth->gensec_security,
+				    call->in_auth_info.credentials);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, dcesrv_bind_done, call);
+
+	return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_bind_done(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call =
+		tevent_req_callback_data(subreq,
+		struct dcesrv_call_state);
+	struct dcesrv_connection *conn = call->conn;
+	NTSTATUS status;
+
+	status = gensec_update_recv(subreq, call,
+				    &call->out_auth_info->credentials);
+	TALLOC_FREE(subreq);
+
+	status = dcesrv_auth_complete(call, status);
+	if (!NT_STATUS_IS_OK(status)) {
+		status = dcesrv_bind_nak(call, 0);
+		dcesrv_conn_auth_wait_finished(conn, status);
+		return;
+	}
+
+	status = dcesrv_auth_reply(call);
+	dcesrv_conn_auth_wait_finished(conn, status);
+	return;
+}
+
+static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
+{
+	struct ncacn_packet *pkt = &call->ack_pkt;
+	struct data_blob_list_item *rep = NULL;
+	NTSTATUS status;
+
+	rep = talloc_zero(call, struct data_blob_list_item);
+	if (!rep) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = dcerpc_ncacn_push_auth(&rep->blob,
+					call,
+					pkt,
+					call->out_auth_info);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	dcerpc_set_frag_length(&rep->blob, rep->blob.length);
+
+	DLIST_ADD_END(call->replies, rep);
+	dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
+
+	if (call->conn->call_list && call->conn->call_list->replies) {
+		if (call->conn->transport.report_output_data) {
+			call->conn->transport.report_output_data(call->conn);
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+
+static void dcesrv_auth3_done(struct tevent_req *subreq);
+
+/*
+  handle a auth3 request
+*/
+static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
+{
+	struct dcesrv_connection *conn = call->conn;
+	struct dcesrv_auth *auth = call->auth_state;
+	struct tevent_req *subreq = NULL;
+	NTSTATUS status;
+
+	if (!auth->auth_started) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	if (auth->auth_finished) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_AUTH3,
+			call->pkt.u.auth3.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	/* handle the auth3 in the auth code */
+	if (!dcesrv_auth_prepare_auth3(call)) {
+		/*
+		 * we don't send a reply to a auth3 request,
+		 * except by a fault.
+		 *
+		 * In anycase we mark the connection as
+		 * invalid.
+		 */
+		auth->auth_invalid = true;
+		if (call->fault_code != 0) {
+			return dcesrv_fault_disconnect(call, call->fault_code);
+		}
+		TALLOC_FREE(call);
+		return NT_STATUS_OK;
+	}
+
+	subreq = gensec_update_send(call, call->event_ctx,
+				    auth->gensec_security,
+				    call->in_auth_info.credentials);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
+
+	return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_auth3_done(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call =
+		tevent_req_callback_data(subreq,
+		struct dcesrv_call_state);
+	struct dcesrv_connection *conn = call->conn;
+	struct dcesrv_auth *auth = call->auth_state;
+	NTSTATUS status;
+
+	status = gensec_update_recv(subreq, call,
+				    &call->out_auth_info->credentials);
+	TALLOC_FREE(subreq);
+
+	status = dcesrv_auth_complete(call, status);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * we don't send a reply to a auth3 request,
+		 * except by a fault.
+		 *
+		 * In anycase we mark the connection as
+		 * invalid.
+		 */
+		auth->auth_invalid = true;
+		if (call->fault_code != 0) {
+			status = dcesrv_fault_disconnect(call, call->fault_code);
+			dcesrv_conn_auth_wait_finished(conn, status);
+			return;
+		}
+		TALLOC_FREE(call);
+		dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
+		return;
+	}
+
+	/*
+	 * we don't send a reply to a auth3 request.
+	 */
+	TALLOC_FREE(call);
+	dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
+	return;
+}
+
+
+static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
+				const struct dcerpc_bind *b,
+				const struct dcerpc_ctx_list *ctx,
+				struct dcerpc_ack_ctx *ack,
+				bool validate_only,
+				const struct ndr_syntax_id *supported_transfer)
+{
+	uint32_t if_version;
+	struct dcesrv_connection_context *context;
+	const struct dcesrv_interface *iface;
+	struct GUID uuid;
+	NTSTATUS status;
+	const struct ndr_syntax_id *selected_transfer = NULL;
+	size_t i;
+	bool ok;
+
+	if (b == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	if (ctx == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	if (ctx->num_transfer_syntaxes < 1) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	if (ack == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	if (supported_transfer == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	switch (ack->result) {
+	case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
+	case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
+		/*
+		 * We is already completed.
+		 */
+		return NT_STATUS_OK;
+	default:
+		break;
+	}
+
+	ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
+	ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
+
+	if_version = ctx->abstract_syntax.if_version;
+	uuid = ctx->abstract_syntax.uuid;
+
+	iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
+	if (iface == NULL) {
+		char *uuid_str = GUID_string(call, &uuid);
+		DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
+		talloc_free(uuid_str);
+		/*
+		 * We report this only via ack->result
+		 */
+		return NT_STATUS_OK;
+	}
+
+	ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
+	ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
+
+	if (validate_only) {
+		/*
+		 * We report this only via ack->result
+		 */
+		return NT_STATUS_OK;
+	}
+
+	for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
+		/*
+		 * we only do NDR encoded dcerpc for now.
+		 */
+		ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
+					 supported_transfer);
+		if (ok) {
+			selected_transfer = supported_transfer;
+			break;
+		}
+	}
+
+	context = dcesrv_find_context(call->conn, ctx->context_id);
+	if (context != NULL) {
+		ok = ndr_syntax_id_equal(&context->iface->syntax_id,
+					 &ctx->abstract_syntax);
+		if (!ok) {
+			return NT_STATUS_RPC_PROTOCOL_ERROR;
+		}
+
+		if (selected_transfer != NULL) {
+			ok = ndr_syntax_id_equal(&context->transfer_syntax,
+						 selected_transfer);
+			if (!ok) {
+				return NT_STATUS_RPC_PROTOCOL_ERROR;
+			}
+
+			ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
+			ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
+			ack->syntax = context->transfer_syntax;
+		}
+
+		/*
+		 * We report this only via ack->result
+		 */
+		return NT_STATUS_OK;
+	}
+
+	if (selected_transfer == NULL) {
+		/*
+		 * We report this only via ack->result
+		 */
+		return NT_STATUS_OK;
+	}
+
+	ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
+	ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
+
+	/* add this context to the list of available context_ids */
+	context = talloc_zero(call->conn, struct dcesrv_connection_context);
+	if (context == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	context->conn = call->conn;
+	context->context_id = ctx->context_id;
+	context->iface = iface;
+	context->transfer_syntax = *selected_transfer;
+	DLIST_ADD(call->conn->contexts, context);
+	call->context = context;
+	talloc_set_destructor(context, dcesrv_connection_context_destructor);
+
+	dcesrv_prepare_context_auth(call);
+
+	/*
+	 * Multiplex is supported by default
+	 */
+	call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
+
+	status = iface->bind(context, iface);
+	call->context = NULL;
+	if (!NT_STATUS_IS_OK(status)) {
+		/* we don't want to trigger the iface->unbind() hook */
+		context->iface = NULL;
+		talloc_free(context);
+		/*
+		 * We report this only via ack->result
+		 */
+		return NT_STATUS_OK;
+	}
+
+	ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
+	ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
+	ack->syntax = context->transfer_syntax;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
+				const struct dcerpc_bind *b,
+				struct dcerpc_ack_ctx *ack_ctx_list)
+{
+	NTSTATUS status;
+	size_t i;
+	bool validate_only = false;
+	bool preferred_ndr32;
+
+	/*
+	 * Try to negotiate one new presentation context,
+	 * using our preferred transfer syntax.
+	 */
+	for (i = 0; i < b->num_contexts; i++) {
+		const struct dcerpc_ctx_list *c = &b->ctx_list[i];
+		struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
+
+		status = dcesrv_check_or_create_context(call, b, c, a,
+						validate_only,
+						call->conn->preferred_transfer);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
+			/*
+			 * We managed to negotiate one context.
+			 *
+			 * => we're done.
+			 */
+			validate_only = true;
+		}
+	}
+
+	preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
+					call->conn->preferred_transfer);
+	if (preferred_ndr32) {
+		/*
+		 * We're done.
+		 */
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * Try to negotiate one new presentation context,
+	 * using NDR 32 as fallback.
+	 */
+	for (i = 0; i < b->num_contexts; i++) {
+		const struct dcerpc_ctx_list *c = &b->ctx_list[i];
+		struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
+
+		status = dcesrv_check_or_create_context(call, b, c, a,
+						validate_only,
+						&ndr_transfer_syntax_ndr);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
+			/*
+			 * We managed to negotiate one context.
+			 *
+			 * => we're done.
+			 */
+			validate_only = true;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+static void dcesrv_alter_done(struct tevent_req *subreq);
+
+/*
+  handle a alter context request
+*/
+static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
+{
+	struct dcesrv_connection *conn = call->conn;
+	NTSTATUS status;
+	bool auth_ok = false;
+	struct ncacn_packet *pkt = &call->ack_pkt;
+	uint32_t extra_flags = 0;
+	struct dcesrv_auth *auth = call->auth_state;
+	struct dcerpc_ack_ctx *ack_ctx_list = NULL;
+	struct tevent_req *subreq = NULL;
+	size_t i;
+
+	if (!call->conn->allow_alter) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_ALTER,
+			call->pkt.u.alter.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	auth_ok = dcesrv_auth_alter(call);
+	if (!auth_ok) {
+		if (call->fault_code != 0) {
+			return dcesrv_fault_disconnect(call, call->fault_code);
+		}
+	}
+
+	if (call->pkt.u.alter.num_contexts < 1) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
+					 call->pkt.u.alter.num_contexts);
+	if (ack_ctx_list == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/*
+	 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
+	 * dcesrv_check_or_create_context()) and do some protocol validation
+	 * and set sane defaults.
+	 */
+	for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
+		const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
+		struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
+
+		if (c->num_transfer_syntaxes == 0) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
+		a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
+	}
+
+	/*
+	 * Try to negotiate one new presentation context.
+	 */
+	status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
+	    (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+		call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
+		extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
+	}
+
+	if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
+		call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
+	}
+
+	/* handle any authentication that is being requested */
+	if (!auth_ok) {
+		if (call->in_auth_info.auth_type != auth->auth_type) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_FAULT_SEC_PKG_ERROR);
+		}
+		return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
+	}
+
+	dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+	pkt->auth_length = 0;
+	pkt->call_id = call->pkt.call_id;
+	pkt->ptype = DCERPC_PKT_ALTER_RESP;
+	pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+	pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
+	pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
+	pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
+	pkt->u.alter_resp.secondary_address = "";
+	pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
+	pkt->u.alter_resp.ctx_list = ack_ctx_list;
+	pkt->u.alter_resp.auth_info = data_blob_null;
+
+	status = dcesrv_auth_prepare_alter_ack(call, pkt);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
+	}
+
+	if (auth->auth_finished) {
+		return dcesrv_auth_reply(call);
+	}
+
+	subreq = gensec_update_send(call, call->event_ctx,
+				    auth->gensec_security,
+				    call->in_auth_info.credentials);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, dcesrv_alter_done, call);
+
+	return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_alter_done(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call =
+		tevent_req_callback_data(subreq,
+		struct dcesrv_call_state);
+	struct dcesrv_connection *conn = call->conn;
+	NTSTATUS status;
+
+	status = gensec_update_recv(subreq, call,
+				    &call->out_auth_info->credentials);
+	TALLOC_FREE(subreq);
+
+	status = dcesrv_auth_complete(call, status);
+	if (!NT_STATUS_IS_OK(status)) {
+		status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
+		dcesrv_conn_auth_wait_finished(conn, status);
+		return;
+	}
+
+	status = dcesrv_auth_reply(call);
+	dcesrv_conn_auth_wait_finished(conn, status);
+	return;
+}
+
+/*
+  possibly save the call for inspection with ndrdump
+ */
+static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
+{
+#ifdef DEVELOPER
+	dcerpc_log_packet(call->conn->packet_log_dir,
+			  call->context->iface->name,
+			  call->pkt.u.request.opnum,
+			  NDR_IN,
+			  &call->pkt.u.request.stub_and_verifier,
+			  why);
+#endif
+}
+
+#ifdef DEVELOPER
+/*
+  Save the call for use as a seed for fuzzing.
+
+  This is only enabled in a developer build, and only has effect if the
+  "dcesrv fuzz directory" param is set.
+*/
+void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
+				struct dcesrv_call_state *call,
+				int flags)
+{
+	const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
+						 NULL,
+						 "dcesrv", "fuzz directory");
+
+	dcerpc_save_ndr_fuzz_seed(call,
+				  call_blob,
+				  dump_dir,
+				  call->context->iface->name,
+				  flags,
+				  call->pkt.u.request.opnum,
+				  call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
+}
+#endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
+
+
+static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	const uint32_t bitmask1 = call->conn->client_hdr_signing ?
+		DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
+	const struct dcerpc_sec_vt_pcontext pcontext = {
+		.abstract_syntax = call->context->iface->syntax_id,
+		.transfer_syntax = call->context->transfer_syntax,
+	};
+	const struct dcerpc_sec_vt_header2 header2 =
+		dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
+	enum ndr_err_code ndr_err;
+	struct dcerpc_sec_verification_trailer *vt = NULL;
+	NTSTATUS status = NT_STATUS_OK;
+	bool ok;
+
+	SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
+
+	ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
+							  frame, &vt);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		status = ndr_map_error2ntstatus(ndr_err);
+		goto done;
+	}
+
+	ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
+						   &pcontext, &header2);
+	if (!ok) {
+		status = NT_STATUS_ACCESS_DENIED;
+		goto done;
+	}
+done:
+	TALLOC_FREE(frame);
+	return status;
+}
+
+/*
+  handle a dcerpc request packet
+*/
+static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
+{
+	const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
+	struct dcesrv_auth *auth = call->auth_state;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+	struct ndr_pull *pull;
+	NTSTATUS status;
+
+	if (auth->auth_invalid) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	if (!auth->auth_finished) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	/* if authenticated, and the mech we use can't do async replies, don't use them... */
+	if (auth->gensec_security != NULL &&
+	    !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
+		call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
+	}
+
+	if (call->context == NULL) {
+		return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
+					DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+	}
+
+	switch (auth->auth_level) {
+	case DCERPC_AUTH_LEVEL_NONE:
+	case DCERPC_AUTH_LEVEL_PACKET:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		break;
+	default:
+		if (!call->context->allow_connect) {
+			char *addr;
+
+			addr = tsocket_address_string(call->conn->remote_address,
+						      call);
+
+			DEBUG(2, ("%s: restrict auth_level_connect access "
+				  "to [%s] with auth[type=0x%x,level=0x%x] "
+				  "on [%s] from [%s]\n",
+				  __func__, call->context->iface->name,
+				  auth->auth_type,
+				  auth->auth_level,
+				  derpc_transport_string_by_transport(transport),
+				  addr));
+			return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+		}
+		break;
+	}
+
+	if (auth->auth_level < call->context->min_auth_level) {
+		char *addr;
+
+		addr = tsocket_address_string(call->conn->remote_address, call);
+
+		DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
+			  "to [%s] with auth[type=0x%x,level=0x%x] "
+			  "on [%s] from [%s]\n",
+			  __func__,
+			  call->context->min_auth_level,
+			  call->context->iface->name,
+			  auth->auth_type,
+			  auth->auth_level,
+			  derpc_transport_string_by_transport(transport),
+			  addr));
+		return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+	}
+
+	pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
+	NT_STATUS_HAVE_NO_MEMORY(pull);
+
+	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+
+	call->ndr_pull	= pull;
+
+	if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
+		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
+	}
+
+	status = dcesrv_check_verification_trailer(call);
+	if (!NT_STATUS_IS_OK(status)) {
+		uint32_t faultcode = DCERPC_FAULT_OTHER;
+		if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+			faultcode = DCERPC_FAULT_ACCESS_DENIED;
+		}
+		DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
+			   nt_errstr(status)));
+		return dcesrv_fault(call, faultcode);
+	}
+
+	/* unravel the NDR for the packet */
+	status = call->context->iface->ndr_pull(call, call, pull, &call->r);
+	if (!NT_STATUS_IS_OK(status)) {
+		uint8_t extra_flags = 0;
+		if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
+			/* we got an unknown call */
+			DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
+				 call->pkt.u.request.opnum,
+				 call->context->iface->name));
+			dcesrv_save_call(call, "unknown");
+			extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
+		} else {
+			dcesrv_save_call(call, "pullfail");
+		}
+
+		return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
+	}
+
+	dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
+				  call,
+				  NDR_IN);
+
+	if (pull->offset != pull->data_size) {
+		dcesrv_save_call(call, "extrabytes");
+		DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
+			 pull->data_size - pull->offset));
+	}
+
+	/* call the dispatch function */
+	status = call->context->iface->dispatch(call, call, call->r);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
+			 call->context->iface->name,
+			 call->pkt.u.request.opnum,
+			 dcerpc_errstr(pull, call->fault_code)));
+		return dcesrv_fault(call, call->fault_code);
+	}
+
+	/* add the call to the pending list */
+	dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
+
+	if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
+		return NT_STATUS_OK;
+	}
+
+	return dcesrv_reply(call);
+}
+
+
+/*
+  remove the call from the right list when freed
+ */
+static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
+{
+	dcesrv_call_set_list(call, DCESRV_LIST_NONE);
+	return 0;
+}
+
+_PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
+{
+	return conn->local_address;
+}
+
+_PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
+{
+	return conn->remote_address;
+}
+
+/*
+  process some input to a dcerpc endpoint server.
+*/
+static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
+					    struct ncacn_packet *pkt,
+					    DATA_BLOB blob)
+{
+	NTSTATUS status;
+	struct dcesrv_call_state *call;
+	struct dcesrv_call_state *existing = NULL;
+	size_t num_auth_ctx = 0;
+	enum dcerpc_AuthType auth_type = 0;
+	enum dcerpc_AuthLevel auth_level = 0;
+	uint32_t auth_context_id = 0;
+	bool auth_invalid = false;
+
+	call = talloc_zero(dce_conn, struct dcesrv_call_state);
+	if (!call) {
+		data_blob_free(&blob);
+		talloc_free(pkt);
+		return NT_STATUS_NO_MEMORY;
+	}
+	call->conn		= dce_conn;
+	call->event_ctx		= dce_conn->event_ctx;
+	call->state_flags	= call->conn->state_flags;
+	call->time		= timeval_current();
+	call->list              = DCESRV_LIST_NONE;
+
+	talloc_steal(call, pkt);
+	talloc_steal(call, blob.data);
+	call->pkt = *pkt;
+
+	if (dce_conn->max_auth_states == 0) {
+		call->auth_state = dce_conn->default_auth_state;
+	} else if (call->pkt.auth_length == 0) {
+		if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
+		    dce_conn->default_auth_level_connect != NULL)
+		{
+			call->auth_state = dce_conn->default_auth_level_connect;
+		} else {
+			call->auth_state = dce_conn->default_auth_state;
+		}
+	}
+
+	if (call->auth_state == NULL) {
+		struct dcesrv_auth *a = NULL;
+		bool check_type_level = true;
+
+		auth_type = dcerpc_get_auth_type(&blob);
+		auth_level = dcerpc_get_auth_level(&blob);
+		auth_context_id = dcerpc_get_auth_context_id(&blob);
+
+		if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+			if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+				check_type_level = false;
+			}
+			dce_conn->default_auth_level_connect = NULL;
+			if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
+				dce_conn->got_explicit_auth_level_connect = true;
+			}
+		}
+
+		for (a = dce_conn->auth_states; a != NULL; a = a->next) {
+			num_auth_ctx++;
+
+			if (a->auth_context_id != auth_context_id) {
+				continue;
+			}
+			if (a->auth_type != auth_type) {
+				auth_invalid = true;
+			}
+			if (a->auth_level != auth_level) {
+				auth_invalid = true;
+			}
+			if (check_type_level && auth_invalid) {
+				a->auth_invalid = true;
+			}
+
+			DLIST_PROMOTE(dce_conn->auth_states, a);
+			call->auth_state = a;
+			break;
+		}
+	}
+
+	if (call->auth_state == NULL) {
+		struct dcesrv_auth *a = NULL;
+
+		if (num_auth_ctx >= dce_conn->max_auth_states) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		a = dcesrv_auth_create(dce_conn);
+		if (a == NULL) {
+			talloc_free(call);
+			return NT_STATUS_NO_MEMORY;
+		}
+		DLIST_ADD(dce_conn->auth_states, a);
+		if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+			/*
+			 * This can never be valid.
+			 */
+			auth_invalid = true;
+			a->auth_invalid = true;
+		}
+		call->auth_state = a;
+	}
+
+	talloc_set_destructor(call, dcesrv_call_dequeue);
+
+	if (call->conn->allow_bind) {
+		/*
+		 * Only one bind is possible per connection
+		 */
+		call->conn->allow_bind = false;
+		return dcesrv_bind(call);
+	}
+
+	/* we have to check the signing here, before combining the
+	   pdus */
+	if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+		dcesrv_default_auth_state_prepare_request(call);
+
+		if (call->auth_state->auth_started &&
+		    !call->auth_state->auth_finished) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+				DCERPC_PKT_REQUEST,
+				call->pkt.u.request.stub_and_verifier.length,
+				0, /* required_flags */
+				DCERPC_PFC_FLAG_FIRST |
+				DCERPC_PFC_FLAG_LAST |
+				DCERPC_PFC_FLAG_PENDING_CANCEL |
+				0x08 | /* this is not defined, but should be ignored */
+				DCERPC_PFC_FLAG_CONC_MPX |
+				DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+				DCERPC_PFC_FLAG_MAYBE |
+				DCERPC_PFC_FLAG_OBJECT_UUID);
+		if (!NT_STATUS_IS_OK(status)) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
+			/*
+			 * We don't use dcesrv_fault_disconnect()
+			 * here, because we don't want to set
+			 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
+			 *
+			 * Note that we don't check against the negotiated
+			 * max_recv_frag, but a hard coded value.
+			 */
+			return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+			if (dce_conn->pending_call_list != NULL) {
+				/*
+				 * concurrent requests are only allowed
+				 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
+				 */
+				if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+					return dcesrv_fault_disconnect0(call,
+						DCERPC_NCA_S_PROTO_ERROR);
+				}
+			}
+			/* only one request is possible in the fragmented list */
+			if (dce_conn->incoming_fragmented_call_list != NULL) {
+				call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
+				existing = dcesrv_find_fragmented_call(dce_conn,
+						call->pkt.call_id);
+				if (existing != NULL && call->auth_state != existing->auth_state) {
+					call->context = dcesrv_find_context(call->conn,
+							call->pkt.u.request.context_id);
+					if (call->pkt.auth_length != 0 && existing->context == call->context) {
+						call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
+					}
+				}
+				if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+					/*
+					 * Without DCERPC_PFC_FLAG_CONC_MPX
+					 * we need to return the FAULT on the
+					 * already existing call.
+					 *
+					 * This is important to get the
+					 * call_id and context_id right.
+					 */
+					dce_conn->incoming_fragmented_call_list->fault_code = call->fault_code;
+					TALLOC_FREE(call);
+					call = dce_conn->incoming_fragmented_call_list;
+				}
+				if (existing != NULL) {
+					call->context = existing->context;
+				}
+				return dcesrv_fault_disconnect0(call, call->fault_code);
+			}
+			if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
+				return dcesrv_fault_disconnect(call,
+						DCERPC_FAULT_NO_CALL_ACTIVE);
+			}
+			call->context = dcesrv_find_context(call->conn,
+						call->pkt.u.request.context_id);
+			if (call->context == NULL) {
+				return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
+					DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+			}
+		} else {
+			int cmp;
+
+			existing = dcesrv_find_fragmented_call(dce_conn,
+							call->pkt.call_id);
+			if (existing == NULL) {
+				if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+					/*
+					 * Without DCERPC_PFC_FLAG_CONC_MPX
+					 * we need to return the FAULT on the
+					 * already existing call.
+					 * This is important to get the
+					 * call_id and context_id right.
+					 */
+					if (dce_conn->incoming_fragmented_call_list != NULL) {
+						TALLOC_FREE(call);
+						call = dce_conn->incoming_fragmented_call_list;
+					}
+					return dcesrv_fault_disconnect0(call,
+							DCERPC_NCA_S_PROTO_ERROR);
+				}
+				if (dce_conn->incoming_fragmented_call_list != NULL) {
+					return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
+				}
+				call->context = dcesrv_find_context(call->conn,
+						call->pkt.u.request.context_id);
+				if (call->context == NULL) {
+					return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
+							DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+				}
+				if (auth_invalid) {
+					return dcesrv_fault_disconnect0(call,
+							DCERPC_FAULT_ACCESS_DENIED);
+				}
+				return dcesrv_fault_disconnect0(call,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+
+			if (call->pkt.ptype != existing->pkt.ptype) {
+				/* trying to play silly buggers are we? */
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			cmp = memcmp(call->pkt.drep, existing->pkt.drep,
+				     sizeof(pkt->drep));
+			if (cmp != 0) {
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			call->auth_state = existing->auth_state;
+			call->context = existing->context;
+		}
+	}
+
+	if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+		bool ok;
+		uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
+
+		if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+			payload_offset += 16;
+		}
+
+		ok = dcesrv_auth_pkt_pull(call, &blob,
+					  0, /* required_flags */
+					  DCERPC_PFC_FLAG_FIRST |
+					  DCERPC_PFC_FLAG_LAST |
+					  DCERPC_PFC_FLAG_PENDING_CANCEL |
+					  0x08 | /* this is not defined, but should be ignored */
+					  DCERPC_PFC_FLAG_CONC_MPX |
+					  DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+					  DCERPC_PFC_FLAG_MAYBE |
+					  DCERPC_PFC_FLAG_OBJECT_UUID,
+					  payload_offset,
+					  &call->pkt.u.request.stub_and_verifier);
+		if (!ok) {
+			/*
+			 * We don't use dcesrv_fault_disconnect()
+			 * here, because we don't want to set
+			 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
+			 */
+			if (call->fault_code == 0) {
+				call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+			}
+			return dcesrv_fault_disconnect0(call, call->fault_code);
+		}
+	}
+
+	/* see if this is a continued packet */
+	if (existing != NULL) {
+		struct dcerpc_request *er = &existing->pkt.u.request;
+		const struct dcerpc_request *nr = &call->pkt.u.request;
+		size_t available;
+		size_t alloc_size;
+		size_t alloc_hint;
+
+		/*
+		 * Up to 4 MByte are allowed by all fragments
+		 */
+		available = dce_conn->max_total_request_size;
+		if (er->stub_and_verifier.length > available) {
+			return dcesrv_fault_disconnect0(existing,
+					DCERPC_FAULT_ACCESS_DENIED);
+		}
+		available -= er->stub_and_verifier.length;
+		if (nr->alloc_hint > available) {
+			return dcesrv_fault_disconnect0(existing,
+					DCERPC_FAULT_ACCESS_DENIED);
+		}
+		if (nr->stub_and_verifier.length > available) {
+			return dcesrv_fault_disconnect0(existing,
+					DCERPC_FAULT_ACCESS_DENIED);
+		}
+		alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
+		/* allocate at least 1 byte */
+		alloc_hint = MAX(alloc_hint, 1);
+		alloc_size = er->stub_and_verifier.length +
+			     nr->stub_and_verifier.length;
+		alloc_size = MAX(alloc_size, alloc_hint);
+
+		er->stub_and_verifier.data =
+			talloc_realloc(existing,
+				       er->stub_and_verifier.data,
+				       uint8_t, alloc_size);
+		if (er->stub_and_verifier.data == NULL) {
+			TALLOC_FREE(call);
+			return dcesrv_fault_with_flags(existing,
+						       DCERPC_FAULT_OUT_OF_RESOURCES,
+						       DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+		}
+		memcpy(er->stub_and_verifier.data +
+		       er->stub_and_verifier.length,
+		       nr->stub_and_verifier.data,
+		       nr->stub_and_verifier.length);
+		er->stub_and_verifier.length += nr->stub_and_verifier.length;
+
+		existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
+
+		TALLOC_FREE(call);
+		call = existing;
+	}
+
+	/* this may not be the last pdu in the chain - if its isn't then
+	   just put it on the incoming_fragmented_call_list and wait for the rest */
+	if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
+	    !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+		/*
+		 * Up to 4 MByte are allowed by all fragments
+		 */
+		if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
+			return dcesrv_fault_disconnect0(call,
+					DCERPC_FAULT_ACCESS_DENIED);
+		}
+		dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
+		return NT_STATUS_OK;
+	}
+
+	/* This removes any fragments we may have had stashed away */
+	dcesrv_call_set_list(call, DCESRV_LIST_NONE);
+
+	switch (call->pkt.ptype) {
+	case DCERPC_PKT_BIND:
+		status = dcesrv_bind_nak(call,
+			DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
+		break;
+	case DCERPC_PKT_AUTH3:
+		status = dcesrv_auth3(call);
+		break;
+	case DCERPC_PKT_ALTER:
+		status = dcesrv_alter(call);
+		break;
+	case DCERPC_PKT_REQUEST:
+		status = dcesrv_request(call);
+		break;
+	case DCERPC_PKT_CO_CANCEL:
+	case DCERPC_PKT_ORPHANED:
+		/*
+		 * Window just ignores CO_CANCEL and ORPHANED,
+		 * so we do...
+		 */
+		status = NT_STATUS_OK;
+		TALLOC_FREE(call);
+		break;
+	case DCERPC_PKT_BIND_ACK:
+	case DCERPC_PKT_BIND_NAK:
+	case DCERPC_PKT_ALTER_RESP:
+	case DCERPC_PKT_RESPONSE:
+	case DCERPC_PKT_FAULT:
+	case DCERPC_PKT_SHUTDOWN:
+	default:
+		status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+		break;
+	}
+
+	/* if we are going to be sending a reply then add
+	   it to the list of pending calls. We add it to the end to keep the call
+	   list in the order we will answer */
+	if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(call);
+	}
+
+	return status;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
+				      struct loadparm_context *lp_ctx,
+				      struct dcesrv_context_callbacks *cb,
+				      struct dcesrv_context **_dce_ctx)
+{
+	struct dcesrv_context *dce_ctx;
+
+	dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
+	NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
+
+	if (uid_wrapper_enabled()) {
+		setenv("UID_WRAPPER_MYUID", "1", 1);
+	}
+	dce_ctx->initial_euid = geteuid();
+	if (uid_wrapper_enabled()) {
+		unsetenv("UID_WRAPPER_MYUID");
+	}
+
+	dce_ctx->endpoint_list	= NULL;
+	dce_ctx->lp_ctx = lp_ctx;
+	dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
+	NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
+	dce_ctx->broken_connections = NULL;
+	if (cb != NULL) {
+		dce_ctx->callbacks = *cb;
+	}
+
+	*_dce_ctx = dce_ctx;
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_reinit_context(struct dcesrv_context *dce_ctx)
+{
+	NTSTATUS status;
+
+	status = dcesrv_shutdown_registered_ep_servers(dce_ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	/* Clear endpoints */
+	while (dce_ctx->endpoint_list != NULL) {
+		struct dcesrv_endpoint *e = dce_ctx->endpoint_list;
+		DLIST_REMOVE(dce_ctx->endpoint_list, e);
+		TALLOC_FREE(e);
+	}
+
+	/* Remove broken connections */
+	dcesrv_cleanup_broken_connections(dce_ctx);
+
+	/* Reinit assoc group idr */
+	TALLOC_FREE(dce_ctx->assoc_groups_idr);
+	dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
+	if (dce_ctx->assoc_groups_idr == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
+					 const char **endpoint_servers)
+{
+	NTSTATUS status;
+	int i;
+
+	if (endpoint_servers == NULL) {
+		DBG_ERR("No endpoint servers configured\n");
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	for (i=0;endpoint_servers[i];i++) {
+		status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("failed to init endpoint server = '%s': %s\n",
+				endpoint_servers[i], nt_errstr(status));
+			return status;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+/* the list of currently registered DCERPC endpoint servers.
+ */
+static struct ep_server {
+	struct dcesrv_endpoint_server *ep_server;
+} *ep_servers = NULL;
+static int num_ep_servers = 0;
+
+_PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
+					struct dcesrv_context *dce_ctx)
+{
+	NTSTATUS status;
+	int i;
+
+	for (i = 0; i < num_ep_servers; i++) {
+		status = dcesrv_init_ep_server(dce_ctx,
+					       ep_servers[i].ep_server->name);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
+					const char *ep_server_name)
+{
+	struct dcesrv_endpoint_server *ep_server = NULL;
+	NTSTATUS status;
+
+	ep_server = discard_const_p(struct dcesrv_endpoint_server,
+				    dcesrv_ep_server_byname(ep_server_name));
+	if (ep_server == NULL) {
+		DBG_ERR("Failed to find endpoint server '%s'\n",
+			ep_server_name);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (ep_server->initialized) {
+		return NT_STATUS_OK;
+	}
+
+	status = ep_server->init_server(dce_ctx, ep_server);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("Failed to init endpoint server '%s': %s\n",
+			ep_server_name, nt_errstr(status));
+		return status;
+	}
+
+	ep_server->initialized = true;
+
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
+					struct dcesrv_context *dce_ctx)
+{
+	NTSTATUS status;
+	int i;
+
+	for (i = 0; i < num_ep_servers; i++) {
+		status = dcesrv_shutdown_ep_server(dce_ctx,
+					ep_servers[i].ep_server->name);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
+					    const char *ep_server_name)
+{
+	struct dcesrv_endpoint_server *ep_server = NULL;
+	NTSTATUS status;
+
+	ep_server = discard_const_p(struct dcesrv_endpoint_server,
+				    dcesrv_ep_server_byname(ep_server_name));
+	if (ep_server == NULL) {
+		DBG_ERR("Failed to find endpoint server '%s'\n",
+			ep_server_name);
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (!ep_server->initialized) {
+		return NT_STATUS_OK;
+	}
+
+	DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
+		 ep_server_name);
+
+	status = ep_server->shutdown_server(dce_ctx, ep_server);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
+			ep_server_name, nt_errstr(status));
+		return status;
+	}
+
+	ep_server->initialized = false;
+
+	return NT_STATUS_OK;
+}
+
+/*
+  register a DCERPC endpoint server.
+
+  The 'name' can be later used by other backends to find the operations
+  structure for this backend.
+
+*/
+_PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
+{
+
+	if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
+		/* its already registered! */
+		DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
+			 ep_server->name));
+		return NT_STATUS_OBJECT_NAME_COLLISION;
+	}
+
+	ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
+	if (!ep_servers) {
+		smb_panic("out of memory in dcerpc_register");
+	}
+
+	ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
+	ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
+
+	num_ep_servers++;
+
+	DEBUG(3,("DCERPC endpoint server '%s' registered\n",
+		 ep_server->name));
+
+	return NT_STATUS_OK;
+}
+
+/*
+  return the operations structure for a named backend of the specified type
+*/
+_PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
+{
+	int i;
+
+	for (i=0;i<num_ep_servers;i++) {
+		if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
+			return ep_servers[i].ep_server;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+  return the DCERPC module version, and the size of some critical types
+  This can be used by endpoint server modules to either detect compilation errors, or provide
+  multiple implementations for different smbd compilation options in one module
+*/
+const struct dcesrv_critical_sizes *dcerpc_module_version(void)
+{
+	static const struct dcesrv_critical_sizes critical_sizes = {
+		DCERPC_MODULE_VERSION,
+		sizeof(struct dcesrv_context),
+		sizeof(struct dcesrv_endpoint),
+		sizeof(struct dcesrv_endpoint_server),
+		sizeof(struct dcesrv_interface),
+		sizeof(struct dcesrv_if_list),
+		sizeof(struct dcesrv_connection),
+		sizeof(struct dcesrv_call_state),
+		sizeof(struct dcesrv_auth),
+		sizeof(struct dcesrv_handle)
+	};
+
+	return &critical_sizes;
+}
+
+_PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
+{
+	struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
+	struct dcesrv_auth *a = NULL;
+
+	dce_conn->wait_send = NULL;
+	dce_conn->wait_recv = NULL;
+	dce_conn->wait_private = NULL;
+
+	dce_conn->allow_bind = false;
+	dce_conn->allow_alter = false;
+
+	dce_conn->default_auth_state->auth_invalid = true;
+
+	for (a = dce_conn->auth_states; a != NULL; a = a->next) {
+		a->auth_invalid = true;
+	}
+
+	if (dce_conn->pending_call_list == NULL) {
+		char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
+
+		DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
+		dce_conn->transport.terminate_connection(dce_conn,
+					full_reason ? full_reason : reason);
+		return;
+	}
+
+	if (dce_conn->terminate != NULL) {
+		return;
+	}
+
+	DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
+		 reason));
+	dce_conn->terminate = talloc_strdup(dce_conn, reason);
+	if (dce_conn->terminate == NULL) {
+		dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
+	}
+	DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
+}
+
+_PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
+{
+	struct dcesrv_connection *cur, *next;
+
+	next = dce_ctx->broken_connections;
+	while (next != NULL) {
+		cur = next;
+		next = cur->next;
+
+		if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
+			struct dcesrv_connection_context *context_cur, *context_next;
+
+			context_next = cur->contexts;
+			while (context_next != NULL) {
+				context_cur = context_next;
+				context_next = context_cur->next;
+
+				dcesrv_connection_context_destructor(context_cur);
+			}
+		}
+
+		dcesrv_terminate_connection(cur, cur->terminate);
+	}
+}
+
+/* We need this include to be able to compile on some plateforms
+ * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
+ * correctly.
+ * It has to be that deep because otherwise we have a conflict on
+ * const struct dcesrv_interface declaration.
+ * This is mostly due to socket_wrapper defining #define bind swrap_bind
+ * which conflict with the bind used before.
+ */
+#include "system/network.h"
+
+struct dcesrv_sock_reply_state {
+	struct dcesrv_connection *dce_conn;
+	struct dcesrv_call_state *call;
+	struct iovec iov;
+};
+
+static void dcesrv_sock_reply_done(struct tevent_req *subreq);
+static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
+
+_PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
+{
+	struct dcesrv_call_state *call;
+
+	call = dce_conn->call_list;
+	if (!call || !call->replies) {
+		return;
+	}
+
+	while (call->replies) {
+		struct data_blob_list_item *rep = call->replies;
+		struct dcesrv_sock_reply_state *substate;
+		struct tevent_req *subreq;
+
+		substate = talloc_zero(call, struct dcesrv_sock_reply_state);
+		if (!substate) {
+			dcesrv_terminate_connection(dce_conn, "no memory");
+			return;
+		}
+
+		substate->dce_conn = dce_conn;
+		substate->call = NULL;
+
+		DLIST_REMOVE(call->replies, rep);
+
+		if (call->replies == NULL && call->terminate_reason == NULL) {
+			substate->call = call;
+		}
+
+		substate->iov.iov_base = (void *) rep->blob.data;
+		substate->iov.iov_len = rep->blob.length;
+
+		subreq = tstream_writev_queue_send(substate,
+						   dce_conn->event_ctx,
+						   dce_conn->stream,
+						   dce_conn->send_queue,
+						   &substate->iov, 1);
+		if (!subreq) {
+			dcesrv_terminate_connection(dce_conn, "no memory");
+			return;
+		}
+		tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
+					substate);
+	}
+
+	if (call->terminate_reason != NULL) {
+		struct tevent_req *subreq;
+
+		subreq = tevent_queue_wait_send(call,
+						dce_conn->event_ctx,
+						dce_conn->send_queue);
+		if (!subreq) {
+			dcesrv_terminate_connection(dce_conn, __location__);
+			return;
+		}
+		tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
+					call);
+	}
+
+	DLIST_REMOVE(call->conn->call_list, call);
+	call->list = DCESRV_LIST_NONE;
+}
+
+static void dcesrv_sock_reply_done(struct tevent_req *subreq)
+{
+	struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
+						struct dcesrv_sock_reply_state);
+	int ret;
+	int sys_errno;
+	NTSTATUS status;
+	struct dcesrv_call_state *call = substate->call;
+
+	ret = tstream_writev_queue_recv(subreq, &sys_errno);
+	TALLOC_FREE(subreq);
+	if (ret == -1) {
+		status = map_nt_error_from_unix_common(sys_errno);
+		dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
+		return;
+	}
+
+	talloc_free(substate);
+	if (call) {
+		talloc_free(call);
+	}
+}
+
+static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
+
+static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
+						struct dcesrv_call_state);
+	bool ok;
+	struct timeval tv;
+
+	/* make sure we stop send queue before removing subreq */
+	tevent_queue_stop(call->conn->send_queue);
+
+	ok = tevent_queue_wait_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ok) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+
+	/* disconnect after 200 usecs */
+	tv = timeval_current_ofs_usec(200);
+	subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
+	if (subreq == NULL) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+	tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
+				call);
+}
+
+static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
+						struct dcesrv_call_state);
+	bool ok;
+
+	ok = tevent_wakeup_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ok) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+
+	dcesrv_terminate_connection(call->conn, call->terminate_reason);
+}
+
+static void dcesrv_conn_wait_done(struct tevent_req *subreq);
+
+static void dcesrv_read_fragment_done(struct tevent_req *subreq)
+{
+	struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
+					     struct dcesrv_connection);
+	struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
+	struct ncacn_packet *pkt;
+	DATA_BLOB buffer;
+	NTSTATUS status;
+
+	if (dce_conn->terminate) {
+		/*
+		 * if the current connection is broken
+		 * we need to clean it up before any other connection
+		 */
+		dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
+		dcesrv_cleanup_broken_connections(dce_ctx);
+		return;
+	}
+
+	dcesrv_cleanup_broken_connections(dce_ctx);
+
+	status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
+					       &pkt, &buffer);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+		return;
+	}
+
+	status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
+	if (!NT_STATUS_IS_OK(status)) {
+		dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+		return;
+	}
+
+	/*
+	 * This is used to block the connection during
+	 * pending authentication.
+	 */
+	if (dce_conn->wait_send != NULL) {
+		subreq = dce_conn->wait_send(dce_conn,
+					     dce_conn->event_ctx,
+					     dce_conn->wait_private);
+		if (!subreq) {
+			status = NT_STATUS_NO_MEMORY;
+			dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+			return;
+		}
+		tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
+		return;
+	}
+
+	subreq = dcerpc_read_ncacn_packet_send(dce_conn,
+					       dce_conn->event_ctx,
+					       dce_conn->stream);
+	if (!subreq) {
+		status = NT_STATUS_NO_MEMORY;
+		dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+		return;
+	}
+	tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
+}
+
+static void dcesrv_conn_wait_done(struct tevent_req *subreq)
+{
+	struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
+					     struct dcesrv_connection);
+	struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
+	NTSTATUS status;
+
+	if (dce_conn->terminate) {
+		/*
+		 * if the current connection is broken
+		 * we need to clean it up before any other connection
+		 */
+		dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
+		dcesrv_cleanup_broken_connections(dce_ctx);
+		return;
+	}
+
+	dcesrv_cleanup_broken_connections(dce_ctx);
+
+	status = dce_conn->wait_recv(subreq);
+	dce_conn->wait_send = NULL;
+	dce_conn->wait_recv = NULL;
+	dce_conn->wait_private = NULL;
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+		return;
+	}
+
+	status = dcesrv_connection_loop_start(dce_conn);
+	if (!NT_STATUS_IS_OK(status)) {
+		dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+		return;
+	}
+}
+
+/**
+ * retrieve credentials from a dce_call
+ */
+_PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
+{
+	struct dcesrv_auth *auth = dce_call->auth_state;
+	SMB_ASSERT(auth->auth_finished);
+	return auth->session_info->credentials;
+}
+
+/**
+ * returns true if this is an authenticated call
+ */
+_PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
+{
+	struct dcesrv_auth *auth = dce_call->auth_state;
+	enum security_user_level level;
+	SMB_ASSERT(auth->auth_finished);
+	level = security_session_user_level(auth->session_info, NULL);
+	return level >= SECURITY_USER;
+}
+
+/**
+ * retrieve account_name for a dce_call
+ */
+_PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
+{
+	struct dcesrv_auth *auth = dce_call->auth_state;
+	SMB_ASSERT(auth->auth_finished);
+	return auth->session_info->info->account_name;
+}
+
+/**
+ * retrieve session_info from a dce_call
+ */
+_PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
+{
+	struct dcesrv_auth *auth = dce_call->auth_state;
+	SMB_ASSERT(auth->auth_finished);
+	return auth->session_info;
+}
+
+/**
+ * retrieve auth type/level from a dce_call
+ */
+_PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
+				    enum dcerpc_AuthType *auth_type,
+				    enum dcerpc_AuthLevel *auth_level)
+{
+	struct dcesrv_auth *auth = dce_call->auth_state;
+
+	SMB_ASSERT(auth->auth_finished);
+
+	if (auth_type != NULL) {
+		*auth_type = auth->auth_type;
+	}
+	if (auth_level != NULL) {
+		*auth_level = auth->auth_level;
+	}
+}
+
+_PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
+{
+	struct tevent_req *subreq;
+
+	subreq = dcerpc_read_ncacn_packet_send(conn,
+					       conn->event_ctx,
+					       conn->stream);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
+
+	return NT_STATUS_OK;
+}
diff --git a/librpc/rpc/dcesrv_reply.c b/librpc/rpc/dcesrv_reply.c
new file mode 100644
index 0000000..057217b
--- /dev/null
+++ b/librpc/rpc/dcesrv_reply.c
@@ -0,0 +1 @@
+#include "librpc/rpc/dcerpc_util.h"
diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h
index f1535d7..d517378 100644
--- a/librpc/rpc/rpc_common.h
+++ b/librpc/rpc/rpc_common.h
@@ -163,79 +163,6 @@ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t);
 enum dcerpc_transport_t dcerpc_transport_by_name(const char *name);
 enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower);
 
-/* The following definitions come from ../librpc/rpc/dcerpc_util.c  */
-
-void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v);
-uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob);
-void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v);
-uint16_t dcerpc_get_auth_length(const DATA_BLOB *blob);
-uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob);
-uint8_t dcerpc_get_auth_type(const DATA_BLOB *blob);
-uint8_t dcerpc_get_auth_level(const DATA_BLOB *blob);
-uint32_t dcerpc_get_auth_context_id(const DATA_BLOB *blob);
-const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx,
-					      enum dcerpc_transport_t transport,
-					      const struct ndr_interface_table *table);
-
-NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
-				  const DATA_BLOB *blob,
-				  struct ncacn_packet *r);
-
-/**
-* @brief	Pull a dcerpc_auth structure, taking account of any auth
-*		padding in the blob. For request/response packets we pass
-*		the whole data blob, so auth_data_only must be set to false
-*		as the blob contains data+pad+auth and no just pad+auth.
-*
-* @param pkt		- The ncacn_packet strcuture
-* @param mem_ctx	- The mem_ctx used to allocate dcerpc_auth elements
-* @param pkt_trailer	- The packet trailer data, usually the trailing
-*			  auth_info blob, but in the request/response case
-*			  this is the stub_and_verifier blob.
-* @param auth		- A preallocated dcerpc_auth *empty* structure
-* @param auth_length	- The length of the auth trail, sum of auth header
-*			  lenght and pkt->auth_length
-* @param auth_data_only	- Whether the pkt_trailer includes only the auth_blob
-*			  (+ padding) or also other data.
-*
-* @return		- A NTSTATUS error code.
-*/
-NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
-				  TALLOC_CTX *mem_ctx,
-				  const DATA_BLOB *pkt_trailer,
-				  struct dcerpc_auth *auth,
-				  uint32_t *auth_length,
-				  bool auth_data_only);
-NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
-					   enum dcerpc_pkt_type ptype,
-					   size_t max_auth_info,
-					   uint8_t required_flags,
-					   uint8_t optional_flags);
-NTSTATUS dcerpc_ncacn_pull_pkt_auth(const struct dcerpc_auth *auth_state,
-				    struct gensec_security *gensec,
-				    TALLOC_CTX *mem_ctx,
-				    enum dcerpc_pkt_type ptype,
-				    uint8_t required_flags,
-				    uint8_t optional_flags,
-				    uint8_t payload_offset,
-				    DATA_BLOB *payload_and_verifier,
-				    DATA_BLOB *raw_packet,
-				    const struct ncacn_packet *pkt);
-NTSTATUS dcerpc_ncacn_push_pkt_auth(const struct dcerpc_auth *auth_state,
-				    struct gensec_security *gensec,
-				    TALLOC_CTX *mem_ctx,
-				    DATA_BLOB *raw_packet,
-				    size_t sig_size,
-				    uint8_t payload_offset,
-				    const DATA_BLOB *payload,
-				    const struct ncacn_packet *pkt);
-struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
-						 struct tevent_context *ev,
-						 struct tstream_context *stream);
-NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
-				       TALLOC_CTX *mem_ctx,
-				       struct ncacn_packet **pkt,
-				       DATA_BLOB *buffer);
 
 /* The following definitions come from ../librpc/rpc/binding_handle.c  */
 
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 4917928..96f9ae8 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -632,11 +632,16 @@ bld.SAMBA_LIBRARY('ndr',
 
 bld.SAMBA_LIBRARY('dcerpc-binding',
     source='rpc/dcerpc_error.c rpc/binding.c rpc/dcerpc_util.c rpc/binding_handle.c',
-    deps='ndr tevent NDR_DCERPC LIBTSOCKET tevent-util gensec',
+    deps='ndr tevent NDR_DCERPC LIBTSOCKET tevent-util',
     pc_files=[],
     public_headers='rpc/rpc_common.h',
     vnum='0.0.1')
 
+bld.SAMBA_LIBRARY('dcerpc-pkt-auth',
+        private_library=True,
+        source='rpc/dcerpc_pkt_auth.c',
+        deps='dcerpc-binding gensec')
+
 bld.SAMBA_SUBSYSTEM('NDR_WINBIND',
 	source='gen_ndr/ndr_winbind.c',
 	public_deps='ndr NDR_LSA'
diff --git a/python/samba/tests/dcerpc/raw_protocol.py b/python/samba/tests/dcerpc/raw_protocol.py
index e2c4560..a88747a 100755
--- a/python/samba/tests/dcerpc/raw_protocol.py
+++ b/python/samba/tests/dcerpc/raw_protocol.py
@@ -66,7 +66,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=rep_pfc_flags, auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -87,7 +87,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -109,7 +109,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -129,7 +129,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=rep_pfc_flags, auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertEquals(rep.u.secondary_address, "")
         self.assertPadding(rep.u._pad1, 2)
@@ -150,7 +150,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -397,7 +397,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -470,7 +470,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -490,7 +490,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -522,7 +522,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -542,7 +542,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -563,7 +563,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, ctx1.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -590,7 +590,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -610,7 +610,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -631,7 +631,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -647,7 +647,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -706,7 +706,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -733,7 +733,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -766,7 +766,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -795,7 +795,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -827,7 +827,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -856,7 +856,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -877,7 +877,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, ctx1a.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -903,7 +903,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -929,7 +929,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -948,7 +948,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -967,7 +967,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -986,7 +986,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1005,7 +1005,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 1)
@@ -1024,7 +1024,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1050,7 +1050,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 2)
@@ -1074,7 +1074,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1086,7 +1086,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 2)
@@ -1110,7 +1110,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1123,7 +1123,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1135,7 +1135,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 2)
@@ -1159,7 +1159,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1172,7 +1172,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1198,7 +1198,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 2)
@@ -1222,7 +1222,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1234,7 +1234,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 0)
         self.assertPadding(rep.u._pad1, 2)
         self.assertEquals(rep.u.num_results, 2)
@@ -1258,7 +1258,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1283,7 +1283,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1319,7 +1319,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1353,7 +1353,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1425,7 +1425,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1460,7 +1460,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1495,7 +1495,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1618,7 +1618,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1639,7 +1639,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1659,7 +1659,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We get a fault back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -1681,6 +1681,1279 @@ class TestDCERPC_BIND(RawDCERPCTest):
     def test_auth_none_call_request(self):
         return self._test_auth_none_level_request(dcerpc.DCERPC_AUTH_LEVEL_CALL)
 
+    def test_ntlmssp_multi_auth_first1_lastSame2(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_SEC_PKG_ERROR
+        auth_context_2nd = 2
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastNext2(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 2
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastSame111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = None
+        auth_context_2nd = 1
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastNext111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_lastNext111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastSameNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_lastSameNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastNextNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_lastNextNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastSameNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_lastSameNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_lastNextNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_lastNextNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_last(auth_type,
+                                                  expected_fault,
+                                                  auth_context_2nd=auth_context_2nd,
+                                                  expected_call_id=expected_call_id,
+                                                  expected_context_id=expected_context_id,
+                                                  not_executed=not_executed,
+                                                  conc_mpx=conc_mpx,
+                                                  forced_call_id=forced_call_id,
+                                                  forced_context_id=forced_context_id,
+                                                  forced_opnum=forced_opnum,
+                                                  forced_auth_context_id=forced_auth_context_id,
+                                                  forced_auth_type=forced_auth_type,
+                                                  forced_auth_level=forced_auth_level)
+
+    def _test_generic_auth_first_2nd(self,
+                                     auth_type,
+                                     pfc_flags_2nd,
+                                     expected_fault,
+                                     auth_context_2nd=2,
+                                     skip_first=False,
+                                     expected_call_id=None,
+                                     expected_context_id=None,
+                                     conc_mpx=False,
+                                     not_executed=False,
+                                     forced_call_id=None,
+                                     forced_context_id=None,
+                                     forced_opnum=None,
+                                     forced_auth_context_id=None,
+                                     forced_auth_type=None,
+                                     forced_auth_level=None):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        auth_level1 = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id1=1
+        auth_level2 = dcerpc.DCERPC_AUTH_LEVEL_PACKET
+        auth_context_id2=2
+
+        creds = self.get_user_creds()
+
+        abstract = samba.dcerpc.mgmt.abstract_syntax()
+        transfer = base.transfer_syntax_ndr()
+
+        tsf1_list = [transfer]
+        ctx = samba.dcerpc.dcerpc.ctx_list()
+        ctx.context_id = 1
+        ctx.num_transfer_syntaxes = len(tsf1_list)
+        ctx.abstract_syntax = abstract
+        ctx.transfer_syntaxes = tsf1_list
+
+        auth_context1 = self.get_auth_context_creds(creds=creds,
+                                                    auth_type=auth_type,
+                                                    auth_level=auth_level1,
+                                                    auth_context_id=auth_context_id1,
+                                                    hdr_signing=False)
+        auth_context2 = self.get_auth_context_creds(creds=creds,
+                                                    auth_type=auth_type,
+                                                    auth_level=auth_level2,
+                                                    auth_context_id=auth_context_id2,
+                                                    hdr_signing=False)
+
+        bind_pfc_flags = dcerpc.DCERPC_PFC_FLAG_FIRST | dcerpc.DCERPC_PFC_FLAG_LAST
+        if conc_mpx:
+            bind_pfc_flags |= dcerpc.DCERPC_PFC_FLAG_CONC_MPX
+
+        ack0 = self.do_generic_bind(call_id=0,
+                                    ctx=ctx,
+                                    pfc_flags=bind_pfc_flags)
+
+        ack1 = self.do_generic_bind(call_id=1,
+                                    ctx=ctx,
+                                    auth_context=auth_context1,
+                                    assoc_group_id = ack0.u.assoc_group_id,
+                                    start_with_alter=True)
+        if auth_context_2nd == 2:
+            ack2 = self.do_generic_bind(call_id=2,
+                                        ctx=ctx,
+                                        auth_context=auth_context2,
+                                        assoc_group_id = ack0.u.assoc_group_id,
+                                        start_with_alter=True)
+
+        ndr_print = self.do_ndr_print
+        hexdump = self.do_hexdump
+        inq_if_ids = samba.dcerpc.mgmt.inq_if_ids()
+        io = inq_if_ids
+        if ndr_print:
+            sys.stderr.write("in: %s" % samba.ndr.ndr_print_in(io))
+        stub_in = samba.ndr.ndr_pack_in(io)
+        stub_in += b'\xfe'*45 # add some padding in order to have some payload
+        if hexdump:
+            sys.stderr.write("stub_in: %d\n%s" % (len(stub_in), self.hexdump(stub_in)))
+
+        call_id = 3
+        context_id = ctx.context_id
+        opnum = io.opnum()
+
+        if not skip_first:
+            pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
+            stub_in_tmp = stub_in[0:16]
+            req = self.generate_request_auth(call_id=call_id,
+                                             context_id=context_id,
+                                             pfc_flags=pfc_flags,
+                                             opnum=opnum,
+                                             alloc_hint=len(stub_in),
+                                             stub=stub_in_tmp,
+                                             auth_context=auth_context1)
+            self.send_pdu(req, ndr_print=ndr_print, hexdump=hexdump)
+            rep = self.recv_pdu(timeout=0.01)
+            self.assertIsNone(rep)
+            self.assertIsConnected()
+
+        # context_id, opnum and auth header values are completely ignored
+        if auth_context_2nd == 1:
+            auth_context_copy = auth_context1.copy()
+        elif auth_context_2nd == 2:
+            auth_context_copy = auth_context2.copy()
+        else:
+            auth_context_copy = None
+
+        expected_pfc_flags = dcerpc.DCERPC_PFC_FLAG_FIRST | dcerpc.DCERPC_PFC_FLAG_LAST
+        if expected_context_id is None:
+            expected_context_id = context_id
+        if expected_call_id is None:
+            expected_call_id = call_id
+        if not_executed:
+            expected_pfc_flags |= dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE
+
+        if forced_call_id is not None:
+            call_id = forced_call_id
+        if forced_context_id is not None:
+            context_id = forced_context_id
+        if forced_opnum is not None:
+            opnum = forced_opnum
+        if forced_auth_context_id is not None:
+            auth_context_copy["auth_context_id"] = forced_auth_context_id
+        if forced_auth_type is not None:
+            auth_context_copy["auth_type"] = forced_auth_type
+        if forced_auth_level is not None:
+            auth_context_copy["auth_level"] = forced_auth_level
+
+        pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
+        stub_in_tmp = stub_in[16:-1]
+        req = self.generate_request_auth(call_id=call_id,
+                                         context_id=context_id,
+                                         pfc_flags=pfc_flags_2nd,
+                                         opnum=opnum,
+                                         alloc_hint=len(stub_in_tmp),
+                                         stub=stub_in_tmp,
+                                         auth_context=auth_context_copy)
+        self.send_pdu(req, ndr_print=ndr_print, hexdump=hexdump)
+        if expected_fault is None:
+            self.do_single_request(call_id=3, ctx=ctx, io=io, send_req=False, auth_context=auth_context1)
+            return
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, expected_call_id,
+                        pfc_flags=expected_pfc_flags,
+                        auth_length=0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
+        self.assertEqual(rep.u.context_id, expected_context_id)
+        self.assertEqual(rep.u.cancel_count, 0)
+        self.assertEqual(rep.u.flags, 0)
+        self.assertEqual(rep.u.status, expected_fault)
+        self.assertEqual(rep.u.reserved, 0)
+        self.assertEqual(len(rep.u.error_and_verifier), 0)
+
+        if not_executed:
+            # still alive
+            rep = self.recv_pdu(timeout=0.01)
+            self.assertIsNone(rep)
+            self.assertIsConnected()
+            return
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def _test_generic_auth_first_last(self,
+                                      auth_type,
+                                      expected_fault,
+                                      auth_context_2nd=2,
+                                      expected_call_id=None,
+                                      expected_context_id=None,
+                                      conc_mpx=False,
+                                      not_executed=False,
+                                      forced_call_id=None,
+                                      forced_context_id=None,
+                                      forced_opnum=None,
+                                      forced_auth_context_id=None,
+                                      forced_auth_type=None,
+                                      forced_auth_level=None):
+        pfc_flags_2nd = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST
+        return self._test_generic_auth_first_2nd(auth_type,
+                                                 pfc_flags_2nd,
+                                                 expected_fault,
+                                                 auth_context_2nd=auth_context_2nd,
+                                                 expected_call_id=expected_call_id,
+                                                 expected_context_id=expected_context_id,
+                                                 not_executed=not_executed,
+                                                 conc_mpx=conc_mpx,
+                                                 forced_call_id=forced_call_id,
+                                                 forced_context_id=forced_context_id,
+                                                 forced_opnum=forced_opnum,
+                                                 forced_auth_context_id=forced_auth_context_id,
+                                                 forced_auth_type=forced_auth_type,
+                                                 forced_auth_level=forced_auth_level)
+
+    def _test_generic_auth_first_first(self,
+                                       auth_type,
+                                       expected_fault,
+                                       auth_context_2nd=2,
+                                       expected_call_id=None,
+                                       expected_context_id=None,
+                                       conc_mpx=False,
+                                       not_executed=False,
+                                       forced_call_id=None,
+                                       forced_context_id=None,
+                                       forced_opnum=None,
+                                       forced_auth_context_id=None,
+                                       forced_auth_type=None,
+                                       forced_auth_level=None):
+        pfc_flags_2nd = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
+        return self._test_generic_auth_first_2nd(auth_type,
+                                                 pfc_flags_2nd,
+                                                 expected_fault,
+                                                 auth_context_2nd=auth_context_2nd,
+                                                 expected_call_id=expected_call_id,
+                                                 expected_context_id=expected_context_id,
+                                                 not_executed=not_executed,
+                                                 conc_mpx=conc_mpx,
+                                                 forced_call_id=forced_call_id,
+                                                 forced_context_id=forced_context_id,
+                                                 forced_opnum=forced_opnum,
+                                                 forced_auth_context_id=forced_auth_context_id,
+                                                 forced_auth_type=forced_auth_type,
+                                                 forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstSame2(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_SEC_PKG_ERROR
+        auth_context_2nd = 2
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstNext2(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 2
+        expected_call_id = 3
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstSame111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstSame111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstNext111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = 3
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstNext111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = 1
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstSameNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstSameNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = None
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstNextNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstNextNone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstSameNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstSameNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = None
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_first1_firstNextNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = None
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = False
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_multi_auth_MPX_first1_firstNextNone111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        auth_context_2nd = None
+        expected_call_id = 4
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = True
+        forced_call_id = 4
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_first_first(auth_type,
+                                                   expected_fault,
+                                                   auth_context_2nd=auth_context_2nd,
+                                                   expected_call_id=expected_call_id,
+                                                   expected_context_id=expected_context_id,
+                                                   not_executed=not_executed,
+                                                   conc_mpx=conc_mpx,
+                                                   forced_call_id=forced_call_id,
+                                                   forced_context_id=forced_context_id,
+                                                   forced_opnum=forced_opnum,
+                                                   forced_auth_context_id=forced_auth_context_id,
+                                                   forced_auth_type=forced_auth_type,
+                                                   forced_auth_level=forced_auth_level)
+
+    def _test_generic_auth_middle(self,
+                                  auth_type,
+                                  expected_fault,
+                                  expected_context_id=None,
+                                  not_executed=False,
+                                  conc_mpx=False,
+                                  forced_context_id=None,
+                                  forced_opnum=None,
+                                  forced_auth_context_id=None,
+                                  forced_auth_type=None,
+                                  forced_auth_level=None):
+        auth_context_2nd = 1
+        skip_first = True
+        pfc_flags_2nd = 0
+        expected_call_id = None
+        forced_call_id = None
+        return self._test_generic_auth_first_2nd(auth_type,
+                                                 pfc_flags_2nd,
+                                                 expected_fault,
+                                                 auth_context_2nd=auth_context_2nd,
+                                                 skip_first=skip_first,
+                                                 expected_call_id=expected_call_id,
+                                                 expected_context_id=expected_context_id,
+                                                 not_executed=not_executed,
+                                                 conc_mpx=conc_mpx,
+                                                 forced_call_id=forced_call_id,
+                                                 forced_context_id=forced_context_id,
+                                                 forced_opnum=forced_opnum,
+                                                 forced_auth_context_id=forced_auth_context_id,
+                                                 forced_auth_type=forced_auth_type,
+                                                 forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_alone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_alone(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_all_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_all_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_UNKNOWN_IF
+        expected_context_id = 0
+        not_executed = True
+        conc_mpx = True
+        forced_context_id = 111
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_auth_all_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = None
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_auth_all_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_ACCESS_DENIED
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_context_id = None
+        forced_opnum = 111
+        forced_auth_context_id = 111
+        forced_auth_type = 111
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_auth_context_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = 111
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_auth_context_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_ACCESS_DENIED
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = 111
+        forced_auth_type = None
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_auth_type_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = 111
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_auth_type_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_ACCESS_DENIED
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = 111
+        forced_auth_level = None
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_middle_auth_level_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_NCA_S_PROTO_ERROR
+        expected_context_id = 0
+        not_executed = False
+        conc_mpx = False
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
+    def test_ntlmssp_auth_MPX_middle_auth_level_111(self):
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NTLMSSP
+        expected_fault = dcerpc.DCERPC_FAULT_ACCESS_DENIED
+        expected_context_id = None
+        not_executed = False
+        conc_mpx = True
+        forced_context_id = None
+        forced_opnum = None
+        forced_auth_context_id = None
+        forced_auth_type = None
+        forced_auth_level = 111
+        return self._test_generic_auth_middle(auth_type,
+                                              expected_fault,
+                                              expected_context_id=expected_context_id,
+                                              not_executed=not_executed,
+                                              conc_mpx=conc_mpx,
+                                              forced_context_id=forced_context_id,
+                                              forced_opnum=forced_opnum,
+                                              forced_auth_context_id=forced_auth_context_id,
+                                              forced_auth_type=forced_auth_type,
+                                              forced_auth_level=forced_auth_level)
+
     def _test_neg_xmit_check_values(self,
                                     req_xmit=None,
                                     req_recv=None,
@@ -1706,7 +2979,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, rep_both)
         self.assertEquals(rep.u.max_recv_frag, rep_both)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1758,7 +3031,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu(ndr_print=True, hexdump=True)
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1773,7 +3046,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1789,7 +3062,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We get a fault
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -1864,7 +3137,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         auth_length=0)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -1886,7 +3159,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1900,7 +3173,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1914,7 +3187,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -1992,7 +3265,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                 # We get a fault back
                 self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                                 auth_length=0)
-                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertNotEqual(rep.u.alloc_hint, 0)
                 self.assertEquals(rep.u.context_id, req.u.context_id)
                 self.assertEquals(rep.u.cancel_count, 0)
                 self.assertEquals(rep.u.flags, 0)
@@ -2012,7 +3285,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                 # We get a fault back
                 self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                                 auth_length=0)
-                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertNotEqual(rep.u.alloc_hint, 0)
                 self.assertEquals(rep.u.context_id, req.u.context_id)
                 self.assertEquals(rep.u.cancel_count, 0)
                 self.assertEquals(rep.u.flags, 0)
@@ -2034,7 +3307,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
             # We get a fault back
             self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                             auth_length=0)
-            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertNotEqual(rep.u.alloc_hint, 0)
             self.assertEquals(rep.u.context_id, req.u.context_id)
             self.assertEquals(rep.u.cancel_count, 0)
             self.assertEquals(rep.u.flags, 0)
@@ -2050,7 +3323,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2096,7 +3369,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
             # We get a fault back
             self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                             auth_length=0)
-            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertNotEqual(rep.u.alloc_hint, 0)
             self.assertEquals(rep.u.context_id, 0)
             self.assertEquals(rep.u.cancel_count, 0)
             self.assertEquals(rep.u.flags, 0)
@@ -2126,7 +3399,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
             # We get a fault back
             self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                             auth_length=0)
-            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertNotEqual(rep.u.alloc_hint, 0)
             self.assertEquals(rep.u.context_id, req.u.context_id)
             self.assertEquals(rep.u.cancel_count, 0)
             self.assertEquals(rep.u.flags, 0)
@@ -2193,7 +3466,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         dcerpc.DCERPC_PFC_FLAG_LAST |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2241,7 +3514,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2275,7 +3548,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2311,7 +3584,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
                         dcerpc.DCERPC_PFC_FLAG_LAST,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2339,7 +3612,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2374,7 +3647,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2388,7 +3661,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2413,7 +3686,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2448,7 +3721,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2462,7 +3735,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2501,7 +3774,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2515,7 +3788,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2550,7 +3823,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req1.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req1.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2598,7 +3871,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req2.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2648,7 +3921,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -2658,7 +3931,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -2689,7 +3962,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -2705,7 +3978,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2725,7 +3998,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We don't get an auth_info back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -2745,7 +4018,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We get a fault back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2795,7 +4068,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -2805,7 +4078,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -2836,7 +4109,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -2858,7 +4131,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We get a fault back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2908,7 +4181,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         assoc_group_id = rep.u.assoc_group_id
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
@@ -2919,7 +4192,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -2943,7 +4216,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -2991,7 +4264,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3001,7 +4274,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3029,7 +4302,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We get a fault back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3080,7 +4353,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3090,7 +4363,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3119,7 +4392,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3135,7 +4408,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -3155,7 +4428,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We don't get an auth_info back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -3187,7 +4460,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3238,7 +4511,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3248,7 +4521,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3277,7 +4550,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3293,7 +4566,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -3313,7 +4586,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We don't get an auth_info back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -3344,7 +4617,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3391,7 +4664,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3401,7 +4674,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3422,7 +4695,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3475,7 +4748,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3485,7 +4758,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3506,7 +4779,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3561,7 +4834,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3571,7 +4844,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3593,7 +4866,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3641,7 +4914,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3651,7 +4924,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3673,7 +4946,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3728,7 +5001,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3738,7 +5011,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3760,7 +5033,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3815,7 +5088,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3825,7 +5098,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3847,7 +5120,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -3912,7 +5185,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -3922,7 +5195,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3966,7 +5239,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -3982,7 +5255,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4002,7 +5275,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We don't get an auth_info back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4126,7 +5399,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -4136,7 +5409,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -4173,7 +5446,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -4238,7 +5511,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -4248,7 +5521,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -4277,7 +5550,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         rep = self.recv_pdu()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4297,7 +5570,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         # We don't get an auth_info back
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4357,7 +5630,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
         self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
         self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
-        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
         self.assertEquals(rep.u.secondary_address_size, 4)
         self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
         self.assertPadding(rep.u._pad1, 2)
@@ -4367,7 +5640,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.assertEquals(rep.u.ctx_list[0].reason,
                           dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
         self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
-        self.assertNotEquals(len(rep.u.auth_info), 0)
+        self.assertNotEqual(len(rep.u.auth_info), 0)
         a = self.parse_auth(rep.u.auth_info)
 
         from_server = a.credentials
@@ -4388,7 +5661,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, 0)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -4503,7 +5776,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
                         pfc_flags=req.pfc_flags | response_fault_flags,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, ctx1.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -4670,7 +5943,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         (rep, rep_blob) = self.recv_pdu_raw()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=sig_size)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4738,7 +6011,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
                         pfc_flags=req.pfc_flags |
                         dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                         auth_length=0)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, ctx1.context_id)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertEquals(rep.u.flags, 0)
@@ -4787,7 +6060,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         (rep, rep_blob) = self.recv_pdu_raw()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=sig_size)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -4852,7 +6125,7 @@ class TestDCERPC_BIND(RawDCERPCTest):
         (rep, rep_blob) = self.recv_pdu_raw()
         self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
                         auth_length=sig_size)
-        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
         self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
         self.assertEquals(rep.u.cancel_count, 0)
         self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
@@ -6221,3 +7494,5 @@ if __name__ == "__main__":
     global_hexdump = True
     import unittest
     unittest.main()
+    
+ 
diff --git a/python/samba/tests/dcerpc/raw_testcase.py b/python/samba/tests/dcerpc/raw_testcase.py
index 1a17436..75980f6 100644
--- a/python/samba/tests/dcerpc/raw_testcase.py
+++ b/python/samba/tests/dcerpc/raw_testcase.py
@@ -318,7 +318,7 @@ class RawDCERPCTest(TestCase):
                                 pfc_flags=req.pfc_flags |
                                 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                                 auth_length=0)
-                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertNotEqual(rep.u.alloc_hint, 0)
                 self.assertEquals(rep.u.context_id, 0)
                 self.assertEquals(rep.u.cancel_count, 0)
                 self.assertEquals(rep.u.flags, 0)
@@ -358,7 +358,7 @@ class RawDCERPCTest(TestCase):
             if assoc_group_id != 0:
                 self.assertEquals(rep.u.assoc_group_id, assoc_group_id)
             else:
-                self.assertNotEquals(rep.u.assoc_group_id, 0)
+                self.assertNotEqual(rep.u.assoc_group_id, 0)
                 assoc_group_id = rep.u.assoc_group_id
             sda_str = self.secondary_address
             sda_len = len(sda_str) + 1
@@ -382,7 +382,7 @@ class RawDCERPCTest(TestCase):
             self.assertEquals(rep.auth_length, 0)
             self.assertEquals(len(rep.u.auth_info), 0)
             return ack
-        self.assertNotEquals(rep.auth_length, 0)
+        self.assertNotEqual(rep.auth_length, 0)
         self.assertGreater(len(rep.u.auth_info), samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
         self.assertEquals(rep.auth_length, len(rep.u.auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
 
@@ -423,7 +423,7 @@ class RawDCERPCTest(TestCase):
                             pfc_flags=req.pfc_flags |
                             samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
                             auth_length=0)
-            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertNotEqual(rep.u.alloc_hint, 0)
             self.assertEquals(rep.u.context_id, 0)
             self.assertEquals(rep.u.cancel_count, 0)
             self.assertEquals(rep.u.flags, 0)
@@ -448,7 +448,7 @@ class RawDCERPCTest(TestCase):
         if finished:
             self.assertEquals(rep.auth_length, 0)
         else:
-            self.assertNotEquals(rep.auth_length, 0)
+            self.assertNotEqual(rep.auth_length, 0)
         self.assertGreaterEqual(len(rep.u.auth_info), samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
         self.assertEquals(rep.auth_length, len(rep.u.auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
 
@@ -523,28 +523,27 @@ class RawDCERPCTest(TestCase):
             if hexdump:
                 sys.stderr.write("stub_in: %d\n%s" % (len(stub_in), self.hexdump(stub_in)))
 
-        pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
-        pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST
-        if object is not None:
-            pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_OBJECT_UUID
-
-        req = self.generate_request_auth(call_id=call_id,
-                                         context_id=ctx.context_id,
-                                         pfc_flags=pfc_flags,
-                                         object=object,
-                                         opnum=io.opnum(),
-                                         stub=stub_in,
-                                         auth_context=auth_context)
-        if send_req:
+            pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST
+            pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST
+            if object is not None:
+                pfc_flags |= samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_OBJECT_UUID
+
+            req = self.generate_request_auth(call_id=call_id,
+                                             context_id=ctx.context_id,
+                                             pfc_flags=pfc_flags,
+                                             object=object,
+                                             opnum=io.opnum(),
+                                            stub=stub_in,
+                                            auth_context=auth_context)
             self.send_pdu(req, ndr_print=ndr_print, hexdump=hexdump)
         if recv_rep:
             (rep, rep_blob) = self.recv_pdu_raw(timeout=timeout,
                                                 ndr_print=ndr_print,
                                                 hexdump=hexdump)
             if fault_status:
-                self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_FAULT, call_id,
                                 pfc_flags=fault_pfc_flags, auth_length=0)
-                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertNotEqual(rep.u.alloc_hint, 0)
                 self.assertEquals(rep.u.context_id, fault_context_id)
                 self.assertEquals(rep.u.cancel_count, 0)
                 self.assertEquals(rep.u.flags, 0)
@@ -556,12 +555,15 @@ class RawDCERPCTest(TestCase):
             expected_auth_length = 0
             if auth_context is not None and \
                auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
-                expected_auth_length = req.auth_length
+                    if send_req:
+                        expected_auth_length = req.auth_length
+                    else:
+                        expected_auth_length = rep.auth_length
 
-            self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+            self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_RESPONSE, call_id,
                             auth_length=expected_auth_length)
-            self.assertNotEquals(rep.u.alloc_hint, 0)
-            self.assertEquals(rep.u.context_id, req.u.context_id & 0xff)
+            self.assertNotEqual(rep.u.alloc_hint, 0)
+            self.assertEqual(rep.u.context_id, ctx.context_id & 0xff)
             self.assertEquals(rep.u.cancel_count, 0)
             self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
             stub_out = self.check_response_auth(rep, rep_blob, auth_context)
@@ -919,12 +921,12 @@ class RawDCERPCTest(TestCase):
         req_data = req_blob[ofs_stub:ofs_trailer]
         req_whole = req_blob[0:ofs_sig]
 
-        if auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PRIVACY:
+        if auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PRIVACY:
             # TODO: not yet supported here
             self.assertTrue(False)
-        elif auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
+        elif auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET:
             req_sig = auth_context["gensec"].sign_packet(req_data, req_whole)
-        elif auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_CONNECT:
+        elif auth_context["g_auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_CONNECT:
             self.assertEquals(auth_context["auth_type"],
                               dcerpc.DCERPC_AUTH_TYPE_NTLMSSP)
             req_sig = b"\x01" +b"\x00" *15
diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c
index 1f67987..c609efd 100644
--- a/source3/librpc/rpc/dcerpc_helpers.c
+++ b/source3/librpc/rpc/dcerpc_helpers.c
@@ -20,6 +20,7 @@
 
 #include "includes.h"
 #include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "librpc/crypto/gse.h"
 #include "auth/gensec/gensec.h"
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 81b6bfb..7bc3e57 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -30,6 +30,7 @@
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "librpc/gen_ndr/ndr_netlogon_c.h"
 #include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "rpc_dce.h"
 #include "cli_pipe.h"
 #include "libsmb/libsmb.h"
diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c
index 9dc5c56..b240236 100644
--- a/source3/rpc_client/rpc_transport_np.c
+++ b/source3/rpc_client/rpc_transport_np.c
@@ -19,6 +19,7 @@
 
 #include "includes.h"
 #include "../lib/util/tevent_ntstatus.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "rpc_client/rpc_transport.h"
 #include "librpc/ndr/ndr_table.h"
 #include "libcli/smb/smbXcli_base.h"
diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c
index c45e9cb..850bca6 100644
--- a/source3/rpc_server/rpc_ncacn_np.c
+++ b/source3/rpc_server/rpc_ncacn_np.c
@@ -39,6 +39,7 @@
 #include "rpc_server/rpc_config.h"
 #include "librpc/ndr/ndr_table.h"
 #include "rpc_server/rpc_server.h"
+#include "librpc/rpc/dcerpc_util.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c
index f0870c8..e0a81b1 100644
--- a/source3/rpc_server/rpc_server.c
+++ b/source3/rpc_server/rpc_server.c
@@ -33,6 +33,7 @@
 #include "rpc_server/rpc_ncacn_np.h"
 #include "rpc_server/srv_pipe_hnd.h"
 #include "rpc_server/srv_pipe.h"
+#include "librpc/rpc/dcerpc_util.h"
 
 /* Creates a pipes_struct and initializes it with the information
  * sent from the client */
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index fec8d27..4ef8ba9 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -44,6 +44,7 @@
 #include "librpc/ndr/ndr_table.h"
 #include "auth/gensec/gensec.h"
 #include "librpc/ndr/ndr_dcerpc.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "lib/tsocket/tsocket.h"
 #include "../librpc/gen_ndr/ndr_samr.h"
 #include "../librpc/gen_ndr/ndr_lsa.h"
diff --git a/source3/wscript_build b/source3/wscript_build
index aa3c717..9a2681a 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -1038,7 +1038,8 @@ bld.SAMBA3_LIBRARY('cli_spoolss',
                    deps='''
                         RPC_NDR_SPOOLSS
                         smbconf
-                        secrets3''',
+                        secrets3
+                        gensec''',
                    private_library=True)
 
 bld.SAMBA3_SUBSYSTEM('LIBCLI_WINREG',
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index a0b00af..ef5ac00 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -26,6 +26,8 @@
 #include "lib/events/events.h"
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_proto.h"
+#include "librpc/rpc/dcerpc_util.h"
+#include "librpc/rpc/dcerpc_pkt_auth.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "auth/gensec/gensec.h"
@@ -724,6 +726,7 @@ static NTSTATUS ncacn_pull_pkt_auth(struct dcecli_connection *c,
 
 	status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
 					    c->security_state.generic_state,
+					    true, /* check_pkt_auth_fields */
 					    mem_ctx,
 					    ptype,
 					    required_flags,
diff --git a/source4/librpc/rpc/dcerpc_roh_channel_out.c b/source4/librpc/rpc/dcerpc_roh_channel_out.c
index d965037..a62814f 100644
--- a/source4/librpc/rpc/dcerpc_roh_channel_out.c
+++ b/source4/librpc/rpc/dcerpc_roh_channel_out.c
@@ -37,6 +37,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_roh.h"
 #include "librpc/rpc/dcerpc_proto.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "lib/http/http.h"
 
 struct roh_connect_channel_state {
diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build
index fc3890d..b0cdf41 100644
--- a/source4/librpc/wscript_build
+++ b/source4/librpc/wscript_build
@@ -151,7 +151,7 @@ bld.SAMBA_LIBRARY('dcerpc',
 	rpc/dcerpc_roh_channel_in.c rpc/dcerpc_roh_channel_out.c rpc/dcerpc_roh.c
 	rpc/dcerpc_connect.c rpc/dcerpc_secondary.c''',
 	pc_files='dcerpc.pc',
-	deps='samba_socket LIBCLI_RESOLVE LIBCLI_SMB LIBCLI_SMB2 ndr NDR_DCERPC RPC_NDR_EPMAPPER NDR_SCHANNEL RPC_NDR_NETLOGON RPC_NDR_MGMT gensec LIBCLI_AUTH smbclient-raw LP_RESOLVE tevent-util dcerpc-binding param_options http',
+	deps='samba_socket LIBCLI_RESOLVE LIBCLI_SMB LIBCLI_SMB2 ndr NDR_DCERPC RPC_NDR_EPMAPPER NDR_SCHANNEL RPC_NDR_NETLOGON RPC_NDR_MGMT gensec LIBCLI_AUTH smbclient-raw LP_RESOLVE tevent-util dcerpc-binding dcerpc-pkt-auth param_options http',
 	autoproto='rpc/dcerpc_proto.h',
 	public_deps='samba-credentials tevent talloc',
 	public_headers='''rpc/dcerpc.h''',
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 3decc34..492c2c3 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -39,6 +39,7 @@
 #include "smbd/process_model.h"
 #include "lib/messaging/irpc.h"
 #include "librpc/rpc/rpc_common.h"
+#include "librpc/rpc/dcerpc_util.h"
 #include "lib/util/samba_modules.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "../lib/util/tevent_ntstatus.h"
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index c71e486..d1d7101 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -31,6 +31,8 @@
 #include "auth/auth.h"
 #include "param/param.h"
 #include "librpc/rpc/rpc_common.h"
+#include "librpc/rpc/dcerpc_util.h"
+#include "librpc/rpc/dcerpc_pkt_auth.h"
 
 static NTSTATUS dcesrv_auth_negotiate_hdr_signing(struct dcesrv_call_state *call,
 						  struct ncacn_packet *pkt)
@@ -634,6 +636,7 @@ bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
 		.auth_level = auth->auth_level,
 		.auth_context_id = auth->auth_context_id,
 	};
+	bool check_pkt_auth_fields;
 	NTSTATUS status;
 
 	if (!auth->auth_started) {
@@ -648,9 +651,15 @@ bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
 	if (auth->auth_invalid) {
 		return false;
 	}
+	if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+		check_pkt_auth_fields = true;
+	} else {
+		check_pkt_auth_fields = false;
+	}
 
 	status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
 					    auth->gensec_security,
+					    check_pkt_auth_fields,
 					    call,
 					    pkt->ptype,
 					    required_flags,
-- 
2.27.0

openSUSE Build Service is sponsored by