Beispiel #1
0
static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
        uint32 security_info, struct security_descriptor **ppdesc)
{
	NTSTATUS status = get_nt_acl_xattr_internal(handle, fsp,
				NULL, security_info, ppdesc);
	if (NT_STATUS_IS_OK(status)) {
		if (DEBUGLEVEL >= 10) {
			DEBUG(10,("fget_nt_acl_xattr: returning xattr sd for file %s\n",
				fsp->fsp_name));
			NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
		}
		return NT_STATUS_OK;
	}

	DEBUG(10,("fget_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
			fsp->fsp_name,
			nt_errstr(status) ));

	return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp,
			security_info, ppdesc);
}
Beispiel #2
0
static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
	uint32 security_info, SEC_DESC **ppdesc)
{
	return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc);
}
static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
{
	return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc);
}
Beispiel #4
0
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        uint32_t security_info_sent, const struct security_descriptor *psd)
{
	NTSTATUS status;
	DATA_BLOB blob;
	struct security_descriptor *pdesc_next = NULL;
	uint8_t hash[XATTR_SD_HASH_SIZE];

	if (DEBUGLEVEL >= 10) {
		DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
			  fsp_str_dbg(fsp)));
		NDR_PRINT_DEBUG(security_descriptor,
			CONST_DISCARD(struct security_descriptor *,psd));
	}

        /* 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)) {
		/* 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),
				&nc_psd);

		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		/* This is safe as nc_psd is discarded at fn exit. */
		if (security_info_sent & OWNER_SECURITY_INFORMATION) {
			nc_psd->owner_sid = psd->owner_sid;
		}
		security_info_sent |= OWNER_SECURITY_INFORMATION;

		if (security_info_sent & GROUP_SECURITY_INFORMATION) {
			nc_psd->group_sid = psd->group_sid;
		}
		security_info_sent |= GROUP_SECURITY_INFORMATION;

		if (security_info_sent & DACL_SECURITY_INFORMATION) {
			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;
		psd = nc_psd;
	}

	status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Get the full underlying sd, then hash. */
	status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
				fsp,
				HASH_SECURITY_INFO,
				&pdesc_next);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = hash_sd_sha256(pdesc_next, hash);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (DEBUGLEVEL >= 10) {
		DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
			  fsp_str_dbg(fsp)));
		NDR_PRINT_DEBUG(security_descriptor,
			CONST_DISCARD(struct security_descriptor *,psd));
	}
	create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
	store_acl_blob_fsp(handle, fsp, &blob);

	return NT_STATUS_OK;
}
Beispiel #5
0
static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
				files_struct *fsp,
				const char *name,
			        uint32_t security_info,
				struct security_descriptor **ppdesc)
{
	DATA_BLOB blob;
	NTSTATUS status;
	uint16_t hash_type;
	uint8_t hash[XATTR_SD_HASH_SIZE];
	uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
	struct security_descriptor *psd = NULL;
	struct security_descriptor *pdesc_next = NULL;

	if (fsp && name == NULL) {
		name = fsp->fsp_name->base_name;
	}

	DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));

	/* Get the full underlying sd for the hash
	   or to return as backup. */
	if (fsp) {
		status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
				fsp,
				HASH_SECURITY_INFO,
				&pdesc_next);
	} else {
		status = SMB_VFS_NEXT_GET_NT_ACL(handle,
				name,
				HASH_SECURITY_INFO,
				&pdesc_next);
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
			"returned %s\n",
			name,
			nt_errstr(status)));
		return status;
	}

	status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
			nt_errstr(status)));
		psd = pdesc_next;
		goto out;
	}

	status = parse_acl_blob(&blob, &psd,
				&hash_type, &hash[0]);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("parse_acl_blob returned %s\n",
				nt_errstr(status)));
		psd = pdesc_next;
		goto out;
	}

	/* Ensure the hash type is one we know. */
	switch (hash_type) {
		case XATTR_SD_HASH_TYPE_NONE:
			/* No hash, just return blob sd. */
			goto out;
		case XATTR_SD_HASH_TYPE_SHA256:
			break;
		default:
			DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
				"mismatch (%u) for file %s\n",
				(unsigned int)hash_type,
				name));
			TALLOC_FREE(psd);
			psd = pdesc_next;
			goto out;
	}


	status = hash_sd_sha256(pdesc_next, hash_tmp);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(psd);
		psd = pdesc_next;
		goto out;
	}

	if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
		/* Hash matches, return blob sd. */
		goto out;
	}

	/* Hash doesn't match, return underlying sd. */
	TALLOC_FREE(psd);
	psd = pdesc_next;

  out:

	if (psd != pdesc_next) {
		/* We're returning the blob, throw
 		 * away the filesystem SD. */
		TALLOC_FREE(pdesc_next);
	} else {
		SMB_STRUCT_STAT sbuf;
		SMB_STRUCT_STAT *psbuf = &sbuf;
		bool is_directory = false;
		/*
		 * We're returning the underlying ACL from the
		 * filesystem. If it's a directory, and has no
		 * inheritable ACE entries we have to fake them.
		 */
		if (fsp) {
			is_directory = fsp->is_directory;
			psbuf = &fsp->fsp_name->st;
		} else {
			if (vfs_stat_smb_fname(handle->conn,
						name,
						&sbuf) == 0) {
				is_directory = S_ISDIR(sbuf.st_ex_mode);
			}
		}
		if (is_directory &&
				!sd_has_inheritable_components(psd,
							true)) {
			add_directory_inheritable_components(handle,
							name,
							psbuf,
							psd);
		}
	}

	if (!(security_info & OWNER_SECURITY_INFORMATION)) {
		psd->owner_sid = NULL;
	}
	if (!(security_info & GROUP_SECURITY_INFORMATION)) {
		psd->group_sid = NULL;
	}
	if (!(security_info & DACL_SECURITY_INFORMATION)) {
		psd->dacl = NULL;
	}
	if (!(security_info & SACL_SECURITY_INFORMATION)) {
		psd->sacl = NULL;
	}

	TALLOC_FREE(blob.data);
	*ppdesc = psd;
	return NT_STATUS_OK;
}
Beispiel #6
0
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
        uint32_t security_info_sent, const struct security_descriptor *orig_psd)
{
	NTSTATUS status;
	DATA_BLOB blob;
	struct security_descriptor *pdesc_next = NULL;
	struct security_descriptor *psd = NULL;
	uint8_t hash[XATTR_SD_HASH_SIZE];
	bool chown_needed = false;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
			  fsp_str_dbg(fsp)));
		NDR_PRINT_DEBUG(security_descriptor,
			discard_const_p(struct security_descriptor, orig_psd));
	}

	status = get_nt_acl_internal(handle, fsp,
			NULL,
			SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
			&psd);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	psd->revision = orig_psd->revision;
	/* All our SD's are self relative. */
	psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;

	if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
		if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) {
			/* We're changing the owner. */
			chown_needed = true;
		}
		psd->owner_sid = orig_psd->owner_sid;
	}
	if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
		if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) {
			/* We're changing the group. */
			chown_needed = true;
		}
		psd->group_sid = orig_psd->group_sid;
	}
	if (security_info_sent & SECINFO_DACL) {
		psd->dacl = orig_psd->dacl;
		psd->type |= SEC_DESC_DACL_PRESENT;
	}
	if (security_info_sent & SECINFO_SACL) {
		psd->sacl = orig_psd->sacl;
		psd->type |= SEC_DESC_SACL_PRESENT;
	}

	status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
	if (!NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
			return status;
		}
		/* We got access denied here. If we're already root,
		   or we didn't need to do a chown, or the fsp isn't
		   open with WRITE_OWNER access, just return. */
		if (get_current_uid(handle->conn) == 0 ||
				chown_needed == false ||
				!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
			return NT_STATUS_ACCESS_DENIED;
		}

		DEBUG(10,("fset_nt_acl_common: overriding chown on file %s "
			"for sid %s\n",
			fsp_str_dbg(fsp),
			sid_string_tos(psd->owner_sid)
			));

		/* Ok, we failed to chown and we have
		   SEC_STD_WRITE_OWNER access - override. */
		become_root();
		status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp,
				security_info_sent, psd);
		unbecome_root();
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	}

	/* Get the full underlying sd, then hash. */
	status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
				fsp,
				HASH_SECURITY_INFO,
				&pdesc_next);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = hash_sd_sha256(pdesc_next, hash);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (DEBUGLEVEL >= 10) {
		DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
			  fsp_str_dbg(fsp)));
		NDR_PRINT_DEBUG(security_descriptor,
			discard_const_p(struct security_descriptor, psd));
	}
	create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
	store_acl_blob_fsp(handle, fsp, &blob);

	return NT_STATUS_OK;
}
Beispiel #7
0
static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
				files_struct *fsp,
				const char *name,
			        uint32_t security_info,
				struct security_descriptor **ppdesc)
{
	DATA_BLOB blob = data_blob_null;
	NTSTATUS status;
	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;
	struct security_descriptor *pdesc_next = NULL;
	bool ignore_file_system_acl = lp_parm_bool(SNUM(handle->conn),
						ACL_MODULE_NAME,
						"ignore system acls",
						false);

	if (fsp && name == NULL) {
		name = fsp->fsp_name->base_name;
	}

	DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));

	/* Get the full underlying sd for the hash
	   or to return as backup. */
	if (fsp) {
		status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
				fsp,
				HASH_SECURITY_INFO,
				&pdesc_next);
	} else {
		status = SMB_VFS_NEXT_GET_NT_ACL(handle,
				name,
				HASH_SECURITY_INFO,
				&pdesc_next);
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("get_nt_acl_internal: get_next_acl for file %s "
			"returned %s\n",
			name,
			nt_errstr(status)));
		return status;
	}

	status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("get_nt_acl_internal: get_acl_blob returned %s\n",
			nt_errstr(status)));
		psd = pdesc_next;
		goto out;
	}

	status = parse_acl_blob(&blob, &psd,
				&hash_type, &hash[0]);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("parse_acl_blob returned %s\n",
				nt_errstr(status)));
		psd = pdesc_next;
		goto out;
	}

	/* Ensure the hash type is one we know. */
	switch (hash_type) {
		case XATTR_SD_HASH_TYPE_NONE:
			/* No hash, just return blob sd. */
			goto out;
		case XATTR_SD_HASH_TYPE_SHA256:
			break;
		default:
			DEBUG(10, ("get_nt_acl_internal: ACL blob revision "
				"mismatch (%u) for file %s\n",
				(unsigned int)hash_type,
				name));
			TALLOC_FREE(psd);
			psd = pdesc_next;
			goto out;
	}

	if (ignore_file_system_acl) {
		goto out;
	}

	status = hash_sd_sha256(pdesc_next, hash_tmp);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(psd);
		psd = pdesc_next;
		goto out;
	}

	if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
		/* Hash matches, return blob sd. */
		DEBUG(10, ("get_nt_acl_internal: blob hash "
			"matches for file %s\n",
			name ));
		goto out;
	}

	/* Hash doesn't match, return underlying sd. */
	TALLOC_FREE(psd);
	psd = pdesc_next;

  out:

	if (psd != pdesc_next) {
		/* We're returning the blob, throw
 		 * away the filesystem SD. */
		TALLOC_FREE(pdesc_next);
	} else {
		SMB_STRUCT_STAT sbuf;
		SMB_STRUCT_STAT *psbuf = &sbuf;
		bool is_directory = false;
		/*
		 * We're returning the underlying ACL from the
		 * filesystem. If it's a directory, and has no
		 * inheritable ACE entries we have to fake them.
		 */
		if (fsp) {
			status = vfs_stat_fsp(fsp);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}
			psbuf = &fsp->fsp_name->st;
		} else {
			int ret = vfs_stat_smb_fname(handle->conn,
						name,
						&sbuf);
			if (ret == -1) {
				return map_nt_error_from_unix(errno);
			}
		}
		is_directory = S_ISDIR(psbuf->st_ex_mode);

		if (ignore_file_system_acl) {
			TALLOC_FREE(pdesc_next);
			status = make_default_filesystem_acl(talloc_tos(),
						name,
						psbuf,
						&psd);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}
		} else {
			if (is_directory &&
				!sd_has_inheritable_components(psd,
							true)) {
				add_directory_inheritable_components(handle,
							name,
							psbuf,
							psd);
			}
			/* The underlying POSIX module always sets
			   the ~SEC_DESC_DACL_PROTECTED bit, as ACLs
			   can't be inherited in this way under POSIX.
			   Remove it for Windows-style ACLs. */
			psd->type &= ~SEC_DESC_DACL_PROTECTED;
		}
	}

	if (!(security_info & SECINFO_OWNER)) {
		psd->owner_sid = NULL;
	}
	if (!(security_info & SECINFO_GROUP)) {
		psd->group_sid = NULL;
	}
	if (!(security_info & SECINFO_DACL)) {
		psd->type &= ~SEC_DESC_DACL_PRESENT;
		psd->dacl = NULL;
	}
	if (!(security_info & SECINFO_SACL)) {
		psd->type &= ~SEC_DESC_SACL_PRESENT;
		psd->sacl = NULL;
	}

	TALLOC_FREE(blob.data);
	*ppdesc = psd;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
			name ));
		NDR_PRINT_DEBUG(security_descriptor, psd);
	}

	return NT_STATUS_OK;
}