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
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.
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, see <http://www.gnu.org/licenses/>.
25 #define DBGC_CLASS DBGC_ACLS
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.
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.
42 int sys_acl_get_entry(SMB_ACL_T acl_d
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
44 if (entry_id
!= SMB_ACL_FIRST_ENTRY
&& entry_id
!= SMB_ACL_NEXT_ENTRY
) {
49 if (entry_p
== NULL
) {
54 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
58 if (acl_d
->next
< 0) {
63 if (acl_d
->next
>= acl_d
->count
) {
67 *entry_p
= &acl_d
->acl
[acl_d
->next
++];
72 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*type_p
)
74 *type_p
= entry_d
->a_type
;
79 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T
*permset_p
)
81 *permset_p
= &entry_d
->a_perm
;
86 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d
)
88 if (entry_d
->a_type
== SMB_ACL_USER
) {
92 if (entry_d
->a_type
== SMB_ACL_GROUP
) {
100 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d
)
107 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d
, SMB_ACL_PERM_T perm
)
109 if (perm
!= SMB_ACL_READ
&& perm
!= SMB_ACL_WRITE
110 && perm
!= SMB_ACL_EXECUTE
) {
115 if (permset_d
== NULL
) {
125 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d
, SMB_ACL_PERM_T perm
)
127 return *permset_d
& perm
;
130 char *sys_acl_to_text(SMB_ACL_T acl_d
, ssize_t
*len_p
)
137 * use an initial estimate of 20 bytes per ACL entry
138 * when allocating memory for the text representation
142 maxlen
= 20 * acl_d
->count
;
143 if ((text
= (char *)SMB_MALLOC(maxlen
)) == NULL
) {
148 for (i
= 0; i
< acl_d
->count
; i
++) {
149 struct smb_acl_entry
*ap
= &acl_d
->acl
[i
];
158 switch (ap
->a_type
) {
160 * for debugging purposes it's probably more
161 * useful to dump unknown tag types rather
162 * than just returning an error
165 slprintf(tagbuf
, sizeof(tagbuf
)-1, "0x%x",
171 id
= uidtoname(ap
->uid
);
172 case SMB_ACL_USER_OBJ
:
177 if ((gr
= getgrgid(ap
->gid
)) == NULL
) {
178 slprintf(idbuf
, sizeof(idbuf
)-1, "%ld",
184 case SMB_ACL_GROUP_OBJ
:
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' : '-';
203 /* <tag> : <qualifier> : rwx \n \0 */
204 nbytes
= strlen(tag
) + 1 + strlen(id
) + 1 + 3 + 1 + 1;
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
212 if ((len
+ nbytes
) > maxlen
) {
213 maxlen
+= nbytes
+ 20 * (acl_d
->count
- i
);
214 if ((text
= (char *)SMB_REALLOC(text
, maxlen
)) == NULL
) {
220 slprintf(&text
[len
], nbytes
-1, "%s:%s:%s\n", tag
, id
, perms
);
230 SMB_ACL_T
sys_acl_init(int count
)
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
245 if ((a
= (struct smb_acl_t
*)SMB_MALLOC(
246 sizeof(struct smb_acl_t
) +
247 count
* sizeof(struct smb_acl_entry
))) == NULL
) {
259 int sys_acl_create_entry(SMB_ACL_T
*acl_p
, SMB_ACL_ENTRY_T
*entry_p
)
262 SMB_ACL_ENTRY_T entry_d
;
264 if (acl_p
== NULL
|| entry_p
== NULL
|| (acl_d
= *acl_p
) == NULL
) {
269 if (acl_d
->count
>= acl_d
->size
) {
274 entry_d
= &acl_d
->acl
[acl_d
->count
++];
275 entry_d
->a_type
= SMB_ACL_TAG_INVALID
;
284 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T tag_type
)
288 case SMB_ACL_USER_OBJ
:
290 case SMB_ACL_GROUP_OBJ
:
293 entry_d
->a_type
= tag_type
;
303 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d
, void *qual_p
)
305 if (entry_d
->a_type
== SMB_ACL_USER
) {
306 entry_d
->uid
= *((uid_t
*)qual_p
);
309 if (entry_d
->a_type
== SMB_ACL_GROUP
) {
310 entry_d
->gid
= *((gid_t
*)qual_p
);
318 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T permset_d
)
320 if (*permset_d
& ~(SMB_ACL_READ
|SMB_ACL_WRITE
|SMB_ACL_EXECUTE
)) {
325 entry_d
->a_perm
= *permset_d
;
330 int sys_acl_free_text(char *text
)
336 int sys_acl_free_acl(SMB_ACL_T acl_d
)
342 int sys_acl_free_qualifier(void *qual
, SMB_ACL_TAG_T tagtype
)
347 int sys_acl_valid(SMB_ACL_T acl_d
)
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.
359 #if defined(HAVE_POSIX_ACLS)
361 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
362 const char *path_p
, SMB_ACL_TYPE_T type
)
364 return posixacl_sys_acl_get_file(handle
, path_p
, type
);
367 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
369 return posixacl_sys_acl_get_fd(handle
, fsp
);
372 int sys_acl_set_file(vfs_handle_struct
*handle
,
373 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
375 return posixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
378 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
381 return posixacl_sys_acl_set_fd(handle
, fsp
, acl_d
);
384 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
387 return posixacl_sys_acl_delete_def_file(handle
, path
);
390 #elif defined(HAVE_AIX_ACLS)
392 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
393 const char *path_p
, SMB_ACL_TYPE_T type
)
395 return aixacl_sys_acl_get_file(handle
, path_p
, type
);
398 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
400 return aixacl_sys_acl_get_fd(handle
, fsp
);
403 int sys_acl_set_file(vfs_handle_struct
*handle
,
404 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
406 return aixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
409 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
412 return aixacl_sys_acl_set_fd(handle
, fsp
, acl_d
);
415 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
418 return aixacl_sys_acl_delete_def_file(handle
, path
);
421 #elif defined(HAVE_TRU64_ACLS)
423 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
424 const char *path_p
, SMB_ACL_TYPE_T type
)
426 return tru64acl_sys_acl_get_file(handle
, path_p
, type
);
429 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
431 return tru64acl_sys_acl_get_fd(handle
, fsp
);
434 int sys_acl_set_file(vfs_handle_struct
*handle
,
435 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
437 return tru64acl_sys_acl_set_file(handle
, name
, type
, acl_d
);
440 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
443 return tru64acl_sys_acl_set_fd(handle
, fsp
, acl_d
);
446 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
449 return tru64acl_sys_acl_delete_def_file(handle
, path
);
452 #elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS)
454 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
455 const char *path_p
, SMB_ACL_TYPE_T type
)
457 return solarisacl_sys_acl_get_file(handle
, path_p
, type
);
460 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
462 return solarisacl_sys_acl_get_fd(handle
, fsp
);
465 int sys_acl_set_file(vfs_handle_struct
*handle
,
466 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
468 return solarisacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
471 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
474 return solarisacl_sys_acl_set_fd(handle
, fsp
, acl_d
);
477 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
480 return solarisacl_sys_acl_delete_def_file(handle
, path
);
483 #elif defined(HAVE_HPUX_ACLS)
485 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
486 const char *path_p
, SMB_ACL_TYPE_T type
)
488 return hpuxacl_sys_acl_get_file(handle
, path_p
, type
);
491 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
493 return hpuxacl_sys_acl_get_fd(handle
, fsp
);
496 int sys_acl_set_file(vfs_handle_struct
*handle
,
497 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
499 return hpuxacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
502 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
505 return hpuxacl_sys_acl_set_fd(handle
, fsp
, acl_d
);
508 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
511 return hpuxacl_sys_acl_delete_def_file(handle
, path
);
514 #elif defined(HAVE_IRIX_ACLS)
516 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
517 const char *path_p
, SMB_ACL_TYPE_T type
)
519 return irixacl_sys_acl_get_file(handle
, path_p
, type
);
522 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
524 return irixacl_sys_acl_get_fd(handle
, fsp
);
527 int sys_acl_set_file(vfs_handle_struct
*handle
,
528 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
530 return irixacl_sys_acl_set_file(handle
, name
, type
, acl_d
);
533 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
536 return irixacl_sys_acl_set_fd(handle
, fsp
, acl_d
);
539 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
542 return irixacl_sys_acl_delete_def_file(handle
, path
);
547 SMB_ACL_T
sys_acl_get_file(vfs_handle_struct
*handle
,
548 const char *path_p
, SMB_ACL_TYPE_T type
)
558 SMB_ACL_T
sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
568 int sys_acl_set_file(vfs_handle_struct
*handle
,
569 const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
579 int sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
,
590 int sys_acl_delete_def_file(vfs_handle_struct
*handle
,
603 /************************************************************************
604 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
606 ************************************************************************/
608 int no_acl_syscall_error(int err
)
616 if (err
== ENOTSUP
) {