4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This module provides Security Descriptor handling functions.
33 #include <smbsrv/ntifs.h>
34 #include <smbsrv/smb_idmap.h>
35 #include <smbsrv/libsmb.h>
37 #define SMB_SHR_ACE_READ_PERMS (ACE_READ_PERMS | ACE_EXECUTE | ACE_SYNCHRONIZE)
38 #define SMB_SHR_ACE_CONTROL_PERMS (ACE_MODIFY_PERMS & (~ACE_DELETE_CHILD))
41 * This mapping table is provided to map permissions set by chmod
42 * using 'read_set' and 'modify_set' to what Windows share ACL GUI
43 * expects as Read and Control, respectively.
49 { ACE_MODIFY_PERMS
, SMB_SHR_ACE_CONTROL_PERMS
},
50 { ACE_READ_PERMS
, SMB_SHR_ACE_READ_PERMS
}
53 #define SMB_ACE_MASK_MAP_SIZE (sizeof (smb_ace_map)/sizeof (smb_ace_map[0]))
55 static void smb_sd_set_sacl(smb_sd_t
*, smb_acl_t
*, boolean_t
, int);
56 static void smb_sd_set_dacl(smb_sd_t
*, smb_acl_t
*, boolean_t
, int);
59 smb_sd_init(smb_sd_t
*sd
, uint8_t revision
)
61 bzero(sd
, sizeof (smb_sd_t
));
62 sd
->sd_revision
= revision
;
68 * Free non-NULL members of 'sd' which has to be in
69 * absolute (pointer) form.
72 smb_sd_term(smb_sd_t
*sd
)
75 assert((sd
->sd_control
& SE_SELF_RELATIVE
) == 0);
77 smb_sid_free(sd
->sd_owner
);
78 smb_sid_free(sd
->sd_group
);
79 smb_acl_free(sd
->sd_dacl
);
80 smb_acl_free(sd
->sd_sacl
);
82 bzero(sd
, sizeof (smb_sd_t
));
86 smb_sd_len(smb_sd_t
*sd
, uint32_t secinfo
)
88 uint32_t length
= SMB_SD_HDRSIZE
;
90 if (secinfo
& SMB_OWNER_SECINFO
)
91 length
+= smb_sid_len(sd
->sd_owner
);
93 if (secinfo
& SMB_GROUP_SECINFO
)
94 length
+= smb_sid_len(sd
->sd_group
);
96 if (secinfo
& SMB_DACL_SECINFO
)
97 length
+= smb_acl_len(sd
->sd_dacl
);
99 if (secinfo
& SMB_SACL_SECINFO
)
100 length
+= smb_acl_len(sd
->sd_sacl
);
108 * Return the security information mask for the specified security
112 smb_sd_get_secinfo(smb_sd_t
*sd
)
114 uint32_t sec_info
= 0;
120 sec_info
|= SMB_OWNER_SECINFO
;
123 sec_info
|= SMB_GROUP_SECINFO
;
126 sec_info
|= SMB_DACL_SECINFO
;
129 sec_info
|= SMB_SACL_SECINFO
;
135 * Adjust the Access Mask so that ZFS ACE mask and Windows ACE read mask match.
138 smb_sd_adjust_read_mask(int mask
)
142 for (i
= 0; i
< SMB_ACE_MASK_MAP_SIZE
; ++i
) {
143 if (smb_ace_map
[i
].am_ace_perms
== mask
)
144 return (smb_ace_map
[i
].am_share_perms
);
151 * Get ZFS acl from the share path via acl_get() method.
154 smb_sd_read_acl(char *path
, smb_fssd_t
*fs_sd
)
159 fs_sd
->sd_gid
= fs_sd
->sd_uid
= 0;
162 if (acl_get(path
, 0, &z_acl
) != 0) {
165 return (NT_STATUS_ACCESS_DENIED
);
167 return (NT_STATUS_OBJECT_PATH_NOT_FOUND
);
169 return (NT_STATUS_INTERNAL_ERROR
);
173 if ((z_ace
= (ace_t
*)z_acl
->acl_aclp
) == NULL
)
174 return (NT_STATUS_INVALID_ACL
);
176 for (int i
= 0; i
< z_acl
->acl_cnt
; i
++, z_ace
++)
177 z_ace
->a_access_mask
=
178 smb_sd_adjust_read_mask(z_ace
->a_access_mask
);
180 fs_sd
->sd_zdacl
= z_acl
;
181 fs_sd
->sd_zsacl
= NULL
;
182 return (NT_STATUS_SUCCESS
);
188 * Reads ZFS acl from filesystem using acl_get() method. Convert the ZFS acl to
189 * a Win SD and return the Win SD in absolute form.
191 * NOTE: upon successful return caller MUST free the memory allocated
192 * for the returned SD by calling smb_sd_term().
195 smb_sd_read(char *path
, smb_sd_t
*sd
, uint32_t secinfo
)
198 uint32_t status
= NT_STATUS_SUCCESS
;
202 sd_flags
= SMB_FSSD_FLAGS_DIR
;
203 smb_fssd_init(&fs_sd
, secinfo
, sd_flags
);
205 error
= smb_sd_read_acl(path
, &fs_sd
);
206 if (error
!= NT_STATUS_SUCCESS
) {
207 smb_fssd_term(&fs_sd
);
211 status
= smb_sd_fromfs(&fs_sd
, sd
);
212 smb_fssd_term(&fs_sd
);
218 * Apply ZFS acl to the share path via acl_set() method.
219 * A NULL ACL pointer here represents an error.
220 * Null or empty ACLs are handled in smb_sd_tofs().
223 smb_sd_write_acl(char *path
, smb_fssd_t
*fs_sd
)
227 uint32_t status
= NT_STATUS_SUCCESS
;
229 z_acl
= fs_sd
->sd_zdacl
;
231 return (NT_STATUS_INVALID_ACL
);
233 z_ace
= (ace_t
*)z_acl
->acl_aclp
;
235 return (NT_STATUS_INVALID_ACL
);
237 fs_sd
->sd_gid
= fs_sd
->sd_uid
= 0;
238 if (acl_set(path
, z_acl
) != 0)
239 status
= NT_STATUS_INTERNAL_ERROR
;
247 * Takes a Win SD in absolute form, converts it to
248 * ZFS acl and applies the acl to the share path via acl_set() method.
251 smb_sd_write(char *path
, smb_sd_t
*sd
, uint32_t secinfo
)
254 uint32_t status
= NT_STATUS_SUCCESS
;
258 sd_flags
= SMB_FSSD_FLAGS_DIR
;
259 smb_fssd_init(&fs_sd
, secinfo
, sd_flags
);
261 error
= smb_sd_tofs(sd
, &fs_sd
);
262 if (error
!= NT_STATUS_SUCCESS
) {
263 smb_fssd_term(&fs_sd
);
267 status
= smb_sd_write_acl(path
, &fs_sd
);
268 smb_fssd_term(&fs_sd
);
276 * Creates a filesystem security structure based on the given
277 * Windows security descriptor.
280 smb_sd_tofs(smb_sd_t
*sd
, smb_fssd_t
*fs_sd
)
283 uint32_t status
= NT_STATUS_SUCCESS
;
289 sd_control
= sd
->sd_control
;
292 * ZFS only has one set of flags so for now only
293 * Windows DACL flags are taken into account.
295 if (sd_control
& SE_DACL_DEFAULTED
)
296 flags
|= ACL_DEFAULTED
;
297 if (sd_control
& SE_DACL_AUTO_INHERITED
)
298 flags
|= ACL_AUTO_INHERIT
;
299 if (sd_control
& SE_DACL_PROTECTED
)
300 flags
|= ACL_PROTECTED
;
302 if (fs_sd
->sd_flags
& SMB_FSSD_FLAGS_DIR
)
306 if (fs_sd
->sd_secinfo
& SMB_OWNER_SECINFO
) {
308 if (!smb_sid_isvalid(sid
))
309 return (NT_STATUS_INVALID_SID
);
311 idtype
= SMB_IDMAP_USER
;
312 idm_stat
= smb_idmap_getid(sid
, &fs_sd
->sd_uid
, &idtype
);
313 if (idm_stat
!= IDMAP_SUCCESS
) {
314 return (NT_STATUS_NONE_MAPPED
);
319 if (fs_sd
->sd_secinfo
& SMB_GROUP_SECINFO
) {
321 if (!smb_sid_isvalid(sid
))
322 return (NT_STATUS_INVALID_SID
);
324 idtype
= SMB_IDMAP_GROUP
;
325 idm_stat
= smb_idmap_getid(sid
, &fs_sd
->sd_gid
, &idtype
);
326 if (idm_stat
!= IDMAP_SUCCESS
) {
327 return (NT_STATUS_NONE_MAPPED
);
332 if (fs_sd
->sd_secinfo
& SMB_DACL_SECINFO
) {
333 if (sd
->sd_control
& SE_DACL_PRESENT
) {
334 status
= smb_acl_to_zfs(sd
->sd_dacl
, flags
,
335 SMB_DACL_SECINFO
, &fs_sd
->sd_zdacl
);
336 if (status
!= NT_STATUS_SUCCESS
)
340 return (NT_STATUS_INVALID_ACL
);
344 if (fs_sd
->sd_secinfo
& SMB_SACL_SECINFO
) {
345 if (sd
->sd_control
& SE_SACL_PRESENT
) {
346 status
= smb_acl_to_zfs(sd
->sd_sacl
, flags
,
347 SMB_SACL_SECINFO
, &fs_sd
->sd_zsacl
);
348 if (status
!= NT_STATUS_SUCCESS
) {
352 return (NT_STATUS_INVALID_ACL
);
362 * Makes an Windows style security descriptor in absolute form
363 * based on the given filesystem security information.
365 * Should call smb_sd_term() for the returned sd to free allocated
369 smb_sd_fromfs(smb_fssd_t
*fs_sd
, smb_sd_t
*sd
)
371 uint32_t status
= NT_STATUS_SUCCESS
;
372 smb_acl_t
*acl
= NULL
;
379 smb_sd_init(sd
, SECURITY_DESCRIPTOR_REVISION
);
382 if (fs_sd
->sd_secinfo
& SMB_OWNER_SECINFO
) {
383 idm_stat
= smb_idmap_getsid(fs_sd
->sd_uid
,
384 SMB_IDMAP_USER
, &sid
);
386 if (idm_stat
!= IDMAP_SUCCESS
) {
388 return (NT_STATUS_NONE_MAPPED
);
395 if (fs_sd
->sd_secinfo
& SMB_GROUP_SECINFO
) {
396 idm_stat
= smb_idmap_getsid(fs_sd
->sd_gid
,
397 SMB_IDMAP_GROUP
, &sid
);
399 if (idm_stat
!= IDMAP_SUCCESS
) {
401 return (NT_STATUS_NONE_MAPPED
);
408 if (fs_sd
->sd_secinfo
& SMB_DACL_SECINFO
) {
409 if (fs_sd
->sd_zdacl
!= NULL
) {
410 acl
= smb_acl_from_zfs(fs_sd
->sd_zdacl
);
413 return (NT_STATUS_INTERNAL_ERROR
);
417 * Need to sort the ACL before send it to Windows
418 * clients. Winodws GUI is sensitive about the order
422 smb_sd_set_dacl(sd
, acl
, B_TRUE
,
423 fs_sd
->sd_zdacl
->acl_flags
);
425 smb_sd_set_dacl(sd
, NULL
, B_FALSE
, 0);
430 if (fs_sd
->sd_secinfo
& SMB_SACL_SECINFO
) {
431 if (fs_sd
->sd_zsacl
!= NULL
) {
432 acl
= smb_acl_from_zfs(fs_sd
->sd_zsacl
);
435 return (NT_STATUS_INTERNAL_ERROR
);
438 smb_sd_set_sacl(sd
, acl
, B_TRUE
,
439 fs_sd
->sd_zsacl
->acl_flags
);
441 smb_sd_set_sacl(sd
, NULL
, B_FALSE
, 0);
449 smb_sd_set_dacl(smb_sd_t
*sd
, smb_acl_t
*acl
, boolean_t present
, int flags
)
451 assert((sd
->sd_control
& SE_SELF_RELATIVE
) == 0);
455 if (flags
& ACL_DEFAULTED
)
456 sd
->sd_control
|= SE_DACL_DEFAULTED
;
457 if (flags
& ACL_AUTO_INHERIT
)
458 sd
->sd_control
|= SE_DACL_AUTO_INHERITED
;
459 if (flags
& ACL_PROTECTED
)
460 sd
->sd_control
|= SE_DACL_PROTECTED
;
463 sd
->sd_control
|= SE_DACL_PRESENT
;
467 smb_sd_set_sacl(smb_sd_t
*sd
, smb_acl_t
*acl
, boolean_t present
, int flags
)
469 assert((sd
->sd_control
& SE_SELF_RELATIVE
) == 0);
473 if (flags
& ACL_DEFAULTED
)
474 sd
->sd_control
|= SE_SACL_DEFAULTED
;
475 if (flags
& ACL_AUTO_INHERIT
)
476 sd
->sd_control
|= SE_SACL_AUTO_INHERITED
;
477 if (flags
& ACL_PROTECTED
)
478 sd
->sd_control
|= SE_SACL_PROTECTED
;
481 sd
->sd_control
|= SE_SACL_PRESENT
;
487 * Initializes the given FS SD structure.
490 smb_fssd_init(smb_fssd_t
*fs_sd
, uint32_t secinfo
, uint32_t flags
)
492 bzero(fs_sd
, sizeof (smb_fssd_t
));
493 fs_sd
->sd_secinfo
= secinfo
;
494 fs_sd
->sd_flags
= flags
;
500 * Frees allocated memory for acl fields.
503 smb_fssd_term(smb_fssd_t
*fs_sd
)
507 acl_free(fs_sd
->sd_zdacl
);
508 acl_free(fs_sd
->sd_zsacl
);
510 bzero(fs_sd
, sizeof (smb_fssd_t
));