diff options
-rw-r--r-- | source4/libcli/raw/rawfile.c | 133 | ||||
-rw-r--r-- | source4/torture/raw/open.c | 176 |
2 files changed, 309 insertions, 0 deletions
diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c index 4da7ff3a9e..5fc40bc45a 100644 --- a/source4/libcli/raw/rawfile.c +++ b/source4/libcli/raw/rawfile.c @@ -22,6 +22,7 @@ #include "includes.h" #include "libcli/raw/libcliraw.h" +#include "librpc/gen_ndr/ndr_security.h" #define SETUP_REQUEST(cmd, wct, buflen) do { \ req = smbcli_request_setup(tree, cmd, wct, buflen); \ @@ -213,6 +214,132 @@ NTSTATUS smb_raw_rmdir(struct smbcli_tree *tree, } +/* + Open a file using TRANSACT2_OPEN - async recv +*/ +static NTSTATUS smb_raw_nttrans_create_recv(struct smbcli_request *req, + TALLOC_CTX *mem_ctx, + union smb_open *parms) +{ + NTSTATUS status; + struct smb_nttrans nt; + uint8_t *params; + + status = smb_raw_nttrans_recv(req, mem_ctx, &nt); + if (!NT_STATUS_IS_OK(status)) return status; + + if (nt.out.params.length < 69) { + return NT_STATUS_INVALID_PARAMETER; + } + + params = nt.out.params.data; + + parms->ntcreatex.out.oplock_level = CVAL(params, 0); + parms->ntcreatex.out.fnum = SVAL(params, 2); + parms->ntcreatex.out.create_action = IVAL(params, 4); + parms->ntcreatex.out.create_time = smbcli_pull_nttime(params, 12); + parms->ntcreatex.out.access_time = smbcli_pull_nttime(params, 20); + parms->ntcreatex.out.write_time = smbcli_pull_nttime(params, 28); + parms->ntcreatex.out.change_time = smbcli_pull_nttime(params, 36); + parms->ntcreatex.out.attrib = IVAL(params, 44); + parms->ntcreatex.out.alloc_size = BVAL(params, 48); + parms->ntcreatex.out.size = BVAL(params, 56); + parms->ntcreatex.out.file_type = SVAL(params, 64); + parms->ntcreatex.out.ipc_state = SVAL(params, 66); + parms->ntcreatex.out.is_directory = CVAL(params, 68); + + return NT_STATUS_OK; +} + + +/* + Open a file using NTTRANS CREATE - async send +*/ +static struct smbcli_request *smb_raw_nttrans_create_send(struct smbcli_tree *tree, + union smb_open *parms) +{ + struct smb_nttrans nt; + uint8_t *params; + TALLOC_CTX *mem_ctx = talloc(tree, 0); + uint16_t fname_len; + DATA_BLOB sd_blob, ea_blob; + struct smbcli_request *req; + NTSTATUS status; + + nt.in.max_setup = 0; + nt.in.max_param = 101; + nt.in.max_data = 0; + nt.in.setup_count = 0; + nt.in.function = NT_TRANSACT_CREATE; + nt.in.setup = NULL; + + sd_blob = data_blob(NULL, 0); + ea_blob = data_blob(NULL, 0); + + if (parms->ntcreatex.in.sec_desc) { + status = ndr_push_struct_blob(&sd_blob, mem_ctx, + parms->ntcreatex.in.sec_desc, + (ndr_push_flags_fn_t)ndr_push_security_descriptor); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); + return NULL; + } + } + + if (parms->ntcreatex.in.ea_list) { + uint32_t ea_size = ea_list_size(parms->ntcreatex.in.ea_list->num_eas, + parms->ntcreatex.in.ea_list->eas); + ea_blob = data_blob_talloc(mem_ctx, NULL, ea_size); + if (ea_blob.data == NULL) { + return NULL; + } + ea_put_list(ea_blob.data, + parms->ntcreatex.in.ea_list->num_eas, + parms->ntcreatex.in.ea_list->eas); + } + + nt.in.params = data_blob_talloc(mem_ctx, NULL, 54); + if (nt.in.params.data == NULL) { + talloc_free(mem_ctx); + return NULL; + } + + /* build the parameter section */ + params = nt.in.params.data; + + SIVAL(params, 0, parms->ntcreatex.in.flags); + SIVAL(params, 4, parms->ntcreatex.in.root_fid); + SIVAL(params, 8, parms->ntcreatex.in.access_mask); + SBVAL(params, 12, parms->ntcreatex.in.alloc_size); + SIVAL(params, 20, parms->ntcreatex.in.file_attr); + SIVAL(params, 24, parms->ntcreatex.in.share_access); + SIVAL(params, 28, parms->ntcreatex.in.open_disposition); + SIVAL(params, 32, parms->ntcreatex.in.create_options); + SIVAL(params, 36, sd_blob.length); + SIVAL(params, 40, ea_blob.length); + SIVAL(params, 48, parms->ntcreatex.in.impersonation); + SCVAL(params, 52, parms->ntcreatex.in.security_flags); + SCVAL(params, 53, 0); + + fname_len = smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params, + parms->ntcreatex.in.fname, STR_TERMINATE); + + SIVAL(nt.in.params.data, 44, fname_len); + + /* build the data section */ + nt.in.data = data_blob_talloc(mem_ctx, NULL, sd_blob.length + ea_blob.length); + memcpy(nt.in.data.data, sd_blob.data, sd_blob.length); + memcpy(nt.in.data.data+sd_blob.length, ea_blob.data, ea_blob.length); + + /* send the request on its way */ + req = smb_raw_nttrans_send(tree, &nt); + + talloc_free(mem_ctx); + + return req; +} + + /**************************************************************************** Open a file using TRANSACT2_OPEN - async send ****************************************************************************/ @@ -377,6 +504,9 @@ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_ope smbcli_req_append_string_len(req, parms->ntcreatex.in.fname, STR_TERMINATE, &len); SSVAL(req->out.vwv, 5, len); break; + + case RAW_OPEN_NTTRANS_CREATE: + return smb_raw_nttrans_create_send(tree, parms); } if (!smbcli_request_send(req)) { @@ -469,6 +599,9 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio parms->ntcreatex.out.ipc_state = SVAL(req->in.vwv, 65); parms->ntcreatex.out.is_directory = CVAL(req->in.vwv, 67); break; + + case RAW_OPEN_NTTRANS_CREATE: + return smb_raw_nttrans_create_recv(req, mem_ctx, parms); } failed: diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c index b80f6278c6..f938c82cfb 100644 --- a/source4/torture/raw/open.c +++ b/source4/torture/raw/open.c @@ -752,6 +752,181 @@ done: return ret; } + +/* + test RAW_OPEN_NTTRANS_CREATE +*/ +static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + union smb_open io; + union smb_fileinfo finfo; + const char *fname = BASEDIR "\\torture_ntcreatex.txt"; + const char *dname = BASEDIR "\\torture_ntcreatex.dir"; + NTSTATUS status; + int fnum = -1; + BOOL ret = True; + int i; + struct { + uint32_t open_disp; + BOOL with_file; + NTSTATUS correct_status; + } open_funcs[] = { + { NTCREATEX_DISP_SUPERSEDE, True, NT_STATUS_OK }, + { NTCREATEX_DISP_SUPERSEDE, False, NT_STATUS_OK }, + { NTCREATEX_DISP_OPEN, True, NT_STATUS_OK }, + { NTCREATEX_DISP_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND }, + { NTCREATEX_DISP_CREATE, True, NT_STATUS_OBJECT_NAME_COLLISION }, + { NTCREATEX_DISP_CREATE, False, NT_STATUS_OK }, + { NTCREATEX_DISP_OPEN_IF, True, NT_STATUS_OK }, + { NTCREATEX_DISP_OPEN_IF, False, NT_STATUS_OK }, + { NTCREATEX_DISP_OVERWRITE, True, NT_STATUS_OK }, + { NTCREATEX_DISP_OVERWRITE, False, NT_STATUS_OBJECT_NAME_NOT_FOUND }, + { NTCREATEX_DISP_OVERWRITE_IF, True, NT_STATUS_OK }, + { NTCREATEX_DISP_OVERWRITE_IF, False, NT_STATUS_OK }, + { 6, True, NT_STATUS_INVALID_PARAMETER }, + { 6, False, NT_STATUS_INVALID_PARAMETER }, + }; + + printf("Checking RAW_OPEN_NTTRANS_CREATE\n"); + + /* reasonable default parameters */ + io.generic.level = RAW_OPEN_NTTRANS_CREATE; + io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS; + io.ntcreatex.in.alloc_size = 1024*1024; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = fname; + io.ntcreatex.in.sec_desc = NULL; + io.ntcreatex.in.ea_list = NULL; + + /* test the open disposition */ + for (i=0; i<ARRAY_SIZE(open_funcs); i++) { + if (open_funcs[i].with_file) { + fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE); + if (fnum == -1) { + d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + smbcli_close(cli->tree, fnum); + } + io.ntcreatex.in.open_disposition = open_funcs[i].open_disp; + status = smb_raw_open(cli->tree, mem_ctx, &io); + if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) { + printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", + __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status), + i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp); + ret = False; + } + if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) { + smbcli_close(cli->tree, io.ntcreatex.out.fnum); + smbcli_unlink(cli->tree, fname); + } + } + + /* basic field testing */ + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = io.ntcreatex.out.fnum; + + CHECK_VAL(io.ntcreatex.out.oplock_level, 0); + CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED); + CHECK_NTTIME(io.ntcreatex.out.create_time, create_time); + CHECK_NTTIME(io.ntcreatex.out.access_time, access_time); + CHECK_NTTIME(io.ntcreatex.out.write_time, write_time); + CHECK_NTTIME(io.ntcreatex.out.change_time, change_time); + CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib); + CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size); + CHECK_ALL_INFO(io.ntcreatex.out.size, size); + CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory); + CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK); + + /* check fields when the file already existed */ + smbcli_close(cli->tree, fnum); + smbcli_unlink(cli->tree, fname); + fnum = create_complex_file(cli, mem_ctx, fname); + if (fnum == -1) { + ret = False; + goto done; + } + smbcli_close(cli->tree, fnum); + + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = io.ntcreatex.out.fnum; + + CHECK_VAL(io.ntcreatex.out.oplock_level, 0); + CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED); + CHECK_NTTIME(io.ntcreatex.out.create_time, create_time); + CHECK_NTTIME(io.ntcreatex.out.access_time, access_time); + CHECK_NTTIME(io.ntcreatex.out.write_time, write_time); + CHECK_NTTIME(io.ntcreatex.out.change_time, change_time); + CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib); + CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size); + CHECK_ALL_INFO(io.ntcreatex.out.size, size); + CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory); + CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK); + smbcli_close(cli->tree, fnum); + smbcli_unlink(cli->tree, fname); + + + /* create a directory */ + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.fname = dname; + fname = dname; + + smbcli_rmdir(cli->tree, fname); + smbcli_unlink(cli->tree, fname); + + io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED; + io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = io.ntcreatex.out.fnum; + + CHECK_VAL(io.ntcreatex.out.oplock_level, 0); + CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED); + CHECK_NTTIME(io.ntcreatex.out.create_time, create_time); + CHECK_NTTIME(io.ntcreatex.out.access_time, access_time); + CHECK_NTTIME(io.ntcreatex.out.write_time, write_time); + CHECK_NTTIME(io.ntcreatex.out.change_time, change_time); + CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib); + CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, + FILE_ATTRIBUTE_DIRECTORY); + CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size); + CHECK_ALL_INFO(io.ntcreatex.out.size, size); + CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory); + CHECK_VAL(io.ntcreatex.out.is_directory, 1); + CHECK_VAL(io.ntcreatex.out.size, 0); + CHECK_VAL(io.ntcreatex.out.alloc_size, 0); + CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK); + smbcli_unlink(cli->tree, fname); + + +done: + smbcli_close(cli->tree, fnum); + smbcli_unlink(cli->tree, fname); + + return ret; +} + /* test RAW_OPEN_NTCREATEX with an already opened and byte range locked file @@ -1001,6 +1176,7 @@ BOOL torture_raw_open(void) ret &= test_open(cli, mem_ctx); ret &= test_openx(cli, mem_ctx); ret &= test_ntcreatex(cli, mem_ctx); + ret &= test_nttrans_create(cli, mem_ctx); ret &= test_t2open(cli, mem_ctx); ret &= test_mknew(cli, mem_ctx); ret &= test_create(cli, mem_ctx); |