summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/librpc/idl/xattr.idl1
-rw-r--r--source4/ntvfs/ntvfs_generic.c49
-rw-r--r--source4/ntvfs/posix/pvfs_open.c37
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c8
-rw-r--r--source4/smb_server/reply.c2
-rw-r--r--source4/smb_server/trans2.c61
-rw-r--r--source4/torture/raw/open.c76
7 files changed, 176 insertions, 58 deletions
diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl
index c2487b705c..0fc965c825 100644
--- a/source4/librpc/idl/xattr.idl
+++ b/source4/librpc/idl/xattr.idl
@@ -37,7 +37,6 @@ interface xattr
/* we store DOS style extended attributes in a DosEAs xattr */
const string XATTR_DOSEAS_NAME = "user.DosEAs";
- const string XATTR_DOSEAS_ESTIMATED_SIZE = 100;
typedef struct {
utf8string name;
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c
index ed41b3d4d2..370463c41d 100644
--- a/source4/ntvfs/ntvfs_generic.c
+++ b/source4/ntvfs/ntvfs_generic.c
@@ -149,6 +149,13 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
union smb_setfileinfo *sf;
uint_t state;
+ /* this is really strange, but matches w2k3 */
+ if (io->generic.level == RAW_OPEN_T2OPEN &&
+ io->t2open.in.open_func != OPENX_OPEN_FUNC_OPEN &&
+ NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -159,7 +166,7 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
io->openold.out.attrib = io2->generic.out.attrib;
io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
io->openold.out.size = io2->generic.out.size;
- io->openold.out.rmode = DOS_OPEN_RDWR;
+ io->openold.out.rmode = io->openold.in.flags;
break;
case RAW_OPEN_OPENX:
@@ -181,6 +188,18 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
}
break;
+ case RAW_OPEN_T2OPEN:
+ io->t2open.out.fnum = io2->openx.out.fnum;
+ io->t2open.out.attrib = io2->openx.out.attrib;
+ io->t2open.out.write_time = 0;
+ io->t2open.out.size = io2->openx.out.size;
+ io->t2open.out.access = io->t2open.in.open_mode;
+ io->t2open.out.ftype = io2->openx.out.ftype;
+ io->t2open.out.devstate = io2->openx.out.devstate;
+ io->t2open.out.action = io2->openx.out.action;
+ io->t2open.out.unknown = 0;
+ break;
+
case RAW_OPEN_MKNEW:
case RAW_OPEN_CREATE:
io->mknew.out.fnum = io2->generic.out.fnum;
@@ -191,7 +210,6 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
io->ctemp.out.fnum = io2->generic.out.fnum;
io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname +
strlen(io->ctemp.in.directory) + 1);
- write_time = io->ctemp.in.write_time;
break;
default:
@@ -217,7 +235,7 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req,
sf = talloc_p(req, union smb_setfileinfo);
sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
sf->generic.file.fnum = io2->generic.out.fnum;
- sf->end_of_file_info.in.size = io->openx.in.size;
+ sf->end_of_file_info.in.size = set_size;
status = ntvfs->ops->setfileinfo(ntvfs, req, sf);
if (NT_STATUS_IS_OK(status)) {
io->openx.out.size = io->openx.in.size;
@@ -262,17 +280,17 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) {
case OPENX_MODE_ACCESS_READ:
- io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
+ io2->generic.in.access_mask = STANDARD_RIGHTS_READ_ACCESS;
io->openx.out.access = OPENX_MODE_ACCESS_READ;
break;
case OPENX_MODE_ACCESS_WRITE:
- io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
+ io2->generic.in.access_mask = STANDARD_RIGHTS_WRITE_ACCESS;
io->openx.out.access = OPENX_MODE_ACCESS_WRITE;
break;
case OPENX_MODE_ACCESS_RDWR:
case OPENX_MODE_ACCESS_FCB:
case OPENX_MODE_ACCESS_EXEC:
- io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE;
+ io2->generic.in.access_mask = STANDARD_RIGHTS_ALL_ACCESS;
io->openx.out.access = OPENX_MODE_ACCESS_RDWR;
break;
default:
@@ -402,8 +420,10 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE |
NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE;
break;
- case 0x70: /* FCB mode */
- io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ case OPEN_FLAGS_DENY_MASK:
+ io2->generic.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
break;
default:
DEBUG(2,("ntvfs_map_open(OPEN): invalid DENY 0x%x\n",
@@ -415,6 +435,19 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
status = ntvfs->ops->openfile(ntvfs, req, io2);
break;
+ case RAW_OPEN_T2OPEN:
+ io2->generic.level = RAW_OPEN_OPENX;
+ io2->openx.in.flags = io->t2open.in.flags;
+ io2->openx.in.open_mode = io->t2open.in.open_mode;
+ io2->openx.in.search_attrs = 0;
+ io2->openx.in.file_attrs = io->t2open.in.file_attrs;
+ io2->openx.in.write_time = io->t2open.in.write_time;
+ io2->openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
+ io2->openx.in.size = io->t2open.in.size;
+ io2->openx.in.timeout = io->t2open.in.timeout;
+ io2->openx.in.fname = io->t2open.in.fname;
+ status = ntvfs->ops->openfile(ntvfs, req, io2);
+ break;
case RAW_OPEN_MKNEW:
io2->generic.in.file_attr = io->mknew.in.attrib;
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 2430f9becb..6f1fb1c87f 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -539,6 +539,39 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
}
/*
+ special handling for t2open
+*/
+static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs,
+ struct smbsrv_request *req, union smb_open *io)
+{
+ struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_filename *name;
+ NTSTATUS status;
+
+ status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname,
+ PVFS_RESOLVE_NO_WILDCARD, &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (io->t2open.in.open_func & OPENX_OPEN_FUNC_CREATE) {
+ if (!name->exists) return NT_STATUS_ACCESS_DENIED;
+ }
+ if (io->t2open.in.open_func & OPENX_OPEN_FUNC_TRUNC) {
+ if (name->exists) return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ if ((io->t2open.in.open_func & 0xF) == OPENX_OPEN_FUNC_FAIL) {
+ if (!name->exists) return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ talloc_free(name);
+
+ return ntvfs_map_open(req, io, ntvfs);
+}
+
+/*
open a file
*/
NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
@@ -555,6 +588,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
uint32_t share_access;
uint32_t access_mask;
+ if (io->generic.level == RAW_OPEN_T2OPEN) {
+ return pvfs_open_t2open(ntvfs, req, io);
+ }
+
/* use the generic mapping code to avoid implementing all the
different open calls. This won't allow openx to work
perfectly as the mapping code has no way of knowing if two
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index e570743aba..22997be94d 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -188,10 +188,16 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
/* possibly change the file size */
if (newstats.st.st_size != f->name->st.st_size) {
+ int ret;
if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- if (ftruncate(f->fd, newstats.st.st_size) == -1) {
+ if (f->access_mask & SA_RIGHT_FILE_WRITE_APPEND) {
+ ret = ftruncate(f->fd, newstats.st.st_size);
+ } else {
+ ret = truncate(f->name->full_name, newstats.st.st_size);
+ }
+ if (ret == -1) {
return pvfs_map_errno(pvfs, errno);
}
}
diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c
index b0e5e8a8d8..9b3675aeac 100644
--- a/source4/smb_server/reply.c
+++ b/source4/smb_server/reply.c
@@ -596,7 +596,7 @@ static void reply_ctemp_send(struct smbsrv_request *req)
SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
/* the returned filename is relative to the directory */
- req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE);
+ req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
req_send_reply(req);
}
diff --git a/source4/smb_server/trans2.c b/source4/smb_server/trans2.c
index 02a7cbff01..9e0a5934d9 100644
--- a/source4/smb_server/trans2.c
+++ b/source4/smb_server/trans2.c
@@ -403,6 +403,65 @@ static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *tr
return NT_STATUS_INVALID_LEVEL;
}
+
+/*
+ trans2 open implementation
+*/
+static NTSTATUS trans2_open(struct smbsrv_request *req, struct smb_trans2 *trans)
+{
+ union smb_open *io;
+ NTSTATUS status;
+
+ /* make sure we got enough parameters */
+ if (trans->in.params.length < 29) {
+ return NT_STATUS_FOOBAR;
+ }
+
+ io = talloc_p(req, union smb_open);
+ if (io == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ io->t2open.level = RAW_OPEN_T2OPEN;
+ io->t2open.in.flags = SVAL(trans->in.params.data, VWV(0));
+ io->t2open.in.open_mode = SVAL(trans->in.params.data, VWV(1));
+ io->t2open.in.file_attrs = SVAL(trans->in.params.data, VWV(3));
+ io->t2open.in.write_time = srv_pull_dos_date(req->smb_conn,
+ trans->in.params.data + VWV(4));;
+ io->t2open.in.open_func = SVAL(trans->in.params.data, VWV(6));
+ io->t2open.in.size = IVAL(trans->in.params.data, VWV(7));
+ io->t2open.in.timeout = IVAL(trans->in.params.data, VWV(9));
+ io->t2open.in.num_eas = 0;
+ io->t2open.in.eas = NULL;
+
+ trans2_pull_blob_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
+
+ status = ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = ntvfs_openfile(req, io);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ trans2_setup_reply(req, trans, 30, 0, 0);
+
+ SSVAL(trans->out.params.data, VWV(0), io->t2open.out.fnum);
+ SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
+ srv_push_dos_date3(req->smb_conn, trans->out.params.data,
+ VWV(2), io->t2open.out.write_time);
+ SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);
+ SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);
+ SIVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);
+ SIVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);
+ SIVAL(trans->out.params.data, VWV(9), io->t2open.out.action);
+ SIVAL(trans->out.params.data, VWV(10), io->t2open.out.unknown);
+
+ return status;
+}
+
/*
fill in the reply from a qpathinfo or qfileinfo call
*/
@@ -1240,6 +1299,8 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *tr
return trans2_setpathinfo(req, trans);
case TRANSACT2_QFSINFO:
return trans2_qfsinfo(req, trans);
+ case TRANSACT2_OPEN:
+ return trans2_open(req, trans);
}
/* an unknown trans2 command */
diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c
index c810984900..e299bba254 100644
--- a/source4/torture/raw/open.c
+++ b/source4/torture/raw/open.c
@@ -126,7 +126,7 @@ static const char *rdwr_string(enum rdwr_mode m)
#define CHECK_VAL(v, correct) do { \
if ((v) != (correct)) { \
- printf("(%s) wrong value for %s 0x%x - 0x%x\n", \
+ printf("(%s) wrong value for %s 0x%x - should be 0x%x\n", \
__location__, #v, (int)(v), (int)correct); \
ret = False; \
}} while (0)
@@ -331,14 +331,14 @@ static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
fnum = io.openx.out.fnum;
CHECK_ALL_INFO(io.openx.out.size, size);
- CHECK_VAL(io.openx.out.size, 1024*1024);
- CHECK_ALL_INFO(io.openx.in.size, size);
CHECK_TIME(io.openx.out.write_time, write_time);
CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
CHECK_VAL(io.openx.out.ftype, 0);
CHECK_VAL(io.openx.out.devstate, 0);
CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
+ CHECK_VAL(io.openx.out.size, 1024*1024);
+ CHECK_ALL_INFO(io.openx.in.size, size);
smbcli_close(cli->tree, fnum);
smbcli_unlink(cli->tree, fname);
@@ -452,7 +452,9 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
union smb_open io;
union smb_fileinfo finfo;
- const char *fname = BASEDIR "\\torture_t2open.txt";
+ const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
+ const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
+ const char *fname = BASEDIR "\\torture_t2open_3.txt";
NTSTATUS status;
int fnum;
BOOL ret = True;
@@ -476,10 +478,17 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
};
+ fnum = create_complex_file(cli, mem_ctx, fname1);
+ if (fnum == -1) {
+ d_printf("Failed to create file %s - %s\n", fname1, smbcli_errstr(cli->tree));
+ ret = False;
+ goto done;
+ }
+ smbcli_close(cli->tree, fnum);
+
printf("Checking RAW_OPEN_T2OPEN\n");
io.t2open.level = RAW_OPEN_T2OPEN;
- io.t2open.in.fname = fname;
io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO |
OPENX_FLAGS_EA_LEN | OPENX_FLAGS_EXTENDED_RETURN;
io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
@@ -498,13 +507,9 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* check all combinations of open_func */
for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
if (open_funcs[i].with_file) {
- fnum = create_complex_file(cli, mem_ctx, fname);
- 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.t2open.in.fname = fname1;
+ } else {
+ io.t2open.in.fname = fname2;
}
io.t2open.in.open_func = open_funcs[i].open_func;
status = smb_raw_open(cli->tree, mem_ctx, &io);
@@ -514,16 +519,18 @@ static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
ret = False;
}
- if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
+ if (NT_STATUS_IS_OK(status)) {
smbcli_close(cli->tree, io.t2open.out.fnum);
- smbcli_unlink(cli->tree, fname);
}
}
+ smbcli_unlink(cli->tree, fname1);
+
/* check the basic return fields */
fnum = create_complex_file(cli, mem_ctx, fname);
smbcli_close(cli->tree, fnum);
io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
+ io.t2open.in.fname = fname;
status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.t2open.out.fnum;
@@ -963,8 +970,6 @@ static BOOL test_ctemp(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
fname = finfo.name_info.out.fname.s;
d_printf("ctemp name=%s real name=%s\n", name, fname);
- CHECK_TIME(basetime, write_time);
-
done:
smbcli_close(cli->tree, fnum);
if (fname) {
@@ -997,37 +1002,14 @@ BOOL torture_raw_open(void)
return False;
}
- if (!test_ntcreatex_brlocked(cli, mem_ctx)) {
- return False;
- }
-
- if (!test_open(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_openx(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_ntcreatex(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_t2open(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_mknew(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_create(cli, mem_ctx)) {
- ret = False;
- }
-
- if (!test_ctemp(cli, mem_ctx)) {
- ret = False;
- }
+ ret &= test_ntcreatex_brlocked(cli, mem_ctx);
+ ret &= test_open(cli, mem_ctx);
+ ret &= test_openx(cli, mem_ctx);
+ ret &= test_ntcreatex(cli, mem_ctx);
+ ret &= test_t2open(cli, mem_ctx);
+ ret &= test_mknew(cli, mem_ctx);
+ ret &= test_create(cli, mem_ctx);
+ ret &= test_ctemp(cli, mem_ctx);
smb_raw_exit(cli->session);
smbcli_deltree(cli->tree, BASEDIR);