From 7d7849b18a625820b1fba05bd17a718c7f98837e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Feb 2004 22:45:53 +0000 Subject: [PATCH] Make us bug-for-bug compatible with W2K3 - to get delete on close semantics on an initial open the desired_access field *must* contain DELETE_ACCESS, simply having it map from a GENERIC_ALL won't do. Fixes delete on close test. Jeremy. (This used to be commit 5c6f8b1053fd1f170fbb76640649653f8aa80f18) --- source3/libsmb/clirap.c | 11 ++++++++--- source3/smbd/nttrans.c | 25 +++++++++++++++++++------ source3/torture/torture.c | 26 +++++++++++++++++--------- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 36bc403e0b4..c4b08d21d81 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -631,7 +631,7 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, /**************************************************************************** send a qfileinfo call ****************************************************************************/ -BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char *outdata) +BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen) { unsigned int data_len = 0; unsigned int param_len = 0; @@ -639,9 +639,13 @@ BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char *outdat pstring param; char *rparam=NULL, *rdata=NULL; + *poutdata = NULL; + *poutlen = 0; + /* if its a win95 server then fail this - win95 totally screws it up */ - if (cli->win95) return False; + if (cli->win95) + return False; param_len = 4; @@ -665,7 +669,8 @@ BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char *outdat return False; } - memcpy(outdata, rdata, data_len); + memdup(poutdata, data_len); + *poutlen = data_len; SAFE_FREE(rdata); SAFE_FREE(rparam); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 92629faa9e2..3127134458f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -353,6 +353,7 @@ static int map_share_mode( char *fname, uint32 create_options, uint32 *desired_access, uint32 share_access, uint32 file_attributes) { int smb_open_mode = -1; + uint32 original_desired_access = *desired_access; /* * Convert GENERIC bits to specific bits. @@ -424,6 +425,10 @@ static int map_share_mode( char *fname, uint32 create_options, DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode)); } + if(*desired_access & DELETE_ACCESS) { + DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); + } + /* * We need to store the intent to open for Delete. This * is what determines if a delete on close flag can be set. @@ -431,11 +436,19 @@ static int map_share_mode( char *fname, uint32 create_options, * is the only practical way. JRA. */ - if(*desired_access & DELETE_ACCESS) { - DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode)); - } - if (create_options & FILE_DELETE_ON_CLOSE) { + /* + * W2K3 bug compatibility mode... To set delete on close + * the redirector must have *specifically* set DELETE_ACCESS + * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA. + */ + + if (!(original_desired_access & DELETE_ACCESS)) { + DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \ +DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n", + fname, (unsigned long)*desired_access)); + return -1; + } /* Implicit delete access is *NOT* requested... */ smb_open_mode |= DELETE_ON_CLOSE_FLAG; DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode)); @@ -738,7 +751,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib share_access, file_attributes)) == -1) { END_PROFILE(SMBntcreateX); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -1267,7 +1280,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if((smb_open_mode = map_share_mode( fname, create_options, &desired_access, share_access, file_attributes)) == -1) - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 2e6bc49d55a..d8bfe53dc3f 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -2493,19 +2493,19 @@ static BOOL run_trans2test(int dummy) static BOOL new_trans(struct cli_state *pcli, int fnum, int level) { - char buf[4096]; + char *buf = NULL; + uint32 len; BOOL correct = True; - memset(buf, 0xff, sizeof(buf)); - - if (!cli_qfileinfo_test(pcli, fnum, level, buf)) { + if (!cli_qfileinfo_test(pcli, fnum, level, &buf, &len)) { printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli)); correct = False; } else { - printf("qfileinfo: level %d\n", level); - dump_data(0, buf, 256); + printf("qfileinfo: level %d, len = %u\n", level, len); + dump_data(0, buf, len); printf("\n"); } + SAFE_FREE(buf); return correct; } @@ -2812,8 +2812,8 @@ static BOOL run_deletetest(int dummy) cli_setatr(cli1, fname, 0, 0); cli_unlink(cli1, fname); - fnum1 = cli_nt_create_full(cli1, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_DELETE, FILE_OVERWRITE_IF, + fnum1 = cli_nt_create_full(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL, + 0, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0); if (fnum1 == -1) { @@ -2821,7 +2821,15 @@ static BOOL run_deletetest(int dummy) correct = False; goto fail; } - + +#if 0 + { + uint32 accinfo = 0; + cli_qfileinfo_test(cli1, fnum1, SMB_FILE_ACCESS_INFORMATION, (char *)&accinfo); + printf("access mode = 0x%lx\n", accinfo); + } +#endif + if (!cli_close(cli1, fnum1)) { printf("[1] close failed (%s)\n", cli_errstr(cli1)); correct = False; -- 2.11.4.GIT