summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2019-08-05 13:39:53 -0700
committerKarolin Seeger <kseeger@samba.org>2019-10-24 11:45:18 +0200
commit13bc9d7365751f12eb2f752eefe95fb610c65f30 (patch)
treeb92e35cd83d93a118f27268c8ce0b2299f314886
parent844c353ca5d1193e338fb4e25cfb8cdbe467d21c (diff)
downloadsamba-13bc9d7365751f12eb2f752eefe95fb610c65f30.tar.gz
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>
-rw-r--r--source3/libsmb/clilist.c75
-rw-r--r--source3/libsmb/proto.h3
2 files changed, 78 insertions, 0 deletions
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
@@ -25,6 +25,66 @@
#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 b0cfcb5aa90..34349701104 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -723,6 +723,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);