s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source3 / modules / vfs_zfsacl.c
index b0a93aa410eab17d80a22204d65dbc4743ce604b..695abf1e0df62f06fc3dfab9c88312b22a1af007 100644 (file)
@@ -40,6 +40,7 @@ struct zfsacl_config_data {
        struct smbacl4_vfs_params nfs4_params;
        bool zfsacl_map_dacl_protected;
        bool zfsacl_denymissingspecial;
+       bool zfsacl_block_special;
 };
 
 /* zfs_get_nt_acl()
@@ -85,12 +86,20 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
        }
        for(i=0; i<naces; i++) {
                SMB_ACE4PROP_T aceprop;
+               uint16_t special = 0;
 
                aceprop.aceType  = (uint32_t) acebuf[i].a_type;
                aceprop.aceFlags = (uint32_t) acebuf[i].a_flags;
                aceprop.aceMask  = (uint32_t) acebuf[i].a_access_mask;
                aceprop.who.id   = (uint32_t) acebuf[i].a_who;
 
+               if (config->zfsacl_block_special &&
+                   (aceprop.aceMask == 0) &&
+                   (aceprop.aceFlags & ACE_EVERYONE) &&
+                   (aceprop.aceFlags & ACE_INHERITED_ACE))
+               {
+                       continue;
+               }
                /*
                 * Windows clients expect SYNC on acls to correctly allow
                 * rename, cf bug #7909. But not on DENY ace entries, cf bug
@@ -100,7 +109,12 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
                        aceprop.aceMask |= SMB_ACE4_SYNCHRONIZE;
                }
 
-               if (is_dir && (aceprop.aceMask & SMB_ACE4_ADD_FILE)) {
+               special = acebuf[i].a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE);
+
+               if (is_dir &&
+                   (aceprop.aceMask & SMB_ACE4_ADD_FILE) &&
+                   (special != 0))
+               {
                        aceprop.aceMask |= SMB_ACE4_DELETE_CHILD;
                }
 
@@ -109,20 +123,25 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
                        inherited_is_present = true;
                }
 #endif
-               if(aceprop.aceFlags & ACE_OWNER) {
+               switch(special) {
+               case(ACE_OWNER):
                        aceprop.flags = SMB_ACE4_ID_SPECIAL;
                        aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
-               } else if(aceprop.aceFlags & ACE_GROUP) {
+                       break;
+               case(ACE_GROUP):
                        aceprop.flags = SMB_ACE4_ID_SPECIAL;
                        aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
-               } else if(aceprop.aceFlags & ACE_EVERYONE) {
+                       break;
+               case(ACE_EVERYONE):
                        aceprop.flags = SMB_ACE4_ID_SPECIAL;
                        aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
-               } else {
+                       break;
+               default:
                        aceprop.flags   = 0;
                }
-               if(smb_add_ace4(pacl, &aceprop) == NULL)
+               if (smb_add_ace4(pacl, &aceprop) == NULL) {
                        return NT_STATUS_NO_MEMORY;
+               }
        }
 
 #ifdef ACE_INHERITED_ACE
@@ -147,12 +166,18 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
        struct SMB4ACE_T *smbace;
        TALLOC_CTX      *mem_ctx;
        bool have_special_id = false;
+       bool must_add_empty_ace = false;
        struct zfsacl_config_data *config = NULL;
+       int fd;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct zfsacl_config_data,
                                return False);
 
+       if (config->zfsacl_block_special && S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
+               naces++;
+               must_add_empty_ace = true;
+       }
        /* allocate the field of ZFS aces */
        mem_ctx = talloc_tos();
        acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
@@ -192,6 +217,15 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
                        have_special_id = true;
                }
        }
+       if (must_add_empty_ace) {
+               acebuf[i].a_type = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE;
+               acebuf[i].a_flags = SMB_ACE4_DIRECTORY_INHERIT_ACE |
+                       SMB_ACE4_FILE_INHERIT_ACE |
+                       ACE_EVERYONE |
+                       ACE_INHERITED_ACE;
+               acebuf[i].a_access_mask = 0;
+               i++;
+       }
 
        if (!have_special_id && config->zfsacl_denymissingspecial) {
                errno = EACCES;
@@ -201,19 +235,19 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
        SMB_ASSERT(i == naces);
 
        /* store acl */
-       if (fsp->fh->fd != -1) {
-               rv = facl(fsp->fh->fd, ACE_SETACL, naces, acebuf);
-       }
-       else {
-               rv = acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf);
+       fd = fsp_get_pathref_fd(fsp);
+       if (fd == -1) {
+               errno = EBADF;
+               return false;
        }
+       rv = facl(fd, ACE_SETACL, naces, acebuf);
        if (rv != 0) {
                if(errno == ENOSYS) {
                        DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not "
                                  "supported on the filesystem where the file "
-                                 "reside", fsp_str_dbg(fsp)));
+                                 "resides\n", fsp_str_dbg(fsp)));
                } else {
-                       DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp_str_dbg(fsp),
+                       DEBUG(9, ("acl(ACE_SETACL, %s): %s\n", fsp_str_dbg(fsp),
                                  strerror(errno)));
                }
                return false;
@@ -244,60 +278,27 @@ static NTSTATUS zfs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                zfs_process_smbacl);
 }
 
-static int get_zfsacl(TALLOC_CTX *mem_ctx,
-                     const struct smb_filename *smb_fname,
-                     ace_t **outbuf)
-{
-       int naces, rv;
-       ace_t *acebuf = NULL;
-
-       naces = acl(smb_fname->base_name, ACE_GETACLCNT, 0, NULL);
-       if (naces == -1) {
-               int dbg_level = 10;
-
-               if (errno == ENOSYS) {
-                       dbg_level = 1;
-               }
-               DEBUG(dbg_level, ("acl(ACE_GETACLCNT, %s): %s ",
-                                 smb_fname->base_name, strerror(errno)));
-               return naces;
-       }
-       acebuf = talloc_size(mem_ctx, sizeof(ace_t)*naces);
-       if (acebuf == NULL) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       rv = acl(smb_fname->base_name, ACE_GETACL, naces, acebuf);
-       if (rv == -1) {
-               DBG_DEBUG("acl(ACE_GETACL, %s) failed: %s ",
-                         smb_fname->base_name, strerror(errno));
-               return -1;
-       }
-
-       *outbuf = acebuf;
-       return naces;
-}
-
 static int fget_zfsacl(TALLOC_CTX *mem_ctx,
                       struct files_struct *fsp,
                       ace_t **outbuf)
 {
        int naces, rv;
        ace_t *acebuf = NULL;
+       int fd;
 
-       if (fsp->fh->fd == -1) {
-               return get_zfsacl(mem_ctx, fsp->fsp_name, outbuf);
+       fd = fsp_get_pathref_fd(fsp);
+       if (fd == -1) {
+               errno = EBADF;
+               return -1;
        }
-
-       naces = facl(fsp->fh->fd, ACE_GETACLCNT, 0, NULL);
+       naces = facl(fd, ACE_GETACLCNT, 0, NULL);
        if (naces == -1) {
                int dbg_level = 10;
 
                if (errno == ENOSYS) {
                        dbg_level = 1;
                }
-               DEBUG(dbg_level, ("facl(ACE_GETACLCNT, %s): %s ",
+               DEBUG(dbg_level, ("facl(ACE_GETACLCNT, %s): %s\n",
                                  fsp_str_dbg(fsp), strerror(errno)));
                return naces;
        }
@@ -308,9 +309,9 @@ static int fget_zfsacl(TALLOC_CTX *mem_ctx,
                return -1;
        }
 
-       rv = facl(fsp->fh->fd, ACE_GETACL, naces, acebuf);
+       rv = facl(fd, ACE_GETACL, naces, acebuf);
        if (rv == -1) {
-               DBG_DEBUG("acl(ACE_GETACL, %s): %s ",
+               DBG_DEBUG("acl(ACE_GETACL, %s): %s\n",
                          fsp_str_dbg(fsp), strerror(errno));
                return -1;
        }
@@ -325,6 +326,7 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
                                   TALLOC_CTX *mem_ctx,
                                   struct security_descriptor **ppdesc)
 {
+       TALLOC_CTX *frame = NULL;
        struct SMB4ACL_T *pacl;
        NTSTATUS status;
        struct zfsacl_config_data *config = NULL;
@@ -335,7 +337,7 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
                                struct zfsacl_config_data,
                                return NT_STATUS_INTERNAL_ERROR);
 
-       TALLOC_CTX *frame = talloc_stackframe();
+       frame = talloc_stackframe();
 
        naces = fget_zfsacl(talloc_tos(), fsp, &acebuf);
        if (naces == -1) {
@@ -375,78 +377,6 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
        return status;
 }
 
-static NTSTATUS zfsacl_get_nt_acl_at(struct vfs_handle_struct *handle,
-                               struct files_struct *dirfsp,
-                               const struct smb_filename *smb_fname,
-                               uint32_t security_info,
-                               TALLOC_CTX *mem_ctx,
-                               struct security_descriptor **ppdesc)
-{
-       struct SMB4ACL_T *pacl = NULL;
-       NTSTATUS status;
-       struct zfsacl_config_data *config = NULL;
-       TALLOC_CTX *frame = NULL;
-       int naces;
-       ace_t *acebuf = NULL;
-
-       SMB_ASSERT(dirfsp == handle->conn->cwd_fsp);
-
-       SMB_VFS_HANDLE_GET_DATA(handle,
-                               config,
-                               struct zfsacl_config_data,
-                               return NT_STATUS_INTERNAL_ERROR);
-
-       frame = talloc_stackframe();
-
-       naces = get_zfsacl(frame, smb_fname, &acebuf);
-       if (naces == -1) {
-               status = map_nt_error_from_unix(errno);
-               TALLOC_FREE(frame);
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
-                       return status;
-               }
-
-               if (!VALID_STAT(smb_fname->st)) {
-                       DBG_ERR("No stat info for [%s]\n",
-                               smb_fname_str_dbg(smb_fname));
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-
-               status = make_default_filesystem_acl(mem_ctx,
-                                                    DEFAULT_ACL_POSIX,
-                                                    smb_fname->base_name,
-                                                    &smb_fname->st,
-                                                    ppdesc);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-               (*ppdesc)->type |= SEC_DESC_DACL_PROTECTED;
-               return NT_STATUS_OK;
-       }
-
-       status = zfs_get_nt_acl_common(handle->conn,
-                                      frame,
-                                      smb_fname,
-                                      acebuf,
-                                      naces,
-                                      &pacl,
-                                      config);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(frame);
-               return status;
-       }
-
-       status = smb_get_nt_acl_nfs4(handle->conn,
-                                       smb_fname,
-                                       NULL,
-                                       security_info,
-                                       mem_ctx,
-                                       ppdesc,
-                                       pacl);
-       TALLOC_FREE(frame);
-       return status;
-}
-
 static NTSTATUS zfsacl_fset_nt_acl(vfs_handle_struct *handle,
                         files_struct *fsp,
                         uint32_t security_info_sent,
@@ -486,47 +416,24 @@ static NTSTATUS zfsacl_fset_nt_acl(vfs_handle_struct *handle,
    Function declarations taken from vfs_solarisacl
 */
 
-static SMB_ACL_T zfsacl_fail__sys_acl_get_file(vfs_handle_struct *handle,
-                                       const struct smb_filename *smb_fname,
-                                       SMB_ACL_TYPE_T type,
-                                       TALLOC_CTX *mem_ctx)
-{
-       return (SMB_ACL_T)NULL;
-}
-
 static SMB_ACL_T zfsacl_fail__sys_acl_get_fd(vfs_handle_struct *handle,
                                             files_struct *fsp,
+                                            SMB_ACL_TYPE_T type,
                                             TALLOC_CTX *mem_ctx)
 {
        return (SMB_ACL_T)NULL;
 }
 
-static int zfsacl_fail__sys_acl_set_file(vfs_handle_struct *handle,
-                                        const struct smb_filename *smb_fname,
-                                        SMB_ACL_TYPE_T type,
-                                        SMB_ACL_T theacl)
-{
-       return -1;
-}
-
 static int zfsacl_fail__sys_acl_set_fd(vfs_handle_struct *handle,
                                       files_struct *fsp,
+                                      SMB_ACL_TYPE_T type,
                                       SMB_ACL_T theacl)
 {
        return -1;
 }
 
-static int zfsacl_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname)
-{
-       return -1;
-}
-
-static int zfsacl_fail__sys_acl_blob_get_file(vfs_handle_struct *handle,
-                       const struct smb_filename *smb_fname,
-                       TALLOC_CTX *mem_ctx,
-                       char **blob_description,
-                       DATA_BLOB *blob)
+static int zfsacl_fail__sys_acl_delete_def_fd(vfs_handle_struct *handle,
+                                             files_struct *fsp)
 {
        return -1;
 }
@@ -560,6 +467,9 @@ static int zfsacl_connect(struct vfs_handle_struct *handle,
        config->zfsacl_denymissingspecial = lp_parm_bool(SNUM(handle->conn),
                                "zfsacl", "denymissingspecial", false);
 
+       config->zfsacl_block_special = lp_parm_bool(SNUM(handle->conn),
+                               "zfsacl", "block_special", true);
+
        ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params);
        if (ret < 0) {
                TALLOC_FREE(config);
@@ -577,15 +487,15 @@ static int zfsacl_connect(struct vfs_handle_struct *handle,
 
 static struct vfs_fn_pointers zfsacl_fns = {
        .connect_fn = zfsacl_connect,
-       .sys_acl_get_file_fn = zfsacl_fail__sys_acl_get_file,
+       .stat_fn = nfs4_acl_stat,
+       .fstat_fn = nfs4_acl_fstat,
+       .lstat_fn = nfs4_acl_lstat,
+       .fstatat_fn = nfs4_acl_fstatat,
        .sys_acl_get_fd_fn = zfsacl_fail__sys_acl_get_fd,
-       .sys_acl_blob_get_file_fn = zfsacl_fail__sys_acl_blob_get_file,
        .sys_acl_blob_get_fd_fn = zfsacl_fail__sys_acl_blob_get_fd,
-       .sys_acl_set_file_fn = zfsacl_fail__sys_acl_set_file,
        .sys_acl_set_fd_fn = zfsacl_fail__sys_acl_set_fd,
-       .sys_acl_delete_def_file_fn = zfsacl_fail__sys_acl_delete_def_file,
+       .sys_acl_delete_def_fd_fn = zfsacl_fail__sys_acl_delete_def_fd,
        .fget_nt_acl_fn = zfsacl_fget_nt_acl,
-       .get_nt_acl_at_fn = zfsacl_get_nt_acl_at,
        .fset_nt_acl_fn = zfsacl_fset_nt_acl,
 };