From f3b8e31f83c44f1e72b15711542d817af7ec9506 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Apr 2010 18:41:14 -0700 Subject: Split out the client unix capabilities to those the server offered, and those the client asked for. This fixes a bug when using encrypted transport and DFS links. Found by my basic DFS torture test, which I'll check in next. Testing *rocks* :-). Jeremy. --- source3/client/client.c | 2 +- source3/include/client.h | 5 ++++- source3/libsmb/clidfs.c | 4 ++-- source3/libsmb/clifsinfo.c | 18 +++++++++++++++--- source3/libsmb/clireadwrite.c | 4 ++-- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 7dc412fe3a..13617155c7 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -332,7 +332,7 @@ static int cmd_pwd(void) static void normalize_name(char *newdir) { - if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) { + if (!(cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) { string_replace(newdir,'/','\\'); } } diff --git a/source3/include/client.h b/source3/include/client.h index 457c02a18f..71232b35fa 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -248,7 +248,10 @@ struct cli_state { int win95; bool is_samba; uint32 capabilities; - uint32 posix_capabilities; + /* What the server offered. */ + uint32_t server_posix_capabilities; + /* What the client requested. */ + uint32_t requested_posix_capabilities; bool dfsroot; #if 0 diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index d5ae11ff8d..345d0f9212 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -320,7 +320,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, DLIST_ADD_END(referring_cli, cli, struct cli_state *); } - if (referring_cli && referring_cli->posix_capabilities) { + if (referring_cli && referring_cli->requested_posix_capabilities) { uint16 major, minor; uint32 caplow, caphigh; NTSTATUS status; @@ -564,7 +564,7 @@ static char *cli_dfs_make_full_path(TALLOC_CTX *ctx, dir++; } - if (cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) { path_sep = '/'; } return talloc_asprintf(ctx, "%c%s%c%s%c%s", diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 3297ec76ca..b8430a5870 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -27,6 +27,7 @@ ****************************************************************************/ struct cli_unix_extensions_version_state { + struct cli_state *cli; uint16_t setup[1]; uint8_t param[2]; uint16_t major, minor; @@ -47,6 +48,7 @@ struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + state->cli = cli; SSVAL(state->setup, 0, TRANSACT2_QFSINFO); SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO); @@ -104,6 +106,7 @@ NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req, *pminor = state->minor; *pcaplow = state->caplow; *pcaphigh = state->caphigh; + state->cli->server_posix_capabilities = *pcaplow; return NT_STATUS_OK; } @@ -143,9 +146,6 @@ NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow, pcaphigh); - if (NT_STATUS_IS_OK(status)) { - cli->posix_capabilities = *pcaplow; - } fail: TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(status)) { @@ -159,6 +159,7 @@ NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, ****************************************************************************/ struct cli_set_unix_extensions_capabilities_state { + struct cli_state *cli; uint16_t setup[1]; uint8_t param[4]; uint8_t data[12]; @@ -181,6 +182,7 @@ struct tevent_req *cli_set_unix_extensions_capabilities_send( return NULL; } + state->cli = cli; SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO); SSVAL(state->param, 0, 0); @@ -207,8 +209,16 @@ struct tevent_req *cli_set_unix_extensions_capabilities_send( static void cli_set_unix_extensions_capabilities_done( struct tevent_req *subreq) { + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_set_unix_extensions_capabilities_state *state = tevent_req_data( + req, struct cli_set_unix_extensions_capabilities_state); + NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, NULL); + if (NT_STATUS_IS_OK(status)) { + state->cli->requested_posix_capabilities = IVAL(state->data, 4); + } tevent_req_simple_finish_ntstatus(subreq, status); } @@ -245,6 +255,8 @@ fail: TALLOC_FREE(ev); if (!NT_STATUS_IS_OK(status)) { cli_set_error(cli, status); + } else { + cli->requested_posix_capabilities = caplow; } return status; } diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 7b688d4ff3..e9a9e0ed3d 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -25,7 +25,7 @@ static size_t cli_read_max_bufsize(struct cli_state *cli) { if (!client_is_signing_on(cli) && !cli_encryption_on(cli) - && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + && (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; } if (cli->capabilities & CAP_LARGE_READX) { @@ -44,7 +44,7 @@ static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode) if (write_mode == 0 && !client_is_signing_on(cli) && !cli_encryption_on(cli) && - (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && + (cli->server_posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && (cli->capabilities & CAP_LARGE_FILES)) { /* Only do massive writes if we can do them direct * with no signing or encrypting - not on a pipe. */ -- cgit