return status;
}
+static NTSTATUS check_parent_access(struct connection_struct *conn,
+ struct smb_filename *smb_fname,
+ uint32_t access_mask,
+ char **pp_parent_dir,
+ struct security_descriptor **pp_parent_sd)
+{
+ NTSTATUS status;
+ char *parent_dir = NULL;
+ struct security_descriptor *parent_sd = NULL;
+ uint32_t access_granted = 0;
+
+ if (!parent_dirname(talloc_tos(),
+ smb_fname->base_name,
+ &parent_dir,
+ NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = SMB_VFS_GET_NT_ACL(conn,
+ parent_dir,
+ SECINFO_DACL,
+ &parent_sd);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("check_parent_access: SMB_VFS_GET_NT_ACL failed for "
+ "%s with error %s\n",
+ parent_dir,
+ nt_errstr(status)));
+ return status;
+ }
+
+ status = smb1_file_se_access_check(conn,
+ parent_sd,
+ get_current_nttok(conn),
+ access_mask,
+ &access_granted);
+ if(!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("check_parent_access: access check "
+ "on directory %s for "
+ "path %s for mask 0x%x returned (0x%x) %s\n",
+ parent_dir,
+ smb_fname->base_name,
+ access_mask,
+ access_granted,
+ nt_errstr(status) ));
+ return status;
+ }
+
+ if (pp_parent_dir) {
+ *pp_parent_dir = parent_dir;
+ }
+ if (pp_parent_sd) {
+ *pp_parent_sd = parent_sd;
+ }
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
fd support routines - attempt to do a dos_open.
****************************************************************************/
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
- conn->session_info->unix_name,
+ conn->session_info->unix_info->unix_name,
smb_fname_str_dbg(smb_fname),
BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
conn->num_files_open));
return NT_STATUS_OK;
}
-/*******************************************************************
- Return True if the filename is one of the special executable types.
-********************************************************************/
-
-bool is_executable(const char *fname)
-{
- if ((fname = strrchr_m(fname,'.'))) {
- if (strequal(fname,".com") ||
- strequal(fname,".dll") ||
- strequal(fname,".exe") ||
- strequal(fname,".sym")) {
- return True;
- }
- }
- return False;
-}
-
/****************************************************************************
Check if we can open a file with a share mode.
Returns True if conflict, False if not.
}
if (is_deferred_open_entry(share_entry) &&
- !open_was_deferred(share_entry->op_mid)) {
+ !open_was_deferred(sconn, share_entry->op_mid)) {
char *str = talloc_asprintf(talloc_tos(),
"Got a deferred entry without a request: "
"PANIC: %s\n",
create_options, fsp_to_dup_into);
}
-/****************************************************************************
- Open a file with a share mode - old openX method - map into NTCreate.
-****************************************************************************/
-
-bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
- int deny_mode, int open_func,
- uint32 *paccess_mask,
- uint32 *pshare_mode,
- uint32 *pcreate_disposition,
- uint32 *pcreate_options,
- uint32_t *pprivate_flags)
-{
- uint32 access_mask;
- uint32 share_mode;
- uint32 create_disposition;
- uint32 create_options = FILE_NON_DIRECTORY_FILE;
- uint32_t private_flags = 0;
-
- DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
- "open_func = 0x%x\n",
- smb_fname_str_dbg(smb_fname), (unsigned int)deny_mode,
- (unsigned int)open_func ));
-
- /* Create the NT compatible access_mask. */
- switch (GET_OPENX_MODE(deny_mode)) {
- case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
- case DOS_OPEN_RDONLY:
- access_mask = FILE_GENERIC_READ;
- break;
- case DOS_OPEN_WRONLY:
- access_mask = FILE_GENERIC_WRITE;
- break;
- case DOS_OPEN_RDWR:
- case DOS_OPEN_FCB:
- access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
- break;
- default:
- DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
- (unsigned int)GET_OPENX_MODE(deny_mode)));
- return False;
- }
-
- /* Create the NT compatible create_disposition. */
- switch (open_func) {
- case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
- create_disposition = FILE_CREATE;
- break;
-
- case OPENX_FILE_EXISTS_OPEN:
- create_disposition = FILE_OPEN;
- break;
-
- case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
- create_disposition = FILE_OPEN_IF;
- break;
-
- case OPENX_FILE_EXISTS_TRUNCATE:
- create_disposition = FILE_OVERWRITE;
- break;
-
- case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
- create_disposition = FILE_OVERWRITE_IF;
- break;
-
- default:
- /* From samba4 - to be confirmed. */
- if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
- create_disposition = FILE_CREATE;
- break;
- }
- DEBUG(10,("map_open_params_to_ntcreate: bad "
- "open_func 0x%x\n", (unsigned int)open_func));
- return False;
- }
-
- /* Create the NT compatible share modes. */
- switch (GET_DENY_MODE(deny_mode)) {
- case DENY_ALL:
- share_mode = FILE_SHARE_NONE;
- break;
-
- case DENY_WRITE:
- share_mode = FILE_SHARE_READ;
- break;
-
- case DENY_READ:
- share_mode = FILE_SHARE_WRITE;
- break;
-
- case DENY_NONE:
- share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
- break;
-
- case DENY_DOS:
- private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
- if (is_executable(smb_fname->base_name)) {
- share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
- } else {
- if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
- share_mode = FILE_SHARE_READ;
- } else {
- share_mode = FILE_SHARE_NONE;
- }
- }
- break;
-
- case DENY_FCB:
- private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
- share_mode = FILE_SHARE_NONE;
- break;
-
- default:
- DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
- (unsigned int)GET_DENY_MODE(deny_mode) ));
- return False;
- }
-
- DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
- "share_mode = 0x%x, create_disposition = 0x%x, "
- "create_options = 0x%x private_flags = 0x%x\n",
- smb_fname_str_dbg(smb_fname),
- (unsigned int)access_mask,
- (unsigned int)share_mode,
- (unsigned int)create_disposition,
- (unsigned int)create_options,
- (unsigned int)private_flags));
-
- if (paccess_mask) {
- *paccess_mask = access_mask;
- }
- if (pshare_mode) {
- *pshare_mode = share_mode;
- }
- if (pcreate_disposition) {
- *pcreate_disposition = create_disposition;
- }
- if (pcreate_options) {
- *pcreate_options = create_options;
- }
- if (pprivate_flags) {
- *pprivate_flags = private_flags;
- }
-
- return True;
-
-}
-
static void schedule_defer_open(struct share_mode_lock *lck,
struct timeval request_time,
struct smb_request *req)
ZERO_STRUCT(id);
- /* Windows allows a new file to be created and
- silently removes a FILE_ATTRIBUTE_DIRECTORY
- sent by the client. Do the same. */
-
- new_dos_attributes &= ~FILE_ATTRIBUTE_DIRECTORY;
-
if (conn->printer) {
/*
* Printers are handled completely differently.
unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
new_dos_attributes = 0;
} else {
+ /* Windows allows a new file to be created and
+ silently removes a FILE_ATTRIBUTE_DIRECTORY
+ sent by the client. Do the same. */
+
+ new_dos_attributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+
/* We add FILE_ATTRIBUTE_ARCHIVE to this as this mode is only used if the file is
* created new. */
unx_mode = unix_mode(conn, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE,
sconn_server_id(req->sconn));
/* Ensure we don't reprocess this message. */
- remove_deferred_open_message_smb(req->mid);
+ remove_deferred_open_message_smb(req->sconn, req->mid);
}
}
uint32 file_attributes)
{
mode_t mode;
- char *parent_dir;
+ char *parent_dir = NULL;
NTSTATUS status;
bool posix_open = false;
bool need_re_stat = false;
+ uint32_t access_mask = SEC_DIR_ADD_SUBDIR;
- if(!CAN_WRITE(conn)) {
- DEBUG(5,("mkdir_internal: failing create on read-only share "
+ if(access_mask & ~(conn->share_access)) {
+ DEBUG(5,("mkdir_internal: failing share access "
"%s\n", lp_servicename(SNUM(conn))));
return NT_STATUS_ACCESS_DENIED;
}
mode = unix_mode(conn, FILE_ATTRIBUTE_DIRECTORY, smb_dname, parent_dir);
}
+ status = check_parent_access(conn,
+ smb_dname,
+ access_mask,
+ &parent_dir,
+ NULL);
+ if(!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("mkdir_internal: check_parent_access "
+ "on directory %s for path %s returned %s\n",
+ parent_dir,
+ smb_dname->base_name,
+ nt_errstr(status) ));
+ return status;
+ }
+
if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) {
return map_nt_error_from_unix(errno);
}
}
if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
- DEBUG(0, ("Directory just '%s' created is not a directory\n",
+ DEBUG(0, ("Directory '%s' just created is not a directory !\n",
smb_fname_str_dbg(smb_dname)));
- return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_NOT_A_DIRECTORY;
}
if (lp_store_dos_attributes(SNUM(conn))) {
/* If directory exists error. If directory doesn't
* exist create. */
+ if (dir_existed) {
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ DEBUG(2, ("open_directory: unable to create "
+ "%s. Error was %s\n",
+ smb_fname_str_dbg(smb_dname),
+ nt_errstr(status)));
+ return status;
+ }
+
status = mkdir_internal(conn, smb_dname,
file_attributes);
* exist create.
*/
- status = mkdir_internal(conn, smb_dname,
+ if (dir_existed) {
+ status = NT_STATUS_OK;
+ info = FILE_WAS_OPENED;
+ } else {
+ status = mkdir_internal(conn, smb_dname,
file_attributes);
- if (NT_STATUS_IS_OK(status)) {
- info = FILE_WAS_CREATED;
+ if (NT_STATUS_IS_OK(status)) {
+ info = FILE_WAS_CREATED;
+ } else {
+ /* Cope with create race. */
+ if (!NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
+ DEBUG(2, ("open_directory: unable to create "
+ "%s. Error was %s\n",
+ smb_fname_str_dbg(smb_dname),
+ nt_errstr(status)));
+ return status;
+ }
+ info = FILE_WAS_OPENED;
+ }
}
- if (NT_STATUS_EQUAL(status,
- NT_STATUS_OBJECT_NAME_COLLISION)) {
- info = FILE_WAS_OPENED;
- status = NT_STATUS_OK;
- }
break;
case FILE_SUPERSEDE:
NTSTATUS open_streams_for_delete(connection_struct *conn,
const char *fname)
{
- struct stream_struct *stream_info;
- files_struct **streams;
+ struct stream_struct *stream_info = NULL;
+ files_struct **streams = NULL;
int i;
- unsigned int num_streams;
+ unsigned int num_streams = 0;
TALLOC_CTX *frame = talloc_stackframe();
NTSTATUS status;
- status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
- &num_streams, &stream_info);
+ status = vfs_streaminfo(conn, NULL, fname, talloc_tos(),
+ &num_streams, &stream_info);
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)
|| NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
}
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
+ DEBUG(10, ("vfs_streaminfo failed: %s\n",
nt_errstr(status)));
goto fail;
}