From f38cf794fe16e5b160db1a3f4f17d5e5c7601d5c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Oct 2019 11:39:02 -0700 Subject: [PATCH 1/2] s3: libsmb: Ensure SMB1 cli_qpathinfo2() doesn't return an inode number. The info level it uses doesn't return that, previously we were using the field that is returned as the EA size as the inode number (which is usually zero, so the code in libsmbclient would then synthesize an inode number from a hash of the pathname, which is all it can do for SMB1). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14161 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit d495074ee27a5f528d5156a69800ee58d799b1eb) --- source3/libsmb/clirap.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index e80dfc92a77..b4b40ebdab4 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -855,7 +855,15 @@ NTSTATUS cli_qpathinfo2_recv(struct tevent_req *req, *size = IVAL2_TO_SMB_BIG_UINT(state->data,48); } if (ino) { - *ino = IVAL(state->data, 64); + /* + * SMB1 qpathinfo2 uses SMB_QUERY_FILE_ALL_INFO + * which doesn't return an inode number (fileid). + * We can't change this to one of the FILE_ID + * info levels as only Win2003 and above support + * these [MS-SMB: 2.2.2.3.1] and the SMB1 code + * needs to support older servers. + */ + *ino = 0; } return NT_STATUS_OK; } -- 2.23.0.866.gb869b98d4c-goog From 9c1abe9348c83a2ecd63563f2b47ddf22fd814be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Oct 2019 12:41:08 -0700 Subject: [PATCH 2/2] s3: torture: Ensure SMB1 cli_qpathinfo2() doesn't return an inode number. Piggyback on existing tests, ensure we don't regress on: BUG: https://bugzilla.samba.org/show_bug.cgi?id=14161 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit 8e55a8562951924e4b1aad5a6d67fc8b309590c1) --- source3/torture/torture.c | 49 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 66dc0cf4d1c..a795e61125f 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -4211,6 +4211,7 @@ static bool run_trans2test(int dummy) bool correct = True; NTSTATUS status; uint32_t fs_attr; + uint64_t ino; printf("starting trans2 test\n"); @@ -4218,6 +4219,14 @@ static bool run_trans2test(int dummy) return False; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* Ensure ino is zero, SMB2 gets a real one. */ + ino = 0; + } else { + /* Ensure ino is -1, SMB1 never gets a real one. */ + ino = (uint64_t)-1; + } + status = cli_get_fs_attr_info(cli, &fs_attr); if (!NT_STATUS_IS_OK(status)) { printf("ERROR: cli_get_fs_attr_info returned %s\n", @@ -4289,7 +4298,7 @@ static bool run_trans2test(int dummy) O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum); cli_close(cli, fnum); status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts, - &m_time_ts, &size, NULL, NULL); + &m_time_ts, &size, NULL, &ino); if (!NT_STATUS_IS_OK(status)) { printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status)); correct = False; @@ -4299,6 +4308,19 @@ static bool run_trans2test(int dummy) printf("This system appears to set a initial 0 write time\n"); correct = False; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* SMB2 should always return an inode. */ + if (ino == 0) { + printf("SMB2 bad inode (0)\n"); + correct = false; + } + } else { + /* SMB1 must always return zero here. */ + if (ino != 0) { + printf("SMB1 bad inode (!0)\n"); + correct = false; + } + } } cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); @@ -11593,11 +11615,20 @@ static bool run_dir_createtime(int dummy) struct timespec create_time1; uint16_t fnum; bool ret = false; + uint64_t ino; if (!torture_open_connection(&cli, 0)) { return false; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* Ensure ino is zero, SMB2 gets a real one. */ + ino = 0; + } else { + /* Ensure ino is -1, SMB1 never gets a real one. */ + ino = (uint64_t)-1; + } + cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); cli_rmdir(cli, dname); @@ -11608,13 +11639,27 @@ static bool run_dir_createtime(int dummy) } status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL, - NULL, NULL, NULL); + NULL, NULL, &ino); if (!NT_STATUS_IS_OK(status)) { printf("cli_qpathinfo2 returned %s\n", nt_errstr(status)); goto out; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* SMB2 should always return an inode. */ + if (ino == 0) { + printf("SMB2 bad inode (0)\n"); + goto out; + } + } else { + /* SMB1 must always return zero here. */ + if (ino != 0) { + printf("SMB1 bad inode (!0)\n"); + goto out; + } + } + /* Sleep 3 seconds, then create a file. */ sleep(3); -- 2.23.0.866.gb869b98d4c-goog