diff options
-rw-r--r-- | lib/tevent/tevent.h | 4 | ||||
-rw-r--r-- | source3/include/vfs_macros.h | 2 | ||||
-rw-r--r-- | source3/modules/vfs_full_audit.c | 35 | ||||
-rw-r--r-- | source3/modules/vfs_streams_depot.c | 30 | ||||
-rw-r--r-- | source3/modules/vfs_streams_xattr.c | 11 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 14 | ||||
-rw-r--r-- | source3/smbd/reply.c | 25 | ||||
-rw-r--r-- | source3/smbd/service.c | 4 | ||||
-rw-r--r-- | source4/lib/ldb/pyldb.c | 2 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision.py | 4 | ||||
-rw-r--r-- | source4/setup/schema-map-openldap-2.3 | 5 | ||||
-rw-r--r-- | source4/setup/schema_samba4.ldif | 2 | ||||
-rw-r--r-- | source4/torture/raw/streams.c | 201 |
13 files changed, 286 insertions, 53 deletions
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index b57d96f5fb..98d31aa7c4 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -82,7 +82,7 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, const char *location); #define tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) \ _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ - #handler, __location__); + #handler, __location__) struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, TALLOC_CTX *mem_ctx, @@ -106,7 +106,7 @@ struct tevent_aio *_tevent_add_aio(struct tevent_context *ev, const char *location); #define tevent_add_aio(ev, mem_ctx, iocb, handler, private_data) \ _tevent_add_aio(ev, mem_ctx, iocb, handler, private_data, \ - #handler, __location__); + #handler, __location__) int tevent_loop_once(struct tevent_context *ev); int tevent_loop_wait(struct tevent_context *ev); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index b008d86b3c..c6ccd4912a 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -340,7 +340,7 @@ #define SMB_VFS_NEXT_CHFLAGS(handle, path, flags) ((handle)->vfs_next.ops.chflags((handle)->vfs_next.handles.chflags, (path), (flags))) #define SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (dev), (inode))) #define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs_next.ops.streaminfo((handle)->vfs_next.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams))) -#define SMB_VFS_NEXT_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs_next.ops.get_real_filename((conn)->vfs_next.handles.get_real_filename, (path), (name), (mem_ctx), (found_name))) +#define SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx, found_name) ((handle)->vfs_next.ops.get_real_filename((handle)->vfs_next.handles.get_real_filename, (path), (name), (mem_ctx), (found_name))) /* NT ACL operations. */ #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (security_info), (ppdesc))) diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 7970bf2644..1d9983a753 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -211,6 +211,11 @@ static NTSTATUS smb_full_audit_streaminfo(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, unsigned int *pnum_streams, struct stream_struct **pstreams); +static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle, + const char *path, + const char *name, + TALLOC_CTX *mem_ctx, + char **found_name); static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc); @@ -444,6 +449,8 @@ static vfs_op_tuple audit_op_tuples[] = { SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_streaminfo), SMB_VFS_OP_STREAMINFO, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(smb_full_audit_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME, + SMB_VFS_LAYER_LOGGER}, /* NT ACL operations. */ @@ -576,6 +583,7 @@ static struct { { SMB_VFS_OP_RMDIR, "rmdir" }, { SMB_VFS_OP_CLOSEDIR, "closedir" }, { SMB_VFS_OP_OPEN, "open" }, + { SMB_VFS_OP_CREATE_FILE, "create_file" }, { SMB_VFS_OP_CLOSE, "close" }, { SMB_VFS_OP_READ, "read" }, { SMB_VFS_OP_PREAD, "pread" }, @@ -612,6 +620,7 @@ static struct { { SMB_VFS_OP_CHFLAGS, "chflags" }, { SMB_VFS_OP_FILE_ID_CREATE, "file_id_create" }, { SMB_VFS_OP_STREAMINFO, "streaminfo" }, + { SMB_VFS_OP_GET_REAL_FILENAME, "get_real_filename" }, { SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" }, { SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" }, { SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" }, @@ -712,6 +721,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle) static char *audit_prefix(TALLOC_CTX *ctx, connection_struct *conn) { char *prefix = NULL; + char *result; prefix = talloc_strdup(ctx, lp_parm_const_string(SNUM(conn), "full_audit", @@ -719,7 +729,7 @@ static char *audit_prefix(TALLOC_CTX *ctx, connection_struct *conn) if (!prefix) { return NULL; } - return talloc_sub_advanced(ctx, + result = talloc_sub_advanced(ctx, lp_servicename(SNUM(conn)), conn->server_info->unix_name, conn->connectpath, @@ -727,6 +737,8 @@ static char *audit_prefix(TALLOC_CTX *ctx, connection_struct *conn) conn->server_info->sanitized_username, pdb_get_domain(conn->server_info->sam_account), prefix); + TALLOC_FREE(prefix); + return result; } static bool log_success(vfs_handle_struct *handle, vfs_op_type op) @@ -840,14 +852,14 @@ static void do_log(vfs_op_type op, bool success, vfs_handle_struct *handle, fstr_sprintf(err_msg, "fail (%s)", strerror(errno)); va_start(ap, format); - op_msg = talloc_vasprintf(NULL, format, ap); + op_msg = talloc_vasprintf(talloc_tos(), format, ap); va_end(ap); if (!op_msg) { return; } - audit_pre = audit_prefix(NULL, handle->conn); + audit_pre = audit_prefix(talloc_tos(), handle->conn); syslog(audit_syslog_priority(handle), "%s|%s|%s|%s\n", audit_pre ? audit_pre : "", audit_opname(op), err_msg, op_msg); @@ -1615,6 +1627,23 @@ static NTSTATUS smb_full_audit_streaminfo(vfs_handle_struct *handle, return result; } +static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle, + const char *path, + const char *name, + TALLOC_CTX *mem_ctx, + char **found_name) +{ + int result; + + result = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx, + found_name); + + do_log(SMB_VFS_OP_GET_REAL_FILENAME, (result == 0), handle, + "%s/%s->%s", path, name, (result == 0) ? "" : *found_name); + + return result; +} + static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 69d34940fd..54c17db1ce 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -525,6 +525,7 @@ static int streams_depot_rename(vfs_handle_struct *handle, char *nsname = NULL; char *ostream_fname = NULL; char *nstream_fname = NULL; + char *newname_full = NULL; DEBUG(10, ("streams_depot_rename called for %s => %s\n", oldname, newname)); @@ -536,11 +537,6 @@ static int streams_depot_rename(vfs_handle_struct *handle, return SMB_VFS_NEXT_RENAME(handle, oldname, newname); } - if (!(old_is_stream && new_is_stream)) { - errno = ENOSYS; - return -1; - } - frame = talloc_stackframe(); if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), oldname, @@ -549,7 +545,7 @@ static int streams_depot_rename(vfs_handle_struct *handle, goto done; } - if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), oldname, + if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), newname, &nbase, &nsname))) { errno = ENOMEM; goto done; @@ -561,17 +557,27 @@ static int streams_depot_rename(vfs_handle_struct *handle, goto done; } - if (StrCaseCmp(obase, nbase) != 0) { - errno = ENOSYS; - goto done; - } - ostream_fname = stream_name(handle, oldname, false); if (ostream_fname == NULL) { return -1; } - nstream_fname = stream_name(handle, newname, false); + /* + * Handle passing in a stream name without the base file. This is + * exercised by the NTRENAME streams rename path. + */ + if (StrCaseCmp(nbase, "./") == 0) { + newname_full = talloc_asprintf(talloc_tos(), "%s:%s", obase, + nsname); + if (newname_full == NULL) { + errno = ENOMEM; + goto done; + } + } + + nstream_fname = stream_name(handle, + newname_full ? newname_full : newname, + false); if (nstream_fname == NULL) { return -1; } diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index ecfc31970d..7124c57520 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -511,11 +511,6 @@ static int streams_xattr_rename(vfs_handle_struct *handle, return SMB_VFS_NEXT_RENAME(handle, oldname, newname); } - if (!(o_is_stream && n_is_stream)) { - errno = ENOSYS; - goto fail; - } - frame = talloc_stackframe(); if (!frame) { goto fail; @@ -544,12 +539,6 @@ static int streams_xattr_rename(vfs_handle_struct *handle, goto fail; } - /* the new base should be empty */ - if (StrCaseCmp(obase, nbase) != 0) { - errno = ENOSYS; - goto fail; - } - if (StrCaseCmp(ostream, nstream) == 0) { goto done; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b17aec80fa..3f33237f18 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1310,13 +1310,6 @@ void reply_ntrename(struct smb_request *req) return; } - if( is_ntfs_stream_name(oldname)) { - /* Can't rename a stream. */ - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - END_PROFILE(SMBntrename); - return; - } - if (ms_has_wild(oldname)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); END_PROFILE(SMBntrename); @@ -1364,6 +1357,13 @@ void reply_ntrename(struct smb_request *req) return; } + /* The new name must begin with a ':' if the old name is a stream. */ + if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBntrename); + return; + } + DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); switch(rename_type) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2133a30dc6..593558e399 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5439,7 +5439,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, SMB_STRUCT_STAT sbuf, sbuf1; NTSTATUS status = NT_STATUS_OK; struct share_mode_lock *lck = NULL; - bool dst_exists; + bool dst_exists, old_is_stream, new_is_stream; ZERO_STRUCT(sbuf); @@ -5508,6 +5508,18 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return NT_STATUS_OK; } + old_is_stream = is_ntfs_stream_name(fsp->fsp_name); + new_is_stream = is_ntfs_stream_name(newname); + + /* Return the correct error code if both names aren't streams. */ + if (!old_is_stream && new_is_stream) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + + if (old_is_stream && !new_is_stream) { + return NT_STATUS_INVALID_PARAMETER; + } + /* * Have vfs_object_exist also fill sbuf1 */ @@ -5519,18 +5531,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return NT_STATUS_OBJECT_NAME_COLLISION; } - if(replace_if_exists && dst_exists) { - /* Ensure both or neither are stream names. */ - if (is_ntfs_stream_name(fsp->fsp_name) != - is_ntfs_stream_name(newname)) { - return NT_STATUS_INVALID_PARAMETER; - } - } - if (dst_exists) { struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1); files_struct *dst_fsp = file_find_di_first(fileid); - if (dst_fsp) { + /* The file can be open when renaming a stream */ + if (dst_fsp && !new_is_stream) { DEBUG(3, ("rename_internals_fsp: Target file open\n")); return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0dea615fb5..e90098fed0 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -235,6 +235,10 @@ static int load_registry_service(const char *servicename) return -1; } + if ((servicename == NULL) || (*servicename == '\0')) { + return -1; + } + if (strequal(servicename, GLOBAL_NAME)) { return -2; } diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c index 10b9691ae0..0dda9aa05b 100644 --- a/source4/lib/ldb/pyldb.c +++ b/source4/lib/ldb/pyldb.c @@ -538,7 +538,7 @@ static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs) { char *url; - int flags; + int flags = 0; PyObject *py_options = Py_None; int ret; const char **options; diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 150e5c00df..763140b486 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -1255,12 +1255,12 @@ def provision_backend(setup_dir=None, message=None, elif ldap_backend_type == "openldap": attrs = ["linkID", "lDAPDisplayName"] - res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs) + res = schemadb.search(expression="(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1))(objectclass=attributeSchema)(omSyntax=127))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs) memberof_config = "# Generated from schema in %s\n" % schemadb_path refint_attributes = "" for i in range (0, len(res)): - expression = "(&(objectclass=attributeSchema)(linkID=%d))" % (int(res[i]["linkID"][0])+1) + expression = "(&(objectclass=attributeSchema)(linkID=%d)(omSyntax=127))" % (int(res[i]["linkID"][0])+1) target = schemadb.searchone(basedn=names.schemadn, expression=expression, attribute="lDAPDisplayName", diff --git a/source4/setup/schema-map-openldap-2.3 b/source4/setup/schema-map-openldap-2.3 index 233f9a9613..0d38652dae 100644 --- a/source4/setup/schema-map-openldap-2.3 +++ b/source4/setup/schema-map-openldap-2.3 @@ -11,7 +11,6 @@ distinguishedName description cn top -entryTTL uidNumber gidNumber #The memberOf plugin provides this attribute @@ -30,6 +29,10 @@ name:samba4RDN #Remap these so that we don't put operational attributes in a schema MAY modifyTimeStamp:samba4ModifyTimestamp 2.5.18.2:1.3.6.1.4.1.7165.4.255.3 +dynamicObject:samba4DynaimcObject +1.3.6.1.4.1.1466.101.119.2:1.3.6.1.4.1.7165.4.255.8 +entryTTL:samba4EntryTTL +1.3.6.1.4.1.1466.101.119.3:1.3.6.1.4.1.7165.4.255.9 #MiddleName has a conflicting OID 2.16.840.1.113730.3.1.34:1.3.6.1.4.1.7165.4.255.1 #defaultGroup has a conflicting OID diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index d42795b94d..47010da637 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -189,6 +189,8 @@ oMSyntax: 20 #Allocated: (objectClasses) samba4ObjectClasses: 1.3.6.1.4.1.7165.4.255.5 #Allocated: (ditContentRules) samba4DitContentRules: 1.3.6.1.4.1.7165.4.255.6 #Allocated: (attributeTypes) samba4AttributeTypes: 1.3.6.1.4.1.7165.4.255.7 +#Allocated: (dynamicObject) samba4DynamicObject: 1.3.6.1.4.1.7165.4.255.8 +#Allocated: (entryTTL) samba4EntryTTL: 1.3.6.1.4.1.7165.4.255.9 # # Fedora DS uses this attribute, and we need to set it via our module stack diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c index ba74530c6f..1898fe9d33 100644 --- a/source4/torture/raw/streams.c +++ b/source4/torture/raw/streams.c @@ -640,6 +640,7 @@ static bool test_stream_delete(struct torture_context *tctx, CHECK_STATUS(status, NT_STATUS_OK); done: smbcli_close(cli->tree, fnum); + smbcli_unlink(cli->tree, fname); return ret; } @@ -1112,6 +1113,198 @@ done: return ret; } +static bool test_stream_rename2(struct torture_context *tctx, + struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + union smb_open io; + const char *fname1 = BASEDIR "\\stream.txt"; + const char *fname2 = BASEDIR "\\stream2.txt"; + const char *stream_name1 = ":Stream One:$DATA"; + const char *stream_name2 = ":Stream Two:$DATA"; + const char *stream_name_default = "::$DATA"; + const char *sname1; + const char *sname2; + bool ret = true; + int fnum = -1; + union smb_setfileinfo sinfo; + union smb_rename rio; + + sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname1, "Stream One"); + sname2 = talloc_asprintf(mem_ctx, "%s:%s", fname1, "Stream Two"); + + io.generic.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.flags = 0; + io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA| + SEC_STD_DELETE|SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL); + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = (NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE); + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = sname1; + + /* Open/create new stream. */ + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); + + /* + * Check raw rename with <base>:<stream>. + */ + printf("(%s) Checking NTRENAME of a stream using <base>:<stream>\n", + __location__); + rio.generic.level = RAW_RENAME_NTRENAME; + rio.ntrename.in.old_name = sname1; + rio.ntrename.in.new_name = sname2; + rio.ntrename.in.attrib = 0; + rio.ntrename.in.cluster_size = 0; + rio.ntrename.in.flags = RENAME_FLAG_RENAME; + status = smb_raw_rename(cli->tree, &rio); + CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + + /* + * Check raw rename to the default stream using :<stream>. + */ + printf("(%s) Checking NTRENAME to default stream using :<stream>\n", + __location__); + rio.ntrename.in.new_name = stream_name_default; + status = smb_raw_rename(cli->tree, &rio); + CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); + + /* + * Check raw rename using :<stream>. + */ + printf("(%s) Checking NTRENAME of a stream using :<stream>\n", + __location__); + rio.ntrename.in.new_name = stream_name2; + status = smb_raw_rename(cli->tree, &rio); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * Check raw rename of a stream to a file. + */ + printf("(%s) Checking NTRENAME of a stream to a file\n", + __location__); + rio.ntrename.in.old_name = sname2; + rio.ntrename.in.new_name = fname2; + status = smb_raw_rename(cli->tree, &rio); + CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + + /* + * Check raw rename of a file to a stream. + */ + printf("(%s) Checking NTRENAME of a file to a stream\n", + __location__); + + /* Create the file. */ + io.ntcreatex.in.fname = fname2; + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); + + /* Try the rename. */ + rio.ntrename.in.old_name = fname2; + rio.ntrename.in.new_name = sname1; + status = smb_raw_rename(cli->tree, &rio); + CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); + + /* + * Reopen the stream for trans2 renames. + */ + io.ntcreatex.in.fname = sname2; + 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.file.fnum; + + /* + * Check trans2 rename of a stream using :<stream>. + */ + printf("(%s) Checking trans2 rename of a stream using :<stream>\n", + __location__); + ZERO_STRUCT(sinfo); + sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; + sinfo.rename_information.in.file.fnum = fnum; + sinfo.rename_information.in.overwrite = 1; + sinfo.rename_information.in.root_fid = 0; + sinfo.rename_information.in.new_name = stream_name1; + status = smb_raw_setfileinfo(cli->tree, &sinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * Check trans2 rename of an overwriting stream using :<stream>. + */ + printf("(%s) Checking trans2 rename of an overwriting stream using " + ":<stream>\n", __location__); + + /* Create second stream. */ + io.ntcreatex.in.fname = sname2; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); + + /* Rename the first stream onto the second. */ + sinfo.rename_information.in.file.fnum = fnum; + sinfo.rename_information.in.new_name = stream_name2; + status = smb_raw_setfileinfo(cli->tree, &sinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + smbcli_close(cli->tree, fnum); + + /* + * Reopen the stream with the new name. + */ + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + io.ntcreatex.in.fname = sname2; + status = smb_raw_open(cli->tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = io.ntcreatex.out.file.fnum; + + /* + * Check trans2 rename of a stream using <base>:<stream>. + */ + printf("(%s) Checking trans2 rename of a stream using " + "<base>:<stream>\n", __location__); + sinfo.rename_information.in.file.fnum = fnum; + sinfo.rename_information.in.new_name = sname1; + status = smb_raw_setfileinfo(cli->tree, &sinfo); + CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED); + + /* + * Samba3 doesn't currently support renaming a stream to the default + * stream. This test does pass on windows. + */ + if (torture_setting_bool(tctx, "samba3", false)) { + goto done; + } + + /* + * Check trans2 rename to the default stream using :<stream>. + */ + printf("(%s) Checking trans2 rename to defaualt stream using " + ":<stream>\n", __location__); + sinfo.rename_information.in.file.fnum = fnum; + sinfo.rename_information.in.new_name = stream_name_default; + status = smb_raw_setfileinfo(cli->tree, &sinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + smbcli_close(cli->tree, fnum); + + done: + smbcli_close(cli->tree, fnum); + status = smbcli_unlink(cli->tree, fname1); + status = smbcli_unlink(cli->tree, fname2); + return ret; +} + /* basic testing of streams calls @@ -1131,15 +1324,17 @@ bool torture_raw_streams(struct torture_context *torture, smb_raw_exit(cli->session); ret &= test_stream_sharemodes(torture, cli, torture); smb_raw_exit(cli->session); + if (!torture_setting_bool(torture, "samba4", false)) { + ret &= test_stream_delete(torture, cli, torture); + } ret &= test_stream_names(torture, cli, torture); smb_raw_exit(cli->session); ret &= test_stream_names2(torture, cli, torture); smb_raw_exit(cli->session); ret &= test_stream_rename(torture, cli, torture); smb_raw_exit(cli->session); - if (!torture_setting_bool(torture, "samba4", false)) { - ret &= test_stream_delete(torture, cli, torture); - } + ret &= test_stream_rename2(torture, cli, torture); + smb_raw_exit(cli->session); smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); |