a68258cfdb968369faea842ca6f4b8549accd34a
[gd/samba/.git] / source3 / modules / vfs_zfsacl.c
1 /*
2  * Convert ZFS/NFSv4 acls to NT acls and vice versa.
3  *
4  * Copyright (C) Jiri Sasek, 2007
5  * based on the foobar.c module which is copyrighted by Volker Lendecke
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #include "includes.h"
24 #include "nfs4_acls.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_VFS
28
29 #define ZFSACL_MODULE_NAME "zfsacl"
30
31 /* zfs_get_nt_acl()
32  * read the local file's acls and return it in NT form
33  * using the NFSv4 format conversion
34  */
35 static size_t zfs_get_nt_acl(struct files_struct *fsp, uint32 security_info,
36                              struct security_descriptor **ppdesc)
37 {
38         int naces, i;
39         ace_t *acebuf;
40         SMB4ACL_T *pacl;
41         TALLOC_CTX      *mem_ctx;
42
43         /* read the number of file aces */
44         if((naces = acl(fsp->fsp_name, ACE_GETACLCNT, 0, NULL)) == -1) {
45                 if(errno == ENOSYS) {
46                         DEBUG(9, ("acl(ACE_GETACLCNT, %s): Operation is not supported on the filesystem where the file reside"));
47                 } else {
48                         DEBUG(9, ("acl(ACE_GETACLCNT, %s): %s ", fsp->fsp_name,
49                                         strerror(errno)));
50                 }
51                 return 0;
52         }
53         /* allocate the field of ZFS aces */
54         mem_ctx = main_loop_talloc_get();
55         acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
56         if(acebuf == NULL) {
57                 errno = ENOMEM;
58                 return 0;
59         }
60         /* read the aces into the field */
61         if(acl(fsp->fsp_name, ACE_GETACL, naces, acebuf) < 0) {
62                 DEBUG(9, ("acl(ACE_GETACL, %s): %s ", fsp->fsp_name,
63                                 strerror(errno)));
64                 return 0;
65         }
66         /* create SMB4ACL data */
67         if((pacl = smb_create_smb4acl()) == NULL) return 0;
68         for(i=0; i<naces; i++) {
69                 SMB_ACE4PROP_T aceprop;
70
71                 aceprop.aceType  = (uint32) acebuf[i].a_type;
72                 aceprop.aceFlags = (uint32) acebuf[i].a_flags;
73                 aceprop.aceMask  = (uint32) acebuf[i].a_access_mask;
74                 aceprop.who.id   = (uint32) acebuf[i].a_who;
75                 aceprop.flags    = 0;
76                 if(smb_add_ace4(pacl, &aceprop) == NULL) return 0;
77         }
78
79         return smb_get_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
80 }
81
82 /* call-back function processing the NT acl -> ZFS acl using NFSv4 conv. */
83 static BOOL zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
84 {
85         int naces = smb_get_naces(smbacl), i;
86         ace_t *acebuf;
87         SMB4ACE_T *smbace;
88         TALLOC_CTX      *mem_ctx;
89
90         /* allocate the field of ZFS aces */
91         mem_ctx = main_loop_talloc_get();
92         acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
93         if(acebuf == NULL) {
94                 errno = ENOMEM;
95                 return False;
96         }
97         /* handle all aces */
98         for(smbace = smb_first_ace4(smbacl), i = 0;
99                         smbace!=NULL;
100                         smbace = smb_next_ace4(smbace), i++) {
101                 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
102
103                 acebuf[i].a_type        = aceprop->aceType;
104                 acebuf[i].a_flags       = aceprop->aceFlags;
105                 acebuf[i].a_access_mask = aceprop->aceMask;
106                 acebuf[i].a_who         = aceprop->who.id;
107         }
108         SMB_ASSERT(i == naces);
109
110         /* store acl */
111         if(acl(fsp->fsp_name, ACE_SETACL, naces, acebuf)) {
112                 if(errno == ENOSYS) {
113                         DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not supported on the filesystem where the file reside"));
114                 } else {
115                         DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp->fsp_name,
116                                         strerror(errno)));
117                 }
118                 return 0;
119         }
120
121         return True;
122 }
123
124 /* zfs_set_nt_acl()
125  * set the local file's acls obtaining it in NT form
126  * using the NFSv4 format conversion
127  */
128 static NTSTATUS zfs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
129                            uint32 security_info_sent,
130                            struct security_descriptor *psd)
131 {
132         return smb_set_nt_acl_nfs4(fsp, security_info_sent, psd,
133                         zfs_process_smbacl);
134 }
135
136 static size_t zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
137                                  struct files_struct *fsp,
138                                  int fd,  uint32 security_info,
139                                  struct security_descriptor **ppdesc)
140 {
141         return zfs_get_nt_acl(fsp, security_info, ppdesc);
142 }
143
144 static size_t zfsacl_get_nt_acl(struct vfs_handle_struct *handle,
145                                 struct files_struct *fsp,
146                                 const char *name,  uint32 security_info,
147                                 struct security_descriptor **ppdesc)
148 {
149         return zfs_get_nt_acl(fsp, security_info, ppdesc);
150 }
151
152 static NTSTATUS zfsacl_fset_nt_acl(vfs_handle_struct *handle,
153                          files_struct *fsp,
154                          int fd, uint32 security_info_sent,
155                          SEC_DESC *psd)
156 {
157         return zfs_set_nt_acl(handle, fsp, security_info_sent, psd);
158 }
159
160 static NTSTATUS zfsacl_set_nt_acl(vfs_handle_struct *handle,
161                        files_struct *fsp,
162                        const char *name, uint32 security_info_sent,
163                        SEC_DESC *psd)
164 {
165         return zfs_set_nt_acl(handle, fsp, security_info_sent, psd);
166 }
167
168 /* VFS operations structure */
169
170 static vfs_op_tuple zfsacl_ops[] = {    
171         {SMB_VFS_OP(zfsacl_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL,
172          SMB_VFS_LAYER_OPAQUE},
173         {SMB_VFS_OP(zfsacl_get_nt_acl), SMB_VFS_OP_GET_NT_ACL,
174          SMB_VFS_LAYER_OPAQUE},
175         {SMB_VFS_OP(zfsacl_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL,
176          SMB_VFS_LAYER_OPAQUE},
177         {SMB_VFS_OP(zfsacl_set_nt_acl), SMB_VFS_OP_SET_NT_ACL,
178          SMB_VFS_LAYER_OPAQUE},
179         {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
180 };
181
182 NTSTATUS vfs_zfsacl_init(void);
183 NTSTATUS vfs_zfsacl_init(void)
184 {
185         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "zfsacl",
186                                 zfsacl_ops);
187 }