samba/samba-3.5.22-CVE-2013-4408.patch

2009 lines
63 KiB
Diff

From a7b7ece7aa3c8288f3373e8101f3d5abca8fac39 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@sernet.private>
Date: Wed, 17 Mar 2010 19:48:56 +0100
Subject: [PATCH 01/20] libcli/util: add more NT_STATUS_RPC_* defines
metze
(cherry picked from commit 6a1f8e67eb6e15bbafca570ac9b3714681025a1f)
---
libcli/util/ntstatus.h | 15 +++++++++++----
source4/libcli/util/nterr.c | 8 ++++++++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/libcli/util/ntstatus.h b/libcli/util/ntstatus.h
index 1025f47..d6191e4 100644
--- a/libcli/util/ntstatus.h
+++ b/libcli/util/ntstatus.h
@@ -604,9 +604,14 @@ typedef uint32_t NTSTATUS;
#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_STAUTS_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 @@ extern bool ntstatus_check_dos_mapping;
#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 */
diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c
index 75bbbde..c9466dd 100644
--- a/source4/libcli/util/nterr.c
+++ b/source4/libcli/util/nterr.c
@@ -546,6 +546,14 @@ static const nt_err_code_struct nt_errs[] =
{ "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_STAUTS_RPC_UNKNOWN_IF", NT_STAUTS_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 },
--
1.7.9.5
From 46f1a08ab4348618c973a4ec16eee7e0c0c14fee Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 18 Mar 2010 15:27:05 +0100
Subject: [PATCH 02/20] s3:libsmb/nterr.c: fix/add NT_STATUS_RPC_* codes
metze
(cherry picked from commit 421a926237f94ebdb90aaf0cf7678a9804bd5cdc)
---
source3/libsmb/nterr.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c
index 197d5bd..52dc5b8 100644
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -539,11 +539,16 @@ static const nt_err_code_struct nt_errs[] =
{ "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_STAUTS_RPC_UNKNOWN_IF", NT_STAUTS_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) }
};
--
1.7.9.5
From a4749747d364c795cac1284e40e70ed20b58507b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Fri, 19 Mar 2010 09:30:36 +0100
Subject: [PATCH 03/20] error_codes: fix NT_STATUS_RPC_UNKNOWN_IF typo.
Metze, please check.
Guenther
(cherry picked from commit e7cc45cb140e1df5731619ae09af6c10b8f9fffa)
---
libcli/util/ntstatus.h | 2 +-
source3/libsmb/nterr.c | 2 +-
source4/libcli/util/nterr.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcli/util/ntstatus.h b/libcli/util/ntstatus.h
index d6191e4..2989764 100644
--- a/libcli/util/ntstatus.h
+++ b/libcli/util/ntstatus.h
@@ -604,7 +604,7 @@ typedef uint32_t NTSTATUS;
#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_STAUTS_RPC_UNKNOWN_IF NT_STATUS(0xC0000000 | 0x20012)
+#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)
diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c
index 52dc5b8..ae41a9b 100644
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -541,7 +541,7 @@ static const nt_err_code_struct nt_errs[] =
{ "STATUS_NO_MORE_FILES", STATUS_NO_MORE_FILES },
{ "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_STAUTS_RPC_UNKNOWN_IF", NT_STAUTS_RPC_UNKNOWN_IF },
+ { "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 },
diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c
index c9466dd..0764a28 100644
--- a/source4/libcli/util/nterr.c
+++ b/source4/libcli/util/nterr.c
@@ -546,7 +546,7 @@ static const nt_err_code_struct nt_errs[] =
{ "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_STAUTS_RPC_UNKNOWN_IF", NT_STAUTS_RPC_UNKNOWN_IF },
+ { "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 },
--
1.7.9.5
From 131d5d789d5ed5550ee6060dd1cc805753a42395 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 25 Sep 2013 23:25:12 +0200
Subject: [PATCH 04/20] CVE-2013-4408:s3:rpc_client: verify frag_len at least
contains the header size
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source3/rpc_client/cli_pipe.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 0298f79..609f209 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -455,6 +455,12 @@ static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
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,
--
1.7.9.5
From b968b39f4d874b6b7fbc14bd833ebdc33a13ab76 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 24 Sep 2013 05:03:40 +0200
Subject: [PATCH 05/20] CVE-2013-4408:s4:rpc_server: check for invalid
frag_len within dcerpc_read_ncacn_packet_done()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/rpc_server/service_rpc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
index ea41689..ca3b3cb 100644
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -303,6 +303,11 @@ static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq)
return;
}
+ if (state->pkt->frag_length != state->buffer.length) {
+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+ return;
+ }
+
tevent_req_done(req);
}
--
1.7.9.5
From e86230c9175bb4eefbecf0d36dffaf15c8254ce8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 24 Sep 2013 05:03:40 +0200
Subject: [PATCH 06/20] CVE-2013-4408:s4:rpc_server: check for invalid
frag_len within
dcerpc_read_ncacn_packet_next_vector()
We should do this explicit instead of relying on
tstream_readv_pdu_ask_for_next_vector() to catch the overflow.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/rpc_server/service_rpc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
index ca3b3cb..1c9c76a 100644
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -232,6 +232,15 @@ static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
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);
--
1.7.9.5
From 0a9482c35325a2d3e3d915274b997dfb6812a4dd Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 25 Sep 2013 23:25:12 +0200
Subject: [PATCH 07/20] CVE-2013-4408:s4:dcerpc: check for invalid frag_len in
ncacn_pull()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/librpc/rpc/dcerpc.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 87d4438..277c7c6 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -213,6 +213,10 @@ static NTSTATUS ncacn_pull(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_
return ndr_map_error2ntstatus(ndr_err);
}
+ if (pkt->frag_length != blob->length) {
+ return NT_STATUS_RPC_PROTOCOL_ERROR;
+ }
+
return NT_STATUS_OK;
}
--
1.7.9.5
From 27ad9277415735c6ab3ec174e02826d85f8b8d91 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 25 Sep 2013 23:25:12 +0200
Subject: [PATCH 08/20] CVE-2013-4408:s4:dcerpc_smb: check for invalid
frag_len in send_read_request_continue()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/librpc/rpc/dcerpc_smb.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index f4e6b8c..909e7e4 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -159,6 +159,12 @@ static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLO
} 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) {
--
1.7.9.5
From 0c87e0818834f9b982ad824a8952803e1ddfdf09 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 25 Sep 2013 23:25:12 +0200
Subject: [PATCH 09/20] CVE-2013-4408:s4:dcerpc_smb2: check for invalid
frag_len in send_read_request_continue()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/librpc/rpc/dcerpc_smb2.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/source4/librpc/rpc/dcerpc_smb2.c b/source4/librpc/rpc/dcerpc_smb2.c
index fbd8476..d322a0b 100644
--- a/source4/librpc/rpc/dcerpc_smb2.c
+++ b/source4/librpc/rpc/dcerpc_smb2.c
@@ -169,6 +169,12 @@ static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLO
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;
--
1.7.9.5
From 6b8495ca22252af01fc0a90c67b5950210c50380 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 24 Sep 2013 05:03:40 +0200
Subject: [PATCH 10/20] CVE-2013-4408:s4:dcerpc_sock: check for invalid
frag_len within sock_complete_packet()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source4/librpc/rpc/dcerpc_sock.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c
index d8bd6d2..f70880f 100644
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -101,6 +101,12 @@ static NTSTATUS sock_complete_packet(void *private_data, DATA_BLOB blob, size_t
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;
}
--
1.7.9.5
From 1232bf297d6d618cf31b590900c707978571fd1e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Oct 2013 14:17:49 +0200
Subject: [PATCH 11/20] CVE-2013-4408:async_sock: add some overflow detection
to read_packet_handler()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
lib/async_req/async_sock.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 18adb42..ab7f884 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -594,6 +594,11 @@ static void read_packet_handler(struct tevent_context *ev,
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;
--
1.7.9.5
From 2abfeaeeff334bec2bcfe7db8af3d122847a985e Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Wed, 9 Oct 2013 11:16:08 -0700
Subject: [PATCH 12/20] CVE-2013-4408:s3:rpc_server: ensure frag_len is at
least as large as RPC_HEADER_LEN.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
source3/rpc_server/srv_pipe_hnd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 83f27fe..ca14886 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -1311,6 +1311,10 @@ static ssize_t rpc_frag_more_fn(uint8_t *buf, size_t buflen, void *priv)
return -1;
}
+ if (hdr.frag_len < RPC_HEADER_LEN) {
+ return -1;
+ }
+
return (hdr.frag_len - RPC_HEADER_LEN);
}
--
1.7.9.5
From 0c04a663f2683a5e8334400bc775fd81664dc07b Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Wed, 9 Oct 2013 11:20:53 -0700
Subject: [PATCH 13/20] CVE-2013-4408:s3:rpc_server: check a pipe with
PIPE_AUTH_TYPE_NONE does not receive auth_len.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
source3/rpc_server/srv_pipe_hnd.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index ca14886..54f4208 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -388,6 +388,11 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
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:
--
1.7.9.5
From db6ab8b22588b9c483fe9d0bf5f4d52f2c5273c1 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Wed, 16 Oct 2013 10:45:02 -0700
Subject: [PATCH 14/20] CVE-2013-4408:s3:rpc_server: for auth_level
DCERPC_AUTH_LEVEL_NONE or DCERPC_AUTH_LEVEL_CONNECT
auth_len must be zero.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
source3/rpc_server/srv_pipe.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 9c80fa2..893fa1b 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -2089,7 +2089,8 @@ bool api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in,
*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) {
--
1.7.9.5
From 0f8f75562aeba87c0d5bdca2c710f704dcabb586 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Wed, 9 Oct 2013 11:23:38 -0700
Subject: [PATCH 15/20] CVE-2013-4408:s3:rpc_server: integer wrap check on
data_len.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
source3/rpc_server/srv_pipe_hnd.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 54f4208..9c0546a 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -362,8 +362,7 @@ static void free_pipe_context(pipes_struct *p)
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"));
@@ -422,6 +421,16 @@ static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
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;
--
1.7.9.5
From 1cfcb587e27c807dd07644b0868f619cf223f5ca Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Oct 2013 14:17:49 +0200
Subject: [PATCH 16/20] CVE-2013-4408:s3:util_tsock: add some overflow
detection to tstream_read_packet_done()
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
source3/lib/util_tsock.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/source3/lib/util_tsock.c b/source3/lib/util_tsock.c
index 7588857..9b48f69 100644
--- a/source3/lib/util_tsock.c
+++ b/source3/lib/util_tsock.c
@@ -108,6 +108,11 @@ static void tstream_read_packet_done(struct tevent_req *subreq)
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;
--
1.7.9.5
From d756dae474213d37dac08fe0951872dd5a76b37d Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Thu, 24 Oct 2013 11:58:48 -0700
Subject: [PATCH 17/20] CVE-2013-4408:s3:Ensure we always check call_id when
validating an RPC reply.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
---
source3/rpc_client/cli_pipe.c | 56 +++++++++++++++++++++++++++++++++++------
1 file changed, 48 insertions(+), 8 deletions(-)
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 609f209..fe1b3fe 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -443,7 +443,8 @@ static NTSTATUS rpc_write_recv(struct tevent_req *req)
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
@@ -468,6 +469,14 @@ static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
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;
}
@@ -480,6 +489,7 @@ struct get_complete_frag_state {
struct event_context *ev;
struct rpc_pipe_client *cli;
struct rpc_hdr_info *prhdr;
+ uint32_t call_id;
prs_struct *pdu;
};
@@ -489,6 +499,7 @@ static void get_complete_frag_got_rest(struct tevent_req *subreq);
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)
{
@@ -505,6 +516,7 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->cli = cli;
state->prhdr = prhdr;
+ state->call_id = call_id;
state->pdu = pdu;
pdu_len = prs_data_size(pdu);
@@ -527,7 +539,7 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
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;
}
@@ -578,7 +590,8 @@ static void get_complete_frag_got_header(struct tevent_req *subreq)
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;
@@ -1321,6 +1334,7 @@ struct rpc_api_pipe_state {
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;
@@ -1343,7 +1357,8 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
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;
@@ -1357,6 +1372,7 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
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);
@@ -1440,6 +1456,7 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
/* 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;
@@ -1531,6 +1548,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
}
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;
@@ -2217,7 +2235,8 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
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;
}
@@ -2353,7 +2372,8 @@ static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
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;
}
@@ -2664,7 +2684,7 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
}
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;
}
@@ -2708,6 +2728,16 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
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"));
@@ -2932,7 +2962,8 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
}
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;
}
@@ -2968,6 +2999,15 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
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)) {
--
1.7.9.5
From d0b51b31ad37807a27fbbd42557f06673366ae10 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 19 Nov 2013 15:36:11 -0800
Subject: [PATCH 18/20] CVE-2013-4408:s3:Ensure LookupSids replies arrays are
range checked.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Jeremy Allison <jra@samba.org>
---
source3/rpc_client/cli_lsarpc.c | 13 +++++++++++++
source3/rpcclient/cmd_lsarpc.c | 9 +++++++--
source4/libcli/util/clilsa.c | 16 +++++++++++++++-
source4/winbind/wb_async_helpers.c | 13 ++++++++++++-
4 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index caa2583..5f89840 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -198,6 +198,11 @@ static NTSTATUS rpccli_lsa_lookup_sids_noalloc(struct rpc_pipe_client *cli,
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 @@ static NTSTATUS rpccli_lsa_lookup_sids_noalloc(struct rpc_pipe_client *cli,
/* 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;
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
index e0f4ac4..fea1096 100644
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -430,7 +430,7 @@ static NTSTATUS cmd_lsa_lookup_sids3(struct rpc_pipe_client *cli,
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 +472,16 @@ static NTSTATUS cmd_lsa_lookup_sids3(struct rpc_pipe_client *cli,
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);
diff --git a/source4/libcli/util/clilsa.c b/source4/libcli/util/clilsa.c
index 16967d7..a7d202d 100644
--- a/source4/libcli/util/clilsa.c
+++ b/source4/libcli/util/clilsa.c
@@ -241,7 +241,21 @@ NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
}
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",
diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c
index a50a0fe..266634c 100644
--- a/source4/winbind/wb_async_helpers.c
+++ b/source4/winbind/wb_async_helpers.c
@@ -122,6 +122,12 @@ static void lsa_lookupsids_recv_names(struct rpc_request *req)
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 @@ static void lsa_lookupsids_recv_names(struct rpc_request *req)
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;
}
--
1.7.9.5
From 26eb2dd21f9e08ab75fbf37bccb3477fc37eca7d Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 19 Nov 2013 16:34:52 -0800
Subject: [PATCH 19/20] CVE-2013-4408:s3:Ensure LookupNames replies arrays are
range checked.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Jeremy Allison <jra@samba.org>
---
source3/lib/netapi/group.c | 84 ++++++++++++++++++++++++++++++++++++
source3/lib/netapi/localgroup.c | 9 +++-
source3/lib/netapi/user.c | 56 ++++++++++++++++++++++++
source3/libnet/libnet_join.c | 16 +++++++
source3/rpc_client/cli_lsarpc.c | 18 ++++++++
source3/rpcclient/cmd_lsarpc.c | 6 ++-
source3/rpcclient/cmd_samr.c | 62 ++++++++++++++++++++++++++
source3/smbd/lanman.c | 8 ++++
source3/utils/net_rpc.c | 41 +++++++++++++++++-
source3/utils/net_rpc_join.c | 9 ++++
source4/libcli/util/clilsa.c | 6 ++-
source4/libnet/groupinfo.c | 10 +++--
source4/libnet/groupman.c | 10 ++---
source4/libnet/libnet_join.c | 12 +++++-
source4/libnet/libnet_lookup.c | 5 +++
source4/libnet/libnet_passwd.c | 10 ++++-
source4/libnet/userinfo.c | 9 +++-
source4/libnet/userman.c | 24 +++++------
source4/winbind/wb_async_helpers.c | 13 +++++-
19 files changed, 376 insertions(+), 32 deletions(-)
diff --git a/source3/lib/netapi/group.c b/source3/lib/netapi/group.c
index f5a7e77..c511ecd 100644
--- a/source3/lib/netapi/group.c
+++ b/source3/lib/netapi/group.c
@@ -273,6 +273,15 @@ WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
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;
@@ -437,6 +446,14 @@ WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
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 +689,14 @@ WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
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 +813,14 @@ WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
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 +849,14 @@ WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
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 +950,14 @@ WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
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 +986,14 @@ WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
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 +1376,15 @@ WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
SAMR_GROUP_ACCESS_GET_MEMBERS,
@@ -1471,6 +1537,15 @@ WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
SAMR_GROUP_ACCESS_GET_MEMBERS |
@@ -1533,6 +1608,15 @@ WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
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;
diff --git a/source3/lib/netapi/localgroup.c b/source3/lib/netapi/localgroup.c
index 03f9da5..6e83d5d 100644
--- a/source3/lib/netapi/localgroup.c
+++ b/source3/lib/netapi/localgroup.c
@@ -50,6 +50,13 @@ static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
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 @@ static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
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);
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
index c5f7b37..e15a8f8 100644
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -546,6 +546,14 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
@@ -1678,6 +1686,14 @@ WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
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,
@@ -1833,6 +1849,14 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
@@ -2852,6 +2876,14 @@ WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
@@ -3003,6 +3035,14 @@ WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
@@ -3053,6 +3093,14 @@ WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
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;
@@ -3297,6 +3345,14 @@ WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
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, talloc_tos(),
&domain_handle,
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 8522c17..c7dad56 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -948,6 +948,14 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
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",
@@ -1274,6 +1282,14 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
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,
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index 5f89840..90f97c7 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -516,9 +516,19 @@ static NTSTATUS rpccli_lsa_lookup_names_generic(struct rpc_pipe_client *cli,
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;
}
@@ -531,6 +541,14 @@ static NTSTATUS rpccli_lsa_lookup_names_generic(struct rpc_pipe_client *cli,
(*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);
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
index fea1096..7b8506c 100644
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -309,7 +309,7 @@ static NTSTATUS cmd_lsa_lookup_names4(struct rpc_pipe_client *cli,
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 @@ static NTSTATUS cmd_lsa_lookup_names4(struct rpc_pipe_client *cli,
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);
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index 3964b7d..9b42eef 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -360,6 +360,15 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
&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 @@ static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
&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 @@ static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
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++)
@@ -2039,6 +2066,15 @@ static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli,
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 +2157,15 @@ static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli,
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 +2481,15 @@ static NTSTATUS cmd_samr_chgpasswd(struct rpc_pipe_client *cli,
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 +2858,14 @@ static NTSTATUS cmd_samr_setuserinfo_int(struct rpc_pipe_client *cli,
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,
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 9b173d4..18ab1e3 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -2494,6 +2494,14 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
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,
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 749b0c2..6e155ea 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -1493,6 +1493,15 @@ static NTSTATUS rpc_group_delete_internals(struct net_context *c,
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 @@ static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
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 @@ static NTSTATUS rpc_del_groupmem(struct net_context *c,
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,
@@ -2695,9 +2720,15 @@ static NTSTATUS rpc_group_members_internals(struct net_context *c,
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,
domain_sid, &domain_pol,
@@ -5479,6 +5510,14 @@ static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
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,
diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c
index bb7d74b..2a4477c 100644
--- a/source3/utils/net_rpc_join.c
+++ b/source3/utils/net_rpc_join.c
@@ -322,6 +322,15 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
("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;
diff --git a/source4/libcli/util/clilsa.c b/source4/libcli/util/clilsa.c
index a7d202d..d4e02c0 100644
--- a/source4/libcli/util/clilsa.c
+++ b/source4/libcli/util/clilsa.c
@@ -312,7 +312,11 @@ NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
}
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;
diff --git a/source4/libnet/groupinfo.c b/source4/libnet/groupinfo.c
index 1779c28..6020350 100644
--- a/source4/libnet/groupinfo.c
+++ b/source4/libnet/groupinfo.c
@@ -87,12 +87,16 @@ static void continue_groupinfo_lookup(struct rpc_request *req)
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 */
diff --git a/source4/libnet/groupman.c b/source4/libnet/groupman.c
index 0f54db9..2bc318a 100644
--- a/source4/libnet/groupman.c
+++ b/source4/libnet/groupman.c
@@ -207,13 +207,13 @@ static void continue_groupdel_name_found(struct rpc_request *req)
/* 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;
}
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index fc7de10..d5d7ee0 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -643,9 +643,17 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
"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;
diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c
index 4548864..24642ba 100644
--- a/source4/libnet/libnet_lookup.c
+++ b/source4/libnet/libnet_lookup.c
@@ -354,6 +354,11 @@ static void continue_name_found(struct rpc_request *req)
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);
}
diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c
index e558c93..bd1110a 100644
--- a/source4/libnet/libnet_passwd.c
+++ b/source4/libnet/libnet_passwd.c
@@ -594,10 +594,18 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *
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;
diff --git a/source4/libnet/userinfo.c b/source4/libnet/userinfo.c
index a718ab9..283b126 100644
--- a/source4/libnet/userinfo.c
+++ b/source4/libnet/userinfo.c
@@ -90,8 +90,13 @@ static void continue_userinfo_lookup(struct rpc_request *req)
/* 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 */
diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c
index 62d4e0e..9e5a30d 100644
--- a/source4/libnet/userman.c
+++ b/source4/libnet/userman.c
@@ -233,14 +233,12 @@ static void continue_userdel_name_found(struct rpc_request *req)
/* 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 @@ static void continue_usermod_name_found(struct rpc_request *req)
/* 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;
}
diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c
index 266634c..433754b 100644
--- a/source4/winbind/wb_async_helpers.c
+++ b/source4/winbind/wb_async_helpers.c
@@ -282,6 +282,12 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req)
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;
@@ -300,9 +306,14 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req)
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;
}
--
1.7.9.5
From 1c392c7fe7794428a4f02c0e3405fb5194803336 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 19 Nov 2013 17:14:48 -0800
Subject: [PATCH 20/20] CVE-2013-4408:s3:Ensure LookupRids() replies arrays
are range checked.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
source3/lib/netapi/group.c | 16 ++++++++++++++++
source3/lib/netapi/user.c | 16 ++++++++++++++++
source3/rpcclient/cmd_samr.c | 8 ++++++++
source3/utils/net_rpc.c | 7 +++++++
source3/winbindd/winbindd_rpc.c | 8 +++++---
5 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/source3/lib/netapi/group.c b/source3/lib/netapi/group.c
index c511ecd..1081c86 100644
--- a/source3/lib/netapi/group.c
+++ b/source3/lib/netapi/group.c
@@ -339,6 +339,14 @@ WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
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++) {
@@ -1413,6 +1421,14 @@ WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
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++) {
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
index e15a8f8..39c6b66 100644
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -2924,6 +2924,14 @@ WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
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,
@@ -3449,6 +3457,14 @@ WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
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,
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index 9b42eef..368e845 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -2001,6 +2001,14 @@ static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
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",
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 6e155ea..517ee9c 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -2513,6 +2513,13 @@ static NTSTATUS rpc_list_group_members(struct net_context *c,
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 */
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index 59d3457..a379b0b 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -839,9 +839,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
/* 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++) {
--
1.7.9.5