source: branches/samba-3.2.x/source/modules/vfs_tru64acl.c

Last change on this file was 133, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0pre3

File size: 13.3 KB
Line 
1/*
2 Unix SMB/Netbios implementation.
3 VFS module to get and set Tru64 acls
4 Copyright (C) Michael Adam 2006,2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "includes.h"
21
22/* prototypes for private functions first - for clarity */
23
24static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl);
25static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
26 struct smb_acl_entry *smb_ace);
27static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl);
28static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag);
29static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag);
30static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset);
31static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset);
32
33
34/* public functions - the api */
35
36SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle,
37 const char *path_p,
38 SMB_ACL_TYPE_T type)
39{
40 struct smb_acl_t *result;
41 acl_type_t the_acl_type;
42 acl_t tru64_acl;
43
44 DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n"));
45
46 switch(type) {
47 case SMB_ACL_TYPE_ACCESS:
48 the_acl_type = ACL_TYPE_ACCESS;
49 break;
50 case SMB_ACL_TYPE_DEFAULT:
51 the_acl_type = ACL_TYPE_DEFAULT;
52 break;
53 default:
54 errno = EINVAL;
55 return NULL;
56 }
57
58 tru64_acl = acl_get_file((char *)path_p, the_acl_type);
59
60 if (tru64_acl == NULL) {
61 return NULL;
62 }
63
64 result = tru64_acl_to_smb_acl(tru64_acl);
65 acl_free(tru64_acl);
66 return result;
67}
68
69SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle,
70 files_struct *fsp)
71{
72 struct smb_acl_t *result;
73 acl_t tru64_acl = acl_get_fd(fsp->fh->fd, ACL_TYPE_ACCESS);
74
75 if (tru64_acl == NULL) {
76 return NULL;
77 }
78
79 result = tru64_acl_to_smb_acl(tru64_acl);
80 acl_free(tru64_acl);
81 return result;
82}
83
84int tru64acl_sys_acl_set_file(vfs_handle_struct *handle,
85 const char *name,
86 SMB_ACL_TYPE_T type,
87 SMB_ACL_T theacl)
88{
89 int res;
90 acl_type_t the_acl_type;
91 acl_t tru64_acl;
92
93 DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n",
94 name, type));
95
96 switch(type) {
97 case SMB_ACL_TYPE_ACCESS:
98 DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n"));
99 the_acl_type = ACL_TYPE_ACCESS;
100 break;
101 case SMB_ACL_TYPE_DEFAULT:
102 DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n"));
103 the_acl_type = ACL_TYPE_DEFAULT;
104 break;
105 default:
106 DEBUGADD(10, ("invalid acl type\n"));
107 errno = EINVAL;
108 goto fail;
109 }
110
111 tru64_acl = smb_acl_to_tru64_acl(theacl);
112 if (tru64_acl == NULL) {
113 DEBUG(10, ("smb_acl_to_tru64_acl failed!\n"));
114 goto fail;
115 }
116 DEBUG(10, ("got tru64 acl...\n"));
117 res = acl_set_file((char *)name, the_acl_type, tru64_acl);
118 acl_free(tru64_acl);
119 if (res != 0) {
120 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
121 goto fail;
122 }
123 return res;
124fail:
125 DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n"));
126 return -1;
127}
128
129int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle,
130 files_struct *fsp,
131 SMB_ACL_T theacl)
132{
133 int res;
134 acl_t tru64_acl = smb_acl_to_tru64_acl(theacl);
135 if (tru64_acl == NULL) {
136 return -1;
137 }
138 res = acl_set_fd(fsp->fh->fd, ACL_TYPE_ACCESS, tru64_acl);
139 acl_free(tru64_acl);
140 return res;
141
142}
143
144int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle,
145 const char *path)
146{
147 return acl_delete_def_file((char *)path);
148}
149
150
151/* private functions */
152
153static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl)
154{
155 struct smb_acl_t *result;
156 acl_entry_t entry;
157
158 DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n"));
159
160 if ((result = SMB_MALLOC_P(struct smb_acl_t)) == NULL) {
161 DEBUG(0, ("SMB_MALLOC_P failed in tru64_acl_to_smb_acl\n"));
162 errno = ENOMEM;
163 goto fail;
164 }
165 ZERO_STRUCTP(result);
166 if (acl_first_entry((struct acl *)tru64_acl) != 0) {
167 DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno)));
168 goto fail;
169 }
170 while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) {
171 result = SMB_REALLOC(result, sizeof(struct smb_acl_t) +
172 (sizeof(struct smb_acl_entry) *
173 (result->count + 1)));
174 if (result == NULL) {
175 DEBUG(0, ("SMB_REALLOC failed in tru64_acl_to_smb_acl\n"));
176 errno = ENOMEM;
177 goto fail;
178 }
179 /* XYZ */
180 if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) {
181 SAFE_FREE(result);
182 goto fail;
183 }
184 result->count += 1;
185 }
186 return result;
187
188fail:
189 if (result != NULL) {
190 SAFE_FREE(result);
191 }
192 DEBUG(1, ("tru64_acl_to_smb_acl failed!\n"));
193 return NULL;
194}
195
196static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
197 struct smb_acl_entry *smb_ace)
198{
199 acl_tag_t tru64_tag;
200 acl_permset_t permset;
201 SMB_ACL_TAG_T smb_tag_type;
202 SMB_ACL_PERM_T smb_permset;
203 void *qualifier;
204
205 if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) {
206 DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno)));
207 return False;
208 }
209
210 /* On could set the tag type directly to save a function call,
211 * but I like this better... */
212 smb_tag_type = tru64_tag_to_smb(tru64_tag);
213 if (smb_tag_type == 0) {
214 DEBUG(3, ("invalid tag type given: %d\n", tru64_tag));
215 return False;
216 }
217 if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) {
218 DEBUG(3, ("sys_acl_set_tag_type failed: %s\n",
219 strerror(errno)));
220 return False;
221 }
222 qualifier = acl_get_qualifier(tru64_ace);
223 if (qualifier != NULL) {
224 if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) {
225 DEBUG(3, ("sys_acl_set_qualifier failed\n"));
226 return False;
227 }
228 }
229 if (acl_get_permset(tru64_ace, &permset) != 0) {
230 DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno)));
231 return False;
232 }
233 smb_permset = tru64_permset_to_smb(*permset);
234 if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) {
235 DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno)));
236 return False;
237 }
238 return True;
239}
240
241static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl)
242{
243 acl_t result;
244 acl_entry_t tru64_entry;
245 int i;
246 char *acl_text;
247 ssize_t acl_text_len;
248
249 /* The tru64 acl_init function takes a size_t value
250 * instead of a count of entries (as with posix).
251 * the size parameter "Specifies the size of the working
252 * storage in bytes" (according to the man page).
253 * But it is unclear to me, how this size is to be
254 * calculated.
255 *
256 * It should not matter, since acl_create_entry enlarges
257 * the working storage at need. ... */
258
259 DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n"));
260
261 result = acl_init(1);
262
263 if (result == NULL) {
264 DEBUG(3, ("acl_init failed!\n"));
265 goto fail;
266 }
267
268 DEBUGADD(10, ("parsing acl entries...\n"));
269 for (i = 0; i < smb_acl->count; i++) {
270 /* XYZ - maybe eliminate this direct access? */
271 const struct smb_acl_entry *smb_entry = &smb_acl->acl[i];
272 acl_tag_t tru64_tag;
273 acl_perm_t tru64_permset;
274
275 tru64_tag = smb_tag_to_tru64(smb_entry->a_type);
276 if (tru64_tag == -1) {
277 DEBUG(3, ("smb_tag_to_tru64 failed!\n"));
278 goto fail;
279 }
280
281 if (tru64_tag == ACL_MASK) {
282 DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n"));
283 continue;
284 }
285
286 tru64_entry = acl_create_entry(&result);
287 if (tru64_entry == NULL) {
288 DEBUG(3, ("acl_create_entry failed: %s\n",
289 strerror(errno)));
290 goto fail;
291 }
292
293 if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) {
294 DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n",
295 strerror(errno)));
296 goto fail;
297 }
298
299 switch (smb_entry->a_type) {
300 case SMB_ACL_USER:
301 if (acl_set_qualifier(tru64_entry,
302 (int *)&smb_entry->uid) != 0)
303 {
304 DEBUG(3, ("acl_set_qualifier failed: %s\n",
305 strerror(errno)));
306 goto fail;
307 }
308 DEBUGADD(10, (" - setting uid to %d\n", smb_entry->uid));
309 break;
310 case SMB_ACL_GROUP:
311 if (acl_set_qualifier(tru64_entry,
312 (int *)&smb_entry->gid) != 0)
313 {
314 DEBUG(3, ("acl_set_qualifier failed: %s\n",
315 strerror(errno)));
316 goto fail;
317 }
318 DEBUGADD(10, (" - setting gid to %d\n", smb_entry->gid));
319 break;
320 default:
321 break;
322 }
323
324 tru64_permset = smb_permset_to_tru64(smb_entry->a_perm);
325 if (tru64_permset == -1) {
326 DEBUG(3, ("smb_permset_to_tru64 failed!\n"));
327 goto fail;
328 }
329 DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset));
330 if (acl_set_permset(tru64_entry, &tru64_permset) != 0)
331 {
332 DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno)));
333 goto fail;
334 }
335 } /* for */
336 DEBUGADD(10, ("done parsing acl entries\n"));
337
338 tru64_entry = NULL;
339 if (acl_valid(result, &tru64_entry) != 0) {
340 DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n",
341 strerror(errno)));
342 if (tru64_entry != NULL) {
343 DEBUGADD(1, ("the acl contains duplicate entries\n"));
344 }
345 goto fail;
346 }
347 DEBUGADD(10, ("acl is valid\n"));
348
349 acl_text = acl_to_text(result, &acl_text_len);
350 if (acl_text == NULL) {
351 DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno)));
352 goto fail;
353 }
354 DEBUG(1, ("acl_text: %s\n", acl_text));
355 free(acl_text);
356
357 return result;
358
359fail:
360 if (result != NULL) {
361 acl_free(result);
362 }
363 DEBUG(1, ("smb_acl_to_tru64_acl failed!\n"));
364 return NULL;
365}
366
367static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag)
368{
369 acl_tag_t result;
370 switch (smb_tag) {
371 case SMB_ACL_USER:
372 result = ACL_USER;
373 DEBUGADD(10, ("got acl type ACL_USER\n"));
374 break;
375 case SMB_ACL_USER_OBJ:
376 result = ACL_USER_OBJ;
377 DEBUGADD(10, ("got acl type ACL_USER_OBJ\n"));
378 break;
379 case SMB_ACL_GROUP:
380 result = ACL_GROUP;
381 DEBUGADD(10, ("got acl type ACL_GROUP\n"));
382 break;
383 case SMB_ACL_GROUP_OBJ:
384 result = ACL_GROUP_OBJ;
385 DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n"));
386 break;
387 case SMB_ACL_OTHER:
388 result = ACL_OTHER;
389 DEBUGADD(10, ("got acl type ACL_OTHER\n"));
390 break;
391 case SMB_ACL_MASK:
392 result = ACL_MASK;
393 DEBUGADD(10, ("got acl type ACL_MASK\n"));
394 break;
395 default:
396 DEBUG(1, ("Unknown tag type %d\n", smb_tag));
397 result = -1;
398 }
399 return result;
400}
401
402
403static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag)
404{
405 SMB_ACL_TAG_T smb_tag_type;
406 switch(tru64_tag) {
407 case ACL_USER:
408 smb_tag_type = SMB_ACL_USER;
409 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n"));
410 break;
411 case ACL_USER_OBJ:
412 smb_tag_type = SMB_ACL_USER_OBJ;
413 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n"));
414 break;
415 case ACL_GROUP:
416 smb_tag_type = SMB_ACL_GROUP;
417 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n"));
418 break;
419 case ACL_GROUP_OBJ:
420 smb_tag_type = SMB_ACL_GROUP_OBJ;
421 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n"));
422 break;
423 case ACL_OTHER:
424 smb_tag_type = SMB_ACL_OTHER;
425 DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n"));
426 break;
427 case ACL_MASK:
428 smb_tag_type = SMB_ACL_MASK;
429 DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n"));
430 break;
431 default:
432 DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag));
433 smb_tag_type = 0;
434 }
435 return smb_tag_type;
436}
437
438static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset)
439{
440 /* originally, I thought that acl_clear_perm was the
441 * proper way to reset the permset to 0. but without
442 * initializing it to 0, acl_clear_perm fails.
443 * so probably, acl_clear_perm is not necessary here... ?! */
444 acl_perm_t tru64_permset = 0;
445 if (acl_clear_perm(&tru64_permset) != 0) {
446 DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno)));
447 return -1;
448 }
449 /* according to original lib/sysacls.c, acl_add_perm is
450 * broken on tru64 ... */
451 tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0);
452 tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0);
453 tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0);
454 return tru64_permset;
455}
456
457static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset)
458{
459 SMB_ACL_PERM_T smb_permset = 0;
460 smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0);
461 smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0);
462 smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
463 return smb_permset;
464}
465
466
467/* VFS operations structure */
468
469static vfs_op_tuple tru64acl_op_tuples[] = {
470 /* Disk operations */
471 {SMB_VFS_OP(tru64acl_sys_acl_get_file),
472 SMB_VFS_OP_SYS_ACL_GET_FILE,
473 SMB_VFS_LAYER_TRANSPARENT},
474
475 {SMB_VFS_OP(tru64acl_sys_acl_get_fd),
476 SMB_VFS_OP_SYS_ACL_GET_FD,
477 SMB_VFS_LAYER_TRANSPARENT},
478
479 {SMB_VFS_OP(tru64acl_sys_acl_set_file),
480 SMB_VFS_OP_SYS_ACL_SET_FILE,
481 SMB_VFS_LAYER_TRANSPARENT},
482
483 {SMB_VFS_OP(tru64acl_sys_acl_set_fd),
484 SMB_VFS_OP_SYS_ACL_SET_FD,
485 SMB_VFS_LAYER_TRANSPARENT},
486
487 {SMB_VFS_OP(tru64acl_sys_acl_delete_def_file),
488 SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
489 SMB_VFS_LAYER_TRANSPARENT},
490
491 {SMB_VFS_OP(NULL),
492 SMB_VFS_OP_NOOP,
493 SMB_VFS_LAYER_NOOP}
494};
495
496NTSTATUS vfs_tru64acl_init(void);
497NTSTATUS vfs_tru64acl_init(void)
498{
499 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl",
500 tru64acl_op_tuples);
501}
502
503/* ENTE */
Note: See TracBrowser for help on using the repository browser.