[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