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
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define DBGC_CLASS DBGC_ACLS
29 * Note that while this code implements sufficient functionality
30 * to support the sys_acl_* interfaces it does not provide all
31 * of the semantics of the POSIX ACL interfaces.
33 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
34 * from a call to sys_acl_get_entry() should not be assumed to be
35 * valid after calling any of the following functions, which may
36 * reorder the entries in the ACL.
43 int sys_acl_get_entry(SMB_ACL_T acl_d
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
45 if (entry_id
!= SMB_ACL_FIRST_ENTRY
&& entry_id
!= SMB_ACL_NEXT_ENTRY
) {
50 if (entry_p
== NULL
) {
55 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
59 if (acl_d
->next
< 0) {
64 if (acl_d
->next
>= acl_d
->count
) {
68 *entry_p
= &acl_d
->acl
[acl_d
->next
++];
73 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*type_p
)
75 *type_p
= entry_d
->a_type
;
80 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T
*permset_p
)
82 *permset_p
= &entry_d
->a_perm
;
87 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d
)
89 if (entry_d
->a_type
== SMB_ACL_USER
) {
93 if (entry_d
->a_type
== SMB_ACL_GROUP
) {
101 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d
)
108 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d
, SMB_ACL_PERM_T perm
)
110 if (perm
!= SMB_ACL_READ
&& perm
!= SMB_ACL_WRITE
111 && perm
!= SMB_ACL_EXECUTE
) {
116 if (permset_d
== NULL
) {
126 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d
, SMB_ACL_PERM_T perm
)
128 return *permset_d
& perm
;
131 char *sys_acl_to_text(SMB_ACL_T acl_d
, ssize_t
*len_p
)
138 * use an initial estimate of 20 bytes per ACL entry
139 * when allocating memory for the text representation
143 maxlen
= 20 * acl_d
->count
;
144 if ((text
= (char *)SMB_MALLOC(maxlen
)) == NULL
) {
149 for (i
= 0; i
< acl_d
->count
; i
++) {
150 struct smb_acl_entry
*ap
= &acl_d
->acl
[i
];
159 switch (ap
->a_type
) {
161 * for debugging purposes it's probably more
162 * useful to dump unknown tag types rather
163 * than just returning an error
166 slprintf(tagbuf
, sizeof(tagbuf
)-1, "0x%x",
172 id
= uidtoname(ap
->uid
);
173 case SMB_ACL_USER_OBJ
:
178 if ((gr
= getgrgid(ap
->gid
)) == NULL
) {
179 slprintf(idbuf
, sizeof(idbuf
)-1, "%ld",
185 case SMB_ACL_GROUP_OBJ
:
199 perms
[0] = (ap
->a_perm
& SMB_ACL_READ
) ? 'r' : '-';
200 perms
[1] = (ap
->a_perm
& SMB_ACL_WRITE
) ? 'w' : '-';
201 perms
[2] = (ap
->a_perm
& SMB_ACL_EXECUTE
) ? 'x' : '-';
204 /* <tag> : <qualifier> : rwx \n \0 */
205 nbytes
= strlen(tag
) + 1 + strlen(id
) + 1 + 3 + 1 + 1;
208 * If this entry would overflow the buffer
209 * allocate enough additional memory for this
210 * entry and an estimate of another 20 bytes
211 * for each entry still to be processed
213 if ((len
+ nbytes
) > maxlen
) {
214 maxlen
+= nbytes
+ 20 * (acl_d
->count
- i
);
215 if ((text
= (char *)SMB_REALLOC(text
, maxlen
)) == NULL
) {
221 slprintf(&text
[len
], nbytes
-1, "%s:%s:%s\n", tag
, id
, perms
);
231 SMB_ACL_T
sys_acl_init(int count
)
241 * note that since the definition of the structure pointed
242 * to by the SMB_ACL_T includes the first element of the
243 * acl[] array, this actually allocates an ACL with room
244 * for (count+1) entries
246 if ((a
= (struct smb_acl_t
*)SMB_MALLOC(
247 sizeof(struct smb_acl_t
) +
248 count
* sizeof(struct smb_acl_entry
))) == NULL
) {
260 int sys_acl_create_entry(SMB_ACL_T
*acl_p
, SMB_ACL_ENTRY_T
*entry_p
)
263 SMB_ACL_ENTRY_T entry_d
;
265 if (acl_p
== NULL
|| entry_p
== NULL
|| (acl_d
= *acl_p
) == NULL
) {
270 if (acl_d
->count
>= acl_d
->size
) {
275 entry_d
= &acl_d
->acl
[acl_d
->count
++];
276 entry_d
->a_type
= SMB_ACL_TAG_INVALID
;
285 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T tag_type
)
289 case SMB_ACL_USER_OBJ
:
291 case SMB_ACL_GROUP_OBJ
:
294 entry_d
->a_type
= tag_type
;
304 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d
, void *qual_p
)
306 if (entry_d
->a_type
== SMB_ACL_USER
) {
307 entry_d
->uid
= *((uid_t
*)qual_p
);
310 if (entry_d
->a_type
== SMB_ACL_GROUP
) {
311 entry_d
->gid
= *((gid_t
*)qual_p
);
319 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T permset_d
)
321 if (*permset_d
& ~(SMB_ACL_READ
|SMB_ACL_WRITE
|SMB_ACL_EXECUTE
)) {
326 entry_d
->a_perm
= *permset_d
;
331 int sys_acl_free_text(char *text
)
337 int sys_acl_free_acl(SMB_ACL_T acl_d
)
343 int sys_acl_free_qualifier(void *qual
, SMB_ACL_TAG_T tagtype
)
348 int sys_acl_valid(SMB_ACL_T acl_d
)
355 * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and
356 * sys_acl_delete_def_file are to be redirected to the default
357 * statically-bound acl vfs module, but they are replacable.
360 #if defined(HAVE_POSIX_ACLS)
362 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
363 const char *path_p
, SMB_ACL_TYPE_T type
)
365 return posixacl_sys_acl_get_file(handle
, path_p
, type
);
368 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
370 return posixacl_sys_acl_get_fd(handle
, fsp
, fd
);
373 int sys_acl_set_file(vfs_handle_struct
*handle
,
374 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
376 return posixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
379 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
380 int fd
, SMB_ACL_T acl_d
)
382 return posixacl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
385 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
388 return posixacl_sys_acl_delete_def_file(handle
, path
);
391 #elif defined(HAVE_AIX_ACLS)
393 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
394 const char *path_p
, SMB_ACL_TYPE_T type
)
396 return aixacl_sys_acl_get_file(handle
, path_p
, type
);
399 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
401 return aixacl_sys_acl_get_fd(handle
, fsp
, fd
);
404 int sys_acl_set_file(vfs_handle_struct
*handle
,
405 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
407 return aixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
410 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
411 int fd
, SMB_ACL_T acl_d
)
413 return aixacl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
416 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
419 return aixacl_sys_acl_delete_def_file(handle
, path
);
422 #elif defined(HAVE_TRU64_ACLS)
424 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
425 const char *path_p
, SMB_ACL_TYPE_T type
)
427 return tru64acl_sys_acl_get_file(handle
, path_p
, type
);
430 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
432 return tru64acl_sys_acl_get_fd(handle
, fsp
, fd
);
435 int sys_acl_set_file(vfs_handle_struct
*handle
,
436 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
438 return tru64acl_sys_acl_set_file(handle
, name
, type
, acl_d
);
441 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
442 int fd
, SMB_ACL_T acl_d
)
444 return tru64acl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
447 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
450 return tru64acl_sys_acl_delete_def_file(handle
, path
);
453 #elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS)
455 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
456 const char *path_p
, SMB_ACL_TYPE_T type
)
458 return solarisacl_sys_acl_get_file(handle
, path_p
, type
);
461 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
463 return solarisacl_sys_acl_get_fd(handle
, fsp
, fd
);
466 int sys_acl_set_file(vfs_handle_struct
*handle
,
467 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
469 return solarisacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
472 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
473 int fd
, SMB_ACL_T acl_d
)
475 return solarisacl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
478 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
481 return solarisacl_sys_acl_delete_def_file(handle
, path
);
484 #elif defined(HAVE_HPUX_ACLS)
486 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
487 const char *path_p
, SMB_ACL_TYPE_T type
)
489 return hpuxacl_sys_acl_get_file(handle
, path_p
, type
);
492 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
494 return hpuxacl_sys_acl_get_fd(handle
, fsp
, fd
);
497 int sys_acl_set_file(vfs_handle_struct
*handle
,
498 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
500 return hpuxacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
503 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
504 int fd
, SMB_ACL_T acl_d
)
506 return hpuxacl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
509 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
512 return hpuxacl_sys_acl_delete_def_file(handle
, path
);
515 #elif defined(HAVE_IRIX_ACLS)
517 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
518 const char *path_p
, SMB_ACL_TYPE_T type
)
520 return irixacl_sys_acl_get_file(handle
, path_p
, type
);
523 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
525 return irixacl_sys_acl_get_fd(handle
, fsp
, fd
);
528 int sys_acl_set_file(vfs_handle_struct
*handle
,
529 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
531 return irixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
534 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
535 int fd
, SMB_ACL_T acl_d
)
537 return irixacl_sys_acl_set_fd(handle
, fsp
, fd
, acl_d
);
540 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
543 return irixacl_sys_acl_delete_def_file(handle
, path
);
548 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
549 const char *path_p
, SMB_ACL_TYPE_T type
)
559 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, int fd
)
569 int sys_acl_set_file(vfs_handle_struct
*handle
,
570 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
580 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
581 int fd
, SMB_ACL_T acl_d
)
591 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
604 /************************************************************************
605 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
607 ************************************************************************/
609 int no_acl_syscall_error(int err
)
617 if (err
== ENOTSUP
) {