[Pkg-samba-maint] [samba] 02/03: add patch for CVE-2013-4408
Ivo De Decker
idd-guest at moszumanska.debian.org
Mon Dec 9 09:15:36 UTC 2013
This is an automated email from the git hooks/post-receive script.
idd-guest pushed a commit to branch wheezy
in repository samba.
commit 8ffb5040be2a75869c066ba329a6980ee5699404
Author: Ivo De Decker <ivo.dedecker at ugent.be>
Date: Sun Dec 1 19:01:06 2013 +0100
add patch for CVE-2013-4408
DCE-RPC fragment length field is incorrectly checked
---
debian/changelog | 1 +
debian/patches/security-CVE-2013-4408.patch | 1584 +++++++++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 1586 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index bb06420..e378f2d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,7 @@ samba (2:3.6.6-6+deb7u2) UNRELEASED; urgency=low
* Security update
* CVE-2013-4475: ACLs are not checked on opening an alternate data stream on
a file or directory
+ * CVE-2013-4408: DCE-RPC fragment length field is incorrectly checked
-- Ivo De Decker <ivo.dedecker at ugent.be> Sun, 01 Dec 2013 18:24:42 +0100
diff --git a/debian/patches/security-CVE-2013-4408.patch b/debian/patches/security-CVE-2013-4408.patch
new file mode 100644
index 0000000..482dbda
--- /dev/null
+++ b/debian/patches/security-CVE-2013-4408.patch
@@ -0,0 +1,1584 @@
+===========================================================
+== 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/librpc/rpc/dcerpc_util.c
++++ b/librpc/rpc/dcerpc_util.c
+@@ -48,6 +48,15 @@
+ }
+ }
+
++uint32_t dcerpc_get_call_id(const DATA_BLOB *blob)
++{
++ if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
++ return IVAL(blob->data, DCERPC_CALL_ID_OFFSET);
++ } else {
++ return RIVAL(blob->data, DCERPC_CALL_ID_OFFSET);
++ }
++}
++
+ void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v)
+ {
+ if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
+@@ -223,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);
+@@ -292,6 +310,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/source3/librpc/rpc/dcerpc_helpers.c
++++ b/source3/librpc/rpc/dcerpc_helpers.c
+@@ -125,6 +125,10 @@
+ NDR_PRINT_DEBUG(ncacn_packet, r);
+ }
+
++ if (r->frag_length != blob->length) {
++ return NT_STATUS_RPC_PROTOCOL_ERROR;
++ }
++
+ return NT_STATUS_OK;
+ }
+
+--- a/source3/rpc_client/cli_pipe.c
++++ b/source3/rpc_client/cli_pipe.c
+@@ -235,6 +235,7 @@
+ struct event_context *ev;
+ struct rpc_pipe_client *cli;
+ uint16_t frag_len;
++ uint32_t call_id;
+ DATA_BLOB *pdu;
+ };
+
+@@ -244,6 +245,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,
+ DATA_BLOB *pdu)
+ {
+ struct tevent_req *req, *subreq;
+@@ -259,6 +261,7 @@
+ state->ev = ev;
+ state->cli = cli;
+ state->frag_len = RPC_HEADER_LEN;
++ state->call_id = call_id;
+ state->pdu = pdu;
+
+ received = pdu->length;
+@@ -281,6 +284,15 @@
+ }
+
+ state->frag_len = dcerpc_get_frag_length(pdu);
++ if (state->frag_len < RPC_HEADER_LEN) {
++ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
++ return tevent_req_post(req, ev);
++ }
++
++ if (state->call_id != dcerpc_get_call_id(pdu)) {
++ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
++ return tevent_req_post(req, ev);
++ }
+
+ /*
+ * Ensure we have frag_len bytes of data.
+@@ -329,6 +341,15 @@
+ }
+
+ state->frag_len = dcerpc_get_frag_length(state->pdu);
++ if (state->frag_len < RPC_HEADER_LEN) {
++ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
++ return;
++ }
++
++ if (state->call_id != dcerpc_get_call_id(state->pdu)) {
++ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
++ return;
++ }
+
+ if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+@@ -690,6 +711,7 @@
+ struct event_context *ev;
+ struct rpc_pipe_client *cli;
+ uint8_t expected_pkt_type;
++ uint32_t call_id;
+
+ DATA_BLOB incoming_frag;
+ struct ncacn_packet *pkt;
+@@ -708,7 +730,8 @@
+ struct event_context *ev,
+ struct rpc_pipe_client *cli,
+ DATA_BLOB *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;
+@@ -722,6 +745,7 @@
+ state->ev = ev;
+ state->cli = cli;
+ state->expected_pkt_type = expected_pkt_type;
++ state->call_id = call_id;
+ state->incoming_frag = data_blob_null;
+ state->reply_pdu = data_blob_null;
+ state->reply_pdu_offset = 0;
+@@ -821,6 +845,7 @@
+
+ /* Ensure we have enough data for a pdu. */
+ subreq = get_complete_frag_send(state, state->ev, state->cli,
++ state->call_id,
+ &state->incoming_frag);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+@@ -940,6 +965,7 @@
+ }
+
+ subreq = get_complete_frag_send(state, state->ev, state->cli,
++ state->call_id,
+ &state->incoming_frag);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+@@ -1292,7 +1318,8 @@
+ if (is_last_frag) {
+ subreq = rpc_api_pipe_send(state, ev, state->cli,
+ &state->rpc_out,
+- DCERPC_PKT_RESPONSE);
++ DCERPC_PKT_RESPONSE,
++ state->call_id);
+ if (subreq == NULL) {
+ goto fail;
+ }
+@@ -1428,7 +1455,8 @@
+ if (is_last_frag) {
+ subreq = rpc_api_pipe_send(state, state->ev, state->cli,
+ &state->rpc_out,
+- DCERPC_PKT_RESPONSE);
++ DCERPC_PKT_RESPONSE,
++ state->call_id);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+@@ -1667,7 +1695,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;
+ }
+@@ -1865,7 +1893,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;
+ }
+@@ -1897,7 +1926,8 @@
+ }
+
+ subreq = rpc_api_pipe_send(state, state->ev, state->cli,
+- &state->rpc_out, DCERPC_PKT_AUTH3);
++ &state->rpc_out, DCERPC_PKT_AUTH3,
++ state->rpc_call_id);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+--- a/source4/librpc/rpc/dcerpc.c
++++ b/source4/librpc/rpc/dcerpc.c
+@@ -658,6 +658,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
+@@ -160,6 +160,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
+@@ -170,6 +170,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
+@@ -102,6 +102,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
+@@ -635,6 +635,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/lib/util_tsock.c
++++ b/source3/lib/util_tsock.c
+@@ -110,6 +110,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/libcli/util/tstream.c
++++ b/libcli/util/tstream.c
+@@ -129,6 +129,11 @@
+ return;
+ }
+
++ if (new_buf_size <= old_buf_size) {
++ tevent_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE);
++ return;
++ }
++
+ buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, new_buf_size);
+ if (tevent_req_nomem(buf, req)) {
+ return;
+--- a/librpc/idl/dcerpc.idl
++++ b/librpc/idl/dcerpc.idl
+@@ -467,6 +467,7 @@
+ const uint8 DCERPC_DREP_OFFSET = 4;
+ const uint8 DCERPC_FRAG_LEN_OFFSET = 8;
+ const uint8 DCERPC_AUTH_LEN_OFFSET = 10;
++ const uint8 DCERPC_CALL_ID_OFFSET = 12;
+
+ /* little-endian flag */
+ const uint8 DCERPC_DREP_LE = 0x10;
+--- a/librpc/rpc/rpc_common.h
++++ b/librpc/rpc/rpc_common.h
+@@ -135,6 +135,7 @@
+
+ void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v);
+ uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob);
++uint32_t dcerpc_get_call_id(const DATA_BLOB *blob);
+ void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v);
+ uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob);
+
+--- a/nsswitch/libwbclient/wbc_sid.c
++++ b/nsswitch/libwbclient/wbc_sid.c
+@@ -421,6 +421,13 @@
+ for (i=0; i<num_names; i++) {
+
+ names[i].domain_index = strtoul(p, &q, 10);
++ if (names[i].domain_index < 0) {
++ goto wbc_err_invalid;
++ }
++ if (names[i].domain_index >= num_domains) {
++ goto wbc_err_invalid;
++ }
++
+ if (*q != ' ') {
+ goto wbc_err_invalid;
+ }
+--- a/nsswitch/wbinfo.c
++++ b/nsswitch/wbinfo.c
+@@ -1380,11 +1380,28 @@
+ }
+
+ for (i=0; i<num_sids; i++) {
++ const char *domain = NULL;
++
+ wbcSidToStringBuf(&sids[i], sidstr, sizeof(sidstr));
+
+- d_printf("%s -> %s\\%s %d\n", sidstr,
+- domains[names[i].domain_index].short_name,
+- names[i].name, names[i].type);
++ if (names[i].domain_index >= num_domains) {
++ domain = "<none>";
++ } else if (names[i].domain_index < 0) {
++ domain = "<none>";
++ } else {
++ domain = domains[names[i].domain_index].short_name;
++ }
++
++ if (names[i].type == WBC_SID_NAME_DOMAIN) {
++ d_printf("%s -> %s %d\n", sidstr,
++ domain,
++ names[i].type);
++ } else {
++ d_printf("%s -> %s%c%s %d\n", sidstr,
++ domain,
++ winbind_separator(),
++ names[i].name, names[i].type);
++ }
+ }
+ return true;
+ }
+--- a/source3/rpc_client/cli_lsarpc.c
++++ b/source3/rpc_client/cli_lsarpc.c
+@@ -279,11 +279,26 @@
+
+ for (i = 0; i < num_sids; i++) {
+ const char *name, *dom_name;
+- uint32_t dom_idx = lsa_names.names[i].sid_index;
++ uint32_t dom_idx;
++
++ if (i >= lsa_names.count) {
++ *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ return status;
++ }
++
++ dom_idx = lsa_names.names[i].sid_index;
+
+ /* Translate optimised name through domain index array */
+
+ if (dom_idx != 0xffffffff) {
++ if (ref_domains == NULL) {
++ *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ return status;
++ }
++ if (dom_idx >= ref_domains->count) {
++ *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ return status;
++ }
+
+ dom_name = ref_domains->domains[dom_idx].name.string;
+ name = lsa_names.names[i].name.string;
+@@ -676,9 +691,19 @@
+ struct dom_sid *sid = &(*sids)[i];
+
+ if (use_lookupnames4) {
++ if (i >= sid_array3.count) {
++ *presult = 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) {
++ *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++
+ dom_idx = sid_array.sids[i].sid_index;
+ (*types)[i] = sid_array.sids[i].sid_type;
+ }
+@@ -691,6 +716,14 @@
+ (*types)[i] = SID_NAME_UNKNOWN;
+ continue;
+ }
++ if (domains == NULL) {
++ *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (dom_idx >= domains->count) {
++ *presult = 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
+@@ -323,7 +323,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;
+@@ -361,6 +361,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);
+@@ -450,7 +454,7 @@
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL, result;
+ int i;
+ struct lsa_SidArray sids;
+- struct lsa_RefDomainList *domains;
++ struct lsa_RefDomainList *domains = NULL;
+ struct lsa_TransNameArray2 names;
+ uint32_t count = 0;
+ struct dcerpc_binding_handle *b = cli->binding_handle;
+@@ -506,9 +510,12 @@
+
+ /* Print results */
+
+- for (i = 0; i < count; i++) {
++ for (i = 0; i < names.count; i++) {
+ fstring sid_str;
+
++ if (i >= sids.num_sids) {
++ break;
++ }
+ sid_to_fstring(sid_str, sids.sids[i].sid);
+ printf("%s %s (%d)\n", sid_str,
+ names.names[i].name.string,
+--- a/source3/winbindd/wb_lookupsids.c
++++ b/source3/winbindd/wb_lookupsids.c
+@@ -402,6 +402,9 @@
+ uint32_t src_domain_index, dst_domain_index;
+
+ src_domain_index = src_name->sid_index;
++ if (src_domain_index >= src_domains->count) {
++ return false;
++ }
+ src_domain = &src_domains->domains[src_domain_index];
+
+ if (!wb_lookupsids_find_dom_idx(
+--- a/source3/winbindd/winbindd_rpc.c
++++ b/source3/winbindd/winbindd_rpc.c
+@@ -871,14 +871,20 @@
+
+ /* 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_names) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++ if (tmp_types.count != num_names) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ for (r = 0; r < tmp_names.count; r++) {
+ if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
+ continue;
+ }
++ if (total_names >= num_names) {
++ break;
++ }
+ names[total_names] = fill_domain_username_talloc(names,
+ domain_name,
+ tmp_names.names[r].string,
+@@ -1038,7 +1044,7 @@
+ struct lsa_TransNameArray **pnames)
+ {
+ struct lsa_TransNameArray2 lsa_names2;
+- struct lsa_TransNameArray *names;
++ struct lsa_TransNameArray *names = *pnames;
+ uint32_t i, count;
+ struct rpc_pipe_client *cli;
+ NTSTATUS status, result;
+@@ -1066,10 +1072,10 @@
+ if (NT_STATUS_IS_ERR(result)) {
+ return result;
+ }
+- names = TALLOC_ZERO_P(mem_ctx, struct lsa_TransNameArray);
+- if (names == NULL) {
+- return NT_STATUS_NO_MEMORY;
++ if (sids->num_sids != lsa_names2.count) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
++
+ names->count = lsa_names2.count;
+ names->names = talloc_array(names, struct lsa_TranslatedName,
+ names->count);
+@@ -1081,8 +1087,17 @@
+ names->names[i].name.string = talloc_move(
+ names->names, &lsa_names2.names[i].name.string);
+ names->names[i].sid_index = lsa_names2.names[i].sid_index;
++
++ if (names->names[i].sid_index == UINT32_MAX) {
++ continue;
++ }
++ if ((*pdomains) == NULL) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++ if (names->names[i].sid_index >= (*pdomains)->count) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
+ }
+- *pnames = names;
+ return result;
+ }
+
+@@ -1092,10 +1107,11 @@
+ struct lsa_RefDomainList **pdomains,
+ struct lsa_TransNameArray **pnames)
+ {
+- struct lsa_TransNameArray *names;
++ struct lsa_TransNameArray *names = *pnames;
+ struct rpc_pipe_client *cli = NULL;
+ struct policy_handle lsa_policy;
+ uint32_t count;
++ uint32_t i;
+ NTSTATUS status, result;
+
+ if (domain->can_do_ncacn_ip_tcp) {
+@@ -1111,10 +1127,6 @@
+ return status;
+ }
+
+- names = TALLOC_ZERO_P(mem_ctx, struct lsa_TransNameArray);
+- if (names == NULL) {
+- return NT_STATUS_NO_MEMORY;
+- }
+ status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
+ &lsa_policy, sids, pdomains,
+ names, LSA_LOOKUP_NAMES_ALL,
+@@ -1125,6 +1137,22 @@
+ if (NT_STATUS_IS_ERR(result)) {
+ return result;
+ }
+- *pnames = names;
++
++ if (sids->num_sids != names->count) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++
++ for (i=0; i < names->count; i++) {
++ if (names->names[i].sid_index == UINT32_MAX) {
++ continue;
++ }
++ if ((*pdomains) == NULL) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++ if (names->names[i].sid_index >= (*pdomains)->count) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++ }
++
+ return result;
+ }
+--- a/source4/libcli/util/clilsa.c
++++ b/source4/libcli/util/clilsa.c
+@@ -254,7 +254,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",
+@@ -315,7 +329,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
+@@ -120,6 +120,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;
+@@ -140,9 +146,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;
+ }
+
+@@ -272,6 +283,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;
+@@ -290,9 +307,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
+@@ -309,6 +309,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;
+@@ -386,6 +395,14 @@
+ werr = ntstatus_to_werror(result);
+ 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++) {
+@@ -511,6 +528,14 @@
+ werr = ntstatus_to_werror(result);
+ 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;
+@@ -781,6 +806,14 @@
+ werr = ntstatus_to_werror(result);
+ 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;
+@@ -921,6 +954,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;
+@@ -959,6 +1000,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;
+@@ -1065,6 +1114,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;
+@@ -1104,6 +1161,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;
+@@ -1514,6 +1579,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+@@ -1558,6 +1631,14 @@
+ werr = ntstatus_to_werror(result);
+ 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++) {
+
+@@ -1689,6 +1770,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+@@ -1767,6 +1856,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;
+
+ status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
+--- a/source3/lib/netapi/localgroup.c
++++ b/source3/lib/netapi/localgroup.c
+@@ -58,6 +58,12 @@
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
++ 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:
+@@ -1041,7 +1047,7 @@
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ 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
+@@ -604,6 +604,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+@@ -1803,6 +1811,14 @@
+ werr = ntstatus_to_werror(result);
+ 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,
+@@ -1967,6 +1983,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+@@ -3026,6 +3050,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+@@ -3081,6 +3113,14 @@
+ werr = ntstatus_to_werror(result);
+ 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,
+@@ -3201,6 +3241,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+@@ -3261,6 +3309,14 @@
+ werr = ntstatus_to_werror(result);
+ 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;
+@@ -3539,6 +3595,14 @@
+ werr = ntstatus_to_werror(result);
+ 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 = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+@@ -3660,6 +3724,14 @@
+ werr = ntstatus_to_werror(result);
+ 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
+@@ -996,6 +996,14 @@
+ status = result;
+ 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",
+@@ -1367,6 +1375,14 @@
+ status = result;
+ 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/rpc_server/netlogon/srv_netlog_nt.c
++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
+@@ -586,7 +586,7 @@
+ status = NT_STATUS_NO_SUCH_USER;
+ goto out;
+ }
+- if (rids.count != types.count) {
++ if (types.count != 1) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto out;
+ }
+--- a/source3/rpcclient/cmd_samr.c
++++ b/source3/rpcclient/cmd_samr.c
+@@ -385,7 +385,17 @@
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
++
+ if (NT_STATUS_IS_OK(result)) {
++ 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 = dcerpc_samr_OpenUser(b, mem_ctx,
+ &domain_pol,
+ access_mask,
+@@ -1450,6 +1460,15 @@
+ goto done;
+ }
+ if (NT_STATUS_IS_OK(result)) {
++ 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 = dcerpc_samr_OpenAlias(b, mem_ctx,
+ &domain_pol,
+ access_mask,
+@@ -2112,6 +2131,14 @@
+ status = result;
+ goto done;
+ }
++ if (rids.count != num_names) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (name_types.count != num_names) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ /* Display results */
+
+@@ -2193,6 +2220,14 @@
+ goto done;
+
+ /* Display results */
++ if (num_rids != names.count) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (num_rids != types.count) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ for (i = 0; i < num_rids; i++) {
+ printf("rid 0x%x: %s (%d)\n",
+@@ -2269,6 +2304,14 @@
+ status = result;
+ goto done;
+ }
++ if (group_rids.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (name_types.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ status = dcerpc_samr_OpenGroup(b, mem_ctx,
+ &domain_pol,
+@@ -2372,6 +2415,14 @@
+ status = result;
+ 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;
++ }
+
+ status = dcerpc_samr_OpenUser(b, mem_ctx,
+ &domain_pol,
+@@ -2758,6 +2809,14 @@
+ status = result;
+ goto done;
+ }
++ 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 = dcerpc_samr_OpenUser(b, mem_ctx,
+ &domain_pol,
+@@ -3161,7 +3220,12 @@
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+-
++ if (rids.count != 1) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
++ if (types.count != 1) {
++ return NT_STATUS_INVALID_NETWORK_RESPONSE;
++ }
+
+ status = dcerpc_samr_OpenUser(b, mem_ctx,
+ &domain_pol,
+--- a/source3/smbd/lanman.c
++++ b/source3/smbd/lanman.c
+@@ -2628,6 +2628,14 @@
+ nt_errstr(result)));
+ 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
+@@ -1656,6 +1656,14 @@
+ d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
+ goto done;
+ }
++ if (group_rids.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (name_types.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ switch (name_types.ids[0])
+ {
+@@ -2063,6 +2071,14 @@
+ member);
+ goto done;
+ }
++ if (rids.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (rid_types.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ status = dcerpc_samr_OpenGroup(b, mem_ctx,
+ &domain_pol,
+@@ -2318,6 +2334,14 @@
+ member);
+ goto done;
+ }
++ if (rids.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
++ if (rid_types.count != 1) {
++ status = NT_STATUS_INVALID_NETWORK_RESPONSE;
++ goto done;
++ }
+
+ status = dcerpc_samr_OpenGroup(b, mem_ctx,
+ &domain_pol,
+@@ -2865,7 +2889,12 @@
+ 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 */
+
+@@ -3101,8 +3130,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,
+@@ -6011,6 +6046,14 @@
+ acct_name, nt_errstr(result) );
+ 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;
++ }
+
+ status = dcerpc_samr_OpenUser(b, mem_ctx,
+ &domain_pol,
+--- a/source3/utils/net_rpc_join.c
++++ b/source3/utils/net_rpc_join.c
+@@ -367,6 +367,15 @@
+ ("error looking up rid for user %s: %s/%s\n",
+ acct_name, nt_errstr(status), nt_errstr(result)));
+
++ 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, 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
+@@ -212,13 +212,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
+@@ -656,9 +656,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
+@@ -363,6 +363,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
+@@ -627,10 +627,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
+@@ -236,14 +236,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;
+ }
+
+@@ -511,14 +509,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_msrpc.c
++++ b/source3/winbindd/winbindd_msrpc.c
+@@ -737,14 +737,20 @@
+ /* 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++) {
+ if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
+ continue;
+ }
++ if (total_names >= *num_names) {
++ break;
++ }
+ (*names)[total_names] = fill_domain_username_talloc(
+ mem_ctx, domain->name,
+ tmp_names.names[r].string, true);
diff --git a/debian/patches/series b/debian/patches/series
index f4d0e31..6d45860 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -26,3 +26,4 @@ security-CVE-2013-0213.patch
security-CVE-2013-0214.patch
security-CVE-2013-4124.patch
security-CVE-2013-4475.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