s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source3 / modules / vfs_posixacl.c
index 109c1e20b2ef24cc65b4254d87f4f016af4d69a9..feb819de98259dc176651e86cde45a5089e67c27 100644 (file)
@@ -5,7 +5,7 @@
 
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #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,
+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:
@@ -51,44 +53,42 @@ SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
                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:
@@ -98,45 +98,49 @@ int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
                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,
+static bool smb_ace_to_internal(acl_entry_t posix_ace,
                                struct smb_acl_entry *ace)
 {
        acl_tag_t tag;
@@ -166,6 +170,11 @@ 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;
@@ -177,18 +186,18 @@ static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
                        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;
        }
@@ -212,30 +221,29 @@ static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
        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;
                }
 
@@ -267,7 +275,8 @@ static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
            ((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)
@@ -324,14 +333,14 @@ 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;
@@ -347,8 +356,10 @@ static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
        }
 
        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;
        }
 
@@ -363,36 +374,16 @@ static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
 
 /* 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);
 }