This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
-#include "libcli/raw/libcliraw.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
#include "lib/cmdline/popt_common.h"
#include "lib/events/events.h"
#include "system/time.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "param/param.h"
/*
struct smb2_close c;
ZERO_STRUCT(c);
- c.in.handle = h;
+ c.in.file.handle = h;
return smb2_close(tree, &c);
}
NTCREATEX_SHARE_ACCESS_WRITE;
io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
io.in.fname = fname;
- io.in.blob = data_blob(NULL, 0);
status = smb2_create(tree, tree, &io);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
}
NT_STATUS_NOT_OK_RETURN(status);
- return smb2_util_close(tree, io.out.handle);
+ return smb2_util_close(tree, io.out.file.handle);
}
/*
struct smb2_write w;
ZERO_STRUCT(w);
+ w.in.file.handle = handle;
w.in.offset = offset;
- w.in.handle = handle;
w.in.data = data_blob_const(buf, size);
return smb2_write(tree, &w);
}
/*
- create a complex file using the SMB2 protocol
+ create a complex file/dir using the SMB2 protocol
*/
-NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, struct smb2_handle *handle)
+static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname,
+ struct smb2_handle *handle, BOOL dir)
{
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
char buf[7] = "abc";
struct smb2_create io;
union smb_setfileinfo setfile;
time_t t = (time(NULL) & ~1);
NTSTATUS status;
+ smb2_util_unlink(tree, fname);
ZERO_STRUCT(io);
- io.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ io.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
io.in.file_attr = FILE_ATTRIBUTE_NORMAL;
io.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
io.in.share_access =
NTCREATEX_SHARE_ACCESS_WRITE;
io.in.create_options = 0;
io.in.fname = fname;
- io.in.blob = data_blob(NULL, 0);
-
- status = smb2_create(tree, tree, &io);
- NT_STATUS_NOT_OK_RETURN(status);
+ if (dir) {
+ io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
+ io.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.open_disposition = NTCREATEX_DISP_CREATE;
+ }
- *handle = io.out.handle;
+ if (strchr(fname, ':') == NULL) {
+ /* setup some EAs */
+ io.in.eas.num_eas = 2;
+ io.in.eas.eas = talloc_array(tmp_ctx, struct ea_struct, 2);
+ io.in.eas.eas[0].flags = 0;
+ io.in.eas.eas[0].name.s = "EAONE";
+ io.in.eas.eas[0].value = data_blob_talloc(tmp_ctx, "VALUE1", 6);
+ io.in.eas.eas[1].flags = 0;
+ io.in.eas.eas[1].name.s = "SECONDEA";
+ io.in.eas.eas[1].value = data_blob_talloc(tmp_ctx, "ValueTwo", 8);
+ }
- status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
+ status = smb2_create(tree, tmp_ctx, &io);
+ talloc_free(tmp_ctx);
NT_STATUS_NOT_OK_RETURN(status);
-#if 0
- if (strchr(fname, ':') == NULL) {
- /* setup some EAs */
- setfile.generic.level = RAW_SFILEINFO_EA_SET;
- setfile.generic.file.fnum = fnum;
- setfile.ea_set.in.num_eas = 2;
- setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
- setfile.ea_set.in.eas[0].flags = 0;
- setfile.ea_set.in.eas[0].name.s = "EAONE";
- setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6);
- setfile.ea_set.in.eas[1].flags = 0;
- setfile.ea_set.in.eas[1].name.s = "SECONDEA";
- setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
- status = smb_raw_setfileinfo(cli->tree, &setfile);
- if (!NT_STATUS_IS_OK(status)) {
- printf("Failed to setup EAs\n");
- }
+ *handle = io.out.file.handle;
+
+ if (!dir) {
+ status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
+ NT_STATUS_NOT_OK_RETURN(status);
}
-#endif
/* make sure all the timestamps aren't the same, and are also
in different DST zones*/
setfile.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
- setfile.generic.file.handle = *handle;
+ setfile.generic.in.file.handle = *handle;
- setfile.basic_info.in.create_time = t + 9*30*24*60*60;
- setfile.basic_info.in.access_time = t + 6*30*24*60*60;
- setfile.basic_info.in.write_time = t + 3*30*24*60*60;
- setfile.basic_info.in.change_time = t + 1*30*24*60*60;
+ unix_to_nt_time(&setfile.basic_info.in.create_time, t + 9*30*24*60*60);
+ unix_to_nt_time(&setfile.basic_info.in.access_time, t + 6*30*24*60*60);
+ unix_to_nt_time(&setfile.basic_info.in.write_time, t + 3*30*24*60*60);
+ unix_to_nt_time(&setfile.basic_info.in.change_time, t + 1*30*24*60*60);
setfile.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
status = smb2_setinfo_file(tree, &setfile);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to setup file times - %s\n", nt_errstr(status));
+ return status;
}
/* make sure all the timestamps aren't the same */
- fileinfo.generic.level = RAW_FILEINFO_BASIC_INFORMATION;
- fileinfo.generic.in.handle = *handle;
+ fileinfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+ fileinfo.generic.in.file.handle = *handle;
status = smb2_getinfo_file(tree, tree, &fileinfo);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to query file times - %s\n", nt_errstr(status));
+ return status;
+
}
- if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) {
- printf("create_time not setup correctly\n");
- }
- if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) {
- printf("access_time not setup correctly\n");
- }
- if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) {
- printf("write_time not setup correctly\n");
- }
-
- return NT_STATUS_OK;
+#define CHECK_TIME(field) do {\
+ if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
+ printf("(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
+ __location__, \
+ nt_time_string(tree, setfile.basic_info.in.field), \
+ (unsigned long long)setfile.basic_info.in.field, \
+ nt_time_string(tree, fileinfo.basic_info.out.field), \
+ (unsigned long long)fileinfo.basic_info.out.field); \
+ status = NT_STATUS_INVALID_PARAMETER; \
+ } \
+} while (0)
+
+ CHECK_TIME(create_time);
+ CHECK_TIME(access_time);
+ CHECK_TIME(write_time);
+ CHECK_TIME(change_time);
+
+ return status;
+}
+
+/*
+ create a complex file using the SMB2 protocol
+*/
+NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname,
+ struct smb2_handle *handle)
+{
+ return smb2_create_complex(tree, fname, handle, False);
+}
+
+/*
+ create a complex dir using the SMB2 protocol
+*/
+NTSTATUS smb2_create_complex_dir(struct smb2_tree *tree, const char *fname,
+ struct smb2_handle *handle)
+{
+ return smb2_create_complex(tree, fname, handle, True);
}
/*
union smb_fileinfo io;
io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
- io.generic.in.handle = handle;
+ io.generic.in.file.handle = handle;
status = smb2_getinfo_file(tree, tmp_ctx, &io);
if (!NT_STATUS_IS_OK(status)) {
return;
}
+ d_printf("all_info for '%s'\n", io.all_info2.out.fname.s);
d_printf("\tcreate_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
d_printf("\taccess_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
d_printf("\twrite_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
d_printf("\tchange_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
d_printf("\tattrib: 0x%x\n", io.all_info2.out.attrib);
d_printf("\tunknown1: 0x%x\n", io.all_info2.out.unknown1);
- d_printf("\talloc_size: %llu\n", (uint64_t)io.all_info2.out.alloc_size);
- d_printf("\tsize: %llu\n", (uint64_t)io.all_info2.out.size);
+ d_printf("\talloc_size: %llu\n", (long long)io.all_info2.out.alloc_size);
+ d_printf("\tsize: %llu\n", (long long)io.all_info2.out.size);
d_printf("\tnlink: %u\n", io.all_info2.out.nlink);
d_printf("\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
d_printf("\tdirectory: %u\n", io.all_info2.out.directory);
- d_printf("\tfile_id: %llu\n", io.all_info2.out.file_id);
+ d_printf("\tfile_id: %llu\n", (long long)io.all_info2.out.file_id);
d_printf("\tea_size: %u\n", io.all_info2.out.ea_size);
d_printf("\taccess_mask: 0x%08x\n", io.all_info2.out.access_mask);
- d_printf("\tunknown2: 0x%llx\n", io.all_info2.out.unknown2);
- d_printf("\tunknown3: 0x%llx\n", io.all_info2.out.unknown3);
- d_printf("\tfname: '%s'\n", io.all_info2.out.fname.s);
+ d_printf("\tposition: 0x%llx\n", (long long)io.all_info2.out.position);
+ d_printf("\tmode: 0x%llx\n", (long long)io.all_info2.out.mode);
/* short name, if any */
io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
}
}
+ if (DEBUGLVL(1)) {
+ /* the security descriptor */
+ io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ io.query_secdesc.in.secinfo_flags =
+ SECINFO_OWNER|SECINFO_GROUP|
+ SECINFO_DACL;
+ status = smb2_getinfo_file(tree, tmp_ctx, &io);
+ if (NT_STATUS_IS_OK(status)) {
+ NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
+ }
+ }
+
talloc_free(tmp_ctx);
}
NTCREATEX_SHARE_ACCESS_DELETE|
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
- io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ io.in.create_options = 0;
io.in.fname = fname;
- io.in.blob = data_blob(NULL, 0);
status = smb2_create(tree, tree, &io);
NT_STATUS_NOT_OK_RETURN(status);
- *handle = io.out.handle;
+ *handle = io.out.file.handle;
ZERO_STRUCT(r);
+ r.in.file.handle = *handle;
r.in.length = 5;
r.in.offset = 0;
- r.in.handle = *handle;
smb2_read(tree, tree, &r);
io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
io.in.fname = fname;
- io.in.blob = data_blob(NULL, 0);
status = smb2_create(tree, tree, &io);
NT_STATUS_NOT_OK_RETURN(status);
- *handle = io.out.handle;
+ *handle = io.out.file.handle;
return NT_STATUS_OK;
}
create a complex file using the old SMB protocol, to make it easier to
find fields in SMB2 getinfo levels
*/
-BOOL torture_setup_complex_file(const char *fname)
+NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
{
- struct smbcli_state *cli;
- int fnum;
-
- if (!torture_open_connection(&cli)) {
- return False;
- }
+ struct smb2_handle handle;
+ NTSTATUS status = smb2_create_complex_file(tree, fname, &handle);
+ NT_STATUS_NOT_OK_RETURN(status);
+ return smb2_util_close(tree, handle);
+}
- fnum = create_complex_file(cli, cli, fname);
- if (DEBUGLVL(1)) {
- torture_all_info(cli->tree, fname);
- }
-
- talloc_free(cli);
- return fnum != -1;
+/*
+ create a complex dir using the old SMB protocol, to make it easier to
+ find fields in SMB2 getinfo levels
+*/
+NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
+{
+ struct smb2_handle handle;
+ NTSTATUS status = smb2_create_complex_dir(tree, fname, &handle);
+ NT_STATUS_NOT_OK_RETURN(status);
+ return smb2_util_close(tree, handle);
}
+
/*
- create a complex directory using the old SMB protocol, to make it easier to
- find fields in SMB2 getinfo levels
+ return a handle to the root of the share
*/
-BOOL torture_setup_complex_dir(const char *dname)
+NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
{
- struct smbcli_state *cli;
- int fnum;
+ struct smb2_create io;
+ NTSTATUS status;
- if (!torture_open_connection(&cli)) {
- return False;
- }
+ ZERO_STRUCT(io);
+ io.in.oplock_flags = 0;
+ io.in.access_mask = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
+ io.in.file_attr = 0;
+ io.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
+ io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
+ io.in.fname = "";
- fnum = create_complex_dir(cli, cli, dname);
+ status = smb2_create(tree, tree, &io);
+ NT_STATUS_NOT_OK_RETURN(status);
- if (DEBUGLVL(1)) {
- torture_all_info(cli->tree, dname);
- }
-
- talloc_free(cli);
- return fnum != -1;
+ *handle = io.out.file.handle;
+
+ return NT_STATUS_OK;
}