/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- sys_acl_get_entry
- sys_acl_get_tag_type
- sys_acl_get_permset
- sys_acl_get_qualifier
- sys_acl_clear_perms
- sys_acl_add_perm
- sys_acl_get_perm
- sys_acl_to_text
- sys_acl_init
- sys_acl_create_entry
- sys_acl_set_tag_type
- sys_acl_set_qualifier
- sys_acl_set_permset
- sys_acl_free_text
- sys_acl_free_acl
- sys_acl_free_qualifier
- sys_acl_valid
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- sys_acl_get_file
- sys_acl_get_fd
- sys_acl_set_file
- sys_acl_set_fd
- sys_acl_delete_def_file
- no_acl_syscall_error
1 /*
2 Unix SMB/CIFS implementation.
3 Samba system utilities for ACL support.
4 Copyright (C) Jeremy Allison 2000.
5 Copyright (C) Volker Lendecke 2006
6 Copyright (C) Michael Adam 2006,2008
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_ACLS
26
27 /*
28 * Note that while this code implements sufficient functionality
29 * to support the sys_acl_* interfaces it does not provide all
30 * of the semantics of the POSIX ACL interfaces.
31 *
32 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
33 * from a call to sys_acl_get_entry() should not be assumed to be
34 * valid after calling any of the following functions, which may
35 * reorder the entries in the ACL.
36 *
37 * sys_acl_valid()
38 * sys_acl_set_file()
39 * sys_acl_set_fd()
40 */
41
42 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
/* [<][>][^][v][top][bottom][index][help] */
43 {
44 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
45 errno = EINVAL;
46 return -1;
47 }
48
49 if (entry_p == NULL) {
50 errno = EINVAL;
51 return -1;
52 }
53
54 if (entry_id == SMB_ACL_FIRST_ENTRY) {
55 acl_d->next = 0;
56 }
57
58 if (acl_d->next < 0) {
59 errno = EINVAL;
60 return -1;
61 }
62
63 if (acl_d->next >= acl_d->count) {
64 return 0;
65 }
66
67 *entry_p = &acl_d->acl[acl_d->next++];
68
69 return 1;
70 }
71
72 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
/* [<][>][^][v][top][bottom][index][help] */
73 {
74 *type_p = entry_d->a_type;
75
76 return 0;
77 }
78
79 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
/* [<][>][^][v][top][bottom][index][help] */
80 {
81 *permset_p = &entry_d->a_perm;
82
83 return 0;
84 }
85
86 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
/* [<][>][^][v][top][bottom][index][help] */
87 {
88 if (entry_d->a_type == SMB_ACL_USER) {
89 return &entry_d->uid;
90 }
91
92 if (entry_d->a_type == SMB_ACL_GROUP) {
93 return &entry_d->gid;
94 }
95
96 errno = EINVAL;
97 return NULL;
98 }
99
100 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
/* [<][>][^][v][top][bottom][index][help] */
101 {
102 *permset_d = 0;
103
104 return 0;
105 }
106
107 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
/* [<][>][^][v][top][bottom][index][help] */
108 {
109 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
110 && perm != SMB_ACL_EXECUTE) {
111 errno = EINVAL;
112 return -1;
113 }
114
115 if (permset_d == NULL) {
116 errno = EINVAL;
117 return -1;
118 }
119
120 *permset_d |= perm;
121
122 return 0;
123 }
124
125 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
/* [<][>][^][v][top][bottom][index][help] */
126 {
127 return *permset_d & perm;
128 }
129
130 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
/* [<][>][^][v][top][bottom][index][help] */
131 {
132 int i;
133 int len, maxlen;
134 char *text;
135
136 /*
137 * use an initial estimate of 20 bytes per ACL entry
138 * when allocating memory for the text representation
139 * of the ACL
140 */
141 len = 0;
142 maxlen = 20 * acl_d->count;
143 if ((text = (char *)SMB_MALLOC(maxlen)) == NULL) {
144 errno = ENOMEM;
145 return NULL;
146 }
147
148 for (i = 0; i < acl_d->count; i++) {
149 struct smb_acl_entry *ap = &acl_d->acl[i];
150 struct group *gr;
151 char tagbuf[12];
152 char idbuf[12];
153 const char *tag;
154 const char *id = "";
155 char perms[4];
156 int nbytes;
157
158 switch (ap->a_type) {
159 /*
160 * for debugging purposes it's probably more
161 * useful to dump unknown tag types rather
162 * than just returning an error
163 */
164 default:
165 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
166 ap->a_type);
167 tag = tagbuf;
168 break;
169
170 case SMB_ACL_USER:
171 id = uidtoname(ap->uid);
172 case SMB_ACL_USER_OBJ:
173 tag = "user";
174 break;
175
176 case SMB_ACL_GROUP:
177 if ((gr = getgrgid(ap->gid)) == NULL) {
178 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
179 (long)ap->gid);
180 id = idbuf;
181 } else {
182 id = gr->gr_name;
183 }
184 case SMB_ACL_GROUP_OBJ:
185 tag = "group";
186 break;
187
188 case SMB_ACL_OTHER:
189 tag = "other";
190 break;
191
192 case SMB_ACL_MASK:
193 tag = "mask";
194 break;
195
196 }
197
198 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
199 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
200 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
201 perms[3] = '\0';
202
203 /* <tag> : <qualifier> : rwx \n \0 */
204 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
205
206 /*
207 * If this entry would overflow the buffer
208 * allocate enough additional memory for this
209 * entry and an estimate of another 20 bytes
210 * for each entry still to be processed
211 */
212 if ((len + nbytes) > maxlen) {
213 maxlen += nbytes + 20 * (acl_d->count - i);
214 if ((text = (char *)SMB_REALLOC(text, maxlen)) == NULL) {
215 errno = ENOMEM;
216 return NULL;
217 }
218 }
219
220 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
221 len += nbytes - 1;
222 }
223
224 if (len_p)
225 *len_p = len;
226
227 return text;
228 }
229
230 SMB_ACL_T sys_acl_init(int count)
/* [<][>][^][v][top][bottom][index][help] */
231 {
232 SMB_ACL_T a;
233
234 if (count < 0) {
235 errno = EINVAL;
236 return NULL;
237 }
238
239 /*
240 * note that since the definition of the structure pointed
241 * to by the SMB_ACL_T includes the first element of the
242 * acl[] array, this actually allocates an ACL with room
243 * for (count+1) entries
244 */
245 if ((a = (struct smb_acl_t *)SMB_MALLOC(
246 sizeof(struct smb_acl_t) +
247 count * sizeof(struct smb_acl_entry))) == NULL) {
248 errno = ENOMEM;
249 return NULL;
250 }
251
252 a->size = count + 1;
253 a->count = 0;
254 a->next = -1;
255
256 return a;
257 }
258
259 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
/* [<][>][^][v][top][bottom][index][help] */
260 {
261 SMB_ACL_T acl_d;
262 SMB_ACL_ENTRY_T entry_d;
263
264 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
265 errno = EINVAL;
266 return -1;
267 }
268
269 if (acl_d->count >= acl_d->size) {
270 errno = ENOSPC;
271 return -1;
272 }
273
274 entry_d = &acl_d->acl[acl_d->count++];
275 entry_d->a_type = SMB_ACL_TAG_INVALID;
276 entry_d->uid = -1;
277 entry_d->gid = -1;
278 entry_d->a_perm = 0;
279 *entry_p = entry_d;
280
281 return 0;
282 }
283
284 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
/* [<][>][^][v][top][bottom][index][help] */
285 {
286 switch (tag_type) {
287 case SMB_ACL_USER:
288 case SMB_ACL_USER_OBJ:
289 case SMB_ACL_GROUP:
290 case SMB_ACL_GROUP_OBJ:
291 case SMB_ACL_OTHER:
292 case SMB_ACL_MASK:
293 entry_d->a_type = tag_type;
294 break;
295 default:
296 errno = EINVAL;
297 return -1;
298 }
299
300 return 0;
301 }
302
303 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
/* [<][>][^][v][top][bottom][index][help] */
304 {
305 if (entry_d->a_type == SMB_ACL_USER) {
306 entry_d->uid = *((uid_t *)qual_p);
307 return 0;
308 }
309 if (entry_d->a_type == SMB_ACL_GROUP) {
310 entry_d->gid = *((gid_t *)qual_p);
311 return 0;
312 }
313
314 errno = EINVAL;
315 return -1;
316 }
317
318 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
/* [<][>][^][v][top][bottom][index][help] */
319 {
320 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
321 errno = EINVAL;
322 return -1;
323 }
324
325 entry_d->a_perm = *permset_d;
326
327 return 0;
328 }
329
330 int sys_acl_free_text(char *text)
/* [<][>][^][v][top][bottom][index][help] */
331 {
332 SAFE_FREE(text);
333 return 0;
334 }
335
336 int sys_acl_free_acl(SMB_ACL_T acl_d)
/* [<][>][^][v][top][bottom][index][help] */
337 {
338 SAFE_FREE(acl_d);
339 return 0;
340 }
341
342 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
/* [<][>][^][v][top][bottom][index][help] */
343 {
344 return 0;
345 }
346
347 int sys_acl_valid(SMB_ACL_T acl_d)
/* [<][>][^][v][top][bottom][index][help] */
348 {
349 errno = EINVAL;
350 return -1;
351 }
352
353 /*
354 * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and
355 * sys_acl_delete_def_file are to be redirected to the default
356 * statically-bound acl vfs module, but they are replacable.
357 */
358
359 #if defined(HAVE_POSIX_ACLS)
360
361 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
362 const char *path_p, SMB_ACL_TYPE_T type)
363 {
364 return posixacl_sys_acl_get_file(handle, path_p, type);
365 }
366
367 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
368 {
369 return posixacl_sys_acl_get_fd(handle, fsp);
370 }
371
372 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
373 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
374 {
375 return posixacl_sys_acl_set_file(handle, name, type, acl_d);
376 }
377
378 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
379 SMB_ACL_T acl_d)
380 {
381 return posixacl_sys_acl_set_fd(handle, fsp, acl_d);
382 }
383
384 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
385 const char *path)
386 {
387 return posixacl_sys_acl_delete_def_file(handle, path);
388 }
389
390 #elif defined(HAVE_AIX_ACLS)
391
392 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
393 const char *path_p, SMB_ACL_TYPE_T type)
394 {
395 return aixacl_sys_acl_get_file(handle, path_p, type);
396 }
397
398 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
399 {
400 return aixacl_sys_acl_get_fd(handle, fsp);
401 }
402
403 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
404 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
405 {
406 return aixacl_sys_acl_set_file(handle, name, type, acl_d);
407 }
408
409 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
410 SMB_ACL_T acl_d)
411 {
412 return aixacl_sys_acl_set_fd(handle, fsp, acl_d);
413 }
414
415 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
416 const char *path)
417 {
418 return aixacl_sys_acl_delete_def_file(handle, path);
419 }
420
421 #elif defined(HAVE_TRU64_ACLS)
422
423 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
424 const char *path_p, SMB_ACL_TYPE_T type)
425 {
426 return tru64acl_sys_acl_get_file(handle, path_p, type);
427 }
428
429 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
430 {
431 return tru64acl_sys_acl_get_fd(handle, fsp);
432 }
433
434 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
435 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
436 {
437 return tru64acl_sys_acl_set_file(handle, name, type, acl_d);
438 }
439
440 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
441 SMB_ACL_T acl_d)
442 {
443 return tru64acl_sys_acl_set_fd(handle, fsp, acl_d);
444 }
445
446 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
447 const char *path)
448 {
449 return tru64acl_sys_acl_delete_def_file(handle, path);
450 }
451
452 #elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS)
453
454 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
455 const char *path_p, SMB_ACL_TYPE_T type)
456 {
457 return solarisacl_sys_acl_get_file(handle, path_p, type);
458 }
459
460 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
461 {
462 return solarisacl_sys_acl_get_fd(handle, fsp);
463 }
464
465 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
466 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
467 {
468 return solarisacl_sys_acl_set_file(handle, name, type, acl_d);
469 }
470
471 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
472 SMB_ACL_T acl_d)
473 {
474 return solarisacl_sys_acl_set_fd(handle, fsp, acl_d);
475 }
476
477 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
478 const char *path)
479 {
480 return solarisacl_sys_acl_delete_def_file(handle, path);
481 }
482
483 #elif defined(HAVE_HPUX_ACLS)
484
485 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
486 const char *path_p, SMB_ACL_TYPE_T type)
487 {
488 return hpuxacl_sys_acl_get_file(handle, path_p, type);
489 }
490
491 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
492 {
493 return hpuxacl_sys_acl_get_fd(handle, fsp);
494 }
495
496 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
497 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
498 {
499 return hpuxacl_sys_acl_set_file(handle, name, type, acl_d);
500 }
501
502 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
503 SMB_ACL_T acl_d)
504 {
505 return hpuxacl_sys_acl_set_fd(handle, fsp, acl_d);
506 }
507
508 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
509 const char *path)
510 {
511 return hpuxacl_sys_acl_delete_def_file(handle, path);
512 }
513
514 #elif defined(HAVE_IRIX_ACLS)
515
516 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
517 const char *path_p, SMB_ACL_TYPE_T type)
518 {
519 return irixacl_sys_acl_get_file(handle, path_p, type);
520 }
521
522 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
523 {
524 return irixacl_sys_acl_get_fd(handle, fsp);
525 }
526
527 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
528 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
529 {
530 return irixacl_sys_acl_set_file(handle, name, type, acl_d);
531 }
532
533 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
534 SMB_ACL_T acl_d)
535 {
536 return irixacl_sys_acl_set_fd(handle, fsp, acl_d);
537 }
538
539 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
540 const char *path)
541 {
542 return irixacl_sys_acl_delete_def_file(handle, path);
543 }
544
545 #else /* No ACLs. */
546
547 SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
548 const char *path_p, SMB_ACL_TYPE_T type)
549 {
550 #ifdef ENOTSUP
551 errno = ENOTSUP;
552 #else
553 errno = ENOSYS;
554 #endif
555 return NULL;
556 }
557
558 SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
/* [<][>][^][v][top][bottom][index][help] */
559 {
560 #ifdef ENOTSUP
561 errno = ENOTSUP;
562 #else
563 errno = ENOSYS;
564 #endif
565 return NULL;
566 }
567
568 int sys_acl_set_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
569 const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
570 {
571 #ifdef ENOTSUP
572 errno = ENOTSUP;
573 #else
574 errno = ENOSYS;
575 #endif
576 return -1;
577 }
578
579 int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
580 SMB_ACL_T acl_d)
581 {
582 #ifdef ENOTSUP
583 errno = ENOTSUP;
584 #else
585 errno = ENOSYS;
586 #endif
587 return -1;
588 }
589
590 int sys_acl_delete_def_file(vfs_handle_struct *handle,
/* [<][>][^][v][top][bottom][index][help] */
591 const char *path)
592 {
593 #ifdef ENOTSUP
594 errno = ENOTSUP;
595 #else
596 errno = ENOSYS;
597 #endif
598 return -1;
599 }
600
601 #endif
602
603 /************************************************************************
604 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
605 errno, 0 if not.
606 ************************************************************************/
607
608 int no_acl_syscall_error(int err)
/* [<][>][^][v][top][bottom][index][help] */
609 {
610 #if defined(ENOSYS)
611 if (err == ENOSYS) {
612 return 1;
613 }
614 #endif
615 #if defined(ENOTSUP)
616 if (err == ENOTSUP) {
617 return 1;
618 }
619 #endif
620 return 0;
621 }