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