===========================================================
== Subject:     DCE-RPC fragment length field is incorrectly checked.
==
== CVE ID#:     CVE-2013-4408
==
== Versions:    All versions of Samba later than 3.4.0
==
== Summary:     Incorrect length checks on DCE-RPC fragment lengths
==              cause Samba client utilities including winbindd to
==              be vulnerable to buffer overrun exploits.
==
===========================================================

===========
Description
===========

Samba versions 3.4.0 and above (versions 3.4.0 - 3.4.17, 3.5.0 -
3.5.22, 3.6.0 - 3.6.21, 4.0.0 - 4.0.12 and including 4.1.2) are
vulnerable to buffer overrun exploits in the client processing of
DCE-RPC packets. This is due to incorrect checking of the DCE-RPC
fragment length in the client code.

This is a critical vulnerability as the DCE-RPC client code is part of
the winbindd authentication and identity mapping daemon, which is
commonly configured as part of many server installations (when joined
to an Active Directory Domain). A malicious Active Directory Domain
Controller or man-in-the-middle attacker impersonating an Active
Directory Domain Controller could achieve root-level access by
compromising the winbindd process.

Samba server versions 3.4.0 - 3.4.17 and versions 3.5.0 - 3.5.22 are
also vulnerable to a denial of service attack (server crash) due to a
similar error in the server code of those versions.

Samba server versions 3.6.0 and above (including all 3.6.x versions,
all 4.0.x versions and 4.1.x) are not vulnerable to this problem.

In addition range checks were missing on arguments returned from calls
to the DCE-RPC functions LookupSids (lsa and samr), LookupNames (lsa and samr)
and LookupRids (samr) which could also cause similar problems.

As this was found during an internal audit of the Samba code there are
no currently known exploits for this problem (as of December 9th 2013).

--- a/libcli/util/ntstatus.h
+++ b/libcli/util/ntstatus.h
@@ -604,9 +604,14 @@
 #define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */
 #define NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED NT_STATUS(0xC0000000 | 0x20004)
 #define NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX NT_STATUS(0xC0000000 | 0x20026)
-#define NT_STATUS_RPC_NT_CALL_FAILED NT_STATUS(0xC0000000 | 0x2001B)
-#define NT_STATUS_RPC_NT_PROTOCOL_ERROR NT_STATUS(0xC0000000 | 0x2001D)
-#define NT_STATUS_RPC_NT_PROCNUM_OUT_OF_RANGE NT_STATUS(0xC0000000 | 0x2002E)
+#define NT_STATUS_RPC_UNKNOWN_IF NT_STATUS(0xC0000000 | 0x20012)
+#define NT_STATUS_RPC_CALL_FAILED NT_STATUS(0xC0000000 | 0x2001B)
+#define NT_STATUS_RPC_PROTOCOL_ERROR NT_STATUS(0xC0000000 | 0x2001D)
+#define NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE NT_STATUS(0xC0000000 | 0x2002E)
+#define NT_STATUS_RPC_CANNOT_SUPPORT NT_STATUS(0xC0000000 | 0x20041)
+#define NT_STATUS_RPC_SS_CONTEXT_MISMATCH NT_STATUS(0xC0000000 | 0x30005)
+#define NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE NT_STATUS(0xC000000 | 0x3000A)
+#define NT_STATUS_RPC_BAD_STUB_DATA NT_STATUS(0xC0000000 | 0x3000C)
 #define NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS NT_STATUS(0xC0000000 | 0x2071)
 #define NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION NT_STATUS(0xC0000000 | 0x00002177)
 
@@ -699,6 +704,8 @@
 #define NT_STATUS_IS_LDAP(status) ((NT_STATUS_V(status) & 0xFF000000) == 0xF2000000)
 #define NT_STATUS_LDAP_CODE(status) (NT_STATUS_V(status) & ~0xFF000000)
 
-#define NT_STATUS_RPC_CANNOT_SUPPORT NT_STATUS(0xC0000000 | 0x20041)
+#define NT_STATUS_IS_RPC(status) \
+	(((NT_STATUS_V(status) & 0xFFFF) == 0xC0020000) || \
+	 ((NT_STATUS_V(status) & 0xFFFF) == 0xC0030000))
 
 #endif /* _NTSTATUS_H */
--- a/source4/libcli/util/nterr.c
+++ b/source4/libcli/util/nterr.c
@@ -546,6 +546,14 @@
         { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
 	{ "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED },
 	{ "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX },
+	{ "NT_STATUS_RPC_UNKNOWN_IF", NT_STATUS_RPC_UNKNOWN_IF },
+	{ "NT_STATUS_RPC_CALL_FAILED", NT_STATUS_RPC_CALL_FAILED },
+	{ "NT_STATUS_RPC_PROTOCOL_ERROR", NT_STATUS_RPC_PROTOCOL_ERROR },
+	{ "NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE", NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE },
+	{ "NT_STATUS_RPC_CANNOT_SUPPORT", NT_STATUS_RPC_CANNOT_SUPPORT },
+	{ "NT_STATUS_RPC_SS_CONTEXT_MISMATCH", NT_STATUS_RPC_SS_CONTEXT_MISMATCH },
+	{ "NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE", NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE },
+	{ "NT_STATUS_RPC_BAD_STUB_DATA", NT_STATUS_RPC_BAD_STUB_DATA },
 	{ "NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED", NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED },
 	{ "NT_STATUS_OBJECTID_NOT_FOUND", NT_STATUS_OBJECTID_NOT_FOUND },
 	{ "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED },
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -539,11 +539,16 @@
 	{ "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
 	{ "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED },
 	{ "STATUS_NO_MORE_FILES", STATUS_NO_MORE_FILES },
-	{ "NT_STATUS_RPC_CANNOT_SUPPORT", NT_STATUS_RPC_CANNOT_SUPPORT },
-	{ "NT_STATUS_RPC_NT_CALL_FAILED", NT_STATUS_RPC_NT_CALL_FAILED },
-	{ "NT_STATUS_RPC_NT_PROTOCOL_ERROR", NT_STATUS_RPC_NT_PROTOCOL_ERROR },
-	{ "NT_STATUS_RPC_NT_PROCNUM_OUT_OF_RANGE", NT_STATUS_RPC_NT_PROCNUM_OUT_OF_RANGE },
 	{ "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED },
+	{ "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX },
+	{ "NT_STATUS_RPC_UNKNOWN_IF", NT_STATUS_RPC_UNKNOWN_IF },
+	{ "NT_STATUS_RPC_CALL_FAILED", NT_STATUS_RPC_CALL_FAILED },
+	{ "NT_STATUS_RPC_PROTOCOL_ERROR", NT_STATUS_RPC_PROTOCOL_ERROR },
+	{ "NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE", NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE },
+	{ "NT_STATUS_RPC_CANNOT_SUPPORT", NT_STATUS_RPC_CANNOT_SUPPORT },
+	{ "NT_STATUS_RPC_SS_CONTEXT_MISMATCH", NT_STATUS_RPC_SS_CONTEXT_MISMATCH },
+	{ "NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE", NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE },
+	{ "NT_STATUS_RPC_BAD_STUB_DATA", NT_STATUS_RPC_BAD_STUB_DATA },
 	{ NULL, NT_STATUS(0) }
 };
 
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -443,7 +443,8 @@
 
 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
 				 struct rpc_hdr_info *prhdr,
-				 prs_struct *pdu)
+				 prs_struct *pdu,
+				 uint32_t call_id)
 {
 	/*
 	 * This next call sets the endian bit correctly in current_pdu. We
@@ -455,6 +456,12 @@
 		return NT_STATUS_BUFFER_TOO_SMALL;
 	}
 
+	if (prhdr->frag_len < RPC_HEADER_LEN) {
+		DEBUG(0, ("parse_rpc_header: Server sent fraglen %d,"
+			  " < RPC_HEADER_LEN\n", (int)prhdr->frag_len));
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	if (prhdr->frag_len > cli->max_recv_frag) {
 		DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
 			  " we only allow %d\n", (int)prhdr->frag_len,
@@ -462,6 +469,14 @@
 		return NT_STATUS_BUFFER_TOO_SMALL;
 	}
 
+	if (prhdr->call_id != call_id) {
+		DEBUG(0, ("parse_rpc_header: call_id was %u,"
+			  " expected %u\n",
+			(unsigned int)prhdr->call_id,
+			(unsigned int)call_id));
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	return NT_STATUS_OK;
 }
 
@@ -474,6 +489,7 @@
 	struct event_context *ev;
 	struct rpc_pipe_client *cli;
 	struct rpc_hdr_info *prhdr;
+	uint32_t call_id;
 	prs_struct *pdu;
 };
 
@@ -483,6 +499,7 @@
 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
 						 struct event_context *ev,
 						 struct rpc_pipe_client *cli,
+						 uint32_t call_id,
 						 struct rpc_hdr_info *prhdr,
 						 prs_struct *pdu)
 {
@@ -499,6 +516,7 @@
 	state->ev = ev;
 	state->cli = cli;
 	state->prhdr = prhdr;
+	state->call_id = call_id;
 	state->pdu = pdu;
 
 	pdu_len = prs_data_size(pdu);
@@ -521,7 +539,7 @@
 		return req;
 	}
 
-	status = parse_rpc_header(cli, prhdr, pdu);
+	status = parse_rpc_header(cli, prhdr, pdu, call_id);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto post_status;
 	}
@@ -572,7 +590,8 @@
 		return;
 	}
 
-	status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
+	status = parse_rpc_header(state->cli, state->prhdr, state->pdu,
+				state->call_id);
 	if (!NT_STATUS_IS_OK(status)) {
 		tevent_req_nterror(req, status);
 		return;
@@ -1315,6 +1334,7 @@
 	struct event_context *ev;
 	struct rpc_pipe_client *cli;
 	uint8_t expected_pkt_type;
+	uint32_t call_id;
 
 	prs_struct incoming_frag;
 	struct rpc_hdr_info rhdr;
@@ -1337,7 +1357,8 @@
 					    struct event_context *ev,
 					    struct rpc_pipe_client *cli,
 					    prs_struct *data, /* Outgoing PDU */
-					    uint8_t expected_pkt_type)
+					    uint8_t expected_pkt_type,
+					    uint32_t call_id)
 {
 	struct tevent_req *req, *subreq;
 	struct rpc_api_pipe_state *state;
@@ -1351,6 +1372,7 @@
 	state->ev = ev;
 	state->cli = cli;
 	state->expected_pkt_type = expected_pkt_type;
+	state->call_id = call_id;
 	state->incoming_pdu_offset = 0;
 
 	prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
@@ -1434,6 +1456,7 @@
 
 	/* Ensure we have enough data for a pdu. */
 	subreq = get_complete_frag_send(state, state->ev, state->cli,
+					state->call_id,
 					&state->rhdr, &state->incoming_frag);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
@@ -1525,6 +1548,7 @@
 	}
 
 	subreq = get_complete_frag_send(state, state->ev, state->cli,
+					state->call_id,
 					&state->rhdr, &state->incoming_frag);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
@@ -2211,7 +2235,8 @@
 	if (is_last_frag) {
 		subreq = rpc_api_pipe_send(state, ev, state->cli,
 					   &state->outgoing_frag,
-					   DCERPC_PKT_RESPONSE);
+					   DCERPC_PKT_RESPONSE,
+					   state->call_id);
 		if (subreq == NULL) {
 			goto fail;
 		}
@@ -2347,7 +2372,8 @@
 	if (is_last_frag) {
 		subreq = rpc_api_pipe_send(state, state->ev, state->cli,
 					   &state->outgoing_frag,
-					   DCERPC_PKT_RESPONSE);
+					   DCERPC_PKT_RESPONSE,
+					   state->call_id);
 		if (tevent_req_nomem(subreq, req)) {
 			return;
 		}
@@ -2658,7 +2684,7 @@
 	}
 
 	subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
-				   DCERPC_PKT_BIND_ACK);
+				   DCERPC_PKT_BIND_ACK, state->rpc_call_id);
 	if (subreq == NULL) {
 		goto fail;
 	}
@@ -2702,6 +2728,16 @@
 		return;
 	}
 
+	if (hdr.call_id != state->rpc_call_id) {
+		DEBUG(0, ("rpc_pipe_bind: Missmatched call_id "
+			"(was %u, should be %u).\n",
+			(unsigned int)hdr.call_id,
+			(unsigned int)state->rpc_call_id));
+		prs_mem_free(&reply_pdu);
+		tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
 	if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
 		DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
 			  "RPC_HDR_BA.\n"));
@@ -2926,7 +2962,8 @@
 	}
 
 	subreq = rpc_api_pipe_send(state, state->ev, state->cli,
-				   &state->rpc_out, DCERPC_PKT_ALTER_RESP);
+				   &state->rpc_out, DCERPC_PKT_ALTER_RESP,
+				   state->rpc_call_id);
 	if (subreq == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -2962,6 +2999,15 @@
 		return;
 	}
 
+	if (hdr.call_id != state->rpc_call_id) {
+		DEBUG(0, ("Missmatched call_id "
+			"(was %u, should be %u).\n",
+			(unsigned int)hdr.call_id,
+			(unsigned int)state->rpc_call_id));
+		tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
 	if (!prs_set_offset(
 		    &reply_pdu,
 		    hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -232,6 +232,15 @@
 
 		ofs = state->buffer.length;
 
+		if (frag_len < ofs) {
+			/*
+			 * something is wrong, let the caller deal with it
+			 */
+			*_vector = NULL;
+			*_count = 0;
+			return 0;
+		}
+
 		state->buffer.data = talloc_realloc(state,
 						    state->buffer.data,
 						    uint8_t, frag_len);
@@ -303,6 +312,11 @@
 		return;
 	}
 
+	if (state->pkt->frag_length != state->buffer.length) {
+		tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
 	tevent_req_done(req);
 }
 
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -213,6 +213,10 @@
 		return ndr_map_error2ntstatus(ndr_err);
 	}
 
+	if (pkt->frag_length != blob->length) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	return NT_STATUS_OK;
 }
 
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -159,6 +159,12 @@
 	} else {
 		uint32_t frag_length = blob->length>=16?
 			dcerpc_get_frag_length(blob):0x2000;
+
+		if (frag_length < state->data.length) {
+			talloc_free(state);
+			return NT_STATUS_RPC_PROTOCOL_ERROR;
+		}
+
 		state->received = blob->length;
 		state->data = data_blob_talloc(state, NULL, frag_length);
 		if (!state->data.data) {
--- a/source4/librpc/rpc/dcerpc_smb2.c
+++ b/source4/librpc/rpc/dcerpc_smb2.c
@@ -169,6 +169,12 @@
 
 	if (state->data.length >= 16) {
 		uint16_t frag_length = dcerpc_get_frag_length(&state->data);
+
+		if (frag_length < state->data.length) {
+			talloc_free(state);
+			return NT_STATUS_RPC_PROTOCOL_ERROR;
+		}
+
 		io.in.length = frag_length - state->data.length;
 	} else {
 		io.in.length = 0x2000;
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -101,6 +101,12 @@
 		return STATUS_MORE_ENTRIES;
 	}
 	*size = dcerpc_get_frag_length(&blob);
+	if (*size < blob.length) {
+		/*
+		 * something is wrong, let the caller deal with it
+		 */
+		*size = blob.length;
+	}
 	if (*size > blob.length) {
 		return STATUS_MORE_ENTRIES;
 	}
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -594,6 +594,11 @@
 		return;
 	}
 
+	if (total + more < total) {
+		tevent_req_error(req, EMSGSIZE);
+		return;
+	}
+
 	tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
 	if (tevent_req_nomem(tmp, req)) {
 		return;
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -362,8 +362,7 @@
 static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
 {
 	uint32 ss_padding_len = 0;
-	size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
-				(p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
+	size_t data_len = 0;
 
 	if(!p->pipe_bound) {
 		DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
@@ -388,6 +387,11 @@
 
 	switch(p->auth.auth_type) {
 		case PIPE_AUTH_TYPE_NONE:
+			if (p->hdr.auth_len != 0) {
+				DEBUG(0,("process_request_pdu: PIPE_AUTH_TYPE_NONE given auth_data.\n"));
+				set_incoming_fault(p);
+				return False;
+			}
 			break;
 
 		case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
@@ -417,6 +421,16 @@
 			return False;
 	}
 
+	data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
+			(p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
+
+	if (data_len > p->hdr.frag_len) {
+		DEBUG(0,("process_request_pdu: rpc frag size too small (%u)\n",
+				(unsigned int)p->hdr.frag_len));
+		set_incoming_fault(p);
+		return False;
+	}
+
 	/* Now we've done the sign/seal we can remove any padding data. */
 	if (data_len > ss_padding_len) {
 		data_len -= ss_padding_len;
@@ -1311,6 +1325,10 @@
 		return -1;
 	}
 
+	if (hdr.frag_len < RPC_HEADER_LEN) {
+		return -1;
+	}
+
 	return (hdr.frag_len - RPC_HEADER_LEN);
 }
 
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -2089,7 +2089,8 @@
 	*pstatus = NT_STATUS_OK;
 
 	if (p->auth.auth_level == DCERPC_AUTH_LEVEL_NONE || p->auth.auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
-		return True;
+		/* For these auth_levels the auth_len must be zero. */
+		return (auth_len == 0);
 	}
 
 	if (!a) {
--- a/source3/lib/util_tsock.c
+++ b/source3/lib/util_tsock.c
@@ -108,6 +108,11 @@
 		return;
 	}
 
+	if (total + more < total) {
+		tevent_req_error(req, EMSGSIZE);
+		return;
+	}
+
 	tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
 	if (tevent_req_nomem(tmp, req)) {
 		return;
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -198,6 +198,11 @@
 		goto done;
 	}
 
+	if (num_sids != lsa_names.count) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	/* Return output parameters */
 
 	if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
@@ -219,6 +224,14 @@
 		/* Translate optimised name through domain index array */
 
 		if (dom_idx != 0xffffffff) {
+			if (ref_domains == NULL) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+			if (dom_idx >= ref_domains->count) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
 
 			dom_name = ref_domains->domains[dom_idx].name.string;
 			name = lsa_names.names[i].name.string;
@@ -503,9 +516,19 @@
 		DOM_SID *sid = &(*sids)[i];
 
 		if (use_lookupnames4) {
+			if (i >= sid_array3.count) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+
 			dom_idx		= sid_array3.sids[i].sid_index;
 			(*types)[i]	= sid_array3.sids[i].sid_type;
 		} else {
+			if (i >= sid_array.count) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+
 			dom_idx		= sid_array.sids[i].sid_index;
 			(*types)[i]	= sid_array.sids[i].sid_type;
 		}
@@ -518,6 +541,14 @@
 			(*types)[i] = SID_NAME_UNKNOWN;
 			continue;
 		}
+		if (domains == NULL) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+		if (dom_idx >= domains->count) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
 
 		if (use_lookupnames4) {
 			sid_copy(sid, sid_array3.sids[i].sid);
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -309,7 +309,7 @@
 
 	uint32_t num_names;
 	struct lsa_String *names;
-	struct lsa_RefDomainList *domains;
+	struct lsa_RefDomainList *domains = NULL;
 	struct lsa_TransSidArray3 sids;
 	uint32_t count = 0;
 	int i;
@@ -342,6 +342,10 @@
 		return result;
 	}
 
+	if (sids.count != num_names) {
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+
 	for (i = 0; i < sids.count; i++) {
 		fstring sid_str;
 		sid_to_fstring(sid_str, sids.sids[i].sid);
@@ -430,7 +434,7 @@
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 	int i;
 	struct lsa_SidArray sids;
-	struct lsa_RefDomainList *domains;
+	struct lsa_RefDomainList *domains = NULL;
 	struct lsa_TransNameArray2 names;
 	uint32_t count = 0;
 
@@ -472,11 +476,16 @@
 	    NT_STATUS_V(STATUS_SOME_UNMAPPED))
 		goto done;
 
+	if (sids.num_sids != names.count) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	result = NT_STATUS_OK;
 
 	/* Print results */
 
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < names.count; i++) {
 		fstring sid_str;
 
 		sid_to_fstring(sid_str, sids.sids[i].sid);
--- a/source4/libcli/util/clilsa.c
+++ b/source4/libcli/util/clilsa.c
@@ -241,7 +241,21 @@
 	}
 	if (names.count != 1) {
 		talloc_free(mem_ctx2);
-		return NT_STATUS_UNSUCCESSFUL;
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+	if (domains == NULL) {
+		talloc_free(mem_ctx2);
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+	if (domains->count != 1) {
+		talloc_free(mem_ctx2);
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+	if (names.names[0].sid_index != UINT32_MAX &&
+	    names.names[0].sid_index >= domains->count)
+	{
+		talloc_free(mem_ctx2);
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
 	}
 
 	(*name) = talloc_asprintf(mem_ctx, "%s\\%s", 
@@ -298,7 +312,11 @@
 	}
 	if (sids.count != 1) {
 		talloc_free(mem_ctx2);
-		return NT_STATUS_UNSUCCESSFUL;
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+	if (domains->count != 1) {
+		talloc_free(mem_ctx2);
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
 	}
 
 	sid = domains->domains[0].sid;
--- a/source4/winbind/wb_async_helpers.c
+++ b/source4/winbind/wb_async_helpers.c
@@ -122,6 +122,12 @@
 		return;
 	}
 
+	if (state->names.count != state->num_sids) {
+		composite_error(state->ctx,
+				NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
 	state->result = talloc_array(state, struct wb_sid_object *,
 				     state->num_sids);
 	if (composite_nomem(state->result, state->ctx)) return;
@@ -142,9 +148,14 @@
 			continue;
 		}
 
+		if (domains == NULL) {
+			composite_error(state->ctx,
+					NT_STATUS_INVALID_NETWORK_RESPONSE);
+			return;
+		}
 		if (name->sid_index >= domains->count) {
 			composite_error(state->ctx,
-					NT_STATUS_INVALID_PARAMETER);
+					NT_STATUS_INVALID_NETWORK_RESPONSE);
 			return;
 		}
 
@@ -271,6 +282,12 @@
 		return;
 	}
 
+	if (state->sids.count != state->num_names) {
+		composite_error(state->ctx,
+				NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
 	state->result = talloc_array(state, struct wb_sid_object *,
 				     state->num_names);
 	if (composite_nomem(state->result, state->ctx)) return;
@@ -289,9 +306,14 @@
 			continue;
 		}
 
+		if (domains == NULL) {
+			composite_error(state->ctx,
+					NT_STATUS_INVALID_NETWORK_RESPONSE);
+			return;
+		}
 		if (sid->sid_index >= domains->count) {
 			composite_error(state->ctx,
-					NT_STATUS_INVALID_PARAMETER);
+					NT_STATUS_INVALID_NETWORK_RESPONSE);
 			return;
 		}
 
--- a/source3/lib/netapi/group.c
+++ b/source3/lib/netapi/group.c
@@ -273,6 +273,15 @@
 		goto done;
 	}
 
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+
 	if (types.ids[0] != SID_NAME_DOM_GRP) {
 		werr = WERR_INVALID_DATATYPE;
 		goto done;
@@ -330,6 +339,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (names.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (member_types.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 	}
 
 	for (i=0; i < rid_array->count; i++) {
@@ -437,6 +454,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_DOM_GRP) {
 		werr = WERR_INVALID_DATATYPE;
@@ -672,6 +697,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_DOM_GRP) {
 		werr = WERR_INVALID_DATATYPE;
@@ -788,6 +821,14 @@
 		werr = WERR_GROUPNOTFOUND;
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_DOM_GRP) {
 		werr = WERR_GROUPNOTFOUND;
@@ -816,6 +857,14 @@
 		werr = WERR_USER_NOT_FOUND;
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_USER) {
 		werr = WERR_USER_NOT_FOUND;
@@ -909,6 +958,14 @@
 		werr = WERR_GROUPNOTFOUND;
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_DOM_GRP) {
 		werr = WERR_GROUPNOTFOUND;
@@ -937,6 +994,14 @@
 		werr = WERR_USER_NOT_FOUND;
 		goto done;
 	}
+	if (rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	if (types.ids[0] != SID_NAME_USER) {
 		werr = WERR_USER_NOT_FOUND;
@@ -1319,6 +1384,15 @@
 		goto done;
 	}
 
+	if (group_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+
 	status = rpccli_samr_OpenGroup(pipe_cli, ctx,
 				       &domain_handle,
 				       SAMR_GROUP_ACCESS_GET_MEMBERS,
@@ -1347,6 +1421,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (names.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (member_types.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	for (i=0; i < names.count; i++) {
 
@@ -1471,6 +1553,15 @@
 		goto done;
 	}
 
+	if (group_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (group_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+
 	status = rpccli_samr_OpenGroup(pipe_cli, ctx,
 				       &domain_handle,
 				       SAMR_GROUP_ACCESS_GET_MEMBERS |
@@ -1533,6 +1624,15 @@
 		goto done;
 	}
 
+	if (r->in.num_entries != user_rids.count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (r->in.num_entries != name_types.count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+
 	member_rids = user_rids.ids;
 	num_member_rids = user_rids.count;
 
--- a/source3/lib/netapi/localgroup.c
+++ b/source3/lib/netapi/localgroup.c
@@ -50,6 +50,13 @@
 		return status;
 	}
 
+	if (user_rids.count != 1) {
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+	if (name_types.count != 1) {
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+
 	switch (name_types.ids[0]) {
 		case SID_NAME_ALIAS:
 		case SID_NAME_WKN_GRP:
@@ -951,7 +958,7 @@
 	NT_STATUS_NOT_OK_RETURN(status);
 
 	if (count != 1 || sids.count != 1) {
-		return NT_STATUS_NONE_MAPPED;
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
 	}
 
 	sid_copy(sid, sids.sids[0].sid);
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -549,6 +549,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = rpccli_samr_OpenUser(pipe_cli, ctx,
 				      &domain_handle,
@@ -1681,6 +1689,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
 							  domain_sid,
@@ -1836,6 +1852,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = rpccli_samr_OpenUser(pipe_cli, ctx,
 				      &domain_handle,
@@ -2855,6 +2879,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = rpccli_samr_OpenUser(pipe_cli, ctx,
 				      &domain_handle,
@@ -2895,6 +2927,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (names.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != rid_array->count) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	for (i=0; i < names.count; i++) {
 		status = add_GROUP_USERS_INFO_X_buffer(ctx,
@@ -3006,6 +3046,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = rpccli_samr_OpenUser(pipe_cli, ctx,
 				      &domain_handle,
@@ -3056,6 +3104,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (group_rids.count != r->in.num_entries) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != r->in.num_entries) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	member_rids = group_rids.ids;
 	num_member_rids = group_rids.count;
@@ -3300,6 +3356,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	status = rpccli_samr_OpenUser(pipe_cli, ctx,
 				      &domain_handle,
@@ -3396,6 +3460,14 @@
 		werr = ntstatus_to_werror(status);
 		goto done;
 	}
+	if (names.count != num_rids) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
+	if (types.count != num_rids) {
+		werr = WERR_BAD_NET_RESP;
+		goto done;
+	}
 
 	for (i=0; i < names.count; i++) {
 		status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -941,6 +941,14 @@
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	if (name_types.ids[0] != SID_NAME_USER) {
 		DEBUG(0,("%s is not a user account (type=%d)\n",
@@ -1267,6 +1275,14 @@
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	if (name_types.ids[0] != SID_NAME_USER) {
 		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name,
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -360,6 +360,15 @@
 						 &types);
 
 		if (NT_STATUS_IS_OK(result)) {
+			if (rids.count != 1) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+			if (types.count != 1) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+
 			result = rpccli_samr_OpenUser(cli, mem_ctx,
 						      &domain_pol,
 						      access_mask,
@@ -1309,6 +1318,15 @@
 						 &types);
 
 		if (NT_STATUS_IS_OK(result)) {
+			if (rids.count != 1) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+			if (types.count != 1) {
+				result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+				goto done;
+			}
+
 			result = rpccli_samr_OpenAlias(cli, mem_ctx,
 						       &domain_pol,
 						       access_mask,
@@ -1899,6 +1917,15 @@
 	if (!NT_STATUS_IS_OK(result))
 		goto done;
 
+	if (rids.count != num_names) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != num_names) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	/* Display results */
 
 	for (i = 0; i < num_names; i++)
@@ -1974,6 +2001,14 @@
 		goto done;
 
 	/* Display results */
+	if (num_rids != names.count) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (num_rids != types.count) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	for (i = 0; i < num_rids; i++) {
 		printf("rid 0x%x: %s (%d)\n",
@@ -2039,6 +2074,15 @@
 		if (!NT_STATUS_IS_OK(result))
 			goto done;
 
+		if (group_rids.count != 1) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+		if (name_types.count != 1) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+
 		result = rpccli_samr_OpenGroup(cli, mem_ctx,
 					       &domain_pol,
 					       access_mask,
@@ -2121,6 +2165,15 @@
 		if (!NT_STATUS_IS_OK(result))
 			goto done;
 
+		if (user_rids.count != 1) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+		if (name_types.count != 1) {
+			result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+
 		result = rpccli_samr_OpenUser(cli, mem_ctx,
 					      &domain_pol,
 					      access_mask,
@@ -2436,6 +2489,15 @@
 		goto done;
 	}
 
+	if (rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	result = rpccli_samr_OpenUser(cli, mem_ctx,
 				      &domain_pol,
 				      access_mask,
@@ -2804,6 +2866,14 @@
 		if (!NT_STATUS_IS_OK(status)) {
 			return status;
 		}
+		if (rids.count != 1) {
+			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
+		if (types.count != 1) {
+			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+			goto done;
+		}
 
 		status = rpccli_samr_OpenUser(cli, mem_ctx,
 					      &domain_pol,
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -2492,6 +2492,14 @@
 			  nt_errstr(status)));
 		goto close_domain;
 	}
+	if (rid.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto close_domain;
+	}
+	if (type.count != 1) {
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto close_domain;
+	}
 
 	if (type.ids[0] != SID_NAME_USER) {
 		DEBUG(10, ("%s is a %s, not a user\n", UserName,
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -1493,6 +1493,15 @@
    		goto done;
 	}
 
+	if (group_rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	switch (name_types.ids[0])
 	{
 	case SID_NAME_DOM_GRP:
@@ -1826,6 +1835,14 @@
 			  member);
 		goto done;
 	}
+	if (rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (rid_types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
 				       &domain_pol,
@@ -2034,6 +2051,14 @@
 			  member);
 		goto done;
 	}
+	if (rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (rid_types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
 				       &domain_pol,
@@ -2488,6 +2513,13 @@
 		if (!NT_STATUS_IS_OK(result))
 			return result;
 
+		if (names.count != this_time) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+		if (types.count != this_time) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+
 		/* We only have users as members, but make the output
 		   the same as the output of alias members */
 
@@ -2695,8 +2727,14 @@
 	if (rids.count != 1) {
 		d_fprintf(stderr, _("Couldn't find group %s\n"),
 			  argv[0]);
-		return result;
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
 	}
+	if (rid_types.count != 1) {
+		d_fprintf(stderr, _("Couldn't find group %s\n"),
+			  argv[0]);
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+
 
 	if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
 		return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
@@ -5479,6 +5517,14 @@
 			acct_name, nt_errstr(result) );
 		goto done;
 	}
+	if (user_rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
 
 	result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
 				      &domain_pol,
--- a/source3/utils/net_rpc_join.c
+++ b/source3/utils/net_rpc_join.c
@@ -322,6 +322,15 @@
 			    ("error looking up rid for user %s: %s\n",
 			     acct_name, nt_errstr(result)));
 
+	if (user_rids.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+	if (name_types.count != 1) {
+		result = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto done;
+	}
+
 	if (name_types.ids[0] != SID_NAME_USER) {
 		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
 		goto done;
--- a/source4/libnet/groupinfo.c
+++ b/source4/libnet/groupinfo.c
@@ -87,12 +87,16 @@
 		
 		s->monitor_fn(&msg);
 	}
-	
 
 	/* have we actually got name resolved
 	   - we're looking for only one at the moment */
-	if (s->lookup.out.rids->count == 0) {
-		composite_error(c, NT_STATUS_NO_SUCH_USER);
+	if (s->lookup.out.rids->count != s->lookup.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+	if (s->lookup.out.types->count != s->lookup.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
 	}
 
 	/* TODO: find proper status code for more than one rid found */
--- a/source4/libnet/groupman.c
+++ b/source4/libnet/groupman.c
@@ -207,13 +207,13 @@
 
 	/* what to do when there's no group account to delete
 	   and what if there's more than one rid resolved */
-	if (!s->lookupname.out.rids->count) {
-		c->status = NT_STATUS_NO_SUCH_GROUP;
+	if (s->lookupname.out.rids->count != s->lookupname.in.num_names) {
+		c->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 		composite_error(c, c->status);
 		return;
-
-	} else if (!s->lookupname.out.rids->count > 1) {
-		c->status = NT_STATUS_INVALID_ACCOUNT_NAME;
+	}
+	if (s->lookupname.out.types->count != s->lookupname.in.num_names) {
+		c->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 		composite_error(c, c->status);
 		return;
 	}
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -643,9 +643,17 @@
 							      "samr_LookupNames for [%s] returns %d RIDs",
 							      r->in.account_name, ln.out.rids->count);
 			talloc_free(tmp_ctx);
-			return NT_STATUS_INVALID_PARAMETER;
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
 		}
-		
+
+		if (ln.out.types->count != 1) {
+			r->out.error_string = talloc_asprintf(mem_ctx,
+								"samr_LookupNames for [%s] returns %d RID TYPEs",
+								r->in.account_name, ln.out.types->count);
+			talloc_free(tmp_ctx);
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+
 		/* prepare samr_OpenUser */
 		ZERO_STRUCTP(u_handle);
 		ou.in.domain_handle = &d_handle;
--- a/source4/libnet/libnet_lookup.c
+++ b/source4/libnet/libnet_lookup.c
@@ -354,6 +354,11 @@
 	c->status = s->lookup.out.result;
 	if (!composite_is_ok(c)) return;
 
+	if (s->lookup.out.sids->count != s->lookup.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
 	composite_done(c);
 }
 
--- a/source4/libnet/libnet_passwd.c
+++ b/source4/libnet/libnet_passwd.c
@@ -594,10 +594,18 @@
 		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 						"samr_LookupNames for [%s] returns %d RIDs",
 						r->samr.in.account_name, ln.out.rids->count);
-		status = NT_STATUS_INVALID_PARAMETER;
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 		goto disconnect;	
 	}
 
+	if (ln.out.types->count != 1) {
+		r->samr.out.error_string = talloc_asprintf(mem_ctx,
+						"samr_LookupNames for [%s] returns %d RID TYPEs",
+						r->samr.in.account_name, ln.out.types->count);
+		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto disconnect;
+	}
+
 	/* prepare samr_OpenUser */
 	ZERO_STRUCT(u_handle);
 	ou.in.domain_handle = &d_handle;
--- a/source4/libnet/userinfo.c
+++ b/source4/libnet/userinfo.c
@@ -90,8 +90,13 @@
 
 	/* have we actually got name resolved
 	   - we're looking for only one at the moment */
-	if (s->lookup.out.rids->count == 0) {
-		composite_error(c, NT_STATUS_NO_SUCH_USER);
+	if (s->lookup.out.rids->count != s->lookup.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+	if (s->lookup.out.types->count != s->lookup.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
 	}
 
 	/* TODO: find proper status code for more than one rid found */
--- a/source4/libnet/userman.c
+++ b/source4/libnet/userman.c
@@ -233,14 +233,12 @@
 
 	/* what to do when there's no user account to delete
 	   and what if there's more than one rid resolved */
-	if (!s->lookupname.out.rids->count) {
-		c->status = NT_STATUS_NO_SUCH_USER;
-		composite_error(c, c->status);
+	if (s->lookupname.out.rids->count != s->lookupname.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
-
-	} else if (!s->lookupname.out.rids->count > 1) {
-		c->status = NT_STATUS_INVALID_ACCOUNT_NAME;
-		composite_error(c, c->status);
+	}
+	if (s->lookupname.out.types->count != s->lookupname.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
 	}
 
@@ -501,14 +499,12 @@
 
 	/* what to do when there's no user account to delete
 	   and what if there's more than one rid resolved */
-	if (!s->lookupname.out.rids->count) {
-		c->status = NT_STATUS_NO_SUCH_USER;
-		composite_error(c, c->status);
+	if (s->lookupname.out.rids->count != s->lookupname.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
-
-	} else if (!s->lookupname.out.rids->count > 1) {
-		c->status = NT_STATUS_INVALID_ACCOUNT_NAME;
-		composite_error(c, c->status);
+	}
+	if (s->lookupname.out.types->count != s->lookupname.in.num_names) {
+		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
 	}
 
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -832,9 +832,11 @@
 
 		/* Copy result into array.  The talloc system will take
 		   care of freeing the temporary arrays later on. */
-
-		if (tmp_names.count != tmp_types.count) {
-			return NT_STATUS_UNSUCCESSFUL;
+		if (tmp_names.count != num_lookup_rids) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+		if (tmp_types.count != num_lookup_rids) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
 		}
 
 		for (r=0; r<tmp_names.count; r++) {
