#include "fake_file.h"
#include "../libcli/security/security.h"
#include "../librpc/gen_ndr/ndr_security.h"
+#include "../librpc/gen_ndr/open_files.h"
#include "auth.h"
#include "messages.h"
return NT_STATUS_OK;
}
+ if (access_mask == DELETE_ACCESS &&
+ VALID_STAT(smb_fname->st) &&
+ S_ISLNK(smb_fname->st.st_ex_mode)) {
+ /* We can always delete a symlink. */
+ DEBUG(10,("smbd_check_access_rights: not checking ACL "
+ "on DELETE_ACCESS on symlink %s.\n",
+ smb_fname_str_dbg(smb_fname) ));
+ return NT_STATUS_OK;
+ }
+
status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
(SECINFO_OWNER |
SECINFO_GROUP |
"share entry with an open file\n");
}
- if (is_deferred_open_entry(share_entry) ||
- is_unused_share_mode_entry(share_entry)) {
+ if (is_deferred_open_entry(share_entry)) {
goto panic;
}
static void find_oplock_types(files_struct *fsp,
int oplock_request,
- struct share_mode_lock *lck,
+ const struct share_mode_lock *lck,
struct share_mode_entry **pp_batch,
struct share_mode_entry **pp_ex_or_batch,
bool *got_level2,
if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
return false;
}
-
- if (batch_entry != NULL) {
- /* Found a batch oplock */
- send_break_message(fsp, batch_entry, mid, oplock_request);
- return true;
+ if (batch_entry == NULL) {
+ return false;
}
- return false;
+
+ /* Found a batch oplock */
+ send_break_message(fsp, batch_entry, mid, oplock_request);
+ return true;
}
static bool delay_for_exclusive_oplocks(files_struct *fsp,
int oplock_request,
struct share_mode_entry *ex_entry)
{
+ bool delay_it;
+
if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
return false;
}
+ if (ex_entry == NULL) {
+ return false;
+ }
- if (ex_entry != NULL) {
- /* Found an exclusive or batch oplock */
- bool delay_it = is_delete_request(fsp) ?
- BATCH_OPLOCK_TYPE(ex_entry->op_type) : true;
- if (delay_it) {
- send_break_message(fsp, ex_entry, mid, oplock_request);
- return true;
- }
+ /* Found an exclusive or batch oplock */
+
+ delay_it = is_delete_request(fsp) ?
+ BATCH_OPLOCK_TYPE(ex_entry->op_type) : true;
+
+ if (!delay_it) {
+ return false;
}
- return false;
+
+ send_break_message(fsp, ex_entry, mid, oplock_request);
+ return true;
}
static void grant_fsp_oplock_type(files_struct *fsp,
for (i=0; i<lck->num_share_modes; i++) {
struct share_mode_entry *e = &lck->share_modes[i];
- if (!is_deferred_open_entry(e)) {
- continue;
- }
-
- if (procid_is_me(&e->pid) && (e->op_mid == req->mid)) {
+ if (is_deferred_open_entry(e) &&
+ procid_is_me(&e->pid) &&
+ (e->op_mid == req->mid)) {
DEBUG(0, ("Trying to defer an already deferred "
"request: mid=%llu, exiting\n",
(unsigned long long)req->mid));
exit_server("push_deferred_open_message_smb failed");
}
add_deferred_open(lck, req->mid, request_time,
- sconn_server_id(req->sconn), state->id);
+ messaging_server_id(req->sconn->msg_ctx), state->id);
}
NULL, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("could not get share mode lock\n"));
- } else {
- del_deferred_open_entry(lck, mid, pid);
- TALLOC_FREE(lck);
+ return;
}
+ del_deferred_open_entry(lck, mid, pid);
+ TALLOC_FREE(lck);
}
/****************************************************************
bool posix_open = False;
bool new_file_created = False;
bool clear_ads = false;
- struct file_id id;
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
mode_t new_unx_mode = (mode_t)0;
mode_t unx_mode = (mode_t)0;
NTSTATUS status;
char *parent_dir;
- ZERO_STRUCT(id);
-
if (conn->printer) {
/*
* Printers are handled completely differently.
/* Remove the deferred open entry under lock. */
remove_deferred_open_entry(
state->id, req->mid,
- sconn_server_id(req->sconn));
+ messaging_server_id(req->sconn->msg_ctx));
/* Ensure we don't reprocess this message. */
remove_deferred_open_message_smb(req->sconn, req->mid);
}
}
- status = check_name(conn, smb_fname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
if (!posix_open) {
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
if (file_existed) {
struct share_mode_entry *exclusive_entry = NULL;
bool got_level2_oplock = false;
bool got_a_none_oplock = false;
+ struct file_id id;
struct timespec old_write_time = smb_fname->st.st_ex_mtime;
id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
bool got_level2_oplock = false;
bool got_a_none_oplock = false;
struct timespec old_write_time = smb_fname->st.st_ex_mtime;
+ struct file_id id;
/*
* Deal with the race condition where two smbd's detect the
* file doesn't exist and do the create at the same time. One
fsp->oplock_type = NO_OPLOCK;
}
- if (!(flags2 & O_TRUNC)) {
- info = FILE_WAS_OPENED;
- } else {
+ if (flags2 & O_TRUNC) {
info = FILE_WAS_OVERWRITTEN;
+ } else {
+ info = FILE_WAS_OPENED;
}
} else {
info = FILE_WAS_CREATED;
fsp->oplock_type = NO_OPLOCK;
}
- if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) {
- new_file_created = True;
- }
-
set_share_mode(lck, fsp, get_current_uid(conn),
req ? req->mid : 0,
fsp->oplock_type);
fsp->initial_delete_on_close = True;
}
+ if (info == FILE_WAS_OVERWRITTEN
+ || info == FILE_WAS_CREATED
+ || info == FILE_WAS_SUPERSEDED) {
+ new_file_created = True;
+ }
+
if (new_file_created) {
/* Files should be initially set as archive */
if (lp_map_archive(SNUM(conn)) ||
* records. */
if (req != NULL) {
del_deferred_open_entry(lck, req->mid,
- sconn_server_id(req->sconn));
+ messaging_server_id(req->sconn->msg_ctx));
}
TALLOC_FREE(lck);
return NT_STATUS_ACCESS_DENIED;
}
- status = check_name(conn, smb_dname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir,
NULL)) {
return NT_STATUS_NO_MEMORY;
struct server_id server_id,
DATA_BLOB *data)
{
- struct smbd_server_connection *sconn;
files_struct *fsp;
char *frm = (char *)data->data;
struct file_id id;
struct smb_filename *smb_fname = NULL;
size_t sp_len, bn_len;
NTSTATUS status;
-
- sconn = msg_ctx_to_sconn(msg);
- if (sconn == NULL) {
- DEBUG(1, ("could not find sconn\n"));
- return;
- }
+ struct smbd_server_connection *sconn =
+ talloc_get_type_abort(private_data,
+ struct smbd_server_connection);
if (data->data == NULL
|| data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) {
return status;
}
+/*********************************************************************
+ Create a default ACL by inheriting from the parent. If no inheritance
+ from the parent available, don't set anything. This will leave the actual
+ permissions the new file or directory already got from the filesystem
+ as the NT ACL when read.
+*********************************************************************/
+
+static NTSTATUS inherit_new_acl(files_struct *fsp)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ char *parent_name = NULL;
+ struct security_descriptor *parent_desc = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+ struct security_descriptor *psd = NULL;
+ struct dom_sid *owner_sid = NULL;
+ struct dom_sid *group_sid = NULL;
+ uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
+ bool inherit_owner = lp_inherit_owner(SNUM(fsp->conn));
+ bool inheritable_components = false;
+ size_t size = 0;
+
+ if (!parent_dirname(ctx, fsp->fsp_name->base_name, &parent_name, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = SMB_VFS_GET_NT_ACL(fsp->conn,
+ parent_name,
+ (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL),
+ &parent_desc);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ inheritable_components = sd_has_inheritable_components(parent_desc,
+ fsp->is_directory);
+
+ if (!inheritable_components && !inherit_owner) {
+ /* Nothing to inherit and not setting owner. */
+ return NT_STATUS_OK;
+ }
+
+ /* Create an inherited descriptor from the parent. */
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
+ fsp_str_dbg(fsp) ));
+ NDR_PRINT_DEBUG(security_descriptor, parent_desc);
+ }
+
+ /* Inherit from parent descriptor if "inherit owner" set. */
+ if (inherit_owner) {
+ owner_sid = parent_desc->owner_sid;
+ group_sid = parent_desc->group_sid;
+ }
+
+ if (owner_sid == NULL) {
+ owner_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
+ }
+ if (group_sid == NULL) {
+ group_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX];
+ }
+
+ status = se_create_child_secdesc(ctx,
+ &psd,
+ &size,
+ parent_desc,
+ owner_sid,
+ group_sid,
+ fsp->is_directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* If inheritable_components == false,
+ se_create_child_secdesc()
+ creates a security desriptor with a NULL dacl
+ entry, but with SEC_DESC_DACL_PRESENT. We need
+ to remove that flag. */
+
+ if (!inheritable_components) {
+ security_info_sent &= ~SECINFO_DACL;
+ psd->type &= ~SEC_DESC_DACL_PRESENT;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
+ fsp_str_dbg(fsp) ));
+ NDR_PRINT_DEBUG(security_descriptor, psd);
+ }
+
+ if (inherit_owner) {
+ /* We need to be root to force this. */
+ become_root();
+ }
+ status = SMB_VFS_FSET_NT_ACL(fsp,
+ security_info_sent,
+ psd);
+ if (inherit_owner) {
+ unbecome_root();
+ }
+ return status;
+}
+
/*
* Wrapper around open_file_ntcreate and open_directory
*/
}
}
- /* This is the correct thing to do (check every time) but can_delete
- * is expensive (it may have to read the parent directory
- * permissions). So for now we're not doing it unless we have a strong
- * hint the client is really going to delete this file. If the client
- * is forcing FILE_CREATE let the filesystem take care of the
- * permissions. */
-
- /* Setting FILE_SHARE_DELETE is the hint. */
-
- if ((create_disposition != FILE_CREATE)
- && (access_mask & DELETE_ACCESS)
- && (!(can_delete_file_in_directory(conn, smb_fname) ||
- can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) {
- status = NT_STATUS_ACCESS_DENIED;
- DEBUG(10,("create_file_unixpath: open file %s "
- "for delete ACCESS_DENIED\n",
- smb_fname_str_dbg(smb_fname)));
- goto fail;
- }
-
if ((access_mask & SEC_FLAG_SYSTEM_SECURITY) &&
!security_token_has_privilege(get_current_nttok(conn),
SEC_PRIV_SECURITY)) {
fsp->base_fsp = base_fsp;
- /*
- * According to the MS documentation, the only time the security
- * descriptor is applied to the opened file is iff we *created* the
- * file; an existing file stays the same.
- *
- * Also, it seems (from observation) that you can open the file with
- * any access mask but you can still write the sd. We need to override
- * the granted access before we call set_sd
- * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
- */
-
- if ((sd != NULL) && (info == FILE_WAS_CREATED)
- && lp_nt_acl_support(SNUM(conn))) {
-
- uint32_t sec_info_sent;
- uint32_t saved_access_mask = fsp->access_mask;
-
- sec_info_sent = get_sec_info(sd);
-
- fsp->access_mask = FILE_GENERIC_ALL;
-
- /* Convert all the generic bits. */
- security_acl_map_generic(sd->dacl, &file_generic_mapping);
- security_acl_map_generic(sd->sacl, &file_generic_mapping);
-
- if (sec_info_sent & (SECINFO_OWNER|
- SECINFO_GROUP|
- SECINFO_DACL|
- SECINFO_SACL)) {
- status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd);
- }
-
- fsp->access_mask = saved_access_mask;
-
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
- }
-
if ((ea_list != NULL) &&
((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN))) {
status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
}
}
+ if ((info == FILE_WAS_CREATED) && lp_nt_acl_support(SNUM(conn)) &&
+ fsp->base_fsp == NULL) {
+ if (sd != NULL) {
+ /*
+ * According to the MS documentation, the only time the security
+ * descriptor is applied to the opened file is iff we *created* the
+ * file; an existing file stays the same.
+ *
+ * Also, it seems (from observation) that you can open the file with
+ * any access mask but you can still write the sd. We need to override
+ * the granted access before we call set_sd
+ * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
+ */
+
+ uint32_t sec_info_sent;
+ uint32_t saved_access_mask = fsp->access_mask;
+
+ sec_info_sent = get_sec_info(sd);
+
+ fsp->access_mask = FILE_GENERIC_ALL;
+
+ /* Convert all the generic bits. */
+ security_acl_map_generic(sd->dacl, &file_generic_mapping);
+ security_acl_map_generic(sd->sacl, &file_generic_mapping);
+
+ if (sec_info_sent & (SECINFO_OWNER|
+ SECINFO_GROUP|
+ SECINFO_DACL|
+ SECINFO_SACL)) {
+ status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd);
+ }
+
+ fsp->access_mask = saved_access_mask;
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ } else if (lp_inherit_acls(SNUM(conn))) {
+ /* Inherit from parent. Errors here are not fatal. */
+ status = inherit_new_acl(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("inherit_new_acl: failed for %s with %s\n",
+ fsp_str_dbg(fsp),
+ nt_errstr(status) ));
+ }
+ }
+ }
+
DEBUG(10, ("create_file_unixpath: info=%d\n", info));
*result = fsp;
}
}
- /* All file access must go through check_name() */
-
- status = check_name(conn, smb_fname->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
if (stream_name && is_ntfs_default_stream_smb_fname(smb_fname)) {
int ret;
smb_fname->stream_name = NULL;