wbclient: "ev" is no longer used in wbc_xids_to_sids
[metze/samba/wip.git] / source4 / ntvfs / posix / pvfs_acl_nfs4.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - NT ACLs mapped to NFS4 ACLs, as per
5    http://www.suse.de/~agruen/nfs4acl/
6
7    Copyright (C) Andrew Tridgell 2006
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "vfs_posix.h"
25 #include "../lib/util/unix_privs.h"
26 #include "librpc/gen_ndr/ndr_nfs4acl.h"
27 #include "libcli/security/security.h"
28
29 NTSTATUS pvfs_acl_nfs4_init(void);
30
31 #define ACE4_IDENTIFIER_GROUP 0x40
32
33 /*
34   load the current ACL from system.nfs4acl
35 */
36 static NTSTATUS pvfs_acl_load_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
37                                    TALLOC_CTX *mem_ctx,
38                                    struct security_descriptor **psd)
39 {
40         NTSTATUS status;
41         struct nfs4acl *acl;
42         struct security_descriptor *sd;
43         int i, num_ids;
44         struct id_map *ids;
45
46         acl = talloc_zero(mem_ctx, struct nfs4acl);
47         NT_STATUS_HAVE_NO_MEMORY(acl);
48
49         status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, fd, 
50                                      NFS4ACL_XATTR_NAME,
51                                      acl, (void *) ndr_pull_nfs4acl);
52         if (!NT_STATUS_IS_OK(status)) {
53                 talloc_free(acl);
54                 return status;
55         }
56
57         *psd = security_descriptor_initialise(mem_ctx);
58         NT_STATUS_HAVE_NO_MEMORY(*psd);
59
60         sd = *psd;
61
62         sd->type |= acl->a_flags;
63
64         /* the number of ids to map is the acl count plus uid and gid */
65         num_ids = acl->a_count +2;
66         ids = talloc_array(sd, struct id_map, num_ids);
67         NT_STATUS_HAVE_NO_MEMORY(ids);
68
69         ids[0].xid.id = name->st.st_uid;
70         ids[0].xid.type = ID_TYPE_UID;
71         ids[0].sid = NULL;
72         ids[0].status = ID_UNKNOWN;
73
74         ids[1].xid.id = name->st.st_gid;
75         ids[1].xid.type = ID_TYPE_GID;
76         ids[1].sid = NULL;
77         ids[1].status = ID_UNKNOWN;
78
79         for (i=0;i<acl->a_count;i++) {
80                 struct nfs4ace *a = &acl->ace[i];
81                 ids[i+2].xid.id = a->e_id;
82                 if (a->e_flags & ACE4_IDENTIFIER_GROUP) {
83                         ids[i+2].xid.type = ID_TYPE_GID;
84                 } else {
85                         ids[i+2].xid.type = ID_TYPE_UID;
86                 }
87                 ids[i+2].sid = NULL;
88                 ids[i+2].status = ID_UNKNOWN;
89         }
90
91         /* Allocate memory for the sids from the security descriptor to be on
92          * the safe side. */
93         status = wbc_xids_to_sids(ids, num_ids);
94         NT_STATUS_NOT_OK_RETURN(status);
95
96         sd->owner_sid = talloc_steal(sd, ids[0].sid);
97         sd->group_sid = talloc_steal(sd, ids[1].sid);
98
99         for (i=0;i<acl->a_count;i++) {
100                 struct nfs4ace *a = &acl->ace[i];
101                 struct security_ace ace;
102                 ace.type = a->e_type;
103                 ace.flags = a->e_flags;
104                 ace.access_mask = a->e_mask;
105                 ace.trustee = *ids[i+2].sid;
106                 security_descriptor_dacl_add(sd, &ace);
107         }
108
109         return NT_STATUS_OK;
110 }
111
112 /*
113   save the acl for a file into system.nfs4acl
114 */
115 static NTSTATUS pvfs_acl_save_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
116                                    struct security_descriptor *sd)
117 {
118         NTSTATUS status;
119         void *privs;
120         struct nfs4acl acl;
121         int i;
122         TALLOC_CTX *tmp_ctx;
123         struct id_map *ids;
124
125         tmp_ctx = talloc_new(pvfs);
126         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
127
128         acl.a_version = 0;
129         acl.a_flags   = sd->type;
130         acl.a_count   = sd->dacl?sd->dacl->num_aces:0;
131         acl.a_owner_mask = 0;
132         acl.a_group_mask = 0;
133         acl.a_other_mask = 0;
134
135         acl.ace = talloc_array(tmp_ctx, struct nfs4ace, acl.a_count);
136         if (!acl.ace) {
137                 talloc_free(tmp_ctx);
138                 return NT_STATUS_NO_MEMORY;
139         }
140
141         ids = talloc_array(tmp_ctx, struct id_map, acl.a_count);
142         if (ids == NULL) {
143                 talloc_free(tmp_ctx);
144                 return NT_STATUS_NO_MEMORY;
145         }
146
147         for (i=0;i<acl.a_count;i++) {
148                 struct security_ace *ace = &sd->dacl->aces[i];
149                 ZERO_STRUCT(ids[i].xid);
150                 ids[i].sid = dom_sid_dup(ids, &ace->trustee);
151                 if (ids[i].sid == NULL) {
152                         talloc_free(tmp_ctx);
153                         return NT_STATUS_NO_MEMORY;
154                 }
155                 ids[i].status = ID_UNKNOWN;
156         }
157
158         status = wbc_sids_to_xids(ids, acl.a_count);
159         if (!NT_STATUS_IS_OK(status)) {
160                 talloc_free(tmp_ctx);
161                 return status;
162         }
163
164         for (i=0;i<acl.a_count;i++) {
165                 struct nfs4ace *a = &acl.ace[i];
166                 struct security_ace *ace = &sd->dacl->aces[i];
167                 a->e_type  = ace->type;
168                 a->e_flags = ace->flags;
169                 a->e_mask  = ace->access_mask;
170                 if (ids[i].xid.type != ID_TYPE_UID) {
171                         a->e_flags |= ACE4_IDENTIFIER_GROUP;
172                 }
173                 a->e_id = ids[i].xid.id;
174                 a->e_who   = "";
175         }
176
177         privs = root_privileges();
178         status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 
179                                      NFS4ACL_XATTR_NAME, 
180                                      &acl, (void *) ndr_push_nfs4acl);
181         talloc_free(privs);
182
183         talloc_free(tmp_ctx);
184         return status;
185 }
186
187
188 /*
189   initialise pvfs acl NFS4 backend
190 */
191 NTSTATUS pvfs_acl_nfs4_init(void)
192 {
193         struct pvfs_acl_ops ops = {
194                 .name = "nfs4acl",
195                 .acl_load = pvfs_acl_load_nfs4,
196                 .acl_save = pvfs_acl_save_nfs4
197         };
198         return pvfs_acl_register(&ops);
199 }