129bd2886SAlan Wright /*
229bd2886SAlan Wright * CDDL HEADER START
329bd2886SAlan Wright *
429bd2886SAlan Wright * The contents of this file are subject to the terms of the
529bd2886SAlan Wright * Common Development and Distribution License (the "License").
629bd2886SAlan Wright * You may not use this file except in compliance with the License.
729bd2886SAlan Wright *
829bd2886SAlan Wright * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
929bd2886SAlan Wright * or http://www.opensolaris.org/os/licensing.
1029bd2886SAlan Wright * See the License for the specific language governing permissions
1129bd2886SAlan Wright * and limitations under the License.
1229bd2886SAlan Wright *
1329bd2886SAlan Wright * When distributing Covered Code, include this CDDL HEADER in each
1429bd2886SAlan Wright * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1529bd2886SAlan Wright * If applicable, add the following below this CDDL HEADER, with the
1629bd2886SAlan Wright * fields enclosed by brackets "[]" replaced with your own identifying
1729bd2886SAlan Wright * information: Portions Copyright [yyyy] [name of copyright owner]
1829bd2886SAlan Wright *
1929bd2886SAlan Wright * CDDL HEADER END
2029bd2886SAlan Wright */
21*148c5f43SAlan Wright
2229bd2886SAlan Wright /*
23*148c5f43SAlan Wright * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2429bd2886SAlan Wright */
2529bd2886SAlan Wright
2629bd2886SAlan Wright /*
2729bd2886SAlan Wright * This is a helper file to get/set Windows SD. This is used by
2829bd2886SAlan Wright * SRVSVC service.
2929bd2886SAlan Wright */
3029bd2886SAlan Wright #include <strings.h>
3129bd2886SAlan Wright #include <libzfs.h>
32*148c5f43SAlan Wright
33*148c5f43SAlan Wright #include <smbsrv/libsmb.h>
3429bd2886SAlan Wright #include <smbsrv/libmlsvc.h>
3529bd2886SAlan Wright #include <smbsrv/ndl/srvsvc.ndl>
3629bd2886SAlan Wright
3729bd2886SAlan Wright /* Size of offset members in mslm_security_descriptor structure */
3829bd2886SAlan Wright #define SRVSVC_SD_OFFSET_SZ 16
3929bd2886SAlan Wright
4029bd2886SAlan Wright #define SRVSVC_ACE_OFFSET 8
4129bd2886SAlan Wright #define SRVSVC_SID_OFFSET 8
4229bd2886SAlan Wright
43f96bd5c8SAlan Wright uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
44f96bd5c8SAlan Wright
45fe1c642dSBill Krier static uint32_t srvsvc_sd_get_autohome(const smb_share_t *, smb_sd_t *);
4629bd2886SAlan Wright static uint32_t srvsvc_sd_status_to_error(uint32_t);
4729bd2886SAlan Wright static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
4829bd2886SAlan Wright
4929bd2886SAlan Wright /*
5029bd2886SAlan Wright * This method computes ACL on share path from a share name.
5129bd2886SAlan Wright * Return 0 upon success, -1 upon failure.
5229bd2886SAlan Wright */
5329bd2886SAlan Wright static int
srvsvc_shareacl_getpath(smb_share_t * si,char * shr_acl_path)5429bd2886SAlan Wright srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path)
5529bd2886SAlan Wright {
5629bd2886SAlan Wright char dataset[MAXPATHLEN];
5729bd2886SAlan Wright char mp[ZFS_MAXPROPLEN];
5829bd2886SAlan Wright libzfs_handle_t *libhd;
5929bd2886SAlan Wright zfs_handle_t *zfshd;
6029bd2886SAlan Wright int ret = 0;
6129bd2886SAlan Wright
6229bd2886SAlan Wright ret = smb_getdataset(si->shr_path, dataset, MAXPATHLEN);
6329bd2886SAlan Wright if (ret != 0)
6429bd2886SAlan Wright return (ret);
6529bd2886SAlan Wright
6629bd2886SAlan Wright if ((libhd = libzfs_init()) == NULL)
6729bd2886SAlan Wright return (-1);
6829bd2886SAlan Wright
6929bd2886SAlan Wright if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
7029bd2886SAlan Wright libzfs_fini(libhd);
7129bd2886SAlan Wright return (-1);
7229bd2886SAlan Wright }
7329bd2886SAlan Wright
7429bd2886SAlan Wright if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL,
7529bd2886SAlan Wright NULL, 0, B_FALSE) != 0) {
7629bd2886SAlan Wright zfs_close(zfshd);
7729bd2886SAlan Wright libzfs_fini(libhd);
7829bd2886SAlan Wright return (-1);
7929bd2886SAlan Wright }
8029bd2886SAlan Wright
8129bd2886SAlan Wright zfs_close(zfshd);
8229bd2886SAlan Wright libzfs_fini(libhd);
8329bd2886SAlan Wright
8429bd2886SAlan Wright (void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s",
8529bd2886SAlan Wright mp, si->shr_name);
8629bd2886SAlan Wright
8729bd2886SAlan Wright return (ret);
8829bd2886SAlan Wright }
8929bd2886SAlan Wright
9029bd2886SAlan Wright /*
9129bd2886SAlan Wright * This method sets Security Descriptor on a share path.
9229bd2886SAlan Wright *
9329bd2886SAlan Wright * Returns:
9429bd2886SAlan Wright * ERROR_SUCCESS
9529bd2886SAlan Wright * ERROR_NOT_ENOUGH_MEMORY
9629bd2886SAlan Wright * ERROR_INVALID_ACL
9729bd2886SAlan Wright * ERROR_INVALID_SID
9829bd2886SAlan Wright * ERROR_INVALID_SECURITY_DESCR
9929bd2886SAlan Wright * ERROR_NONE_MAPPED
10029bd2886SAlan Wright * ERROR_INTERNAL_ERROR
10129bd2886SAlan Wright * ERROR_PATH_NOT_FOUND
10229bd2886SAlan Wright */
10329bd2886SAlan Wright uint32_t
srvsvc_sd_set(smb_share_t * si,uint8_t * sdbuf)10429bd2886SAlan Wright srvsvc_sd_set(smb_share_t *si, uint8_t *sdbuf)
10529bd2886SAlan Wright {
10629bd2886SAlan Wright smb_sd_t sd;
10729bd2886SAlan Wright uint32_t status = ERROR_SUCCESS;
10829bd2886SAlan Wright char path[MAXPATHLEN];
10929bd2886SAlan Wright int ret = 0;
11029bd2886SAlan Wright
11129bd2886SAlan Wright ret = srvsvc_shareacl_getpath(si, path);
11229bd2886SAlan Wright if (ret != 0)
11329bd2886SAlan Wright return (ERROR_PATH_NOT_FOUND);
11429bd2886SAlan Wright
11529bd2886SAlan Wright smb_sd_init(&sd, 0);
11629bd2886SAlan Wright status = srvsvc_sd_set_absolute(sdbuf, &sd);
11729bd2886SAlan Wright if (status != ERROR_SUCCESS) {
11829bd2886SAlan Wright smb_sd_term(&sd);
11929bd2886SAlan Wright return (status);
12029bd2886SAlan Wright }
12129bd2886SAlan Wright
12229bd2886SAlan Wright status = smb_sd_write(path, &sd, SMB_DACL_SECINFO);
12329bd2886SAlan Wright status = srvsvc_sd_status_to_error(status);
12429bd2886SAlan Wright smb_sd_term(&sd);
12529bd2886SAlan Wright
12629bd2886SAlan Wright return (status);
12729bd2886SAlan Wright }
12829bd2886SAlan Wright
12929bd2886SAlan Wright /*
13029bd2886SAlan Wright * This method returns a Security Descriptor of a share path in self relative
13129bd2886SAlan Wright * format. Call to this function with NULL buffer, returns the size of the
13229bd2886SAlan Wright * security descriptor, which can be used to allocate buffer.
13329bd2886SAlan Wright *
13429bd2886SAlan Wright * Returns:
13529bd2886SAlan Wright * ERROR_SUCCESS
13629bd2886SAlan Wright * ERROR_NOT_ENOUGH_MEMORY
13729bd2886SAlan Wright * ERROR_INVALID_ACL
13829bd2886SAlan Wright * ERROR_INVALID_SID
13929bd2886SAlan Wright * ERROR_INVALID_SECURITY_DESCR
14029bd2886SAlan Wright * ERROR_INVALID_PARAMETER
14129bd2886SAlan Wright * ERROR_NONE_MAPPED
14229bd2886SAlan Wright * ERROR_INTERNAL_ERROR
14329bd2886SAlan Wright * ERROR_PATH_NOT_FOUND
14429bd2886SAlan Wright */
14529bd2886SAlan Wright uint32_t
srvsvc_sd_get(smb_share_t * si,uint8_t * sdbuf,uint32_t * size)14629bd2886SAlan Wright srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
14729bd2886SAlan Wright {
14829bd2886SAlan Wright smb_sd_t sd;
14929bd2886SAlan Wright uint32_t status = ERROR_SUCCESS;
15029bd2886SAlan Wright char path[MAXPATHLEN];
15129bd2886SAlan Wright int ret = 0;
15229bd2886SAlan Wright
15329bd2886SAlan Wright if (sdbuf == NULL && size == NULL)
15429bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
15529bd2886SAlan Wright
156fe1c642dSBill Krier bzero(&sd, sizeof (smb_sd_t));
157fe1c642dSBill Krier
158fe1c642dSBill Krier if (si->shr_flags & SMB_SHRF_AUTOHOME) {
159fe1c642dSBill Krier status = srvsvc_sd_get_autohome(si, &sd);
160fe1c642dSBill Krier } else {
16129bd2886SAlan Wright ret = srvsvc_shareacl_getpath(si, path);
16229bd2886SAlan Wright if (ret != 0)
16329bd2886SAlan Wright return (ERROR_PATH_NOT_FOUND);
16429bd2886SAlan Wright
16529bd2886SAlan Wright status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
16629bd2886SAlan Wright status = srvsvc_sd_status_to_error(status);
167fe1c642dSBill Krier }
168fe1c642dSBill Krier
16929bd2886SAlan Wright if (status != ERROR_SUCCESS) {
17029bd2886SAlan Wright smb_sd_term(&sd);
17129bd2886SAlan Wright return (status);
17229bd2886SAlan Wright }
17329bd2886SAlan Wright
17429bd2886SAlan Wright if (sdbuf == NULL) {
17529bd2886SAlan Wright *size = smb_sd_len(&sd, SMB_ALL_SECINFO);
17629bd2886SAlan Wright smb_sd_term(&sd);
17729bd2886SAlan Wright return (status);
17829bd2886SAlan Wright }
17929bd2886SAlan Wright
18029bd2886SAlan Wright status = srvsvc_sd_set_relative(&sd, sdbuf);
18129bd2886SAlan Wright
18229bd2886SAlan Wright smb_sd_term(&sd);
18329bd2886SAlan Wright return (status);
18429bd2886SAlan Wright }
18529bd2886SAlan Wright
186fe1c642dSBill Krier static uint32_t
srvsvc_sd_get_autohome(const smb_share_t * si,smb_sd_t * sd)187fe1c642dSBill Krier srvsvc_sd_get_autohome(const smb_share_t *si, smb_sd_t *sd)
188fe1c642dSBill Krier {
189fe1c642dSBill Krier smb_fssd_t fs_sd;
190fe1c642dSBill Krier acl_t *acl;
191fe1c642dSBill Krier uint32_t status;
192fe1c642dSBill Krier
193fe1c642dSBill Krier if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
194fe1c642dSBill Krier return (ERROR_NOT_ENOUGH_MEMORY);
195fe1c642dSBill Krier
196fe1c642dSBill Krier smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
197fe1c642dSBill Krier fs_sd.sd_uid = si->shr_uid;
198fe1c642dSBill Krier fs_sd.sd_gid = si->shr_gid;
199fe1c642dSBill Krier fs_sd.sd_zdacl = acl;
200fe1c642dSBill Krier fs_sd.sd_zsacl = NULL;
201fe1c642dSBill Krier
202fe1c642dSBill Krier status = smb_sd_fromfs(&fs_sd, sd);
203fe1c642dSBill Krier status = srvsvc_sd_status_to_error(status);
204fe1c642dSBill Krier smb_fssd_term(&fs_sd);
205fe1c642dSBill Krier return (status);
206fe1c642dSBill Krier }
207fe1c642dSBill Krier
20829bd2886SAlan Wright /*
20929bd2886SAlan Wright * This method converts an ACE from absolute (pointer) to
21029bd2886SAlan Wright * self relative (flat buffer) format.
21129bd2886SAlan Wright *
21229bd2886SAlan Wright * Returns Win32 error codes.
21329bd2886SAlan Wright */
21429bd2886SAlan Wright static uint32_t
srvsvc_ace_set_relative(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)21529bd2886SAlan Wright srvsvc_ace_set_relative(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
21629bd2886SAlan Wright smb_ace_t *ace)
21729bd2886SAlan Wright {
21829bd2886SAlan Wright if ((m_ace == NULL) || (ace == NULL))
21929bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
22029bd2886SAlan Wright
22129bd2886SAlan Wright bcopy(&ace->se_hdr, &m_ace->header, sizeof (mslm_ace_hdr_t));
22229bd2886SAlan Wright m_ace->mask = ace->se_mask;
22329bd2886SAlan Wright
22429bd2886SAlan Wright if ((ace->se_sid == NULL) || (m_sid == NULL))
22529bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
22629bd2886SAlan Wright bcopy(ace->se_sid, m_sid, smb_sid_len(ace->se_sid));
22729bd2886SAlan Wright
22829bd2886SAlan Wright return (ERROR_SUCCESS);
22929bd2886SAlan Wright }
23029bd2886SAlan Wright
23129bd2886SAlan Wright /*
23229bd2886SAlan Wright * This method converts an ACL from absolute (pointer) to
23329bd2886SAlan Wright * self relative (flat buffer) format.
23429bd2886SAlan Wright *
23529bd2886SAlan Wright * Returns an initialized mslm_acl structure on success.
23629bd2886SAlan Wright * Returns NULL on failure.
23729bd2886SAlan Wright */
23829bd2886SAlan Wright static struct mslm_acl *
srvsvc_acl_set_relative(uint8_t * sdbuf,smb_acl_t * acl)23929bd2886SAlan Wright srvsvc_acl_set_relative(uint8_t *sdbuf, smb_acl_t *acl)
24029bd2886SAlan Wright {
24129bd2886SAlan Wright struct mslm_acl *m_acl;
24229bd2886SAlan Wright
24329bd2886SAlan Wright if (sdbuf == NULL)
24429bd2886SAlan Wright return (NULL);
24529bd2886SAlan Wright
24629bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
24729bd2886SAlan Wright m_acl = (struct mslm_acl *)sdbuf;
24829bd2886SAlan Wright m_acl->revision = acl->sl_revision;
24929bd2886SAlan Wright m_acl->sbz1 = 0;
25029bd2886SAlan Wright m_acl->size = acl->sl_bsize;
25129bd2886SAlan Wright m_acl->sbz2 = 0;
25229bd2886SAlan Wright m_acl->ace_count = acl->sl_acecnt;
25329bd2886SAlan Wright
25429bd2886SAlan Wright return (m_acl);
25529bd2886SAlan Wright }
25629bd2886SAlan Wright
25729bd2886SAlan Wright /*
25829bd2886SAlan Wright * This method converts Security Descriptor from absolute (pointer) to
25929bd2886SAlan Wright * self relative (flat buffer) format.
26029bd2886SAlan Wright *
26129bd2886SAlan Wright * Returns Win32 error codes.
26229bd2886SAlan Wright */
263f96bd5c8SAlan Wright uint32_t
srvsvc_sd_set_relative(smb_sd_t * sd,uint8_t * sdbuf)26429bd2886SAlan Wright srvsvc_sd_set_relative(smb_sd_t *sd, uint8_t *sdbuf)
26529bd2886SAlan Wright {
26629bd2886SAlan Wright mslm_security_descriptor_t *msd;
26729bd2886SAlan Wright int offset, len, i;
26829bd2886SAlan Wright smb_ace_t *ace;
26929bd2886SAlan Wright mslm_ace_t *m_ace;
27029bd2886SAlan Wright struct mslm_sid *m_sid;
27129bd2886SAlan Wright uint16_t ace_cnt;
27229bd2886SAlan Wright uint32_t status = ERROR_SUCCESS;
27329bd2886SAlan Wright
27429bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
27529bd2886SAlan Wright msd = (mslm_security_descriptor_t *)sdbuf;
27629bd2886SAlan Wright if (msd == NULL)
27729bd2886SAlan Wright return (ERROR_INVALID_SECURITY_DESCR);
27829bd2886SAlan Wright
27929bd2886SAlan Wright msd->revision = sd->sd_revision;
28029bd2886SAlan Wright msd->sbz1 = 0;
28129bd2886SAlan Wright msd->control = sd->sd_control | SE_SELF_RELATIVE;
28229bd2886SAlan Wright
28329bd2886SAlan Wright offset = sizeof (mslm_security_descriptor_t) - SRVSVC_SD_OFFSET_SZ;
28429bd2886SAlan Wright msd->offset_owner = msd->offset_group = 0;
28529bd2886SAlan Wright msd->offset_sacl = msd->offset_dacl = 0;
28629bd2886SAlan Wright
28729bd2886SAlan Wright if (sd->sd_owner != NULL) {
28829bd2886SAlan Wright msd->offset_owner = offset;
28929bd2886SAlan Wright
29029bd2886SAlan Wright if (sd->sd_owner == NULL)
29129bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
29229bd2886SAlan Wright
29329bd2886SAlan Wright len = smb_sid_len(sd->sd_owner);
29429bd2886SAlan Wright bcopy(sd->sd_owner, &sdbuf[offset], len);
29529bd2886SAlan Wright offset += len;
29629bd2886SAlan Wright }
29729bd2886SAlan Wright
29829bd2886SAlan Wright if (sd->sd_group != NULL) {
29929bd2886SAlan Wright msd->offset_group = offset;
30029bd2886SAlan Wright
30129bd2886SAlan Wright if (sd->sd_group == NULL)
30229bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
30329bd2886SAlan Wright
30429bd2886SAlan Wright len = smb_sid_len(sd->sd_group);
30529bd2886SAlan Wright bcopy(sd->sd_group, &sdbuf[offset], len);
30629bd2886SAlan Wright offset += len;
30729bd2886SAlan Wright }
30829bd2886SAlan Wright
30929bd2886SAlan Wright if (sd->sd_sacl != NULL) {
31029bd2886SAlan Wright msd->offset_sacl = offset;
31129bd2886SAlan Wright msd->sacl = srvsvc_acl_set_relative(&sdbuf[offset],
31229bd2886SAlan Wright sd->sd_sacl);
31329bd2886SAlan Wright if (msd->sacl == NULL)
31429bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
31529bd2886SAlan Wright
31629bd2886SAlan Wright ace = sd->sd_sacl->sl_aces;
31729bd2886SAlan Wright ace_cnt = msd->sacl->ace_count;
31829bd2886SAlan Wright offset += SRVSVC_ACE_OFFSET;
31929bd2886SAlan Wright
32029bd2886SAlan Wright for (i = 0; i < ace_cnt; i++, ace++) {
32129bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
32229bd2886SAlan Wright m_ace = (mslm_ace_t *)&sdbuf[offset];
32329bd2886SAlan Wright offset += SRVSVC_SID_OFFSET;
32429bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
32529bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[offset];
32629bd2886SAlan Wright
32729bd2886SAlan Wright status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
32829bd2886SAlan Wright if (status != ERROR_SUCCESS)
32929bd2886SAlan Wright return (status);
33029bd2886SAlan Wright offset += smb_sid_len(ace->se_sid);
33129bd2886SAlan Wright }
33229bd2886SAlan Wright }
33329bd2886SAlan Wright
33429bd2886SAlan Wright if (sd->sd_dacl != NULL) {
33529bd2886SAlan Wright msd->offset_dacl = offset;
33629bd2886SAlan Wright msd->dacl = srvsvc_acl_set_relative(&sdbuf[offset],
33729bd2886SAlan Wright sd->sd_dacl);
33829bd2886SAlan Wright if (msd->dacl == NULL)
33929bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
34029bd2886SAlan Wright
34129bd2886SAlan Wright ace = sd->sd_dacl->sl_aces;
34229bd2886SAlan Wright ace_cnt = msd->dacl->ace_count;
34329bd2886SAlan Wright offset += SRVSVC_ACE_OFFSET;
34429bd2886SAlan Wright
34529bd2886SAlan Wright for (i = 0; i < ace_cnt; i++, ace++) {
34629bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
34729bd2886SAlan Wright m_ace = (mslm_ace_t *)&sdbuf[offset];
34829bd2886SAlan Wright offset += SRVSVC_SID_OFFSET;
34929bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
35029bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[offset];
35129bd2886SAlan Wright
35229bd2886SAlan Wright status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
35329bd2886SAlan Wright if (status != ERROR_SUCCESS)
35429bd2886SAlan Wright return (status);
35529bd2886SAlan Wright offset += smb_sid_len(ace->se_sid);
35629bd2886SAlan Wright }
35729bd2886SAlan Wright }
35829bd2886SAlan Wright
35929bd2886SAlan Wright return (status);
36029bd2886SAlan Wright }
36129bd2886SAlan Wright
36229bd2886SAlan Wright /*
36329bd2886SAlan Wright * This method converts an ACE from self relative (flat buffer) to
36429bd2886SAlan Wright * absolute (pointer) format.
36529bd2886SAlan Wright *
36629bd2886SAlan Wright * Returns Win32 error codes.
36729bd2886SAlan Wright */
36829bd2886SAlan Wright static uint32_t
srvsvc_ace_set_absolute(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)36929bd2886SAlan Wright srvsvc_ace_set_absolute(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
37029bd2886SAlan Wright smb_ace_t *ace)
37129bd2886SAlan Wright {
37229bd2886SAlan Wright int sid_size = 0;
37329bd2886SAlan Wright if ((m_ace == NULL) || (ace == NULL) || (m_sid == NULL))
37429bd2886SAlan Wright return (ERROR_INVALID_PARAMETER);
37529bd2886SAlan Wright
37629bd2886SAlan Wright bzero(ace, sizeof (smb_ace_t));
37729bd2886SAlan Wright bcopy(&m_ace->header, &ace->se_hdr, sizeof (mslm_ace_hdr_t));
37829bd2886SAlan Wright ace->se_mask = m_ace->mask;
37929bd2886SAlan Wright
38029bd2886SAlan Wright sid_size = smb_sid_len((smb_sid_t *)m_sid);
38129bd2886SAlan Wright if ((ace->se_sid = malloc(sid_size)) == NULL)
38229bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
38329bd2886SAlan Wright bcopy(m_sid, ace->se_sid, sid_size);
38429bd2886SAlan Wright
38529bd2886SAlan Wright return (ERROR_SUCCESS);
38629bd2886SAlan Wright }
38729bd2886SAlan Wright
38829bd2886SAlan Wright /*
38929bd2886SAlan Wright * This method converts an ACL from self relative (flat buffer) to
39029bd2886SAlan Wright * absolute (pointer) format.
39129bd2886SAlan Wright *
39229bd2886SAlan Wright * Returns an initialized smb_acl_t structure on success.
39329bd2886SAlan Wright * Returns NULL on failure.
39429bd2886SAlan Wright */
39529bd2886SAlan Wright static smb_acl_t *
srvsvc_acl_set_absolute(uint8_t * sdbuf,int * offset)39629bd2886SAlan Wright srvsvc_acl_set_absolute(uint8_t *sdbuf, int *offset)
39729bd2886SAlan Wright {
39829bd2886SAlan Wright uint8_t rev;
39929bd2886SAlan Wright uint16_t sz, ace_cnt;
40029bd2886SAlan Wright smb_acl_t *acl;
40129bd2886SAlan Wright
40229bd2886SAlan Wright bcopy(&sdbuf[*offset], &rev, sizeof (uint8_t));
40329bd2886SAlan Wright *offset += 2; /* Pad for Sbz1 */
40429bd2886SAlan Wright bcopy(&sdbuf[*offset], &sz, sizeof (uint16_t));
40529bd2886SAlan Wright *offset += 2;
40629bd2886SAlan Wright bcopy(&sdbuf[*offset], &ace_cnt, sizeof (uint16_t));
40729bd2886SAlan Wright *offset += 4; /* Pad for Sbz2 */
40829bd2886SAlan Wright
40929bd2886SAlan Wright acl = smb_acl_alloc(rev, sz, ace_cnt);
41029bd2886SAlan Wright
41129bd2886SAlan Wright return (acl);
41229bd2886SAlan Wright }
41329bd2886SAlan Wright
41429bd2886SAlan Wright /*
41529bd2886SAlan Wright * This method converts Security Descriptor from self relative (flat buffer) to
41629bd2886SAlan Wright * absolute (pointer) format.
41729bd2886SAlan Wright *
41829bd2886SAlan Wright * Returns Win32 error codes.
41929bd2886SAlan Wright */
42029bd2886SAlan Wright static uint32_t
srvsvc_sd_set_absolute(uint8_t * sdbuf,smb_sd_t * sd)42129bd2886SAlan Wright srvsvc_sd_set_absolute(uint8_t *sdbuf, smb_sd_t *sd)
42229bd2886SAlan Wright {
42329bd2886SAlan Wright mslm_security_descriptor_t *msd;
42429bd2886SAlan Wright mslm_ace_t *m_ace;
42529bd2886SAlan Wright struct mslm_sid *m_sid;
42629bd2886SAlan Wright smb_ace_t *ace;
42729bd2886SAlan Wright uint16_t ace_cnt;
42829bd2886SAlan Wright int offset, i, sid_size;
42929bd2886SAlan Wright uint32_t status = ERROR_SUCCESS;
43029bd2886SAlan Wright
43129bd2886SAlan Wright if (sdbuf == NULL)
43229bd2886SAlan Wright return (ERROR_INVALID_SECURITY_DESCR);
43329bd2886SAlan Wright
43429bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
43529bd2886SAlan Wright msd = (mslm_security_descriptor_t *)sdbuf;
43629bd2886SAlan Wright
43729bd2886SAlan Wright sd->sd_revision = msd->revision;
43829bd2886SAlan Wright sd->sd_control = msd->control & (~SE_SELF_RELATIVE);
43929bd2886SAlan Wright
44029bd2886SAlan Wright if (msd->offset_owner != 0) {
44129bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
44229bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[msd->offset_owner];
44329bd2886SAlan Wright sid_size = smb_sid_len((smb_sid_t *)m_sid);
44429bd2886SAlan Wright
44529bd2886SAlan Wright if ((sd->sd_owner = malloc(sid_size)) == NULL)
44629bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
44729bd2886SAlan Wright bcopy(m_sid, sd->sd_owner, sid_size);
44829bd2886SAlan Wright }
44929bd2886SAlan Wright
45029bd2886SAlan Wright if (msd->offset_group != 0) {
45129bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
45229bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[msd->offset_group];
45329bd2886SAlan Wright sid_size = smb_sid_len((smb_sid_t *)m_sid);
45429bd2886SAlan Wright
45529bd2886SAlan Wright if ((sd->sd_group = malloc(sid_size)) == NULL)
45629bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
45729bd2886SAlan Wright bcopy(m_sid, sd->sd_group, sid_size);
45829bd2886SAlan Wright }
45929bd2886SAlan Wright
46029bd2886SAlan Wright if (msd->offset_sacl != 0) {
46129bd2886SAlan Wright offset = msd->offset_sacl;
46229bd2886SAlan Wright sd->sd_sacl = srvsvc_acl_set_absolute(sdbuf, &offset);
46329bd2886SAlan Wright if (sd->sd_sacl == NULL)
46429bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
46529bd2886SAlan Wright
46629bd2886SAlan Wright ace = sd->sd_sacl->sl_aces;
46729bd2886SAlan Wright ace_cnt = sd->sd_sacl->sl_acecnt;
46829bd2886SAlan Wright
46929bd2886SAlan Wright for (i = 0; i < ace_cnt; i++, ace++) {
47029bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
47129bd2886SAlan Wright m_ace = (mslm_ace_t *)&sdbuf[offset];
47229bd2886SAlan Wright offset += SRVSVC_SID_OFFSET;
47329bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
47429bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[offset];
47529bd2886SAlan Wright
47629bd2886SAlan Wright status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
47729bd2886SAlan Wright if (status != ERROR_SUCCESS)
47829bd2886SAlan Wright return (status);
47929bd2886SAlan Wright offset += smb_sid_len(ace->se_sid);
48029bd2886SAlan Wright }
48129bd2886SAlan Wright }
48229bd2886SAlan Wright
48329bd2886SAlan Wright if (msd->offset_dacl != 0) {
48429bd2886SAlan Wright offset = msd->offset_dacl;
48529bd2886SAlan Wright sd->sd_dacl = srvsvc_acl_set_absolute(sdbuf, &offset);
48629bd2886SAlan Wright if (sd->sd_dacl == NULL)
48729bd2886SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY);
48829bd2886SAlan Wright
48929bd2886SAlan Wright ace = sd->sd_dacl->sl_aces;
49029bd2886SAlan Wright ace_cnt = sd->sd_dacl->sl_acecnt;
49129bd2886SAlan Wright
49229bd2886SAlan Wright for (i = 0; i < ace_cnt; i++, ace++) {
49329bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
49429bd2886SAlan Wright m_ace = (mslm_ace_t *)&sdbuf[offset];
49529bd2886SAlan Wright offset += SRVSVC_SID_OFFSET;
49629bd2886SAlan Wright /*LINTED E_BAD_PTR_CAST_ALIGN*/
49729bd2886SAlan Wright m_sid = (struct mslm_sid *)&sdbuf[offset];
49829bd2886SAlan Wright
49929bd2886SAlan Wright status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
50029bd2886SAlan Wright if (status != ERROR_SUCCESS)
50129bd2886SAlan Wright return (status);
50229bd2886SAlan Wright offset += smb_sid_len(ace->se_sid);
50329bd2886SAlan Wright }
50429bd2886SAlan Wright }
50529bd2886SAlan Wright
50629bd2886SAlan Wright return (status);
50729bd2886SAlan Wright }
50829bd2886SAlan Wright
50929bd2886SAlan Wright /*
51029bd2886SAlan Wright * This method maps NT status codes into Win 32 error codes.
51129bd2886SAlan Wright * This method operates on status codes that are related
51229bd2886SAlan Wright * to processing of Security Descriptor.
51329bd2886SAlan Wright */
51429bd2886SAlan Wright static uint32_t
srvsvc_sd_status_to_error(uint32_t status)51529bd2886SAlan Wright srvsvc_sd_status_to_error(uint32_t status)
51629bd2886SAlan Wright {
51729bd2886SAlan Wright int i;
51829bd2886SAlan Wright static struct {
51929bd2886SAlan Wright uint32_t nt_status;
52029bd2886SAlan Wright uint32_t err_code;
52129bd2886SAlan Wright } errmap[] = {
52229bd2886SAlan Wright { NT_STATUS_SUCCESS, ERROR_SUCCESS },
52329bd2886SAlan Wright { NT_STATUS_INVALID_ACL, ERROR_INVALID_ACL },
52429bd2886SAlan Wright { NT_STATUS_INVALID_SID, ERROR_INVALID_SID },
52529bd2886SAlan Wright { NT_STATUS_NONE_MAPPED, ERROR_NONE_MAPPED }
52629bd2886SAlan Wright };
52729bd2886SAlan Wright
52829bd2886SAlan Wright for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
52929bd2886SAlan Wright if (status == errmap[i].nt_status)
53029bd2886SAlan Wright return (errmap[i].err_code);
53129bd2886SAlan Wright }
53229bd2886SAlan Wright
53329bd2886SAlan Wright return (ERROR_INTERNAL_ERROR);
53429bd2886SAlan Wright }
535