mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
dc5dad4813
Get it from parent/deriving smb_filename if present. Use 0 (as usually this a Windows-style lookup) if not. Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Uri Simchoni <uri@samba.org>
653 lines
18 KiB
C
653 lines
18 KiB
C
/*
|
|
* Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
|
|
*
|
|
* Copyright (C) Jiri Sasek, 2007
|
|
* based on the foobar.c module which is copyrighted by Volker Lendecke
|
|
* based on pvfs_acl_nfs4.c Copyright (C) Andrew Tridgell 2006
|
|
*
|
|
* based on vfs_fake_acls:
|
|
* Copyright (C) Tim Potter, 1999-2000
|
|
* Copyright (C) Alexander Bokovoy, 2002
|
|
* Copyright (C) Andrew Bartlett, 2002,2012
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "system/filesys.h"
|
|
#include "smbd/smbd.h"
|
|
#include "nfs4_acls.h"
|
|
#include "librpc/gen_ndr/ndr_nfs4acl.h"
|
|
|
|
#undef DBGC_CLASS
|
|
#define DBGC_CLASS DBGC_VFS
|
|
|
|
static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
|
|
{
|
|
enum ndr_err_code ndr_err;
|
|
struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl);
|
|
if (!acl) {
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
ndr_err = ndr_pull_struct_blob(blob, acl, acl,
|
|
(ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
|
|
|
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
DEBUG(0, ("ndr_pull_acl_t failed: %s\n",
|
|
ndr_errstr(ndr_err)));
|
|
TALLOC_FREE(acl);
|
|
return NULL;
|
|
}
|
|
return acl;
|
|
}
|
|
|
|
static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
|
|
{
|
|
enum ndr_err_code ndr_err;
|
|
DATA_BLOB blob;
|
|
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
|
|
(ndr_push_flags_fn_t)ndr_push_nfs4acl);
|
|
|
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
DEBUG(0, ("ndr_push_acl_t failed: %s\n",
|
|
ndr_errstr(ndr_err)));
|
|
return data_blob_null;
|
|
}
|
|
return blob;
|
|
}
|
|
|
|
static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx,
|
|
DATA_BLOB *blob,
|
|
struct SMB4ACL_T **ppacl)
|
|
{
|
|
int i;
|
|
struct nfs4acl *nfs4acl = NULL;
|
|
struct SMB4ACL_T *pacl = NULL;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
nfs4acl = nfs4acl_blob2acl(blob, frame);
|
|
|
|
/* create SMB4ACL data */
|
|
if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
|
|
TALLOC_FREE(frame);
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
for(i=0; i<nfs4acl->a_count; i++) {
|
|
SMB_ACE4PROP_T aceprop;
|
|
|
|
aceprop.aceType = (uint32_t) nfs4acl->ace[i].e_type;
|
|
aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags;
|
|
aceprop.aceMask = (uint32_t) nfs4acl->ace[i].e_mask;
|
|
aceprop.who.id = (uint32_t) nfs4acl->ace[i].e_id;
|
|
if (!strcmp(nfs4acl->ace[i].e_who,
|
|
NFS4ACL_XATTR_OWNER_WHO)) {
|
|
aceprop.flags = SMB_ACE4_ID_SPECIAL;
|
|
aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
|
|
} else if (!strcmp(nfs4acl->ace[i].e_who,
|
|
NFS4ACL_XATTR_GROUP_WHO)) {
|
|
aceprop.flags = SMB_ACE4_ID_SPECIAL;
|
|
aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
|
|
} else if (!strcmp(nfs4acl->ace[i].e_who,
|
|
NFS4ACL_XATTR_EVERYONE_WHO)) {
|
|
aceprop.flags = SMB_ACE4_ID_SPECIAL;
|
|
aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
|
|
} else {
|
|
aceprop.flags = 0;
|
|
}
|
|
if(smb_add_ace4(pacl, &aceprop) == NULL) {
|
|
TALLOC_FREE(frame);
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
*ppacl = pacl;
|
|
TALLOC_FREE(frame);
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
|
|
static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
|
|
files_struct *fsp, struct SMB4ACL_T **ppacl)
|
|
{
|
|
NTSTATUS status;
|
|
DATA_BLOB blob = data_blob_null;
|
|
ssize_t length;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
|
|
do {
|
|
blob.length += 1000;
|
|
blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
|
|
if (!blob.data) {
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length);
|
|
blob.length = length;
|
|
} while (length == -1 && errno == ERANGE);
|
|
if (length == -1) {
|
|
TALLOC_FREE(frame);
|
|
return map_nt_error_from_unix(errno);
|
|
}
|
|
status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
/* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
|
|
static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
|
|
const char *path, struct SMB4ACL_T **ppacl)
|
|
{
|
|
NTSTATUS status;
|
|
DATA_BLOB blob = data_blob_null;
|
|
ssize_t length;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
|
|
do {
|
|
blob.length += 1000;
|
|
blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
|
|
if (!blob.data) {
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
length = SMB_VFS_NEXT_GETXATTR(handle, path, NFS4ACL_XATTR_NAME, blob.data, blob.length);
|
|
blob.length = length;
|
|
} while (length == -1 && errno == ERANGE);
|
|
if (length == -1) {
|
|
TALLOC_FREE(frame);
|
|
return map_nt_error_from_unix(errno);
|
|
}
|
|
status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
|
|
struct SMB4ACL_T *smbacl,
|
|
struct nfs4acl **pnfs4acl,
|
|
bool denymissingspecial)
|
|
{
|
|
struct nfs4acl *nfs4acl;
|
|
struct SMB4ACE_T *smbace;
|
|
bool have_special_id = false;
|
|
int i;
|
|
|
|
/* allocate the field of NFS4 aces */
|
|
nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
|
|
if(nfs4acl == NULL) {
|
|
errno = ENOMEM;
|
|
return false;
|
|
}
|
|
|
|
nfs4acl->a_count = smb_get_naces(smbacl);
|
|
|
|
nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
|
|
nfs4acl->a_count);
|
|
if(nfs4acl->ace == NULL) {
|
|
TALLOC_FREE(nfs4acl);
|
|
errno = ENOMEM;
|
|
return false;
|
|
}
|
|
|
|
/* handle all aces */
|
|
for(smbace = smb_first_ace4(smbacl), i = 0;
|
|
smbace!=NULL;
|
|
smbace = smb_next_ace4(smbace), i++) {
|
|
SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
|
|
|
|
nfs4acl->ace[i].e_type = aceprop->aceType;
|
|
nfs4acl->ace[i].e_flags = aceprop->aceFlags;
|
|
nfs4acl->ace[i].e_mask = aceprop->aceMask;
|
|
nfs4acl->ace[i].e_id = aceprop->who.id;
|
|
if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
|
|
switch(aceprop->who.special_id) {
|
|
case SMB_ACE4_WHO_EVERYONE:
|
|
nfs4acl->ace[i].e_who =
|
|
NFS4ACL_XATTR_EVERYONE_WHO;
|
|
break;
|
|
case SMB_ACE4_WHO_OWNER:
|
|
nfs4acl->ace[i].e_who =
|
|
NFS4ACL_XATTR_OWNER_WHO;
|
|
break;
|
|
case SMB_ACE4_WHO_GROUP:
|
|
nfs4acl->ace[i].e_who =
|
|
NFS4ACL_XATTR_GROUP_WHO;
|
|
break;
|
|
default:
|
|
DEBUG(8, ("unsupported special_id %d\n", \
|
|
aceprop->who.special_id));
|
|
continue; /* don't add it !!! */
|
|
}
|
|
have_special_id = true;
|
|
} else {
|
|
nfs4acl->ace[i].e_who = "";
|
|
}
|
|
}
|
|
|
|
if (!have_special_id && denymissingspecial) {
|
|
TALLOC_FREE(nfs4acl);
|
|
errno = EACCES;
|
|
return false;
|
|
}
|
|
|
|
SMB_ASSERT(i == nfs4acl->a_count);
|
|
|
|
*pnfs4acl = nfs4acl;
|
|
return true;
|
|
}
|
|
|
|
static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
|
|
const char *path,
|
|
struct SMB4ACL_T *smbacl)
|
|
{
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
struct nfs4acl *nfs4acl;
|
|
int ret;
|
|
bool denymissingspecial;
|
|
DATA_BLOB blob;
|
|
|
|
denymissingspecial = lp_parm_bool(handle->conn->params->service,
|
|
"nfs4acl_xattr",
|
|
"denymissingspecial", false);
|
|
|
|
if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
|
|
denymissingspecial)) {
|
|
DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
|
|
TALLOC_FREE(frame);
|
|
return false;
|
|
}
|
|
|
|
blob = nfs4acl_acl2blob(frame, nfs4acl);
|
|
if (!blob.data) {
|
|
DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
|
|
TALLOC_FREE(frame);
|
|
errno = EINVAL;
|
|
return false;
|
|
}
|
|
ret = SMB_VFS_NEXT_SETXATTR(handle, path, NFS4ACL_XATTR_NAME,
|
|
blob.data, blob.length, 0);
|
|
if (ret != 0) {
|
|
DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
|
|
}
|
|
TALLOC_FREE(frame);
|
|
return ret == 0;
|
|
}
|
|
|
|
/* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
|
|
static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle,
|
|
files_struct *fsp,
|
|
struct SMB4ACL_T *smbacl)
|
|
{
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
struct nfs4acl *nfs4acl;
|
|
int ret;
|
|
bool denymissingspecial;
|
|
DATA_BLOB blob;
|
|
|
|
denymissingspecial = lp_parm_bool(fsp->conn->params->service,
|
|
"nfs4acl_xattr",
|
|
"denymissingspecial", false);
|
|
|
|
if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
|
|
denymissingspecial)) {
|
|
DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
|
|
TALLOC_FREE(frame);
|
|
return false;
|
|
}
|
|
|
|
blob = nfs4acl_acl2blob(frame, nfs4acl);
|
|
if (!blob.data) {
|
|
DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
|
|
TALLOC_FREE(frame);
|
|
errno = EINVAL;
|
|
return false;
|
|
}
|
|
if (fsp->fh->fd == -1) {
|
|
DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
|
|
}
|
|
ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME,
|
|
blob.data, blob.length, 0);
|
|
if (ret != 0) {
|
|
DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
|
|
}
|
|
TALLOC_FREE(frame);
|
|
return ret == 0;
|
|
}
|
|
|
|
/* nfs4_set_nt_acl()
|
|
* set the local file's acls obtaining it in NT form
|
|
* using the NFSv4 format conversion
|
|
*/
|
|
static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
|
|
uint32_t security_info_sent,
|
|
const struct security_descriptor *psd)
|
|
{
|
|
return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
|
|
nfs4acl_xattr_fset_smb4acl);
|
|
}
|
|
|
|
static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
|
|
{
|
|
struct SMB4ACL_T *pacl = NULL;
|
|
struct SMB4ACE_T *pace;
|
|
SMB_ACE4PROP_T ace = {
|
|
.flags = SMB_ACE4_ID_SPECIAL,
|
|
.who = {
|
|
.id = SMB_ACE4_WHO_EVERYONE,
|
|
},
|
|
.aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
|
|
.aceFlags = 0,
|
|
.aceMask = SMB_ACE4_ALL_MASKS,
|
|
};
|
|
|
|
DEBUG(10, ("Building default full access acl\n"));
|
|
|
|
pacl = smb_create_smb4acl(mem_ctx);
|
|
if (pacl == NULL) {
|
|
DEBUG(0, ("talloc failed\n"));
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
pace = smb_add_ace4(pacl, &ace);
|
|
if (pace == NULL) {
|
|
DEBUG(0, ("talloc failed\n"));
|
|
TALLOC_FREE(pacl);
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
return pacl;
|
|
}
|
|
|
|
/*
|
|
* Because there is no good way to guarantee that a new xattr will be
|
|
* created on file creation there might be no acl xattr on a file when
|
|
* trying to read the acl. In this case the acl xattr will get
|
|
* constructed at that time from the parent acl.
|
|
* If the parent ACL doesn't have an xattr either the call will
|
|
* recurse to the next parent directory until the share root is
|
|
* reached. If the share root doesn't contain an ACL xattr either a
|
|
* default ACL will be used.
|
|
* Also a default ACL will be set if a non inheriting ACL is encountered.
|
|
*
|
|
* Basic algorithm:
|
|
* read acl xattr blob
|
|
* if acl xattr blob doesn't exist
|
|
* stat current directory to know if it's a file or directory
|
|
* read acl xattr blob from parent dir
|
|
* acl xattr blob to smb nfs4 acl
|
|
* calculate inherited smb nfs4 acl
|
|
* without inheritance use default smb nfs4 acl
|
|
* smb nfs4 acl to acl xattr blob
|
|
* set acl xattr blob
|
|
* return smb nfs4 acl
|
|
* else
|
|
* acl xattr blob to smb nfs4 acl
|
|
*
|
|
* Todo: Really use mem_ctx after fixing interface of nfs4_acls
|
|
*/
|
|
static struct SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
|
|
const char *path,
|
|
TALLOC_CTX *mem_ctx)
|
|
{
|
|
char *parent_dir = NULL;
|
|
struct SMB4ACL_T *pparentacl = NULL;
|
|
struct SMB4ACL_T *pchildacl = NULL;
|
|
struct SMB4ACE_T *pace;
|
|
SMB_ACE4PROP_T ace;
|
|
bool isdir;
|
|
struct smb_filename *smb_fname = NULL;
|
|
NTSTATUS status;
|
|
int ret;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
|
|
DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n", path));
|
|
smb_fname = synthetic_smb_fname(frame, path, NULL, NULL, 0);
|
|
if (smb_fname == NULL) {
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
ret = SMB_VFS_STAT(handle->conn, smb_fname);
|
|
if (ret == -1) {
|
|
DEBUG(0,("nfs4acls_inheritacl: failed to stat "
|
|
"directory %s. Error was %s\n",
|
|
smb_fname_str_dbg(smb_fname),
|
|
strerror(errno)));
|
|
TALLOC_FREE(frame);
|
|
return NULL;
|
|
}
|
|
isdir = S_ISDIR(smb_fname->st.st_ex_mode);
|
|
|
|
if (!parent_dirname(talloc_tos(),
|
|
path,
|
|
&parent_dir,
|
|
NULL)) {
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
status = nfs4_get_nfs4_acl(handle, frame, parent_dir, &pparentacl);
|
|
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)
|
|
&& strncmp(parent_dir, ".", 2) != 0) {
|
|
pparentacl = nfs4acls_inheritacl(handle, parent_dir,
|
|
frame);
|
|
}
|
|
else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
|
pparentacl = nfs4acls_defaultacl(frame);
|
|
|
|
}
|
|
else if (!NT_STATUS_IS_OK(status)) {
|
|
TALLOC_FREE(frame);
|
|
return NULL;
|
|
}
|
|
|
|
pchildacl = smb_create_smb4acl(mem_ctx);
|
|
if (pchildacl == NULL) {
|
|
DEBUG(0, ("talloc failed\n"));
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
for (pace = smb_first_ace4(pparentacl); pace != NULL;
|
|
pace = smb_next_ace4(pace)) {
|
|
struct SMB4ACE_T *pchildace;
|
|
ace = *smb_get_ace4(pace);
|
|
if ((isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) ||
|
|
(!isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))) {
|
|
DEBUG(10, ("non inheriting ace type: %d, iflags: %x, "
|
|
"flags: %x, mask: %x, who: %d\n",
|
|
ace.aceType, ace.flags, ace.aceFlags,
|
|
ace.aceMask, ace.who.id));
|
|
continue;
|
|
}
|
|
DEBUG(10, ("inheriting ace type: %d, iflags: %x, "
|
|
"flags: %x, mask: %x, who: %d\n",
|
|
ace.aceType, ace.flags, ace.aceFlags,
|
|
ace.aceMask, ace.who.id));
|
|
ace.aceFlags |= SMB_ACE4_INHERITED_ACE;
|
|
if (ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) {
|
|
ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE;
|
|
}
|
|
if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) {
|
|
ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE;
|
|
ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE;
|
|
ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE;
|
|
}
|
|
pchildace = smb_add_ace4(pchildacl, &ace);
|
|
if (pchildace == NULL) {
|
|
DEBUG(0, ("talloc failed\n"));
|
|
TALLOC_FREE(frame);
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Set a default ACL if we didn't inherit anything. */
|
|
if (smb_first_ace4(pchildacl) == NULL) {
|
|
TALLOC_FREE(pchildacl);
|
|
pchildacl = nfs4acls_defaultacl(mem_ctx);
|
|
}
|
|
|
|
/* store the returned ACL to get it directly in the
|
|
future and avoid dynamic inheritance behavior. */
|
|
nfs4acl_xattr_set_smb4acl(handle, path, pchildacl);
|
|
|
|
TALLOC_FREE(frame);
|
|
return pchildacl;
|
|
}
|
|
|
|
static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
|
|
struct files_struct *fsp,
|
|
uint32_t security_info,
|
|
TALLOC_CTX *mem_ctx,
|
|
struct security_descriptor **ppdesc)
|
|
{
|
|
struct SMB4ACL_T *pacl;
|
|
NTSTATUS status;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
|
|
status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
|
|
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
|
pacl = nfs4acls_inheritacl(handle, fsp->fsp_name->base_name,
|
|
frame);
|
|
}
|
|
else if (!NT_STATUS_IS_OK(status)) {
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
|
|
const struct smb_filename *smb_fname,
|
|
uint32_t security_info,
|
|
TALLOC_CTX *mem_ctx,
|
|
struct security_descriptor **ppdesc)
|
|
{
|
|
struct SMB4ACL_T *pacl;
|
|
NTSTATUS status;
|
|
const char *name = smb_fname->base_name;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
|
|
status = nfs4_get_nfs4_acl(handle, frame, name, &pacl);
|
|
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
|
pacl = nfs4acls_inheritacl(handle, name, frame);
|
|
}
|
|
else if (!NT_STATUS_IS_OK(status)) {
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, security_info,
|
|
mem_ctx, ppdesc,
|
|
pacl);
|
|
TALLOC_FREE(frame);
|
|
return status;
|
|
}
|
|
|
|
static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
|
|
files_struct *fsp,
|
|
uint32_t security_info_sent,
|
|
const struct security_descriptor *psd)
|
|
{
|
|
return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd);
|
|
}
|
|
|
|
/*
|
|
As long as Samba does not support an exiplicit method for a module
|
|
to define conflicting vfs methods, we should override all conflicting
|
|
methods here. That way, we know we are using the NFSv4 storage
|
|
|
|
Function declarations taken from vfs_solarisacl
|
|
*/
|
|
|
|
static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
|
|
const char *path_p,
|
|
SMB_ACL_TYPE_T type,
|
|
TALLOC_CTX *mem_ctx)
|
|
{
|
|
return (SMB_ACL_T)NULL;
|
|
}
|
|
|
|
static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
|
|
files_struct *fsp,
|
|
TALLOC_CTX *mem_ctx)
|
|
{
|
|
return (SMB_ACL_T)NULL;
|
|
}
|
|
|
|
static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
|
|
const char *name,
|
|
SMB_ACL_TYPE_T type,
|
|
SMB_ACL_T theacl)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
|
|
files_struct *fsp,
|
|
SMB_ACL_T theacl)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
|
|
const char *path)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle, const char *path_p, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *fsp, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* VFS operations structure */
|
|
|
|
static struct vfs_fn_pointers nfs4acl_xattr_fns = {
|
|
.sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
|
|
.sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
|
|
.sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
|
|
.sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
|
|
.sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
|
|
.sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
|
|
.sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
|
|
.fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
|
|
.get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
|
|
.fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
|
|
};
|
|
|
|
NTSTATUS vfs_nfs4acl_xattr_init(void);
|
|
NTSTATUS vfs_nfs4acl_xattr_init(void)
|
|
{
|
|
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
|
|
&nfs4acl_xattr_fns);
|
|
}
|