*/
#include "includes.h"
-
+#include "system/filesys.h"
+#include "smbd/smbd.h"
+#include "modules/vfs_posixacl.h"
/* prototypes for static functions first - for clarity */
static bool smb_ace_to_internal(acl_entry_t posix_ace,
struct smb_acl_entry *ace);
-static struct smb_acl_t *smb_acl_to_internal(acl_t acl);
+static struct smb_acl_t *smb_acl_to_internal(acl_t acl, TALLOC_CTX *mem_ctx);
static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
/* public functions - the api */
-SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
- const char *path_p,
- SMB_ACL_TYPE_T type)
+SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_TYPE_T type,
+ TALLOC_CTX *mem_ctx)
{
struct smb_acl_t *result;
+ acl_t acl = NULL;
acl_type_t acl_type;
- acl_t acl;
switch(type) {
case SMB_ACL_TYPE_ACCESS:
errno = EINVAL;
return NULL;
}
-
- acl = acl_get_file(path_p, acl_type);
-
- if (acl == NULL) {
- return NULL;
+ if (!fsp->fsp_flags.is_pathref && (acl_type == ACL_TYPE_ACCESS)) {
+ /* POSIX API only allows ACL_TYPE_ACCESS fetched on fd. */
+ acl = acl_get_fd(fsp_get_io_fd(fsp));
+ } else if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
+
+ acl = acl_get_file(sys_proc_fd_path(fd, &buf), acl_type);
+ } else {
+ /*
+ * This is no longer a handle based call.
+ */
+ acl = acl_get_file(fsp->fsp_name->base_name, acl_type);
}
-
- result = smb_acl_to_internal(acl);
- acl_free(acl);
- return result;
-}
-
-SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- int fd)
-{
- struct smb_acl_t *result;
- acl_t acl = acl_get_fd(fd);
-
if (acl == NULL) {
return NULL;
}
- result = smb_acl_to_internal(acl);
+ result = smb_acl_to_internal(acl, mem_ctx);
acl_free(acl);
return result;
}
-int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
- const char *name,
- SMB_ACL_TYPE_T type,
- SMB_ACL_T theacl)
+int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
{
int res;
+ acl_t acl = smb_acl_to_posix(theacl);
acl_type_t acl_type;
- acl_t acl;
+ int fd = fsp_get_pathref_fd(fsp);
- DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type));
+ if (acl == NULL) {
+ return -1;
+ }
switch(type) {
case SMB_ACL_TYPE_ACCESS:
acl_type = ACL_TYPE_DEFAULT;
break;
default:
+ acl_free(acl);
errno = EINVAL;
return -1;
}
- if ((acl = smb_acl_to_posix(theacl)) == NULL) {
- return -1;
- }
- res = acl_set_file(name, acl_type, acl);
- if (res != 0) {
- DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
+ if (!fsp->fsp_flags.is_pathref && type == SMB_ACL_TYPE_ACCESS) {
+ res = acl_set_fd(fd, acl);
+ } else if (fsp->fsp_flags.have_proc_fds) {
+ struct sys_proc_fd_path_buf buf;
+
+ res = acl_set_file(sys_proc_fd_path(fd, &buf), acl_type, acl);
+ } else {
+ /*
+ * This is no longer a handle based call.
+ */
+ res = acl_set_file(fsp->fsp_name->base_name,
+ acl_type,
+ acl);
}
+
acl_free(acl);
return res;
}
-int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
- files_struct *fsp,
- int fd, SMB_ACL_T theacl)
+int posixacl_sys_acl_delete_def_fd(vfs_handle_struct *handle,
+ files_struct *fsp)
{
- int res;
- acl_t acl = smb_acl_to_posix(theacl);
- if (acl == NULL) {
- return -1;
+ if (fsp->fsp_flags.have_proc_fds) {
+ int fd = fsp_get_pathref_fd(fsp);
+ struct sys_proc_fd_path_buf buf;
+
+ return acl_delete_def_file(sys_proc_fd_path(fd, &buf));
}
- res = acl_set_fd(fd, acl);
- acl_free(acl);
- return res;
-}
-int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
- const char *path)
-{
- return acl_delete_def_file(path);
+ /*
+ * This is no longer a handle based call.
+ */
+ return acl_delete_def_file(fsp->fsp_name->base_name);
}
-
/* private functions */
static bool smb_ace_to_internal(acl_entry_t posix_ace,
case ACL_MASK:
ace->a_type = SMB_ACL_MASK;
break;
+#ifdef HAVE_ACL_EVERYONE
+ case ACL_EVERYONE:
+ DEBUG(1, ("ACL tag type ACL_EVERYONE. FreeBSD with ZFS? Use 'vfs objects = zfsacl'\n"));
+ return false;
+#endif
default:
DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
return False;
DEBUG(0, ("smb_acl_get_qualifier failed\n"));
return False;
}
- ace->uid = *puid;
+ ace->info.user.uid = *puid;
acl_free(puid);
break;
}
-
+
case SMB_ACL_GROUP: {
gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
if (pgid == NULL) {
DEBUG(0, ("smb_acl_get_qualifier failed\n"));
return False;
}
- ace->gid = *pgid;
+ ace->info.group.gid = *pgid;
acl_free(pgid);
break;
}
return True;
}
-static struct smb_acl_t *smb_acl_to_internal(acl_t acl)
+static struct smb_acl_t *smb_acl_to_internal(acl_t acl, TALLOC_CTX *mem_ctx)
{
- struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
+ struct smb_acl_t *result = sys_acl_init(mem_ctx);
int entry_id = ACL_FIRST_ENTRY;
acl_entry_t e;
if (result == NULL) {
return NULL;
}
- ZERO_STRUCTP(result);
while (acl_get_entry(acl, entry_id, &e) == 1) {
entry_id = ACL_NEXT_ENTRY;
- result = (struct smb_acl_t *)SMB_REALLOC(
- result, sizeof(struct smb_acl_t) +
- (sizeof(struct smb_acl_entry) * (result->count+1)));
- if (result == NULL) {
- DEBUG(0, ("SMB_REALLOC failed\n"));
+ result->acl = talloc_realloc(result, result->acl,
+ struct smb_acl_entry, result->count+1);
+ if (result->acl == NULL) {
+ TALLOC_FREE(result);
+ DEBUG(0, ("talloc_realloc failed\n"));
errno = ENOMEM;
return NULL;
}
if (!smb_ace_to_internal(e, &result->acl[result->count])) {
- SAFE_FREE(result);
+ TALLOC_FREE(result);
return NULL;
}
((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
return ret;
}
- return acl_set_permset(entry, permset);
+
+ return 0;
}
static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
switch (entry->a_type) {
case SMB_ACL_USER:
- if (acl_set_qualifier(e, &entry->uid) != 0) {
+ if (acl_set_qualifier(e, &entry->info.user.uid) != 0) {
DEBUG(1, ("acl_set_qualifiier failed: %s\n",
strerror(errno)));
goto fail;
}
break;
case SMB_ACL_GROUP:
- if (acl_set_qualifier(e, &entry->gid) != 0) {
+ if (acl_set_qualifier(e, &entry->info.group.gid) != 0) {
DEBUG(1, ("acl_set_qualifiier failed: %s\n",
strerror(errno)));
goto fail;
}
if (acl_valid(result) != 0) {
- DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
- strerror(errno)));
+ char *acl_string = sys_acl_to_text(acl, NULL);
+ DEBUG(0, ("smb_acl_to_posix: ACL %s is invalid for set (%s)\n",
+ acl_string, strerror(errno)));
+ SAFE_FREE(acl_string);
goto fail;
}
/* VFS operations structure */
-static vfs_op_tuple posixacl_op_tuples[] = {
- /* Disk operations */
- {SMB_VFS_OP(posixacl_sys_acl_get_file),
- SMB_VFS_OP_SYS_ACL_GET_FILE,
- SMB_VFS_LAYER_TRANSPARENT},
-
- {SMB_VFS_OP(posixacl_sys_acl_get_fd),
- SMB_VFS_OP_SYS_ACL_GET_FD,
- SMB_VFS_LAYER_TRANSPARENT},
-
- {SMB_VFS_OP(posixacl_sys_acl_set_file),
- SMB_VFS_OP_SYS_ACL_SET_FILE,
- SMB_VFS_LAYER_TRANSPARENT},
-
- {SMB_VFS_OP(posixacl_sys_acl_set_fd),
- SMB_VFS_OP_SYS_ACL_SET_FD,
- SMB_VFS_LAYER_TRANSPARENT},
-
- {SMB_VFS_OP(posixacl_sys_acl_delete_def_file),
- SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
- SMB_VFS_LAYER_TRANSPARENT},
-
- {SMB_VFS_OP(NULL),
- SMB_VFS_OP_NOOP,
- SMB_VFS_LAYER_NOOP}
+static struct vfs_fn_pointers posixacl_fns = {
+ .sys_acl_get_fd_fn = posixacl_sys_acl_get_fd,
+ .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
+ .sys_acl_set_fd_fn = posixacl_sys_acl_set_fd,
+ .sys_acl_delete_def_fd_fn = posixacl_sys_acl_delete_def_fd,
};
-NTSTATUS vfs_posixacl_init(void);
-NTSTATUS vfs_posixacl_init(void)
+static_decl_vfs;
+NTSTATUS vfs_posixacl_init(TALLOC_CTX *ctx)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
- posixacl_op_tuples);
+ &posixacl_fns);
}