From 884d175d24f5b0dad420ae0d900c80b75e602e21 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 10:50:39 +0200 Subject: [PATCH 01/10] s3:libsmb: pass creation or birth time in cli_qpathinfo_basic() --- source3/libsmb/clirap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index d6d2fae..e01e139 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -1265,6 +1265,7 @@ NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req, return status; } + sbuf->st_ex_btime = interpret_long_date((char *)state->data); sbuf->st_ex_atime = interpret_long_date((char *)state->data+8); sbuf->st_ex_mtime = interpret_long_date((char *)state->data+16); sbuf->st_ex_ctime = interpret_long_date((char *)state->data+24); -- 1.7.9.5 From c5a663e760cbafbc912c654150a9b0f5bf1b3d08 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 10:52:21 +0200 Subject: [PATCH 02/10] s3:libsmb: add function cli_qpathinfo_standard() --- source3/libsmb/clirap.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ source3/libsmb/clirap.h | 4 ++++ 2 files changed, 56 insertions(+) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index e01e139..b18cb07 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -1363,3 +1363,55 @@ NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstrin return NT_STATUS_OK; } + +/**************************************************************************** + Send a qpathinfo SMB_QUERY_FILE_STADNDARD_INFO call. +****************************************************************************/ + +NTSTATUS cli_qpathinfo_standard(struct cli_state *cli, const char *fname, + uint64_t *allocated, uint64_t *size, + uint32_t *nlinks, + bool *is_del_pending, bool *is_dir) +{ + uint8_t *rdata; + uint32_t num_rdata; + NTSTATUS status; + + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return NT_STATUS_NOT_IMPLEMENTED; + /* return cli_smb2_qpathinfo_standard(cli, fname, */ + /* allocation, size, nlinks, */ + /* del_pending, is_dir); */ + } + + status = cli_qpathinfo(talloc_tos(), cli, fname, + SMB_QUERY_FILE_STANDARD_INFO, + 24, CLI_BUFFER_SIZE, &rdata, &num_rdata); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (allocated) { + *allocated = BVAL(rdata, 0); + } + + if (size) { + *size = BVAL(rdata, 8); + } + + if (nlinks) { + *nlinks = IVAL(rdata, 16); + } + + if (is_del_pending) { + *is_del_pending = CVAL(rdata, 20); + } + + if (is_dir) { + *is_dir = CVAL(rdata, 20); + } + + TALLOC_FREE(rdata); + + return NT_STATUS_OK; +} diff --git a/source3/libsmb/clirap.h b/source3/libsmb/clirap.h index e105182..4326420 100644 --- a/source3/libsmb/clirap.h +++ b/source3/libsmb/clirap.h @@ -115,6 +115,10 @@ NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req, SMB_STRUCT_STAT *sbuf, uint32 *attributes); NTSTATUS cli_qpathinfo_basic(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf, uint32 *attributes); +NTSTATUS cli_qpathinfo_standard(struct cli_state *cli, const char *fname, + uint64_t *allocated, uint64_t *size, + uint32_t *nlinks, + bool *is_del_pending, bool *is_dir); NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name); struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, -- 1.7.9.5 From d55e945ea1bc2e9ddd9609c1e153477c84d2faec Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 10:53:45 +0200 Subject: [PATCH 03/10] s3:libsmb: add function cli_qpathinfo3() This is a reimplemantation of cli_qpathinfo2 without the use of info level SMB_QFILEINFO_ALL_INFO which leads to brocken packages from NetApp. --- source3/libsmb/clirap.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ source3/libsmb/clirap.h | 7 +++++++ 2 files changed, 59 insertions(+) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index b18cb07..eee3ab8 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -1415,3 +1415,55 @@ NTSTATUS cli_qpathinfo_standard(struct cli_state *cli, const char *fname, return NT_STATUS_OK; } + + +/* like cli_qpathinfo2 but do not use SMB_QUERY_FILE_ALL_INFO */ +NTSTATUS cli_qpathinfo3(struct cli_state *cli, const char *fname, + struct timespec *create_time, + struct timespec *access_time, + struct timespec *write_time, + struct timespec *change_time, + off_t *size, uint16 *mode, + SMB_INO_T *ino) +{ + NTSTATUS status = NT_STATUS_OK; + SMB_STRUCT_STAT st; + uint32_t attr; + uint64_t pos; + + if (create_time || access_time || write_time || change_time || mode) { + status = cli_qpathinfo_basic(cli, fname, &st, &attr); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + if (size) { + status = cli_qpathinfo_standard(cli, fname, + NULL, &pos, NULL, NULL, NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + if (create_time) { + *create_time = st.st_ex_btime; + } + if (access_time) { + *access_time = st.st_ex_atime; + } + if (write_time) { + *write_time = st.st_ex_mtime; + } + if (change_time) { + *change_time = st.st_ex_ctime; + } + if (mode) { + *mode = attr; + } + if (ino) { + *ino = 0; + } + + return NT_STATUS_OK; +} diff --git a/source3/libsmb/clirap.h b/source3/libsmb/clirap.h index 4326420..54f06b4 100644 --- a/source3/libsmb/clirap.h +++ b/source3/libsmb/clirap.h @@ -82,6 +82,13 @@ NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname, struct timespec *change_time, off_t *size, uint16 *mode, SMB_INO_T *ino); +NTSTATUS cli_qpathinfo3(struct cli_state *cli, const char *fname, + struct timespec *create_time, + struct timespec *access_time, + struct timespec *write_time, + struct timespec *change_time, + off_t *size, uint16 *mode, + SMB_INO_T *ino); struct tevent_req *cli_qpathinfo_streams_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, -- 1.7.9.5 From 53b93738e5010dd36fd64c5f348b2238447abffd Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 10:59:59 +0200 Subject: [PATCH 04/10] s3:libsmb: SMBC_getatr try pathinfo2 only once --- source3/libsmb/libsmb_file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 32210b6..b4d9f8e 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -558,6 +558,8 @@ SMBC_getatr(SMBCCTX * context, return True; } + srv->no_pathinfo2 = True; + /* if this is NT then don't bother with the getatr */ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) { errno = EPERM; @@ -581,7 +583,6 @@ SMBC_getatr(SMBCCTX * context, if (change_time_ts != NULL) { *change_time_ts = w_time_ts; } - srv->no_pathinfo2 = True; TALLOC_FREE(frame); return True; } -- 1.7.9.5 From 01a5438915db7416d44eee27cfefa457dfef2a79 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 11:00:48 +0200 Subject: [PATCH 05/10] s3:libsmb: SMBC_getatr do not let ino undefined on success --- source3/libsmb/libsmb_file.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index b4d9f8e..09f5810 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -583,6 +583,9 @@ SMBC_getatr(SMBCCTX * context, if (change_time_ts != NULL) { *change_time_ts = w_time_ts; } + if (ino) { + *ino = 0; + } TALLOC_FREE(frame); return True; } -- 1.7.9.5 From 7bf18a1082b5d93389f534268f98f5a69d9a2cf0 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 11:02:24 +0200 Subject: [PATCH 06/10] s3:libsmb: SMBC_getatr use pathinfo3 for second try The pathinfo2 call might fail against NetApp because it is sending broken packages. --- source3/include/libsmb_internal.h | 1 + source3/libsmb/libsmb_file.c | 13 +++++++++++++ source3/libsmb/libsmb_server.c | 1 + 3 files changed, 15 insertions(+) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 63c96fec..ce73181 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -78,6 +78,7 @@ struct _SMBCSRV { dev_t dev; bool no_pathinfo; bool no_pathinfo2; + bool no_pathinfo3; bool no_nt_session; struct policy_handle pol; diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 09f5810..277ca83 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -560,6 +560,19 @@ SMBC_getatr(SMBCCTX * context, srv->no_pathinfo2 = True; + if (!srv->no_pathinfo3 && + NT_STATUS_IS_OK(cli_qpathinfo3(targetcli, targetpath, + create_time_ts, + access_time_ts, + write_time_ts, + change_time_ts, + size, mode, ino))) { + TALLOC_FREE(frame); + return True; + } + + srv->no_pathinfo3 = True; + /* if this is NT then don't bother with the getatr */ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) { errno = EPERM; diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 9d87f42..2f3ea96 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -606,6 +606,7 @@ SMBC_server_internal(TALLOC_CTX *ctx, srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = False; + srv->no_pathinfo3 = False; srv->no_nt_session = False; done: -- 1.7.9.5 From acd7b0493a03dda36781ba8d899ce1a3131de380 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 11 Oct 2013 11:05:06 +0200 Subject: [PATCH 07/10] client: remove a write only variable --- source3/client/client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index c3a557e..6e1c870 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1695,7 +1695,6 @@ static int do_allinfo(const char *name) struct timespec b_time, a_time, m_time, c_time; off_t size; uint16_t mode; - SMB_INO_T ino; NTTIME tmp; uint16_t fnum; unsigned int num_streams; @@ -1723,7 +1722,7 @@ static int do_allinfo(const char *name) d_printf("altname: %s\n", altname); status = cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time, - &size, &mode, &ino); + &size, &mode, NULL); if (!NT_STATUS_IS_OK(status)) { d_printf("%s getting pathinfo for %s\n", nt_errstr(status), name); -- 1.7.9.5 From 878d95bd0695669fc30f9a93ea29f7e2e677cc49 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 14 Oct 2013 11:43:45 +0200 Subject: [PATCH 08/10] s3:libsmb: cli_qpathinfo3 use cli_qpathinfo2 for smb2 cli_qpathinfo3 only works (and is only needed as fallback so far) for smb1. Use cli_qpathinfo2 in the smb2 case to make it universally usable. --- source3/libsmb/clirap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index eee3ab8..2e3df92 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -1417,7 +1417,7 @@ NTSTATUS cli_qpathinfo_standard(struct cli_state *cli, const char *fname, } -/* like cli_qpathinfo2 but do not use SMB_QUERY_FILE_ALL_INFO */ +/* like cli_qpathinfo2 but do not use SMB_QUERY_FILE_ALL_INFO with smb1 */ NTSTATUS cli_qpathinfo3(struct cli_state *cli, const char *fname, struct timespec *create_time, struct timespec *access_time, @@ -1431,6 +1431,12 @@ NTSTATUS cli_qpathinfo3(struct cli_state *cli, const char *fname, uint32_t attr; uint64_t pos; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + return cli_qpathinfo2(cli, fname, + create_time, access_time, write_time, change_time, + size, mode, ino); + } + if (create_time || access_time || write_time || change_time || mode) { status = cli_qpathinfo_basic(cli, fname, &st, &attr); if (!NT_STATUS_IS_OK(status)) { -- 1.7.9.5 From 92f58ca3f7f124d8c4f5db169a0074d94e9e7934 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 14 Oct 2013 11:44:36 +0200 Subject: [PATCH 09/10] client: use cli_qpathinfo3 for allinfo --- source3/client/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 6e1c870..2ed47c4 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1721,7 +1721,7 @@ static int do_allinfo(const char *name) } d_printf("altname: %s\n", altname); - status = cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time, + status = cli_qpathinfo3(cli, name, &b_time, &a_time, &m_time, &c_time, &size, &mode, NULL); if (!NT_STATUS_IS_OK(status)) { d_printf("%s getting pathinfo for %s\n", nt_errstr(status), @@ -1799,7 +1799,7 @@ static int do_allinfo(const char *name) d_printf("%s\n", snapshots[i]); snap_name = talloc_asprintf(talloc_tos(), "%s%s", snapshots[i], name); - status = cli_qpathinfo2(cli, snap_name, &b_time, &a_time, + status = cli_qpathinfo3(cli, snap_name, &b_time, &a_time, &m_time, &c_time, &size, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { -- 1.7.9.5 From c9ecbf202fa0a98a0428d4f61421c2a7e4a9fd86 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Fri, 18 Oct 2013 15:32:55 +0200 Subject: [PATCH 10/10] s3:libsmb: SMBC_getatr() if no method worked, try all methods again on next attempt --- source3/libsmb/libsmb_file.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 277ca83..8fb7a2e 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -575,9 +575,7 @@ SMBC_getatr(SMBCCTX * context, /* if this is NT then don't bother with the getatr */ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) { - errno = EPERM; - TALLOC_FREE(frame); - return False; + goto all_failed; } if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) { @@ -603,6 +601,10 @@ SMBC_getatr(SMBCCTX * context, return True; } +all_failed: + srv->no_pathinfo2 = False; + srv->no_pathinfo3 = False; + errno = EPERM; TALLOC_FREE(frame); return False; -- 1.7.9.5