102d09e03SGordon Ross /* 202d09e03SGordon Ross * CDDL HEADER START 302d09e03SGordon Ross * 402d09e03SGordon Ross * The contents of this file are subject to the terms of the 502d09e03SGordon Ross * Common Development and Distribution License (the "License"). 602d09e03SGordon Ross * You may not use this file except in compliance with the License. 702d09e03SGordon Ross * 802d09e03SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 902d09e03SGordon Ross * or http://www.opensolaris.org/os/licensing. 1002d09e03SGordon Ross * See the License for the specific language governing permissions 1102d09e03SGordon Ross * and limitations under the License. 1202d09e03SGordon Ross * 1302d09e03SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 1402d09e03SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1502d09e03SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 1602d09e03SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 1702d09e03SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 1802d09e03SGordon Ross * 1902d09e03SGordon Ross * CDDL HEADER END 2002d09e03SGordon Ross */ 2102d09e03SGordon Ross 2202d09e03SGordon Ross /* 23*bd7c6f51SGordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2402d09e03SGordon Ross * Use is subject to license terms. 2502d09e03SGordon Ross */ 2602d09e03SGordon Ross 2702d09e03SGordon Ross /* 2802d09e03SGordon Ross * ACL conversion support for smbfs 2902d09e03SGordon Ross * (To/from NT/ZFS-style ACLs.) 3002d09e03SGordon Ross */ 3102d09e03SGordon Ross 3202d09e03SGordon Ross #include <sys/types.h> 3302d09e03SGordon Ross #include <sys/errno.h> 3402d09e03SGordon Ross #include <sys/acl.h> 3502d09e03SGordon Ross #include <sys/byteorder.h> 3602d09e03SGordon Ross 3702d09e03SGordon Ross #ifdef _KERNEL 3802d09e03SGordon Ross 3902d09e03SGordon Ross #include <sys/cred.h> 4002d09e03SGordon Ross #include <sys/cmn_err.h> 4102d09e03SGordon Ross #include <sys/kmem.h> 4202d09e03SGordon Ross #include <sys/sunddi.h> 4302d09e03SGordon Ross #include <sys/vnode.h> 4402d09e03SGordon Ross #include <sys/vfs.h> 4502d09e03SGordon Ross 4602d09e03SGordon Ross #include <sys/kidmap.h> 4702d09e03SGordon Ross 4802d09e03SGordon Ross #else /* _KERNEL */ 4902d09e03SGordon Ross 5002d09e03SGordon Ross #include <stdio.h> 5102d09e03SGordon Ross #include <stdlib.h> 5202d09e03SGordon Ross #include <strings.h> 5302d09e03SGordon Ross 5402d09e03SGordon Ross #include <idmap.h> 5502d09e03SGordon Ross 5602d09e03SGordon Ross #endif /* _KERNEL */ 5702d09e03SGordon Ross 5802d09e03SGordon Ross #include <netsmb/mchain.h> 5902d09e03SGordon Ross #include <netsmb/smb.h> 6002d09e03SGordon Ross #include "smbfs_ntacl.h" 6102d09e03SGordon Ross 62*bd7c6f51SGordon Ross #define NT_SD_REVISION 1 63*bd7c6f51SGordon Ross #define NT_ACL_REVISION 2 64*bd7c6f51SGordon Ross 6502d09e03SGordon Ross #ifdef _KERNEL 6602d09e03SGordon Ross #define MALLOC(size) kmem_alloc(size, KM_SLEEP) 6702d09e03SGordon Ross #define FREESZ(p, sz) kmem_free(p, sz) 6802d09e03SGordon Ross #else /* _KERNEL */ 6902d09e03SGordon Ross #define MALLOC(size) malloc(size) 7002d09e03SGordon Ross #ifndef lint 7102d09e03SGordon Ross #define FREESZ(p, sz) free(p) 7202d09e03SGordon Ross #else /* lint */ 7302d09e03SGordon Ross /* ARGSUSED */ 7402d09e03SGordon Ross static void 7502d09e03SGordon Ross FREESZ(void *p, size_t sz) 7602d09e03SGordon Ross { 7702d09e03SGordon Ross free(p); 7802d09e03SGordon Ross } 7902d09e03SGordon Ross #endif /* lint */ 8002d09e03SGordon Ross #endif /* _KERNEL */ 8102d09e03SGordon Ross 8202d09e03SGordon Ross #define ERRCHK(expr) if ((error = expr) != 0) goto errout 8302d09e03SGordon Ross 8402d09e03SGordon Ross /* 8502d09e03SGordon Ross * Security IDentifier (SID) 8602d09e03SGordon Ross */ 8702d09e03SGordon Ross static void 8802d09e03SGordon Ross ifree_sid(i_ntsid_t *sid) 8902d09e03SGordon Ross { 9002d09e03SGordon Ross size_t sz; 9102d09e03SGordon Ross 9202d09e03SGordon Ross if (sid == NULL) 9302d09e03SGordon Ross return; 9402d09e03SGordon Ross 9502d09e03SGordon Ross sz = I_SID_SIZE(sid->sid_subauthcount); 9602d09e03SGordon Ross FREESZ(sid, sz); 9702d09e03SGordon Ross } 9802d09e03SGordon Ross 9902d09e03SGordon Ross static int 10002d09e03SGordon Ross md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp) 10102d09e03SGordon Ross { 10202d09e03SGordon Ross i_ntsid_t *sid = NULL; 10302d09e03SGordon Ross uint8_t revision, subauthcount; 10402d09e03SGordon Ross uint32_t *subauthp; 10502d09e03SGordon Ross size_t sidsz; 10602d09e03SGordon Ross int error, i; 10702d09e03SGordon Ross 10802d09e03SGordon Ross if ((error = md_get_uint8(mdp, &revision)) != 0) 10902d09e03SGordon Ross return (error); 11002d09e03SGordon Ross if ((error = md_get_uint8(mdp, &subauthcount)) != 0) 11102d09e03SGordon Ross return (error); 11202d09e03SGordon Ross 11302d09e03SGordon Ross sidsz = I_SID_SIZE(subauthcount); 11402d09e03SGordon Ross 11502d09e03SGordon Ross if ((sid = MALLOC(sidsz)) == NULL) 11602d09e03SGordon Ross return (ENOMEM); 11702d09e03SGordon Ross 11802d09e03SGordon Ross bzero(sid, sidsz); 11902d09e03SGordon Ross sid->sid_revision = revision; 12002d09e03SGordon Ross sid->sid_subauthcount = subauthcount; 12102d09e03SGordon Ross ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM)); 12202d09e03SGordon Ross 12302d09e03SGordon Ross subauthp = &sid->sid_subauthvec[0]; 12402d09e03SGordon Ross for (i = 0; i < subauthcount; i++) { 12502d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, subauthp)); 12602d09e03SGordon Ross subauthp++; 12702d09e03SGordon Ross } 12802d09e03SGordon Ross 12902d09e03SGordon Ross /* Success! */ 13002d09e03SGordon Ross *sidp = sid; 13102d09e03SGordon Ross return (0); 13202d09e03SGordon Ross 13302d09e03SGordon Ross errout: 13402d09e03SGordon Ross ifree_sid(sid); 13502d09e03SGordon Ross return (error); 13602d09e03SGordon Ross } 13702d09e03SGordon Ross 13802d09e03SGordon Ross static int 13902d09e03SGordon Ross mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid) 14002d09e03SGordon Ross { 14102d09e03SGordon Ross uint32_t *subauthp; 14202d09e03SGordon Ross int error, i; 14302d09e03SGordon Ross 14402d09e03SGordon Ross if (sid == NULL) 14502d09e03SGordon Ross return (EINVAL); 14602d09e03SGordon Ross 14702d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sid->sid_revision)); 14802d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount)); 14902d09e03SGordon Ross ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM)); 15002d09e03SGordon Ross 15102d09e03SGordon Ross subauthp = &sid->sid_subauthvec[0]; 15202d09e03SGordon Ross for (i = 0; i < sid->sid_subauthcount; i++) { 15302d09e03SGordon Ross ERRCHK(mb_put_uint32le(mbp, *subauthp)); 15402d09e03SGordon Ross subauthp++; 15502d09e03SGordon Ross } 15602d09e03SGordon Ross 15702d09e03SGordon Ross /* Success! */ 15802d09e03SGordon Ross return (0); 15902d09e03SGordon Ross 16002d09e03SGordon Ross errout: 16102d09e03SGordon Ross return (error); 16202d09e03SGordon Ross } 16302d09e03SGordon Ross 16402d09e03SGordon Ross 16502d09e03SGordon Ross /* 16602d09e03SGordon Ross * Access Control Entry (ACE) 16702d09e03SGordon Ross */ 16802d09e03SGordon Ross static void 16902d09e03SGordon Ross ifree_ace(i_ntace_t *ace) 17002d09e03SGordon Ross { 17102d09e03SGordon Ross 17202d09e03SGordon Ross if (ace == NULL) 17302d09e03SGordon Ross return; 17402d09e03SGordon Ross 175*bd7c6f51SGordon Ross switch (ace->ace_hdr.ace_type) { 176*bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE: 177*bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE: 178*bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE: 179*bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE: 180*bd7c6f51SGordon Ross ifree_sid(ace->ace_v2.ace_sid); 181*bd7c6f51SGordon Ross FREESZ(ace, sizeof (i_ntace_v2_t)); 182*bd7c6f51SGordon Ross break; 183*bd7c6f51SGordon Ross /* other types todo */ 184*bd7c6f51SGordon Ross default: 185*bd7c6f51SGordon Ross break; 186*bd7c6f51SGordon Ross } 18702d09e03SGordon Ross } 18802d09e03SGordon Ross 18902d09e03SGordon Ross static int 19002d09e03SGordon Ross md_get_ace(mdchain_t *mdp, i_ntace_t **acep) 19102d09e03SGordon Ross { 19202d09e03SGordon Ross mdchain_t tmp_md; 193*bd7c6f51SGordon Ross i_ntace_hdr_t ace_hdr; 19402d09e03SGordon Ross i_ntace_t *ace = NULL; 195*bd7c6f51SGordon Ross uint16_t alloc_size; 19602d09e03SGordon Ross int error; 19702d09e03SGordon Ross 19802d09e03SGordon Ross /* 19902d09e03SGordon Ross * The ACE is realy variable length, 20002d09e03SGordon Ross * with format determined by the type. 20102d09e03SGordon Ross * 20202d09e03SGordon Ross * There may also be padding after it, so 203*bd7c6f51SGordon Ross * decode it using a copy of the mdchain, 20402d09e03SGordon Ross * and then consume the specified length. 20502d09e03SGordon Ross */ 20602d09e03SGordon Ross tmp_md = *mdp; 20702d09e03SGordon Ross 208*bd7c6f51SGordon Ross /* Fixed-size ACE header */ 209*bd7c6f51SGordon Ross ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type)); 210*bd7c6f51SGordon Ross ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags)); 211*bd7c6f51SGordon Ross ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size)); 21202d09e03SGordon Ross 213*bd7c6f51SGordon Ross switch (ace_hdr.ace_type) { 214*bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE: 215*bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE: 216*bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE: 217*bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE: 218*bd7c6f51SGordon Ross alloc_size = sizeof (i_ntace_v2_t); 219*bd7c6f51SGordon Ross if ((ace = MALLOC(alloc_size)) == NULL) 220*bd7c6f51SGordon Ross return (ENOMEM); 221*bd7c6f51SGordon Ross bzero(ace, alloc_size); 222*bd7c6f51SGordon Ross /* ACE header */ 223*bd7c6f51SGordon Ross ace->ace_hdr.ace_type = ace_hdr.ace_type; 224*bd7c6f51SGordon Ross ace->ace_hdr.ace_flags = ace_hdr.ace_flags; 225*bd7c6f51SGordon Ross ace->ace_hdr.ace_size = alloc_size; 226*bd7c6f51SGordon Ross /* Type-specific data. */ 227*bd7c6f51SGordon Ross ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights)); 228*bd7c6f51SGordon Ross ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid)); 229*bd7c6f51SGordon Ross break; 23002d09e03SGordon Ross 231*bd7c6f51SGordon Ross /* other types todo */ 232*bd7c6f51SGordon Ross default: 233*bd7c6f51SGordon Ross error = EIO; 234*bd7c6f51SGordon Ross goto errout; 235*bd7c6f51SGordon Ross } 236*bd7c6f51SGordon Ross 237*bd7c6f51SGordon Ross /* Now actually consume ace_hdr.ace_size */ 238*bd7c6f51SGordon Ross ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM)); 23902d09e03SGordon Ross 24002d09e03SGordon Ross /* Success! */ 24102d09e03SGordon Ross *acep = ace; 24202d09e03SGordon Ross return (0); 24302d09e03SGordon Ross 24402d09e03SGordon Ross errout: 24502d09e03SGordon Ross ifree_ace(ace); 24602d09e03SGordon Ross return (error); 24702d09e03SGordon Ross } 24802d09e03SGordon Ross 24902d09e03SGordon Ross static int 25002d09e03SGordon Ross mb_put_ace(mbchain_t *mbp, i_ntace_t *ace) 25102d09e03SGordon Ross { 25202d09e03SGordon Ross int cnt0, error; 25302d09e03SGordon Ross uint16_t ace_len, *ace_len_p; 25402d09e03SGordon Ross 25502d09e03SGordon Ross if (ace == NULL) 25602d09e03SGordon Ross return (EINVAL); 25702d09e03SGordon Ross 25802d09e03SGordon Ross cnt0 = mbp->mb_count; 25902d09e03SGordon Ross 260*bd7c6f51SGordon Ross /* 261*bd7c6f51SGordon Ross * Put the (fixed-size) ACE header 262*bd7c6f51SGordon Ross * Will fill in the length later. 263*bd7c6f51SGordon Ross */ 264*bd7c6f51SGordon Ross ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type)); 265*bd7c6f51SGordon Ross ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags)); 26602d09e03SGordon Ross ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p)); 26702d09e03SGordon Ross if (ace_len_p == NULL) { 26802d09e03SGordon Ross error = ENOMEM; 26902d09e03SGordon Ross goto errout; 27002d09e03SGordon Ross } 27102d09e03SGordon Ross 272*bd7c6f51SGordon Ross switch (ace->ace_hdr.ace_type) { 273*bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE: 274*bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE: 275*bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE: 276*bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE: 277*bd7c6f51SGordon Ross /* Put type-specific data. */ 278*bd7c6f51SGordon Ross ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights)); 279*bd7c6f51SGordon Ross ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid)); 280*bd7c6f51SGordon Ross break; 28102d09e03SGordon Ross 282*bd7c6f51SGordon Ross /* other types todo */ 283*bd7c6f51SGordon Ross default: 284*bd7c6f51SGordon Ross error = EIO; 285*bd7c6f51SGordon Ross goto errout; 286*bd7c6f51SGordon Ross } 287*bd7c6f51SGordon Ross 288*bd7c6f51SGordon Ross /* Fill in the (OtW) ACE length. */ 28902d09e03SGordon Ross ace_len = mbp->mb_count - cnt0; 29002d09e03SGordon Ross *ace_len_p = htoles(ace_len); 29102d09e03SGordon Ross 29202d09e03SGordon Ross /* Success! */ 29302d09e03SGordon Ross return (0); 29402d09e03SGordon Ross 29502d09e03SGordon Ross errout: 29602d09e03SGordon Ross return (error); 29702d09e03SGordon Ross } 29802d09e03SGordon Ross 29902d09e03SGordon Ross 30002d09e03SGordon Ross /* 30102d09e03SGordon Ross * Access Control List (ACL) 30202d09e03SGordon Ross */ 30302d09e03SGordon Ross 30402d09e03SGordon Ross /* Not an OTW structure, so size can be at our convenience. */ 30502d09e03SGordon Ross #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *)) 30602d09e03SGordon Ross 30702d09e03SGordon Ross static void 30802d09e03SGordon Ross ifree_acl(i_ntacl_t *acl) 30902d09e03SGordon Ross { 31002d09e03SGordon Ross i_ntace_t **acep; 31102d09e03SGordon Ross size_t sz; 31202d09e03SGordon Ross int i; 31302d09e03SGordon Ross 31402d09e03SGordon Ross if (acl == NULL) 31502d09e03SGordon Ross return; 31602d09e03SGordon Ross 31702d09e03SGordon Ross acep = &acl->acl_acevec[0]; 31802d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) { 31902d09e03SGordon Ross ifree_ace(*acep); 32002d09e03SGordon Ross acep++; 32102d09e03SGordon Ross } 32202d09e03SGordon Ross sz = I_ACL_SIZE(acl->acl_acecount); 32302d09e03SGordon Ross FREESZ(acl, sz); 32402d09e03SGordon Ross } 32502d09e03SGordon Ross 32602d09e03SGordon Ross static int 32702d09e03SGordon Ross md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp) 32802d09e03SGordon Ross { 32902d09e03SGordon Ross i_ntacl_t *acl = NULL; 33002d09e03SGordon Ross i_ntace_t **acep; 33102d09e03SGordon Ross uint8_t revision; 33202d09e03SGordon Ross uint16_t acl_len, acecount; 33302d09e03SGordon Ross size_t aclsz; 33402d09e03SGordon Ross int i, error; 33502d09e03SGordon Ross 33602d09e03SGordon Ross if ((error = md_get_uint8(mdp, &revision)) != 0) 33702d09e03SGordon Ross return (error); 338*bd7c6f51SGordon Ross if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */ 33902d09e03SGordon Ross return (error); 34002d09e03SGordon Ross if ((error = md_get_uint16le(mdp, &acl_len)) != 0) 34102d09e03SGordon Ross return (error); 34202d09e03SGordon Ross if ((error = md_get_uint16le(mdp, &acecount)) != 0) 34302d09e03SGordon Ross return (error); 344*bd7c6f51SGordon Ross if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */ 34502d09e03SGordon Ross return (error); 34602d09e03SGordon Ross 34702d09e03SGordon Ross aclsz = I_ACL_SIZE(acecount); 34802d09e03SGordon Ross if ((acl = MALLOC(aclsz)) == NULL) 34902d09e03SGordon Ross return (ENOMEM); 35002d09e03SGordon Ross bzero(acl, aclsz); 35102d09e03SGordon Ross acl->acl_revision = revision; 35202d09e03SGordon Ross acl->acl_acecount = acecount; 35302d09e03SGordon Ross 35402d09e03SGordon Ross acep = &acl->acl_acevec[0]; 35502d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) { 35602d09e03SGordon Ross ERRCHK(md_get_ace(mdp, acep)); 35702d09e03SGordon Ross acep++; 35802d09e03SGordon Ross } 35902d09e03SGordon Ross /* 36002d09e03SGordon Ross * There may be more data here, but 36102d09e03SGordon Ross * the caller takes care of that. 36202d09e03SGordon Ross */ 36302d09e03SGordon Ross 36402d09e03SGordon Ross /* Success! */ 36502d09e03SGordon Ross *aclp = acl; 36602d09e03SGordon Ross return (0); 36702d09e03SGordon Ross 36802d09e03SGordon Ross errout: 36902d09e03SGordon Ross ifree_acl(acl); 37002d09e03SGordon Ross return (error); 37102d09e03SGordon Ross } 37202d09e03SGordon Ross 37302d09e03SGordon Ross static int 37402d09e03SGordon Ross mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl) 37502d09e03SGordon Ross { 37602d09e03SGordon Ross i_ntace_t **acep; 37702d09e03SGordon Ross uint16_t acl_len, *acl_len_p; 37802d09e03SGordon Ross int i, cnt0, error; 37902d09e03SGordon Ross 38002d09e03SGordon Ross cnt0 = mbp->mb_count; 38102d09e03SGordon Ross 38202d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, acl->acl_revision)); 38302d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */ 38402d09e03SGordon Ross acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p)); 38502d09e03SGordon Ross if (acl_len_p == NULL) { 38602d09e03SGordon Ross error = ENOMEM; 38702d09e03SGordon Ross goto errout; 38802d09e03SGordon Ross } 38902d09e03SGordon Ross ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount)); 39002d09e03SGordon Ross ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */ 39102d09e03SGordon Ross 39202d09e03SGordon Ross acep = &acl->acl_acevec[0]; 39302d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) { 39402d09e03SGordon Ross ERRCHK(mb_put_ace(mbp, *acep)); 39502d09e03SGordon Ross acep++; 39602d09e03SGordon Ross } 39702d09e03SGordon Ross 39802d09e03SGordon Ross /* Fill in acl_len_p */ 39902d09e03SGordon Ross acl_len = mbp->mb_count - cnt0; 40002d09e03SGordon Ross *acl_len_p = htoles(acl_len); 40102d09e03SGordon Ross 40202d09e03SGordon Ross /* Success! */ 40302d09e03SGordon Ross return (0); 40402d09e03SGordon Ross 40502d09e03SGordon Ross errout: 40602d09e03SGordon Ross return (error); 40702d09e03SGordon Ross } 40802d09e03SGordon Ross 40902d09e03SGordon Ross 41002d09e03SGordon Ross /* 41102d09e03SGordon Ross * Security Descriptor 41202d09e03SGordon Ross */ 41302d09e03SGordon Ross void 41402d09e03SGordon Ross smbfs_acl_free_sd(i_ntsd_t *sd) 41502d09e03SGordon Ross { 41602d09e03SGordon Ross 41702d09e03SGordon Ross if (sd == NULL) 41802d09e03SGordon Ross return; 41902d09e03SGordon Ross 42002d09e03SGordon Ross ifree_sid(sd->sd_owner); 42102d09e03SGordon Ross ifree_sid(sd->sd_group); 42202d09e03SGordon Ross ifree_acl(sd->sd_sacl); 42302d09e03SGordon Ross ifree_acl(sd->sd_dacl); 42402d09e03SGordon Ross 42502d09e03SGordon Ross FREESZ(sd, sizeof (*sd)); 42602d09e03SGordon Ross } 42702d09e03SGordon Ross 42802d09e03SGordon Ross /* 42902d09e03SGordon Ross * Import a raw SD (mb chain) into "internal" form. 43002d09e03SGordon Ross * (like "absolute" form per. NT docs) 43102d09e03SGordon Ross * Returns allocated data in sdp 43202d09e03SGordon Ross * 43302d09e03SGordon Ross * Note: does NOT consume all the mdp data, so the 43402d09e03SGordon Ross * caller has to take care of that if necessary. 43502d09e03SGordon Ross */ 43602d09e03SGordon Ross int 43702d09e03SGordon Ross md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp) 43802d09e03SGordon Ross { 43902d09e03SGordon Ross i_ntsd_t *sd = NULL; 44002d09e03SGordon Ross mdchain_t top_md, tmp_md; 44102d09e03SGordon Ross uint32_t owneroff, groupoff, sacloff, dacloff; 44202d09e03SGordon Ross int error; 44302d09e03SGordon Ross 44402d09e03SGordon Ross if ((sd = MALLOC(sizeof (*sd))) == NULL) 44502d09e03SGordon Ross return (ENOMEM); 44602d09e03SGordon Ross bzero(sd, sizeof (*sd)); 44702d09e03SGordon Ross 44802d09e03SGordon Ross /* 44902d09e03SGordon Ross * Offsets below are relative to this point, 45002d09e03SGordon Ross * so save the mdp state for use below. 45102d09e03SGordon Ross */ 45202d09e03SGordon Ross top_md = *mdp; 45302d09e03SGordon Ross 45402d09e03SGordon Ross ERRCHK(md_get_uint8(mdp, &sd->sd_revision)); 45502d09e03SGordon Ross ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl)); 45602d09e03SGordon Ross ERRCHK(md_get_uint16le(mdp, &sd->sd_flags)); 45702d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &owneroff)); 45802d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &groupoff)); 45902d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &sacloff)); 46002d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &dacloff)); 46102d09e03SGordon Ross 46202d09e03SGordon Ross /* 463*bd7c6f51SGordon Ross * The SD is "self-relative" on the wire, 464*bd7c6f51SGordon Ross * but not after this decodes it. 465*bd7c6f51SGordon Ross */ 466*bd7c6f51SGordon Ross sd->sd_flags &= ~SD_SELF_RELATIVE; 467*bd7c6f51SGordon Ross 468*bd7c6f51SGordon Ross /* 46902d09e03SGordon Ross * For each section make a temporary copy of the 47002d09e03SGordon Ross * top_md state, advance to the given offset, and 47102d09e03SGordon Ross * pass that to the lower md_get_xxx functions. 47202d09e03SGordon Ross * These could be marshalled in any order, but 47302d09e03SGordon Ross * are normally found in the order shown here. 47402d09e03SGordon Ross */ 47502d09e03SGordon Ross if (sacloff) { 47602d09e03SGordon Ross tmp_md = top_md; 47702d09e03SGordon Ross md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM); 47802d09e03SGordon Ross ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl)); 47902d09e03SGordon Ross } 48002d09e03SGordon Ross if (dacloff) { 48102d09e03SGordon Ross tmp_md = top_md; 48202d09e03SGordon Ross md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM); 48302d09e03SGordon Ross ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl)); 48402d09e03SGordon Ross } 48502d09e03SGordon Ross if (owneroff) { 48602d09e03SGordon Ross tmp_md = top_md; 48702d09e03SGordon Ross md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM); 48802d09e03SGordon Ross ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner)); 48902d09e03SGordon Ross } 49002d09e03SGordon Ross if (groupoff) { 49102d09e03SGordon Ross tmp_md = top_md; 49202d09e03SGordon Ross md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM); 49302d09e03SGordon Ross ERRCHK(md_get_sid(&tmp_md, &sd->sd_group)); 49402d09e03SGordon Ross } 49502d09e03SGordon Ross 49602d09e03SGordon Ross /* Success! */ 49702d09e03SGordon Ross *sdp = sd; 49802d09e03SGordon Ross return (0); 49902d09e03SGordon Ross 50002d09e03SGordon Ross errout: 50102d09e03SGordon Ross smbfs_acl_free_sd(sd); 50202d09e03SGordon Ross return (error); 50302d09e03SGordon Ross } 50402d09e03SGordon Ross 50502d09e03SGordon Ross /* 50602d09e03SGordon Ross * Export an "internal" SD into an raw SD (mb chain). 50702d09e03SGordon Ross * (a.k.a "self-relative" form per. NT docs) 50802d09e03SGordon Ross * Returns allocated mbchain in mbp. 50902d09e03SGordon Ross */ 51002d09e03SGordon Ross int 51102d09e03SGordon Ross mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd) 51202d09e03SGordon Ross { 51302d09e03SGordon Ross uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp; 51402d09e03SGordon Ross uint32_t owneroff, groupoff, sacloff, dacloff; 515*bd7c6f51SGordon Ross uint16_t flags; 51602d09e03SGordon Ross int cnt0, error; 51702d09e03SGordon Ross 51802d09e03SGordon Ross cnt0 = mbp->mb_count; 51902d09e03SGordon Ross owneroff = groupoff = sacloff = dacloff = 0; 52002d09e03SGordon Ross 521*bd7c6f51SGordon Ross /* The SD is "self-relative" on the wire. */ 522*bd7c6f51SGordon Ross flags = sd->sd_flags | SD_SELF_RELATIVE; 523*bd7c6f51SGordon Ross 52402d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sd->sd_revision)); 52502d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl)); 526*bd7c6f51SGordon Ross ERRCHK(mb_put_uint16le(mbp, flags)); 52702d09e03SGordon Ross 52802d09e03SGordon Ross owneroffp = mb_reserve(mbp, sizeof (*owneroffp)); 52902d09e03SGordon Ross groupoffp = mb_reserve(mbp, sizeof (*groupoffp)); 53002d09e03SGordon Ross sacloffp = mb_reserve(mbp, sizeof (*sacloffp)); 53102d09e03SGordon Ross dacloffp = mb_reserve(mbp, sizeof (*dacloffp)); 53202d09e03SGordon Ross if (owneroffp == NULL || groupoffp == NULL || 53302d09e03SGordon Ross sacloffp == NULL || dacloffp == NULL) { 53402d09e03SGordon Ross error = ENOMEM; 53502d09e03SGordon Ross goto errout; 53602d09e03SGordon Ross } 53702d09e03SGordon Ross 53802d09e03SGordon Ross /* 53902d09e03SGordon Ross * These could be marshalled in any order, but 54002d09e03SGordon Ross * are normally found in the order shown here. 54102d09e03SGordon Ross */ 54202d09e03SGordon Ross if (sd->sd_sacl) { 54302d09e03SGordon Ross sacloff = mbp->mb_count - cnt0; 54402d09e03SGordon Ross ERRCHK(mb_put_acl(mbp, sd->sd_sacl)); 54502d09e03SGordon Ross } 54602d09e03SGordon Ross if (sd->sd_dacl) { 54702d09e03SGordon Ross dacloff = mbp->mb_count - cnt0; 54802d09e03SGordon Ross ERRCHK(mb_put_acl(mbp, sd->sd_dacl)); 54902d09e03SGordon Ross } 55002d09e03SGordon Ross if (sd->sd_owner) { 55102d09e03SGordon Ross owneroff = mbp->mb_count - cnt0; 55202d09e03SGordon Ross ERRCHK(mb_put_sid(mbp, sd->sd_owner)); 55302d09e03SGordon Ross } 55402d09e03SGordon Ross if (sd->sd_group) { 55502d09e03SGordon Ross groupoff = mbp->mb_count - cnt0; 55602d09e03SGordon Ross ERRCHK(mb_put_sid(mbp, sd->sd_group)); 55702d09e03SGordon Ross } 55802d09e03SGordon Ross 55902d09e03SGordon Ross /* Fill in the offsets */ 56002d09e03SGordon Ross *owneroffp = htolel(owneroff); 56102d09e03SGordon Ross *groupoffp = htolel(groupoff); 56202d09e03SGordon Ross *sacloffp = htolel(sacloff); 56302d09e03SGordon Ross *dacloffp = htolel(dacloff); 56402d09e03SGordon Ross 56502d09e03SGordon Ross /* Success! */ 56602d09e03SGordon Ross return (0); 56702d09e03SGordon Ross 56802d09e03SGordon Ross errout: 56902d09e03SGordon Ross return (error); 57002d09e03SGordon Ross } 57102d09e03SGordon Ross 57202d09e03SGordon Ross /* 573*bd7c6f51SGordon Ross * ================================================================ 574*bd7c6f51SGordon Ross * Support for ACL fetch, including conversions 575*bd7c6f51SGordon Ross * from Windows ACLs to NFSv4-style ACLs. 576*bd7c6f51SGordon Ross * ================================================================ 57702d09e03SGordon Ross */ 57802d09e03SGordon Ross 579*bd7c6f51SGordon Ross #define GENERIC_RIGHTS_MASK \ 580*bd7c6f51SGordon Ross (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\ 581*bd7c6f51SGordon Ross GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS) 582*bd7c6f51SGordon Ross 583*bd7c6f51SGordon Ross /* 584*bd7c6f51SGordon Ross * Table for converting NT GENERIC_RIGHT_... to specific rights 585*bd7c6f51SGordon Ross * appropriate for objects of type file. 586*bd7c6f51SGordon Ross */ 587*bd7c6f51SGordon Ross struct gen2fsr { 588*bd7c6f51SGordon Ross uint32_t gf_generic; 589*bd7c6f51SGordon Ross uint32_t gf_specific; 590*bd7c6f51SGordon Ross }; 591*bd7c6f51SGordon Ross static const struct gen2fsr 592*bd7c6f51SGordon Ross smbfs_gen2fsr[] = { 593*bd7c6f51SGordon Ross { 594*bd7c6f51SGordon Ross GENERIC_RIGHT_READ_ACCESS, 595*bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS | 596*bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS | 597*bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_ATTRIBUTES | 598*bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_EA | 599*bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_DATA }, 600*bd7c6f51SGordon Ross { 601*bd7c6f51SGordon Ross GENERIC_RIGHT_WRITE_ACCESS, 602*bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS | 603*bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS | 604*bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_ATTRIBUTES | 605*bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_EA | 606*bd7c6f51SGordon Ross SA_RIGHT_FILE_APPEND_DATA | 607*bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_DATA }, 608*bd7c6f51SGordon Ross { 609*bd7c6f51SGordon Ross GENERIC_RIGHT_EXECUTE_ACCESS, 610*bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS | 611*bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS | 612*bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_ATTRIBUTES | 613*bd7c6f51SGordon Ross SA_RIGHT_FILE_EXECUTE }, 614*bd7c6f51SGordon Ross { 615*bd7c6f51SGordon Ross GENERIC_RIGHT_ALL_ACCESS, 616*bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS | 617*bd7c6f51SGordon Ross STD_RIGHT_WRITE_OWNER_ACCESS | 618*bd7c6f51SGordon Ross STD_RIGHT_WRITE_DAC_ACCESS | 619*bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS | 620*bd7c6f51SGordon Ross STD_RIGHT_DELETE_ACCESS | 621*bd7c6f51SGordon Ross SA_RIGHT_FILE_ALL_ACCESS }, 622*bd7c6f51SGordon Ross { 0, 0 } 623*bd7c6f51SGordon Ross }; 624*bd7c6f51SGordon Ross 625*bd7c6f51SGordon Ross /* 626*bd7c6f51SGordon Ross * Table for translating ZFS ACE flags to NT ACE flags. 627*bd7c6f51SGordon Ross * The low four bits are the same, but not others. 628*bd7c6f51SGordon Ross */ 629*bd7c6f51SGordon Ross struct zaf2naf { 630*bd7c6f51SGordon Ross uint16_t za_flag; 631*bd7c6f51SGordon Ross uint8_t na_flag; 632*bd7c6f51SGordon Ross }; 633*bd7c6f51SGordon Ross static const struct zaf2naf 634*bd7c6f51SGordon Ross smbfs_zaf2naf[] = { 635*bd7c6f51SGordon Ross { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG }, 636*bd7c6f51SGordon Ross { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG }, 637*bd7c6f51SGordon Ross { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG }, 638*bd7c6f51SGordon Ross { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG }, 639*bd7c6f51SGordon Ross { ACE_INHERITED_ACE, INHERITED_ACE_FLAG }, 640*bd7c6f51SGordon Ross { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG }, 641*bd7c6f51SGordon Ross { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG }, 642*bd7c6f51SGordon Ross { 0, 0 } 643*bd7c6f51SGordon Ross }; 64402d09e03SGordon Ross 64502d09e03SGordon Ross /* 64602d09e03SGordon Ross * Convert an NT SID to a string. Optionally return the 64702d09e03SGordon Ross * last sub-authority (or "relative ID" -- RID) in *ridp 64802d09e03SGordon Ross * and truncate the output string after the domain part. 64902d09e03SGordon Ross * If ridp==NULL, the output string is the whole SID, 65002d09e03SGordon Ross * including both the domain and RID. 65102d09e03SGordon Ross * 65202d09e03SGordon Ross * Return length written, or -1 on error. 65302d09e03SGordon Ross */ 65402d09e03SGordon Ross int 65502d09e03SGordon Ross smbfs_sid2str(i_ntsid_t *sid, 65602d09e03SGordon Ross char *obuf, size_t osz, uint32_t *ridp) 65702d09e03SGordon Ross { 65802d09e03SGordon Ross char *s = obuf; 65902d09e03SGordon Ross uint64_t auth = 0; 66002d09e03SGordon Ross uint_t i, n; 66102d09e03SGordon Ross uint32_t subs, *ip; 66202d09e03SGordon Ross 66302d09e03SGordon Ross n = snprintf(s, osz, "S-%u", sid->sid_revision); 66402d09e03SGordon Ross if (n > osz) 66502d09e03SGordon Ross return (-1); 66602d09e03SGordon Ross s += n; osz -= n; 66702d09e03SGordon Ross 66802d09e03SGordon Ross for (i = 0; i < 6; i++) 66902d09e03SGordon Ross auth = (auth << 8) | sid->sid_authority[i]; 67002d09e03SGordon Ross n = snprintf(s, osz, "-%llu", (u_longlong_t)auth); 67102d09e03SGordon Ross if (n > osz) 67202d09e03SGordon Ross return (-1); 67302d09e03SGordon Ross s += n; osz -= n; 67402d09e03SGordon Ross 67502d09e03SGordon Ross subs = sid->sid_subauthcount; 67602d09e03SGordon Ross if (subs < 1 || subs > 15) 67702d09e03SGordon Ross return (-1); 67802d09e03SGordon Ross if (ridp) 67902d09e03SGordon Ross subs--; 68002d09e03SGordon Ross 68102d09e03SGordon Ross ip = &sid->sid_subauthvec[0]; 68202d09e03SGordon Ross for (; subs; subs--, ip++) { 68302d09e03SGordon Ross n = snprintf(s, osz, "-%u", *ip); 68402d09e03SGordon Ross if (n > osz) 68502d09e03SGordon Ross return (-1); 68602d09e03SGordon Ross s += n; osz -= n; 68702d09e03SGordon Ross } 68802d09e03SGordon Ross if (ridp) 68902d09e03SGordon Ross *ridp = *ip; 69002d09e03SGordon Ross 69102d09e03SGordon Ross /* LINTED E_PTRDIFF_OVERFLOW */ 69202d09e03SGordon Ross return (s - obuf); 69302d09e03SGordon Ross } 69402d09e03SGordon Ross 69502d09e03SGordon Ross /* 69602d09e03SGordon Ross * Our interface to the idmap service. 69702d09e03SGordon Ross * 69802d09e03SGordon Ross * The idmap API is _almost_ the same between 69902d09e03SGordon Ross * kernel and user-level. But not quite... 70002d09e03SGordon Ross * Hope this improves readability below. 70102d09e03SGordon Ross */ 70202d09e03SGordon Ross #ifdef _KERNEL 70302d09e03SGordon Ross 704*bd7c6f51SGordon Ross #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \ 705*bd7c6f51SGordon Ross kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP) 706*bd7c6f51SGordon Ross 707*bd7c6f51SGordon Ross #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \ 708*bd7c6f51SGordon Ross kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP) 709*bd7c6f51SGordon Ross 710*bd7c6f51SGordon Ross #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \ 71102d09e03SGordon Ross kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) 712*bd7c6f51SGordon Ross 713*bd7c6f51SGordon Ross #define I_getmappings kidmap_get_mappings 71402d09e03SGordon Ross 71502d09e03SGordon Ross #else /* _KERNEL */ 71602d09e03SGordon Ross 717*bd7c6f51SGordon Ross #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \ 718*bd7c6f51SGordon Ross idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP) 719*bd7c6f51SGordon Ross 720*bd7c6f51SGordon Ross #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \ 721*bd7c6f51SGordon Ross idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP) 722*bd7c6f51SGordon Ross 723*bd7c6f51SGordon Ross #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \ 72402d09e03SGordon Ross idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP) 725*bd7c6f51SGordon Ross 726*bd7c6f51SGordon Ross #define I_getmappings idmap_get_mappings 72702d09e03SGordon Ross 72802d09e03SGordon Ross #endif /* _KERNEL */ 72902d09e03SGordon Ross 73002d09e03SGordon Ross 73102d09e03SGordon Ross /* 732*bd7c6f51SGordon Ross * The idmap request types, chosen so they also 733*bd7c6f51SGordon Ross * match the values returned in mi_isuser. 734*bd7c6f51SGordon Ross */ 735*bd7c6f51SGordon Ross #define IDM_TYPE_ANY -1 736*bd7c6f51SGordon Ross #define IDM_TYPE_GROUP 0 737*bd7c6f51SGordon Ross #define IDM_TYPE_USER 1 738*bd7c6f51SGordon Ross 739*bd7c6f51SGordon Ross /* 740*bd7c6f51SGordon Ross * A sentinel value for mi_isuser (below) to indicate 74102d09e03SGordon Ross * that the SID is the well-known "Everyone" (S-1-1-0). 74202d09e03SGordon Ross * The idmap library only uses -1, 0, 1, so this value 74302d09e03SGordon Ross * is arbitrary but must not overlap w/ idmap values. 74402d09e03SGordon Ross * XXX: Could use a way for idmap to tell us when 74502d09e03SGordon Ross * it recognizes this well-known SID. 74602d09e03SGordon Ross */ 747*bd7c6f51SGordon Ross #define IDM_EVERYONE 11 748*bd7c6f51SGordon Ross 749*bd7c6f51SGordon Ross struct mapinfo2uid { 750*bd7c6f51SGordon Ross uid_t mi_uid; /* or gid, or pid */ 751*bd7c6f51SGordon Ross int mi_isuser; /* IDM_TYPE */ 752*bd7c6f51SGordon Ross idmap_stat mi_status; 753*bd7c6f51SGordon Ross }; 75402d09e03SGordon Ross 75502d09e03SGordon Ross /* 75602d09e03SGordon Ross * Build an idmap request. Cleanup is 75702d09e03SGordon Ross * handled by the caller (error or not) 75802d09e03SGordon Ross */ 75902d09e03SGordon Ross static int 76002d09e03SGordon Ross mkrq_idmap_sid2ux( 76102d09e03SGordon Ross idmap_get_handle_t *idmap_gh, 762*bd7c6f51SGordon Ross struct mapinfo2uid *mip, 76302d09e03SGordon Ross i_ntsid_t *sid, 764*bd7c6f51SGordon Ross int req_type) 76502d09e03SGordon Ross { 766*bd7c6f51SGordon Ross char strbuf[256]; 767*bd7c6f51SGordon Ross char *sid_prefix; 76802d09e03SGordon Ross uint32_t rid; 76902d09e03SGordon Ross idmap_stat idms; 77002d09e03SGordon Ross 771*bd7c6f51SGordon Ross if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0) 77202d09e03SGordon Ross return (EINVAL); 773*bd7c6f51SGordon Ross sid_prefix = strbuf; 77402d09e03SGordon Ross 77502d09e03SGordon Ross /* 77602d09e03SGordon Ross * Give the "Everyone" group special treatment. 77702d09e03SGordon Ross */ 77802d09e03SGordon Ross if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) { 77902d09e03SGordon Ross /* This is "Everyone" */ 78002d09e03SGordon Ross mip->mi_uid = (uid_t)-1; 781*bd7c6f51SGordon Ross mip->mi_isuser = IDM_EVERYONE; 78202d09e03SGordon Ross mip->mi_status = 0; 78302d09e03SGordon Ross return (0); 78402d09e03SGordon Ross } 78502d09e03SGordon Ross 786*bd7c6f51SGordon Ross switch (req_type) { 787*bd7c6f51SGordon Ross 788*bd7c6f51SGordon Ross case IDM_TYPE_USER: 789*bd7c6f51SGordon Ross mip->mi_isuser = req_type; 790*bd7c6f51SGordon Ross idms = I_getuidbysid(idmap_gh, sid_prefix, rid, 791*bd7c6f51SGordon Ross &mip->mi_uid, &mip->mi_status); 792*bd7c6f51SGordon Ross break; 793*bd7c6f51SGordon Ross 794*bd7c6f51SGordon Ross case IDM_TYPE_GROUP: 795*bd7c6f51SGordon Ross mip->mi_isuser = req_type; 796*bd7c6f51SGordon Ross idms = I_getgidbysid(idmap_gh, sid_prefix, rid, 797*bd7c6f51SGordon Ross &mip->mi_uid, &mip->mi_status); 798*bd7c6f51SGordon Ross break; 799*bd7c6f51SGordon Ross 800*bd7c6f51SGordon Ross case IDM_TYPE_ANY: 801*bd7c6f51SGordon Ross idms = I_getpidbysid(idmap_gh, sid_prefix, rid, 80202d09e03SGordon Ross &mip->mi_uid, &mip->mi_isuser, &mip->mi_status); 803*bd7c6f51SGordon Ross break; 804*bd7c6f51SGordon Ross 805*bd7c6f51SGordon Ross default: 806*bd7c6f51SGordon Ross idms = IDMAP_ERR_OTHER; 807*bd7c6f51SGordon Ross break; 808*bd7c6f51SGordon Ross } 809*bd7c6f51SGordon Ross 81002d09e03SGordon Ross if (idms != IDMAP_SUCCESS) 81102d09e03SGordon Ross return (EINVAL); 81202d09e03SGordon Ross 81302d09e03SGordon Ross return (0); 81402d09e03SGordon Ross } 81502d09e03SGordon Ross 816*bd7c6f51SGordon Ross /* 817*bd7c6f51SGordon Ross * Convert an NT ACE to a ZFS ACE. 818*bd7c6f51SGordon Ross * ACE type was already validated. 819*bd7c6f51SGordon Ross */ 82002d09e03SGordon Ross static void 821*bd7c6f51SGordon Ross ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip) 82202d09e03SGordon Ross { 823*bd7c6f51SGordon Ross const struct zaf2naf *znaf; 824*bd7c6f51SGordon Ross uid_t zwho; 82502d09e03SGordon Ross uint32_t zamask; 826*bd7c6f51SGordon Ross uint16_t zflags; 82702d09e03SGordon Ross 82802d09e03SGordon Ross /* 829*bd7c6f51SGordon Ross * Set the "ID type" flags in the ZFS ace flags. 83002d09e03SGordon Ross */ 83102d09e03SGordon Ross zflags = 0; 83202d09e03SGordon Ross switch (mip->mi_isuser) { 833*bd7c6f51SGordon Ross case IDM_EVERYONE: 834*bd7c6f51SGordon Ross zflags = ACE_EVERYONE; 835*bd7c6f51SGordon Ross zwho = (uid_t)-1; 83602d09e03SGordon Ross break; 837*bd7c6f51SGordon Ross 838*bd7c6f51SGordon Ross case IDM_TYPE_GROUP: /* it's a GID */ 839*bd7c6f51SGordon Ross zflags = ACE_IDENTIFIER_GROUP; 840*bd7c6f51SGordon Ross zwho = mip->mi_uid; 84102d09e03SGordon Ross break; 842*bd7c6f51SGordon Ross 84302d09e03SGordon Ross default: 844*bd7c6f51SGordon Ross case IDM_TYPE_USER: /* it's a UID */ 845*bd7c6f51SGordon Ross zflags = 0; 846*bd7c6f51SGordon Ross zwho = mip->mi_uid; 84702d09e03SGordon Ross break; 84802d09e03SGordon Ross } 84902d09e03SGordon Ross 85002d09e03SGordon Ross /* 851*bd7c6f51SGordon Ross * Translate NT ACE flags to ZFS ACE flags. 85202d09e03SGordon Ross */ 853*bd7c6f51SGordon Ross for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++) 854*bd7c6f51SGordon Ross if (ntace->ace_hdr.ace_flags & znaf->na_flag) 855*bd7c6f51SGordon Ross zflags |= znaf->za_flag; 85602d09e03SGordon Ross 85702d09e03SGordon Ross /* 858*bd7c6f51SGordon Ross * The "normal" access mask bits are the same, but 859*bd7c6f51SGordon Ross * if the ACE has any GENERIC_RIGHT_... convert those 860*bd7c6f51SGordon Ross * to specific rights. GENERIC bits are rarely seen, 861*bd7c6f51SGordon Ross * but reportedly can happen with inherit-only ACEs. 86202d09e03SGordon Ross */ 863*bd7c6f51SGordon Ross zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS; 864*bd7c6f51SGordon Ross if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) { 865*bd7c6f51SGordon Ross const struct gen2fsr *gf; 866*bd7c6f51SGordon Ross for (gf = smbfs_gen2fsr; gf->gf_generic; gf++) 867*bd7c6f51SGordon Ross if (ntace->ace_v2.ace_rights & gf->gf_generic) 868*bd7c6f51SGordon Ross zamask |= gf->gf_specific; 86902d09e03SGordon Ross } 87002d09e03SGordon Ross 87102d09e03SGordon Ross /* 87202d09e03SGordon Ross * Fill in the ZFS-style ACE 87302d09e03SGordon Ross */ 874*bd7c6f51SGordon Ross zacep->a_who = zwho; 87502d09e03SGordon Ross zacep->a_access_mask = zamask; 87602d09e03SGordon Ross zacep->a_flags = zflags; 877*bd7c6f51SGordon Ross zacep->a_type = ntace->ace_hdr.ace_type; 87802d09e03SGordon Ross } 87902d09e03SGordon Ross 88002d09e03SGordon Ross /* 88102d09e03SGordon Ross * Convert an internal SD to a ZFS-style ACL. 88202d09e03SGordon Ross * Note optional args: vsa/acl, uidp, gidp. 883*bd7c6f51SGordon Ross * 884*bd7c6f51SGordon Ross * This makes two passes over the SD, the first building a 885*bd7c6f51SGordon Ross * "batch" request for idmap with results in mapinfo, the 886*bd7c6f51SGordon Ross * second building a ZFS-style ACL using the idmap results. 88702d09e03SGordon Ross */ 88802d09e03SGordon Ross int 88902d09e03SGordon Ross smbfs_acl_sd2zfs( 89002d09e03SGordon Ross i_ntsd_t *sd, 89102d09e03SGordon Ross #ifdef _KERNEL 89202d09e03SGordon Ross vsecattr_t *acl_info, 89302d09e03SGordon Ross #else /* _KERNEL */ 89402d09e03SGordon Ross acl_t *acl_info, 89502d09e03SGordon Ross #endif /* _KERNEL */ 89602d09e03SGordon Ross uid_t *uidp, gid_t *gidp) 89702d09e03SGordon Ross { 898*bd7c6f51SGordon Ross struct mapinfo2uid *mip, *mapinfo = NULL; 89902d09e03SGordon Ross int error, i, mapcnt, zacecnt, zacl_size; 900*bd7c6f51SGordon Ross ace_t *zacep0, *zacep; 901*bd7c6f51SGordon Ross uid_t own_uid = (uid_t)-1; 902*bd7c6f51SGordon Ross gid_t own_gid = (gid_t)-1; 90302d09e03SGordon Ross i_ntacl_t *ntacl; 90402d09e03SGordon Ross i_ntace_t **ntacep; 90502d09e03SGordon Ross #ifndef _KERNEL 90602d09e03SGordon Ross idmap_handle_t *idmap_h = NULL; 90702d09e03SGordon Ross #endif /* _KERNEL */ 90802d09e03SGordon Ross idmap_get_handle_t *idmap_gh = NULL; 90902d09e03SGordon Ross idmap_stat idms; 91002d09e03SGordon Ross 91102d09e03SGordon Ross /* 91202d09e03SGordon Ross * sanity checks 91302d09e03SGordon Ross */ 91402d09e03SGordon Ross if (acl_info) { 915*bd7c6f51SGordon Ross #ifndef _KERNEL 91602d09e03SGordon Ross if (acl_info->acl_type != ACE_T || 91702d09e03SGordon Ross acl_info->acl_aclp != NULL || 91802d09e03SGordon Ross acl_info->acl_entry_size != sizeof (ace_t)) 91902d09e03SGordon Ross return (EINVAL); 92002d09e03SGordon Ross #endif /* _KERNEL */ 921*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) == 0) 922*bd7c6f51SGordon Ross return (EINVAL); 923*bd7c6f51SGordon Ross } 92402d09e03SGordon Ross 92502d09e03SGordon Ross /* 926*bd7c6f51SGordon Ross * How many SID mappings will we need? 92702d09e03SGordon Ross */ 92802d09e03SGordon Ross mapcnt = 0; 92902d09e03SGordon Ross if (sd->sd_owner) 93002d09e03SGordon Ross mapcnt++; 93102d09e03SGordon Ross if (sd->sd_group) 93202d09e03SGordon Ross mapcnt++; 933*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) && 934*bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) 93502d09e03SGordon Ross mapcnt += sd->sd_sacl->acl_acecount; 936*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) && 937*bd7c6f51SGordon Ross (sd->sd_dacl != NULL)) 93802d09e03SGordon Ross mapcnt += sd->sd_dacl->acl_acecount; 939*bd7c6f51SGordon Ross if (mapcnt == 0) { 940*bd7c6f51SGordon Ross /* 941*bd7c6f51SGordon Ross * We have a NULL DACL, SACL, and don't 942*bd7c6f51SGordon Ross * have an owner or group, so there's no 943*bd7c6f51SGordon Ross * idmap work to do. This is very rare, 944*bd7c6f51SGordon Ross * so rather than complicate things below, 945*bd7c6f51SGordon Ross * pretend we need one mapping slot. 946*bd7c6f51SGordon Ross */ 947*bd7c6f51SGordon Ross mapcnt = 1; 948*bd7c6f51SGordon Ross } 94902d09e03SGordon Ross 95002d09e03SGordon Ross mapinfo = MALLOC(mapcnt * sizeof (*mapinfo)); 95102d09e03SGordon Ross if (mapinfo == NULL) { 95202d09e03SGordon Ross error = ENOMEM; 95302d09e03SGordon Ross goto errout; 95402d09e03SGordon Ross } 95502d09e03SGordon Ross bzero(mapinfo, mapcnt * sizeof (*mapinfo)); 95602d09e03SGordon Ross 95702d09e03SGordon Ross 95802d09e03SGordon Ross /* 959*bd7c6f51SGordon Ross * Get an imap "batch" request handle. 96002d09e03SGordon Ross */ 96102d09e03SGordon Ross #ifdef _KERNEL 96202d09e03SGordon Ross idmap_gh = kidmap_get_create(curproc->p_zone); 96302d09e03SGordon Ross #else /* _KERNEL */ 96402d09e03SGordon Ross idms = idmap_init(&idmap_h); 96502d09e03SGordon Ross if (idms != IDMAP_SUCCESS) { 96602d09e03SGordon Ross error = ENOTACTIVE; 96702d09e03SGordon Ross goto errout; 96802d09e03SGordon Ross } 96902d09e03SGordon Ross idms = idmap_get_create(idmap_h, &idmap_gh); 97002d09e03SGordon Ross if (idms != IDMAP_SUCCESS) { 97102d09e03SGordon Ross error = ENOTACTIVE; 97202d09e03SGordon Ross goto errout; 97302d09e03SGordon Ross } 97402d09e03SGordon Ross #endif /* _KERNEL */ 97502d09e03SGordon Ross 976*bd7c6f51SGordon Ross /* 977*bd7c6f51SGordon Ross * Build our request to the idmap deamon, 978*bd7c6f51SGordon Ross * getting Unix IDs for every SID. 979*bd7c6f51SGordon Ross */ 98002d09e03SGordon Ross mip = mapinfo; 98102d09e03SGordon Ross if (sd->sd_owner) { 982*bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip, 983*bd7c6f51SGordon Ross sd->sd_owner, IDM_TYPE_USER); 98402d09e03SGordon Ross if (error) 98502d09e03SGordon Ross goto errout; 98602d09e03SGordon Ross mip++; 98702d09e03SGordon Ross } 98802d09e03SGordon Ross if (sd->sd_group) { 989*bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip, 990*bd7c6f51SGordon Ross sd->sd_group, IDM_TYPE_GROUP); 99102d09e03SGordon Ross if (error) 99202d09e03SGordon Ross goto errout; 99302d09e03SGordon Ross mip++; 99402d09e03SGordon Ross } 995*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) && 996*bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) { 99702d09e03SGordon Ross ntacl = sd->sd_sacl; 99802d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0]; 99902d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) { 1000*bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip, 1001*bd7c6f51SGordon Ross (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY); 100202d09e03SGordon Ross if (error) 100302d09e03SGordon Ross goto errout; 100402d09e03SGordon Ross ntacep++; 100502d09e03SGordon Ross mip++; 100602d09e03SGordon Ross } 100702d09e03SGordon Ross } 1008*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) && 1009*bd7c6f51SGordon Ross (sd->sd_dacl != NULL)) { 101002d09e03SGordon Ross ntacl = sd->sd_dacl; 101102d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0]; 101202d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) { 1013*bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip, 1014*bd7c6f51SGordon Ross (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY); 101502d09e03SGordon Ross if (error) 101602d09e03SGordon Ross goto errout; 101702d09e03SGordon Ross ntacep++; 101802d09e03SGordon Ross mip++; 101902d09e03SGordon Ross } 102002d09e03SGordon Ross } 102102d09e03SGordon Ross 1022*bd7c6f51SGordon Ross if (mip != mapinfo) { 1023*bd7c6f51SGordon Ross idms = I_getmappings(idmap_gh); 102402d09e03SGordon Ross if (idms != IDMAP_SUCCESS) { 102502d09e03SGordon Ross /* creative error choice */ 102602d09e03SGordon Ross error = EIDRM; 102702d09e03SGordon Ross goto errout; 102802d09e03SGordon Ross } 1029*bd7c6f51SGordon Ross } 103002d09e03SGordon Ross 103102d09e03SGordon Ross /* 103202d09e03SGordon Ross * With any luck, we now have Unix user/group IDs 103302d09e03SGordon Ross * for every Windows SID in the security descriptor. 103402d09e03SGordon Ross * The remaining work is just format conversion. 103502d09e03SGordon Ross */ 103602d09e03SGordon Ross mip = mapinfo; 103702d09e03SGordon Ross if (sd->sd_owner) { 1038*bd7c6f51SGordon Ross own_uid = mip->mi_uid; 103902d09e03SGordon Ross mip++; 104002d09e03SGordon Ross } 104102d09e03SGordon Ross if (sd->sd_group) { 1042*bd7c6f51SGordon Ross own_gid = mip->mi_uid; 104302d09e03SGordon Ross mip++; 104402d09e03SGordon Ross } 104502d09e03SGordon Ross 1046*bd7c6f51SGordon Ross if (uidp) 1047*bd7c6f51SGordon Ross *uidp = own_uid; 1048*bd7c6f51SGordon Ross if (gidp) 1049*bd7c6f51SGordon Ross *gidp = own_gid; 1050*bd7c6f51SGordon Ross 105102d09e03SGordon Ross if (acl_info == NULL) { 105202d09e03SGordon Ross /* Caller only wanted uid/gid */ 1053*bd7c6f51SGordon Ross goto done; 105402d09e03SGordon Ross } 105502d09e03SGordon Ross 105602d09e03SGordon Ross /* 105702d09e03SGordon Ross * Build the ZFS-style ACL 1058*bd7c6f51SGordon Ross * First, allocate the most ZFS ACEs we'll need. 105902d09e03SGordon Ross */ 106002d09e03SGordon Ross zacecnt = 0; 1061*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) && 1062*bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) 106302d09e03SGordon Ross zacecnt += sd->sd_sacl->acl_acecount; 1064*bd7c6f51SGordon Ross 1065*bd7c6f51SGordon Ross /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */ 1066*bd7c6f51SGordon Ross if ((sd->sd_dacl != NULL) && 1067*bd7c6f51SGordon Ross (sd->sd_dacl->acl_acecount > 0)) { 106802d09e03SGordon Ross zacecnt += sd->sd_dacl->acl_acecount; 1069*bd7c6f51SGordon Ross } else { 1070*bd7c6f51SGordon Ross /* 1071*bd7c6f51SGordon Ross * DACL is NULL or empty. Either way, 1072*bd7c6f51SGordon Ross * we'll need to add a ZFS ACE below. 1073*bd7c6f51SGordon Ross */ 1074*bd7c6f51SGordon Ross zacecnt++; 1075*bd7c6f51SGordon Ross } 107602d09e03SGordon Ross zacl_size = zacecnt * sizeof (ace_t); 1077*bd7c6f51SGordon Ross zacep0 = MALLOC(zacl_size); 1078*bd7c6f51SGordon Ross if (zacep0 == NULL) { 107902d09e03SGordon Ross error = ENOMEM; 108002d09e03SGordon Ross goto errout; 108102d09e03SGordon Ross } 1082*bd7c6f51SGordon Ross zacep = zacep0; 108302d09e03SGordon Ross 1084*bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) && 1085*bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) { 108602d09e03SGordon Ross ntacl = sd->sd_sacl; 108702d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0]; 108802d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) { 108902d09e03SGordon Ross ntace2zace(zacep, *ntacep, mip); 109002d09e03SGordon Ross zacep++; 109102d09e03SGordon Ross ntacep++; 109202d09e03SGordon Ross mip++; 109302d09e03SGordon Ross } 109402d09e03SGordon Ross } 1095*bd7c6f51SGordon Ross 1096*bd7c6f51SGordon Ross /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */ 1097*bd7c6f51SGordon Ross if (sd->sd_dacl != NULL) { 109802d09e03SGordon Ross ntacl = sd->sd_dacl; 109902d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0]; 110002d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) { 110102d09e03SGordon Ross ntace2zace(zacep, *ntacep, mip); 110202d09e03SGordon Ross zacep++; 110302d09e03SGordon Ross ntacep++; 110402d09e03SGordon Ross mip++; 110502d09e03SGordon Ross } 110602d09e03SGordon Ross } 1107*bd7c6f51SGordon Ross if (sd->sd_dacl == NULL) { 1108*bd7c6f51SGordon Ross /* 1109*bd7c6f51SGordon Ross * The SD has a NULL DACL. That means 1110*bd7c6f51SGordon Ross * everyone@, full-control 1111*bd7c6f51SGordon Ross */ 1112*bd7c6f51SGordon Ross zacep->a_who = (uid_t)-1; 1113*bd7c6f51SGordon Ross zacep->a_access_mask = ACE_ALL_PERMS; 1114*bd7c6f51SGordon Ross zacep->a_flags = ACE_EVERYONE; 1115*bd7c6f51SGordon Ross zacep->a_type = ACCESS_ALLOWED_ACE_TYPE; 1116*bd7c6f51SGordon Ross } else if (sd->sd_dacl->acl_acecount == 0) { 1117*bd7c6f51SGordon Ross /* 1118*bd7c6f51SGordon Ross * The SD has an Empty DACL. We need 1119*bd7c6f51SGordon Ross * at least one ACE, so add one giving 1120*bd7c6f51SGordon Ross * the owner the usual implied access. 1121*bd7c6f51SGordon Ross */ 1122*bd7c6f51SGordon Ross zacep->a_who = (uid_t)-1; 1123*bd7c6f51SGordon Ross zacep->a_access_mask = ACE_READ_ATTRIBUTES | \ 1124*bd7c6f51SGordon Ross ACE_READ_ACL | ACE_WRITE_ACL; 1125*bd7c6f51SGordon Ross zacep->a_flags = ACE_OWNER; 1126*bd7c6f51SGordon Ross zacep->a_type = ACCESS_ALLOWED_ACE_TYPE; 1127*bd7c6f51SGordon Ross } 112802d09e03SGordon Ross 1129*bd7c6f51SGordon Ross #ifdef _KERNEL 1130*bd7c6f51SGordon Ross acl_info->vsa_aclcnt = zacecnt; 1131*bd7c6f51SGordon Ross acl_info->vsa_aclentp = zacep0; 1132*bd7c6f51SGordon Ross acl_info->vsa_aclentsz = zacl_size; 1133*bd7c6f51SGordon Ross #else /* _KERNEL */ 1134*bd7c6f51SGordon Ross acl_info->acl_cnt = zacecnt; 1135*bd7c6f51SGordon Ross acl_info->acl_aclp = zacep0; 1136*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1137*bd7c6f51SGordon Ross 1138*bd7c6f51SGordon Ross done: 113902d09e03SGordon Ross error = 0; 114002d09e03SGordon Ross 114102d09e03SGordon Ross errout: 1142*bd7c6f51SGordon Ross if (mapinfo != NULL) 114302d09e03SGordon Ross FREESZ(mapinfo, mapcnt * sizeof (*mapinfo)); 1144*bd7c6f51SGordon Ross #ifdef _KERNEL 1145*bd7c6f51SGordon Ross if (idmap_gh != NULL) 1146*bd7c6f51SGordon Ross kidmap_get_destroy(idmap_gh); 1147*bd7c6f51SGordon Ross #else /* _KERNEL */ 1148*bd7c6f51SGordon Ross if (idmap_gh != NULL) 1149*bd7c6f51SGordon Ross idmap_get_destroy(idmap_gh); 1150*bd7c6f51SGordon Ross if (idmap_h != NULL) 1151*bd7c6f51SGordon Ross (void) idmap_fini(idmap_h); 1152*bd7c6f51SGordon Ross #endif /* _KERNEL */ 115302d09e03SGordon Ross 115402d09e03SGordon Ross return (error); 115502d09e03SGordon Ross } 115602d09e03SGordon Ross 115702d09e03SGordon Ross 115802d09e03SGordon Ross /* 1159*bd7c6f51SGordon Ross * ================================================================ 1160*bd7c6f51SGordon Ross * Support for ACL store, including conversions 1161*bd7c6f51SGordon Ross * from NFSv4-style ACLs to Windows ACLs. 1162*bd7c6f51SGordon Ross * ================================================================ 116302d09e03SGordon Ross */ 1164*bd7c6f51SGordon Ross 1165*bd7c6f51SGordon Ross /* 1166*bd7c6f51SGordon Ross * Convert a "sid-prefix" string plus RID into an NT SID. 1167*bd7c6f51SGordon Ross * 1168*bd7c6f51SGordon Ross * If successful, sets *osid and returns zero, 1169*bd7c6f51SGordon Ross * otherwise returns an errno value. 1170*bd7c6f51SGordon Ross */ 1171*bd7c6f51SGordon Ross int 1172*bd7c6f51SGordon Ross smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp) 1173*bd7c6f51SGordon Ross { 1174*bd7c6f51SGordon Ross i_ntsid_t *sid = NULL; 1175*bd7c6f51SGordon Ross u_longlong_t auth = 0; 1176*bd7c6f51SGordon Ross ulong_t sa; 1177*bd7c6f51SGordon Ross uint8_t sacnt; 1178*bd7c6f51SGordon Ross const char *p; 1179*bd7c6f51SGordon Ross char *np; 1180*bd7c6f51SGordon Ross size_t size; 1181*bd7c6f51SGordon Ross int i; 1182*bd7c6f51SGordon Ross int err; 1183*bd7c6f51SGordon Ross 1184*bd7c6f51SGordon Ross if (sid_prefix == NULL) 1185*bd7c6f51SGordon Ross return (EINVAL); 1186*bd7c6f51SGordon Ross 1187*bd7c6f51SGordon Ross p = sid_prefix; 1188*bd7c6f51SGordon Ross if (strncmp(p, "S-1-", 4) != 0) 1189*bd7c6f51SGordon Ross return (EINVAL); 1190*bd7c6f51SGordon Ross p += 4; 1191*bd7c6f51SGordon Ross 1192*bd7c6f51SGordon Ross /* Parse the "authority" */ 119302d09e03SGordon Ross #ifdef _KERNEL 1194*bd7c6f51SGordon Ross err = ddi_strtoull(p, &np, 10, &auth); 1195*bd7c6f51SGordon Ross if (err != 0) 1196*bd7c6f51SGordon Ross return (err); 119702d09e03SGordon Ross #else /* _KERNEL */ 1198*bd7c6f51SGordon Ross auth = strtoull(p, &np, 10); 1199*bd7c6f51SGordon Ross if (p == np) 1200*bd7c6f51SGordon Ross return (EINVAL); 120102d09e03SGordon Ross #endif /* _KERNEL */ 1202*bd7c6f51SGordon Ross 1203*bd7c6f51SGordon Ross /* 1204*bd7c6f51SGordon Ross * Count the sub-authorities. Here, np points to 1205*bd7c6f51SGordon Ross * the "-" before the first sub-authority. 1206*bd7c6f51SGordon Ross */ 1207*bd7c6f51SGordon Ross sacnt = 0; 1208*bd7c6f51SGordon Ross for (p = np; *p; p++) { 1209*bd7c6f51SGordon Ross if (*p == '-') 1210*bd7c6f51SGordon Ross sacnt++; 1211*bd7c6f51SGordon Ross } 1212*bd7c6f51SGordon Ross if (ridp != NULL) 1213*bd7c6f51SGordon Ross sacnt++; 1214*bd7c6f51SGordon Ross 1215*bd7c6f51SGordon Ross /* Allocate the internal SID. */ 1216*bd7c6f51SGordon Ross size = I_SID_SIZE(sacnt); 1217*bd7c6f51SGordon Ross sid = MALLOC(size); 1218*bd7c6f51SGordon Ross if (sid == NULL) 1219*bd7c6f51SGordon Ross return (ENOMEM); 1220*bd7c6f51SGordon Ross bzero(sid, size); 1221*bd7c6f51SGordon Ross 1222*bd7c6f51SGordon Ross /* Fill it in. */ 1223*bd7c6f51SGordon Ross sid->sid_revision = 1; 1224*bd7c6f51SGordon Ross sid->sid_subauthcount = sacnt; 1225*bd7c6f51SGordon Ross for (i = 5; i >= 0; i--) { 1226*bd7c6f51SGordon Ross sid->sid_authority[i] = auth & 0xFF; 1227*bd7c6f51SGordon Ross auth = auth >> 8; 1228*bd7c6f51SGordon Ross } 1229*bd7c6f51SGordon Ross 1230*bd7c6f51SGordon Ross err = EINVAL; 1231*bd7c6f51SGordon Ross if (ridp != NULL) 1232*bd7c6f51SGordon Ross sacnt--; /* Last SA not from string */ 1233*bd7c6f51SGordon Ross p = np; 1234*bd7c6f51SGordon Ross for (i = 0; i < sacnt; i++) { 1235*bd7c6f51SGordon Ross if (*p != '-') { 1236*bd7c6f51SGordon Ross err = EINVAL; 1237*bd7c6f51SGordon Ross goto out; 1238*bd7c6f51SGordon Ross } 1239*bd7c6f51SGordon Ross p++; 1240*bd7c6f51SGordon Ross #ifdef _KERNEL 1241*bd7c6f51SGordon Ross err = ddi_strtoul(p, &np, 10, &sa); 1242*bd7c6f51SGordon Ross if (err != 0) 1243*bd7c6f51SGordon Ross goto out; 1244*bd7c6f51SGordon Ross #else /* _KERNEL */ 1245*bd7c6f51SGordon Ross sa = strtoul(p, &np, 10); 1246*bd7c6f51SGordon Ross if (p == np) { 1247*bd7c6f51SGordon Ross err = EINVAL; 1248*bd7c6f51SGordon Ross goto out; 1249*bd7c6f51SGordon Ross } 1250*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1251*bd7c6f51SGordon Ross sid->sid_subauthvec[i] = (uint32_t)sa; 1252*bd7c6f51SGordon Ross p = np; 1253*bd7c6f51SGordon Ross } 1254*bd7c6f51SGordon Ross if (*p != '\0') 1255*bd7c6f51SGordon Ross goto out; 1256*bd7c6f51SGordon Ross if (ridp != NULL) 1257*bd7c6f51SGordon Ross sid->sid_subauthvec[i] = *ridp; 1258*bd7c6f51SGordon Ross err = 0; 1259*bd7c6f51SGordon Ross 1260*bd7c6f51SGordon Ross out: 1261*bd7c6f51SGordon Ross if (err) 1262*bd7c6f51SGordon Ross FREESZ(sid, size); 1263*bd7c6f51SGordon Ross else 1264*bd7c6f51SGordon Ross *osidp = sid; 1265*bd7c6f51SGordon Ross 1266*bd7c6f51SGordon Ross return (err); 1267*bd7c6f51SGordon Ross } 1268*bd7c6f51SGordon Ross 1269*bd7c6f51SGordon Ross /* 1270*bd7c6f51SGordon Ross * The idmap API is _almost_ the same between 1271*bd7c6f51SGordon Ross * kernel and user-level. But not quite... 1272*bd7c6f51SGordon Ross * Hope this improves readability below. 1273*bd7c6f51SGordon Ross */ 1274*bd7c6f51SGordon Ross #ifdef _KERNEL 1275*bd7c6f51SGordon Ross 1276*bd7c6f51SGordon Ross #define I_getsidbyuid(GH, UID, SPP, RP, ST) \ 1277*bd7c6f51SGordon Ross kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST) 1278*bd7c6f51SGordon Ross 1279*bd7c6f51SGordon Ross #define I_getsidbygid(GH, GID, SPP, RP, ST) \ 1280*bd7c6f51SGordon Ross kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST) 1281*bd7c6f51SGordon Ross 1282*bd7c6f51SGordon Ross #else /* _KERNEL */ 1283*bd7c6f51SGordon Ross 1284*bd7c6f51SGordon Ross #define I_getsidbyuid(GH, UID, SPP, RP, ST) \ 1285*bd7c6f51SGordon Ross idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST) 1286*bd7c6f51SGordon Ross 1287*bd7c6f51SGordon Ross #define I_getsidbygid(GH, GID, SPP, RP, ST) \ 1288*bd7c6f51SGordon Ross idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST) 1289*bd7c6f51SGordon Ross 1290*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1291*bd7c6f51SGordon Ross 1292*bd7c6f51SGordon Ross struct mapinfo2sid { 1293*bd7c6f51SGordon Ross /* Yet another kernel vs. user difference. */ 1294*bd7c6f51SGordon Ross #ifdef _KERNEL 1295*bd7c6f51SGordon Ross const char *mi_dsid; /* domain SID */ 1296*bd7c6f51SGordon Ross #else /* _KERNEL */ 1297*bd7c6f51SGordon Ross char *mi_dsid; 1298*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1299*bd7c6f51SGordon Ross uint32_t mi_rid; /* relative ID */ 1300*bd7c6f51SGordon Ross idmap_stat mi_status; 1301*bd7c6f51SGordon Ross }; 1302*bd7c6f51SGordon Ross 1303*bd7c6f51SGordon Ross /* 1304*bd7c6f51SGordon Ross * Build an idmap request. Cleanup is 1305*bd7c6f51SGordon Ross * handled by the caller (error or not) 1306*bd7c6f51SGordon Ross */ 1307*bd7c6f51SGordon Ross static int 1308*bd7c6f51SGordon Ross mkrq_idmap_ux2sid( 1309*bd7c6f51SGordon Ross idmap_get_handle_t *idmap_gh, 1310*bd7c6f51SGordon Ross struct mapinfo2sid *mip, 1311*bd7c6f51SGordon Ross uid_t uid, /* or gid */ 1312*bd7c6f51SGordon Ross int req_type) 1313*bd7c6f51SGordon Ross { 1314*bd7c6f51SGordon Ross idmap_stat idms; 1315*bd7c6f51SGordon Ross 1316*bd7c6f51SGordon Ross switch (req_type) { 1317*bd7c6f51SGordon Ross 1318*bd7c6f51SGordon Ross case IDM_TYPE_USER: 1319*bd7c6f51SGordon Ross if (uid == (uid_t)-1) 1320*bd7c6f51SGordon Ross return (EINVAL); 1321*bd7c6f51SGordon Ross idms = I_getsidbyuid(idmap_gh, uid, 1322*bd7c6f51SGordon Ross &mip->mi_dsid, &mip->mi_rid, &mip->mi_status); 1323*bd7c6f51SGordon Ross break; 1324*bd7c6f51SGordon Ross 1325*bd7c6f51SGordon Ross case IDM_TYPE_GROUP: 1326*bd7c6f51SGordon Ross if (uid == (uid_t)-1) 1327*bd7c6f51SGordon Ross return (EINVAL); 1328*bd7c6f51SGordon Ross idms = I_getsidbygid(idmap_gh, uid, 1329*bd7c6f51SGordon Ross &mip->mi_dsid, &mip->mi_rid, &mip->mi_status); 1330*bd7c6f51SGordon Ross break; 1331*bd7c6f51SGordon Ross 1332*bd7c6f51SGordon Ross case IDM_EVERYONE: 1333*bd7c6f51SGordon Ross mip->mi_dsid = "S-1-1"; 1334*bd7c6f51SGordon Ross mip->mi_rid = 0; 1335*bd7c6f51SGordon Ross mip->mi_status = 0; 1336*bd7c6f51SGordon Ross idms = IDMAP_SUCCESS; 1337*bd7c6f51SGordon Ross break; 1338*bd7c6f51SGordon Ross 1339*bd7c6f51SGordon Ross default: 1340*bd7c6f51SGordon Ross idms = IDMAP_ERR_OTHER; 1341*bd7c6f51SGordon Ross break; 1342*bd7c6f51SGordon Ross } 1343*bd7c6f51SGordon Ross 1344*bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) 1345*bd7c6f51SGordon Ross return (EINVAL); 1346*bd7c6f51SGordon Ross 1347*bd7c6f51SGordon Ross return (0); 1348*bd7c6f51SGordon Ross } 1349*bd7c6f51SGordon Ross 1350*bd7c6f51SGordon Ross /* 1351*bd7c6f51SGordon Ross * Convert a ZFS ACE to an NT ACE. 1352*bd7c6f51SGordon Ross * ACE type was already validated. 1353*bd7c6f51SGordon Ross */ 1354*bd7c6f51SGordon Ross static int 1355*bd7c6f51SGordon Ross zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip) 1356*bd7c6f51SGordon Ross { 1357*bd7c6f51SGordon Ross const struct zaf2naf *znaf; 1358*bd7c6f51SGordon Ross uint8_t aflags; 1359*bd7c6f51SGordon Ross uint16_t alloc_size; 1360*bd7c6f51SGordon Ross uint32_t rights; 1361*bd7c6f51SGordon Ross i_ntace_t *ntace = NULL; 1362*bd7c6f51SGordon Ross i_ntsid_t *sid = NULL; 1363*bd7c6f51SGordon Ross int error; 1364*bd7c6f51SGordon Ross 1365*bd7c6f51SGordon Ross if (mip->mi_dsid == NULL || mip->mi_status != 0) { 1366*bd7c6f51SGordon Ross return (EINVAL); 1367*bd7c6f51SGordon Ross } 1368*bd7c6f51SGordon Ross 1369*bd7c6f51SGordon Ross /* 1370*bd7c6f51SGordon Ross * Translate ZFS ACE flags to NT ACE flags. 1371*bd7c6f51SGordon Ross */ 1372*bd7c6f51SGordon Ross aflags = 0; 1373*bd7c6f51SGordon Ross for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++) 1374*bd7c6f51SGordon Ross if (zacep->a_flags & znaf->za_flag) 1375*bd7c6f51SGordon Ross aflags |= znaf->na_flag; 1376*bd7c6f51SGordon Ross 1377*bd7c6f51SGordon Ross /* 1378*bd7c6f51SGordon Ross * The access rights bits are OK as-is. 1379*bd7c6f51SGordon Ross */ 1380*bd7c6f51SGordon Ross rights = zacep->a_access_mask; 1381*bd7c6f51SGordon Ross 1382*bd7c6f51SGordon Ross /* 1383*bd7c6f51SGordon Ross * Make sure we can get the SID. 1384*bd7c6f51SGordon Ross * Note: allocates sid. 1385*bd7c6f51SGordon Ross */ 1386*bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid); 1387*bd7c6f51SGordon Ross if (error) 1388*bd7c6f51SGordon Ross return (error); 1389*bd7c6f51SGordon Ross 1390*bd7c6f51SGordon Ross /* 1391*bd7c6f51SGordon Ross * Allocate the NT ACE and fill it in. 1392*bd7c6f51SGordon Ross */ 1393*bd7c6f51SGordon Ross alloc_size = sizeof (i_ntace_v2_t); 1394*bd7c6f51SGordon Ross if ((ntace = MALLOC(alloc_size)) == NULL) { 1395*bd7c6f51SGordon Ross ifree_sid(sid); 1396*bd7c6f51SGordon Ross return (ENOMEM); 1397*bd7c6f51SGordon Ross } 1398*bd7c6f51SGordon Ross bzero(ntace, alloc_size); 1399*bd7c6f51SGordon Ross 1400*bd7c6f51SGordon Ross ntace->ace_hdr.ace_type = zacep->a_type; 1401*bd7c6f51SGordon Ross ntace->ace_hdr.ace_flags = aflags; 1402*bd7c6f51SGordon Ross ntace->ace_hdr.ace_size = alloc_size; 1403*bd7c6f51SGordon Ross ntace->ace_v2.ace_rights = rights; 1404*bd7c6f51SGordon Ross ntace->ace_v2.ace_sid = sid; 1405*bd7c6f51SGordon Ross 1406*bd7c6f51SGordon Ross *ntacep = ntace; 1407*bd7c6f51SGordon Ross return (0); 1408*bd7c6f51SGordon Ross } 1409*bd7c6f51SGordon Ross 1410*bd7c6f51SGordon Ross /* 1411*bd7c6f51SGordon Ross * Convert a ZFS-style ACL to an internal SD. 1412*bd7c6f51SGordon Ross * Set owner/group too if selector indicates. 1413*bd7c6f51SGordon Ross * Always need to pass uid+gid, either the new 1414*bd7c6f51SGordon Ross * (when setting them) or existing, so that any 1415*bd7c6f51SGordon Ross * owner@ or group@ ACEs can be translated. 1416*bd7c6f51SGordon Ross * 1417*bd7c6f51SGordon Ross * This makes two passes over the ZFS ACL. The first builds a 1418*bd7c6f51SGordon Ross * "batch" request for idmap with results in mapinfo, and the 1419*bd7c6f51SGordon Ross * second builds the NT SD using the idmap SID results. 1420*bd7c6f51SGordon Ross */ 1421*bd7c6f51SGordon Ross int 1422*bd7c6f51SGordon Ross smbfs_acl_zfs2sd( 1423*bd7c6f51SGordon Ross #ifdef _KERNEL 1424*bd7c6f51SGordon Ross vsecattr_t *acl_info, 1425*bd7c6f51SGordon Ross #else /* _KERNEL */ 1426*bd7c6f51SGordon Ross acl_t *acl_info, 1427*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1428*bd7c6f51SGordon Ross uid_t own_uid, 1429*bd7c6f51SGordon Ross gid_t own_gid, 1430*bd7c6f51SGordon Ross uint32_t selector, 143102d09e03SGordon Ross i_ntsd_t **sdp) 143202d09e03SGordon Ross { 1433*bd7c6f51SGordon Ross struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL; 1434*bd7c6f51SGordon Ross int aclsz, error, i, mapcnt; 1435*bd7c6f51SGordon Ross int dacl_acecnt = 0; 1436*bd7c6f51SGordon Ross int sacl_acecnt = 0; 1437*bd7c6f51SGordon Ross int zacecnt = 0; 1438*bd7c6f51SGordon Ross ace_t *zacevec = NULL; 1439*bd7c6f51SGordon Ross ace_t *zacep; 1440*bd7c6f51SGordon Ross i_ntsd_t *sd = NULL; 1441*bd7c6f51SGordon Ross i_ntacl_t *acl = NULL; 1442*bd7c6f51SGordon Ross i_ntace_t **acep = NULL; 1443*bd7c6f51SGordon Ross #ifndef _KERNEL 1444*bd7c6f51SGordon Ross idmap_handle_t *idmap_h = NULL; 1445*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1446*bd7c6f51SGordon Ross idmap_get_handle_t *idmap_gh = NULL; 1447*bd7c6f51SGordon Ross idmap_stat idms; 1448*bd7c6f51SGordon Ross 1449*bd7c6f51SGordon Ross /* 1450*bd7c6f51SGordon Ross * First, get all the UID+GID to SID mappings. 1451*bd7c6f51SGordon Ross * How many? Also sanity checks. 1452*bd7c6f51SGordon Ross */ 1453*bd7c6f51SGordon Ross mapcnt = 0; 1454*bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) { 1455*bd7c6f51SGordon Ross if (own_uid == (uid_t)-1) 1456*bd7c6f51SGordon Ross return (EINVAL); 1457*bd7c6f51SGordon Ross mapcnt++; 1458*bd7c6f51SGordon Ross } 1459*bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) { 1460*bd7c6f51SGordon Ross if (own_gid == (gid_t)-1) 1461*bd7c6f51SGordon Ross return (EINVAL); 1462*bd7c6f51SGordon Ross mapcnt++; 1463*bd7c6f51SGordon Ross } 1464*bd7c6f51SGordon Ross if (selector & (DACL_SECURITY_INFORMATION | 1465*bd7c6f51SGordon Ross SACL_SECURITY_INFORMATION)) { 1466*bd7c6f51SGordon Ross if (acl_info == NULL) 1467*bd7c6f51SGordon Ross return (EINVAL); 1468*bd7c6f51SGordon Ross if (own_uid == (uid_t)-1) 1469*bd7c6f51SGordon Ross return (EINVAL); 1470*bd7c6f51SGordon Ross if (own_gid == (gid_t)-1) 1471*bd7c6f51SGordon Ross return (EINVAL); 1472*bd7c6f51SGordon Ross #ifdef _KERNEL 1473*bd7c6f51SGordon Ross if ((acl_info->vsa_mask & VSA_ACE) == 0) 1474*bd7c6f51SGordon Ross return (EINVAL); 1475*bd7c6f51SGordon Ross zacecnt = acl_info->vsa_aclcnt; 1476*bd7c6f51SGordon Ross zacevec = acl_info->vsa_aclentp; 1477*bd7c6f51SGordon Ross #else /* _KERNEL */ 1478*bd7c6f51SGordon Ross if (acl_info->acl_type != ACE_T || 1479*bd7c6f51SGordon Ross acl_info->acl_entry_size != sizeof (ace_t)) 1480*bd7c6f51SGordon Ross return (EINVAL); 1481*bd7c6f51SGordon Ross zacecnt = acl_info->acl_cnt; 1482*bd7c6f51SGordon Ross zacevec = acl_info->acl_aclp; 1483*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1484*bd7c6f51SGordon Ross if (zacecnt == 0 || zacevec == NULL) 1485*bd7c6f51SGordon Ross return (EINVAL); 1486*bd7c6f51SGordon Ross mapcnt += zacecnt; 1487*bd7c6f51SGordon Ross } 1488*bd7c6f51SGordon Ross if (mapcnt == 0) 1489*bd7c6f51SGordon Ross return (EINVAL); 1490*bd7c6f51SGordon Ross mapinfo = MALLOC(mapcnt * sizeof (*mapinfo)); 1491*bd7c6f51SGordon Ross if (mapinfo == NULL) 1492*bd7c6f51SGordon Ross return (ENOMEM); 1493*bd7c6f51SGordon Ross bzero(mapinfo, mapcnt * sizeof (*mapinfo)); 1494*bd7c6f51SGordon Ross /* no more returns until errout */ 1495*bd7c6f51SGordon Ross 1496*bd7c6f51SGordon Ross /* 1497*bd7c6f51SGordon Ross * Get an imap "batch" request handle. 1498*bd7c6f51SGordon Ross */ 1499*bd7c6f51SGordon Ross #ifdef _KERNEL 1500*bd7c6f51SGordon Ross idmap_gh = kidmap_get_create(curproc->p_zone); 1501*bd7c6f51SGordon Ross #else /* _KERNEL */ 1502*bd7c6f51SGordon Ross idms = idmap_init(&idmap_h); 1503*bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) { 1504*bd7c6f51SGordon Ross error = ENOTACTIVE; 1505*bd7c6f51SGordon Ross goto errout; 1506*bd7c6f51SGordon Ross } 1507*bd7c6f51SGordon Ross idms = idmap_get_create(idmap_h, &idmap_gh); 1508*bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) { 1509*bd7c6f51SGordon Ross error = ENOTACTIVE; 1510*bd7c6f51SGordon Ross goto errout; 1511*bd7c6f51SGordon Ross } 1512*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1513*bd7c6f51SGordon Ross 1514*bd7c6f51SGordon Ross /* 1515*bd7c6f51SGordon Ross * Build our request to the idmap deamon, 1516*bd7c6f51SGordon Ross * getting SIDs for every Unix UID/GID. 1517*bd7c6f51SGordon Ross * Also count DACL and SACL ACEs here. 1518*bd7c6f51SGordon Ross */ 1519*bd7c6f51SGordon Ross mip = mapinfo; 1520*bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) { 1521*bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip, 1522*bd7c6f51SGordon Ross own_uid, IDM_TYPE_USER); 1523*bd7c6f51SGordon Ross if (error) 1524*bd7c6f51SGordon Ross goto errout; 1525*bd7c6f51SGordon Ross mip++; 1526*bd7c6f51SGordon Ross } 1527*bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) { 1528*bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip, 1529*bd7c6f51SGordon Ross own_gid, IDM_TYPE_GROUP); 1530*bd7c6f51SGordon Ross if (error) 1531*bd7c6f51SGordon Ross goto errout; 1532*bd7c6f51SGordon Ross mip++; 1533*bd7c6f51SGordon Ross } 1534*bd7c6f51SGordon Ross if (selector & (DACL_SECURITY_INFORMATION | 1535*bd7c6f51SGordon Ross SACL_SECURITY_INFORMATION)) { 1536*bd7c6f51SGordon Ross int rqtype; 1537*bd7c6f51SGordon Ross uid_t uid; 1538*bd7c6f51SGordon Ross 1539*bd7c6f51SGordon Ross zacep = zacevec; 1540*bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) { 1541*bd7c6f51SGordon Ross 1542*bd7c6f51SGordon Ross switch (zacep->a_type) { 1543*bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE: 1544*bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE: 1545*bd7c6f51SGordon Ross dacl_acecnt++; 1546*bd7c6f51SGordon Ross break; 1547*bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE: 1548*bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE: 1549*bd7c6f51SGordon Ross sacl_acecnt++; 1550*bd7c6f51SGordon Ross break; 1551*bd7c6f51SGordon Ross /* other types todo */ 1552*bd7c6f51SGordon Ross } 1553*bd7c6f51SGordon Ross 1554*bd7c6f51SGordon Ross if (zacep->a_flags & ACE_EVERYONE) { 1555*bd7c6f51SGordon Ross rqtype = IDM_EVERYONE; 1556*bd7c6f51SGordon Ross uid = (uid_t)-1; 1557*bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_GROUP) { 1558*bd7c6f51SGordon Ross /* owning group (a_who = -1) */ 1559*bd7c6f51SGordon Ross rqtype = IDM_TYPE_GROUP; 1560*bd7c6f51SGordon Ross uid = (uid_t)own_gid; 1561*bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_OWNER) { 1562*bd7c6f51SGordon Ross /* owning user (a_who = -1) */ 1563*bd7c6f51SGordon Ross rqtype = IDM_TYPE_USER; 1564*bd7c6f51SGordon Ross uid = (uid_t)own_uid; 1565*bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) { 1566*bd7c6f51SGordon Ross /* regular group */ 1567*bd7c6f51SGordon Ross rqtype = IDM_TYPE_GROUP; 1568*bd7c6f51SGordon Ross uid = zacep->a_who; 1569*bd7c6f51SGordon Ross } else { 1570*bd7c6f51SGordon Ross rqtype = IDM_TYPE_USER; 1571*bd7c6f51SGordon Ross uid = zacep->a_who; 1572*bd7c6f51SGordon Ross } 1573*bd7c6f51SGordon Ross 1574*bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype); 1575*bd7c6f51SGordon Ross if (error) 1576*bd7c6f51SGordon Ross goto errout; 1577*bd7c6f51SGordon Ross zacep++; 1578*bd7c6f51SGordon Ross mip++; 1579*bd7c6f51SGordon Ross } 1580*bd7c6f51SGordon Ross } 1581*bd7c6f51SGordon Ross 1582*bd7c6f51SGordon Ross idms = I_getmappings(idmap_gh); 1583*bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) { 1584*bd7c6f51SGordon Ross /* creative error choice */ 1585*bd7c6f51SGordon Ross error = EIDRM; 1586*bd7c6f51SGordon Ross goto errout; 1587*bd7c6f51SGordon Ross } 1588*bd7c6f51SGordon Ross 1589*bd7c6f51SGordon Ross /* 1590*bd7c6f51SGordon Ross * With any luck, we now have a Windows SID for 1591*bd7c6f51SGordon Ross * every Unix UID or GID in the NFS/ZFS ACL. 1592*bd7c6f51SGordon Ross * The remaining work is just format conversion, 1593*bd7c6f51SGordon Ross * memory allocation, etc. 1594*bd7c6f51SGordon Ross */ 1595*bd7c6f51SGordon Ross if ((sd = MALLOC(sizeof (*sd))) == NULL) { 1596*bd7c6f51SGordon Ross error = ENOMEM; 1597*bd7c6f51SGordon Ross goto errout; 1598*bd7c6f51SGordon Ross } 1599*bd7c6f51SGordon Ross bzero(sd, sizeof (*sd)); 1600*bd7c6f51SGordon Ross sd->sd_revision = NT_SD_REVISION; 1601*bd7c6f51SGordon Ross 1602*bd7c6f51SGordon Ross mip = mapinfo; 1603*bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) { 1604*bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, 1605*bd7c6f51SGordon Ross &sd->sd_owner); 1606*bd7c6f51SGordon Ross mip++; 1607*bd7c6f51SGordon Ross } 1608*bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) { 1609*bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, 1610*bd7c6f51SGordon Ross &sd->sd_group); 1611*bd7c6f51SGordon Ross mip++; 1612*bd7c6f51SGordon Ross } 1613*bd7c6f51SGordon Ross 1614*bd7c6f51SGordon Ross /* 1615*bd7c6f51SGordon Ross * If setting both DACL and SACL, we will 1616*bd7c6f51SGordon Ross * make two passes starting here in mapinfo. 1617*bd7c6f51SGordon Ross */ 1618*bd7c6f51SGordon Ross mip_acl = mip; 1619*bd7c6f51SGordon Ross 1620*bd7c6f51SGordon Ross if (selector & DACL_SECURITY_INFORMATION) { 1621*bd7c6f51SGordon Ross /* 1622*bd7c6f51SGordon Ross * Caller wants to set the DACL. 1623*bd7c6f51SGordon Ross */ 1624*bd7c6f51SGordon Ross aclsz = I_ACL_SIZE(dacl_acecnt); 1625*bd7c6f51SGordon Ross if ((acl = MALLOC(aclsz)) == NULL) { 1626*bd7c6f51SGordon Ross error = ENOMEM; 1627*bd7c6f51SGordon Ross goto errout; 1628*bd7c6f51SGordon Ross } 1629*bd7c6f51SGordon Ross bzero(acl, aclsz); 1630*bd7c6f51SGordon Ross 1631*bd7c6f51SGordon Ross acl->acl_revision = NT_ACL_REVISION; 1632*bd7c6f51SGordon Ross acl->acl_acecount = (uint16_t)dacl_acecnt; 1633*bd7c6f51SGordon Ross acep = &acl->acl_acevec[0]; 1634*bd7c6f51SGordon Ross 1635*bd7c6f51SGordon Ross /* 1st pass - scan for DACL ACE types. */ 1636*bd7c6f51SGordon Ross mip = mip_acl; 1637*bd7c6f51SGordon Ross zacep = zacevec; 1638*bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) { 1639*bd7c6f51SGordon Ross 1640*bd7c6f51SGordon Ross switch (zacep->a_type) { 1641*bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE: 1642*bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE: 1643*bd7c6f51SGordon Ross error = zace2ntace(acep, zacep, mip); 1644*bd7c6f51SGordon Ross if (error != 0) 1645*bd7c6f51SGordon Ross goto errout; 1646*bd7c6f51SGordon Ross acep++; 1647*bd7c6f51SGordon Ross break; 1648*bd7c6f51SGordon Ross 1649*bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE: 1650*bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE: 1651*bd7c6f51SGordon Ross break; 1652*bd7c6f51SGordon Ross /* other types todo */ 1653*bd7c6f51SGordon Ross } 1654*bd7c6f51SGordon Ross zacep++; 1655*bd7c6f51SGordon Ross mip++; 1656*bd7c6f51SGordon Ross } 1657*bd7c6f51SGordon Ross sd->sd_dacl = acl; 1658*bd7c6f51SGordon Ross acl = NULL; 1659*bd7c6f51SGordon Ross sd->sd_flags |= SD_DACL_PRESENT; 1660*bd7c6f51SGordon Ross } 1661*bd7c6f51SGordon Ross 1662*bd7c6f51SGordon Ross if (selector & SACL_SECURITY_INFORMATION) { 1663*bd7c6f51SGordon Ross /* 1664*bd7c6f51SGordon Ross * Caller wants to set the SACL. 1665*bd7c6f51SGordon Ross */ 1666*bd7c6f51SGordon Ross aclsz = I_ACL_SIZE(sacl_acecnt); 1667*bd7c6f51SGordon Ross if ((acl = MALLOC(aclsz)) == NULL) { 1668*bd7c6f51SGordon Ross error = ENOMEM; 1669*bd7c6f51SGordon Ross goto errout; 1670*bd7c6f51SGordon Ross } 1671*bd7c6f51SGordon Ross bzero(acl, aclsz); 1672*bd7c6f51SGordon Ross 1673*bd7c6f51SGordon Ross acl->acl_revision = NT_ACL_REVISION; 1674*bd7c6f51SGordon Ross acl->acl_acecount = (uint16_t)sacl_acecnt; 1675*bd7c6f51SGordon Ross acep = &acl->acl_acevec[0]; 1676*bd7c6f51SGordon Ross 1677*bd7c6f51SGordon Ross /* 2nd pass - scan for SACL ACE types. */ 1678*bd7c6f51SGordon Ross mip = mip_acl; 1679*bd7c6f51SGordon Ross zacep = zacevec; 1680*bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) { 1681*bd7c6f51SGordon Ross 1682*bd7c6f51SGordon Ross switch (zacep->a_type) { 1683*bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE: 1684*bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE: 1685*bd7c6f51SGordon Ross break; 1686*bd7c6f51SGordon Ross 1687*bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE: 1688*bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE: 1689*bd7c6f51SGordon Ross error = zace2ntace(acep, zacep, mip); 1690*bd7c6f51SGordon Ross if (error != 0) 1691*bd7c6f51SGordon Ross goto errout; 1692*bd7c6f51SGordon Ross acep++; 1693*bd7c6f51SGordon Ross break; 1694*bd7c6f51SGordon Ross /* other types todo */ 1695*bd7c6f51SGordon Ross } 1696*bd7c6f51SGordon Ross zacep++; 1697*bd7c6f51SGordon Ross mip++; 1698*bd7c6f51SGordon Ross } 1699*bd7c6f51SGordon Ross sd->sd_sacl = acl; 1700*bd7c6f51SGordon Ross acl = NULL; 1701*bd7c6f51SGordon Ross sd->sd_flags |= SD_SACL_PRESENT; 1702*bd7c6f51SGordon Ross } 1703*bd7c6f51SGordon Ross 1704*bd7c6f51SGordon Ross *sdp = sd; 1705*bd7c6f51SGordon Ross error = 0; 1706*bd7c6f51SGordon Ross 1707*bd7c6f51SGordon Ross errout: 1708*bd7c6f51SGordon Ross if (error != 0) { 1709*bd7c6f51SGordon Ross if (acl != NULL) 1710*bd7c6f51SGordon Ross ifree_acl(acl); 1711*bd7c6f51SGordon Ross if (sd != NULL) 1712*bd7c6f51SGordon Ross smbfs_acl_free_sd(sd); 1713*bd7c6f51SGordon Ross } 1714*bd7c6f51SGordon Ross if (mapinfo != NULL) 1715*bd7c6f51SGordon Ross FREESZ(mapinfo, mapcnt * sizeof (*mapinfo)); 1716*bd7c6f51SGordon Ross #ifdef _KERNEL 1717*bd7c6f51SGordon Ross if (idmap_gh != NULL) 1718*bd7c6f51SGordon Ross kidmap_get_destroy(idmap_gh); 1719*bd7c6f51SGordon Ross #else /* _KERNEL */ 1720*bd7c6f51SGordon Ross if (idmap_gh != NULL) 1721*bd7c6f51SGordon Ross idmap_get_destroy(idmap_gh); 1722*bd7c6f51SGordon Ross if (idmap_h != NULL) 1723*bd7c6f51SGordon Ross (void) idmap_fini(idmap_h); 1724*bd7c6f51SGordon Ross #endif /* _KERNEL */ 1725*bd7c6f51SGordon Ross 1726*bd7c6f51SGordon Ross return (error); 172702d09e03SGordon Ross } 1728