[Pkg-samba-maint] [samba] 01/02: add patch for CVE-2013-4408

Ivo De Decker idd-guest at moszumanska.debian.org
Mon Dec 9 09:15:34 UTC 2013


This is an automated email from the git hooks/post-receive script.

idd-guest pushed a commit to branch squeeze
in repository samba.

commit 0814bf5dd75c86dfc238a3d7909b10ab0594ca00
Author: Ivo De Decker <ivo.dedecker at ugent.be>
Date:   Sun Dec 1 20:00:39 2013 +0100

    add patch for CVE-2013-4408
    
    DCERPC frag_len not checked
---
 debian/changelog                            |    7 +
 debian/patches/security-CVE-2013-4408.patch | 1517 +++++++++++++++++++++++++++
 debian/patches/series                       |    1 +
 3 files changed, 1525 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index d22a26b..795b323 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+samba (2:3.5.6~dfsg-3squeeze11) UNRELEASED; urgency=high
+
+  * Security update
+  * CVE-2013-4408: DCERPC frag_len not checked
+
+ -- Ivo De Decker <ivo.dedecker at ugent.be>  Sun, 01 Dec 2013 19:59:03 +0100
+
 samba (2:3.5.6~dfsg-3squeeze10) squeeze; urgency=low
 
   [ Ivo De Decker ]
diff --git a/debian/patches/security-CVE-2013-4408.patch b/debian/patches/security-CVE-2013-4408.patch
new file mode 100644
index 0000000..35ceb3f
--- /dev/null
+++ b/debian/patches/security-CVE-2013-4408.patch
@@ -0,0 +1,1517 @@
+===========================================================
+== 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++) {
diff --git a/debian/patches/series b/debian/patches/series
index 45c6761..bd77d21 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -36,3 +36,4 @@ debian-changes-2:3.5.6~dfsg-3squeeze8
 security-CVE-2013-0213.patch
 security-CVE-2013-0214.patch
 security-CVE-2013-4124.patch
+security-CVE-2013-4408.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-samba/samba.git




More information about the Pkg-samba-maint mailing list