samba/0001-CVE-2019-10218.patch
2019-12-25 16:07:00 +08:00

134 lines
4.0 KiB
Diff

From fc6022b9b19473076c4236fdf4ac474f44ca73e2 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Mon, 5 Aug 2019 13:39:53 -0700
Subject: [PATCH 1/7] CVE-2019-10218 - s3: libsmb: Protect SMB1 client code
from evil server returned names.
Disconnect with NT_STATUS_INVALID_NETWORK_RESPONSE if so.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14071
Signed-off-by: Jeremy Allison <jra@samba.org>
---
source3/libsmb/clilist.c | 75 ++++++++++++++++++++++++++++++++++++++++
source3/libsmb/proto.h | 3 ++
2 files changed, 78 insertions(+)
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 5cb1fce4338..4f518339e2b 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -24,6 +24,66 @@
#include "trans2.h"
#include "../libcli/smb/smbXcli_base.h"
+/****************************************************************************
+ Check if a returned directory name is safe.
+****************************************************************************/
+
+static NTSTATUS is_bad_name(bool windows_names, const char *name)
+{
+ const char *bad_name_p = NULL;
+
+ bad_name_p = strchr(name, '/');
+ if (bad_name_p != NULL) {
+ /*
+ * Windows and POSIX names can't have '/'.
+ * Server is attacking us.
+ */
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ if (windows_names) {
+ bad_name_p = strchr(name, '\\');
+ if (bad_name_p != NULL) {
+ /*
+ * Windows names can't have '\\'.
+ * Server is attacking us.
+ */
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Check if a returned directory name is safe. Disconnect if server is
+ sending bad names.
+****************************************************************************/
+
+NTSTATUS is_bad_finfo_name(const struct cli_state *cli,
+ const struct file_info *finfo)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ bool windows_names = true;
+
+ if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ windows_names = false;
+ }
+ if (finfo->name != NULL) {
+ status = is_bad_name(windows_names, finfo->name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_ERR("bad finfo->name\n");
+ return status;
+ }
+ }
+ if (finfo->short_name != NULL) {
+ status = is_bad_name(windows_names, finfo->short_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_ERR("bad finfo->short_name\n");
+ return status;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Calculate a safe next_entry_offset.
****************************************************************************/
@@ -492,6 +552,13 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
TALLOC_FREE(finfo);
return NT_STATUS_NO_MEMORY;
}
+
+ status = is_bad_finfo_name(state->cli, finfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbXcli_conn_disconnect(state->cli->conn, status);
+ TALLOC_FREE(finfo);
+ return status;
+ }
}
*pfinfo = finfo;
return NT_STATUS_OK;
@@ -727,6 +794,14 @@ static void cli_list_trans_done(struct tevent_req *subreq)
ff_eos = true;
break;
}
+
+ status = is_bad_finfo_name(state->cli, finfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbXcli_conn_disconnect(state->cli->conn, status);
+ tevent_req_nterror(req, status);
+ return;
+ }
+
if (!state->first && (state->mask[0] != '\0') &&
strcsequal(finfo->name, state->mask)) {
DEBUG(1, ("Error: Looping in FIND_NEXT as name %s has "
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 2bd61b1d2c2..e708e911b97 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -722,6 +722,9 @@ NTSTATUS cli_posix_whoami(struct cli_state *cli,
/* The following definitions come from libsmb/clilist.c */
+NTSTATUS is_bad_finfo_name(const struct cli_state *cli,
+ const struct file_info *finfo);
+
NTSTATUS cli_list_old(struct cli_state *cli,const char *Mask,uint16_t attribute,
NTSTATUS (*fn)(const char *, struct file_info *,
const char *, void *), void *state);
--
2.17.1