diff --git a/source3/client/client.c b/source3/client/client.c index f14e3f4130e..d8b939ab3bd 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3164,11 +3164,16 @@ static int cmd_posix(void) char *caps; NTSTATUS status; - if (!SERVER_HAS_UNIX_CIFS(cli)) { + if (!(SERVER_HAS_UNIX_CIFS(cli) || cli->smb2.server_smb311_posix)) { d_printf("Server doesn't support UNIX CIFS extensions.\n"); return 1; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB3_11) { + cli->smb2.client_smb311_posix = true; + return 0; + } + status = cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/include/client.h b/source3/include/client.h index 5ac9d649142..3644e40ca50 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -91,6 +91,8 @@ struct cli_state { struct smbXcli_session *session; struct smbXcli_tcon *tcon; struct idr_context *open_handles; + bool server_smb311_posix; + bool client_smb311_posix; } smb2; }; diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 1437844b427..7bc733492ce 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -28,6 +28,7 @@ #include "../libcli/smb/smbXcli_base.h" #include "auth/credentials/credentials.h" #include "lib/param/param.h" +#include "libcli/smb/smb2_negotiate_context.h" /******************************************************************** Important point. @@ -148,6 +149,8 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, cli_credentials_get_smb_signing(creds); enum smb_encryption_setting encryption_state = cli_credentials_get_smb_encryption(creds); + struct smb2_negotiate_contexts *in_contexts = NULL; + struct smb2_negotiate_contexts *out_contexts = NULL; if (encryption_state >= SMB_ENCRYPTION_DESIRED) { signing_state = SMB_SIGNING_REQUIRED; @@ -193,13 +196,29 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, DEBUG(4,(" session request ok\n")); + in_contexts = talloc_zero(ctx, struct smb2_negotiate_contexts); + if (in_contexts == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = smb2_negotiate_context_add( + in_contexts, + in_contexts, + SMB2_POSIX_EXTENSIONS_AVAILABLE, + (const uint8_t *)SMB2_CREATE_TAG_POSIX, + strlen(SMB2_CREATE_TAG_POSIX)); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = smbXcli_negprot(c->conn, c->timeout, lp_client_min_protocol(), lp_client_max_protocol(), - NULL, - NULL, - NULL); + in_contexts, + ctx, + &out_contexts); + TALLOC_FREE(in_contexts); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { d_printf("Protocol negotiation (with timeout %d ms) timed out against server %s\n", @@ -226,6 +245,12 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS); } + if ((protocol >= PROTOCOL_SMB3_11) && (out_contexts != NULL)) { + c->smb2.server_smb311_posix = smb2_negotiate_context_find( + out_contexts, + SMB2_POSIX_EXTENSIONS_AVAILABLE); + } + status = cli_session_setup_creds(c, creds); if (!NT_STATUS_IS_OK(status)) { /* If a password was not supplied then