* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "../librpc/gen_ndr/ndr_security.h"
+
static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
DATA_BLOB *pblob,
uint16_t hash_type,
files_struct *fsp,
DATA_BLOB *pblob);
-#define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
- GROUP_SECURITY_INFORMATION | \
- DACL_SECURITY_INFORMATION | \
- SACL_SECURITY_INFORMATION)
+#define HASH_SECURITY_INFO (SECINFO_OWNER | \
+ SECINFO_GROUP | \
+ SECINFO_DACL | \
+ SECINFO_SACL)
/*******************************************************************
Hash a security descriptor.
enum ndr_err_code ndr_err;
size_t sd_size;
- ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
+ ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
(ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
switch (xacl.version) {
case 2:
- *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+ *ppdesc = make_sec_desc(ctx, SD_REVISION,
xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
xacl.info.sd_hs2->sd->owner_sid,
xacl.info.sd_hs2->sd->group_sid,
memset(hash, '\0', XATTR_SD_HASH_SIZE);
break;
case 3:
- *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+ *ppdesc = make_sec_desc(ctx, SD_REVISION,
xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
xacl.info.sd_hs3->sd->owner_sid,
xacl.info.sd_hs3->sd->group_sid,
memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
ndr_err = ndr_push_struct_blob(
- pblob, ctx, NULL, &xacl,
+ pblob, ctx, &xacl,
(ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
struct connection_struct *conn = handle->conn;
int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
struct smb_filename smb_fname;
- enum security_ace_type acl_type;
+ enum security_ace_type acltype;
uint32_t access_mask;
mode_t dir_mode;
mode_t file_mode;
memcpy(new_ace_list, psd->dacl->aces,
num_aces * sizeof(struct security_ace));
}
- access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+ access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
mode & 0700, false);
init_sec_ace(&new_ace_list[num_aces],
&global_sid_Creator_Owner,
- acl_type,
+ acltype,
access_mask,
SEC_ACE_FLAG_CONTAINER_INHERIT|
SEC_ACE_FLAG_OBJECT_INHERIT|
SEC_ACE_FLAG_INHERIT_ONLY);
- access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+ access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
(mode << 3) & 0700, false);
init_sec_ace(&new_ace_list[num_aces+1],
&global_sid_Creator_Group,
- acl_type,
+ acltype,
access_mask,
SEC_ACE_FLAG_CONTAINER_INHERIT|
SEC_ACE_FLAG_OBJECT_INHERIT|
SEC_ACE_FLAG_INHERIT_ONLY);
- access_mask = map_canon_ace_perms(SNUM(conn), &acl_type,
+ access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
(mode << 6) & 0700, false);
init_sec_ace(&new_ace_list[num_aces+2],
&global_sid_World,
- acl_type,
+ acltype,
access_mask,
SEC_ACE_FLAG_CONTAINER_INHERIT|
SEC_ACE_FLAG_OBJECT_INHERIT|
{
DATA_BLOB blob;
NTSTATUS status;
- uint16_t hash_type;
+ uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
uint8_t hash[XATTR_SD_HASH_SIZE];
uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
struct security_descriptor *psd = NULL;
}
}
- if (!(security_info & OWNER_SECURITY_INFORMATION)) {
+ if (!(security_info & SECINFO_OWNER)) {
psd->owner_sid = NULL;
}
- if (!(security_info & GROUP_SECURITY_INFORMATION)) {
+ if (!(security_info & SECINFO_GROUP)) {
psd->group_sid = NULL;
}
- if (!(security_info & DACL_SECURITY_INFORMATION)) {
+ if (!(security_info & SECINFO_DACL)) {
psd->dacl = NULL;
}
- if (!(security_info & SACL_SECURITY_INFORMATION)) {
+ if (!(security_info & SECINFO_SACL)) {
psd->sacl = NULL;
}
&psd,
&size,
parent_desc,
- &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
- &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
+ &handle->conn->server_info->ptok->sids[PRIMARY_USER_SID_INDEX],
+ &handle->conn->server_info->ptok->sids[PRIMARY_GROUP_SID_INDEX],
is_directory);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return SMB_VFS_FSET_NT_ACL(fsp,
- (OWNER_SECURITY_INFORMATION |
- GROUP_SECURITY_INFORMATION |
- DACL_SECURITY_INFORMATION),
+ (SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL),
psd);
}
status = get_nt_acl_internal(handle,
NULL,
parent_name,
- (OWNER_SECURITY_INFORMATION |
- GROUP_SECURITY_INFORMATION |
- DACL_SECURITY_INFORMATION),
+ (SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL),
&parent_desc);
if (!NT_STATUS_IS_OK(status)) {
nt_errstr(status) ));
return status;
}
- status = smb1_file_se_access_check(parent_desc,
- handle->conn->server_info->ptok,
+ if (pp_parent_desc) {
+ *pp_parent_desc = parent_desc;
+ }
+ status = smb1_file_se_access_check(handle->conn,
+ parent_desc,
+ get_current_nttok(handle->conn),
access_mask,
&access_granted);
if(!NT_STATUS_IS_OK(status)) {
nt_errstr(status) ));
return status;
}
- if (pp_parent_desc) {
- *pp_parent_desc = parent_desc;
- }
return NT_STATUS_OK;
}
status = get_nt_acl_internal(handle,
NULL,
fname,
- (OWNER_SECURITY_INFORMATION |
- GROUP_SECURITY_INFORMATION |
- DACL_SECURITY_INFORMATION),
+ (SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL),
&pdesc);
if (NT_STATUS_IS_OK(status)) {
/* See if we can access it. */
- status = smb1_file_se_access_check(pdesc,
- handle->conn->server_info->ptok,
+ status = smb1_file_se_access_check(handle->conn,
+ pdesc,
+ get_current_nttok(handle->conn),
fsp->access_mask,
&access_granted);
if (!NT_STATUS_IS_OK(status)) {
/* Ensure we have OWNER/GROUP/DACL set. */
- if ((security_info_sent & (OWNER_SECURITY_INFORMATION|
- GROUP_SECURITY_INFORMATION|
- DACL_SECURITY_INFORMATION)) !=
- (OWNER_SECURITY_INFORMATION|
- GROUP_SECURITY_INFORMATION|
- DACL_SECURITY_INFORMATION)) {
+ if ((security_info_sent & (SECINFO_OWNER|
+ SECINFO_GROUP|
+ SECINFO_DACL)) !=
+ (SECINFO_OWNER|
+ SECINFO_GROUP|
+ SECINFO_DACL)) {
/* No we don't - read from the existing SD. */
struct security_descriptor *nc_psd = NULL;
status = get_nt_acl_internal(handle, fsp,
NULL,
- (OWNER_SECURITY_INFORMATION|
- GROUP_SECURITY_INFORMATION|
- DACL_SECURITY_INFORMATION),
+ (SECINFO_OWNER|
+ SECINFO_GROUP|
+ SECINFO_DACL),
&nc_psd);
if (!NT_STATUS_IS_OK(status)) {
}
/* This is safe as nc_psd is discarded at fn exit. */
- if (security_info_sent & OWNER_SECURITY_INFORMATION) {
+ if (security_info_sent & SECINFO_OWNER) {
nc_psd->owner_sid = psd->owner_sid;
}
- security_info_sent |= OWNER_SECURITY_INFORMATION;
+ security_info_sent |= SECINFO_OWNER;
- if (security_info_sent & GROUP_SECURITY_INFORMATION) {
+ if (security_info_sent & SECINFO_GROUP) {
nc_psd->group_sid = psd->group_sid;
}
- security_info_sent |= GROUP_SECURITY_INFORMATION;
+ security_info_sent |= SECINFO_GROUP;
- if (security_info_sent & DACL_SECURITY_INFORMATION) {
+ if (security_info_sent & SECINFO_DACL) {
nc_psd->dacl = dup_sec_acl(talloc_tos(), psd->dacl);
if (nc_psd->dacl == NULL) {
return NT_STATUS_NO_MEMORY;
}
}
- security_info_sent |= DACL_SECURITY_INFORMATION;
+ security_info_sent |= SECINFO_DACL;
psd = nc_psd;
}
return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
}
+static int acl_common_remove_object(vfs_handle_struct *handle,
+ const char *path,
+ bool is_directory)
+{
+ connection_struct *conn = handle->conn;
+ struct file_id id;
+ files_struct *fsp = NULL;
+ int ret = 0;
+ char *parent_dir = NULL;
+ const char *final_component = NULL;
+ struct smb_filename local_fname;
+ int saved_errno = 0;
+
+ if (!parent_dirname(talloc_tos(), path,
+ &parent_dir, &final_component)) {
+ saved_errno = ENOMEM;
+ goto out;
+ }
+
+ DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
+ is_directory ? "directory" : "file",
+ parent_dir, final_component ));
+
+ /* cd into the parent dir to pin it. */
+ ret = SMB_VFS_CHDIR(conn, parent_dir);
+ if (ret == -1) {
+ saved_errno = errno;
+ goto out;
+ }
+
+ ZERO_STRUCT(local_fname);
+ local_fname.base_name = CONST_DISCARD(char *,final_component);
+
+ /* Must use lstat here. */
+ ret = SMB_VFS_LSTAT(conn, &local_fname);
+ if (ret == -1) {
+ saved_errno = errno;
+ goto out;
+ }
+
+ /* Ensure we have this file open with DELETE access. */
+ id = vfs_file_id_from_sbuf(conn, &local_fname.st);
+ for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) {
+ if (fsp->access_mask & DELETE_ACCESS &&
+ fsp->delete_on_close) {
+ /* We did open this for delete,
+ * allow the delete as root.
+ */
+ break;
+ }
+ }
+
+ if (!fsp) {
+ DEBUG(10,("acl_common_remove_object: %s %s/%s "
+ "not an open file\n",
+ is_directory ? "directory" : "file",
+ parent_dir, final_component ));
+ saved_errno = EACCES;
+ goto out;
+ }
+
+ become_root();
+ if (is_directory) {
+ ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
+ } else {
+ ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
+ }
+ unbecome_root();
+
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+
+ out:
+
+ TALLOC_FREE(parent_dir);
+
+ vfs_ChDir(conn, conn->connectpath);
+ if (saved_errno) {
+ errno = saved_errno;
+ }
+ return ret;
+}
+
+static int rmdir_acl_common(struct vfs_handle_struct *handle,
+ const char *path)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_RMDIR(handle, path);
+ if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+ DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
+ path,
+ strerror(errno) ));
+ return ret;
+ }
+
+ return acl_common_remove_object(handle,
+ path,
+ true);
+}
+
static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle,
struct smb_request *req,
uint16_t root_dir_fid,
uint32_t file_attributes,
uint32_t oplock_request,
uint64_t allocation_size,
+ uint32_t private_flags,
struct security_descriptor *sd,
struct ea_list *ea_list,
files_struct **result,
file_attributes,
oplock_request,
allocation_size,
+ private_flags,
sd,
ea_list,
result,
/* NOTREACHED */
return status;
}
+
+static int unlink_acl_common(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+ if (!(ret == -1 && (errno == EACCES || errno == EPERM))) {
+ DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
+ smb_fname->base_name,
+ strerror(errno) ));
+ return ret;
+ }
+ /* Don't do anything fancy for streams. */
+ if (smb_fname->stream_name) {
+ return ret;
+ }
+
+ return acl_common_remove_object(handle,
+ smb_fname->base_name,
+ false);
+}