Home | History | Annotate | Download | only in smbsrv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <smbsrv/smb_kproto.h>
     27 
     28 static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t);
     29 static void smb_encode_sacl(struct smb_xa *, smb_acl_t *);
     30 static void smb_encode_dacl(struct smb_xa *, smb_acl_t *);
     31 
     32 static smb_sid_t *smb_decode_sid(struct smb_xa *, uint32_t);
     33 static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t);
     34 
     35 /*
     36  * smb_nt_transact_query_security_info
     37  *
     38  * This command allows the client to retrieve the security descriptor
     39  * on a file. The result of the call is returned to the client in the
     40  * Data part of the transaction response.
     41  *
     42  * Some clients specify a non-zero maximum data return size (mdrcnt)
     43  * for the SD and some specify zero. In either case, if the mdrcnt is
     44  * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer
     45  * size hint. The client should then retry with the appropriate buffer
     46  * size.
     47  *
     48  *  Client Parameter Block             Description
     49  *  ================================== =================================
     50  *
     51  *  USHORT Fid;                        FID of target
     52  *  USHORT Reserved;                   MBZ
     53  *  ULONG secinfo;                     Fields of descriptor to set
     54  *
     55  *   Data Block Encoding                Description
     56  *   ================================== ==================================
     57  *
     58  *   Data[TotalDataCount]               Security Descriptor information
     59  */
     60 
     61 smb_sdrc_t
     62 smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
     63 {
     64 	smb_sd_t sd;
     65 	uint32_t secinfo;
     66 	uint32_t sdlen;
     67 	uint32_t status;
     68 	smb_error_t err;
     69 
     70 	if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
     71 	    &sr->smb_fid, &secinfo) != 0) {
     72 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
     73 		return (SDRC_ERROR);
     74 	}
     75 
     76 	smbsr_lookup_file(sr);
     77 	if (sr->fid_ofile == NULL) {
     78 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
     79 		return (SDRC_ERROR);
     80 	}
     81 
     82 
     83 	if ((sr->fid_ofile->f_node == NULL) ||
     84 	    (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
     85 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
     86 		    ERRDOS, ERROR_ACCESS_DENIED);
     87 		return (SDRC_ERROR);
     88 	}
     89 
     90 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
     91 
     92 	if (sr->tid_tree->t_acltype != ACE_T) {
     93 		/*
     94 		 * If target filesystem doesn't support ACE_T acls then
     95 		 * don't process SACL
     96 		 */
     97 		secinfo &= ~SMB_SACL_SECINFO;
     98 	}
     99 
    100 	status = smb_sd_read(sr, &sd, secinfo);
    101 	if (status != NT_STATUS_SUCCESS) {
    102 		smbsr_error(sr, status, 0, 0);
    103 		return (SDRC_ERROR);
    104 	}
    105 
    106 	sdlen = smb_sd_len(&sd, secinfo);
    107 	if (sdlen == 0) {
    108 		smb_sd_term(&sd);
    109 		smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0);
    110 		return (SDRC_ERROR);
    111 	}
    112 
    113 	if (sdlen > xa->smb_mdrcnt) {
    114 		/*
    115 		 * The maximum data return count specified by the
    116 		 * client is not big enough to hold the security
    117 		 * descriptor. We have to return an error but we
    118 		 * should provide a buffer size hint for the client.
    119 		 */
    120 		(void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
    121 		err.severity = ERROR_SEVERITY_ERROR;
    122 		err.status   = NT_STATUS_BUFFER_TOO_SMALL;
    123 		err.errcls   = ERRDOS;
    124 		err.errcode  = ERROR_INSUFFICIENT_BUFFER;
    125 		smbsr_set_error(sr, &err);
    126 		smb_sd_term(&sd);
    127 		return (SDRC_SUCCESS);
    128 	}
    129 
    130 	smb_encode_sd(xa, &sd, secinfo);
    131 	(void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
    132 	smb_sd_term(&sd);
    133 	return (SDRC_SUCCESS);
    134 }
    135 
    136 /*
    137  * smb_nt_transact_set_security_info
    138  *
    139  * This command allows the client to change the security descriptor on a
    140  * file. All we do here is decode the parameters and the data. The data
    141  * is passed directly to smb_nt_set_security_object, with the security
    142  * information describing the information to set. There are no response
    143  * parameters or data.
    144  *
    145  *   Client Parameter Block Encoding    Description
    146  *   ================================== ==================================
    147  *   USHORT Fid;                        FID of target
    148  *   USHORT Reserved;                   MBZ
    149  *   ULONG SecurityInformation;         Fields of SD that to set
    150  *
    151  *   Data Block Encoding                Description
    152  *   ================================== ==================================
    153  *   Data[TotalDataCount]               Security Descriptor information
    154  */
    155 smb_sdrc_t
    156 smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
    157 {
    158 	smb_sd_t sd;
    159 	uint32_t secinfo;
    160 	uint32_t status;
    161 
    162 	if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
    163 	    &sr->smb_fid, &secinfo) != 0) {
    164 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
    165 		return (SDRC_ERROR);
    166 	}
    167 
    168 	smbsr_lookup_file(sr);
    169 	if (sr->fid_ofile == NULL) {
    170 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
    171 		return (SDRC_ERROR);
    172 	}
    173 
    174 	if ((sr->fid_ofile->f_node == NULL) ||
    175 	    (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
    176 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0);
    177 		return (SDRC_ERROR);
    178 	}
    179 
    180 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
    181 
    182 	if (SMB_TREE_IS_READONLY(sr)) {
    183 		smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0);
    184 		return (SDRC_ERROR);
    185 	}
    186 
    187 	if (sr->tid_tree->t_acltype != ACE_T) {
    188 		/*
    189 		 * If target filesystem doesn't support ACE_T acls then
    190 		 * don't process SACL
    191 		 */
    192 		secinfo &= ~SMB_SACL_SECINFO;
    193 	}
    194 
    195 	if ((secinfo & SMB_ALL_SECINFO) == 0) {
    196 		return (NT_STATUS_SUCCESS);
    197 	}
    198 
    199 	status = smb_decode_sd(xa, &sd);
    200 	if (status != NT_STATUS_SUCCESS) {
    201 		smbsr_error(sr, status, 0, 0);
    202 		return (SDRC_ERROR);
    203 	}
    204 
    205 	if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) ||
    206 	    ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) {
    207 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
    208 		return (SDRC_ERROR);
    209 	}
    210 
    211 	status = smb_sd_write(sr, &sd, secinfo);
    212 	smb_sd_term(&sd);
    213 	if (status != NT_STATUS_SUCCESS) {
    214 		smbsr_error(sr, status, 0, 0);
    215 		return (SDRC_ERROR);
    216 	}
    217 
    218 	return (SDRC_SUCCESS);
    219 }
    220 
    221 /*
    222  * smb_encode_sd
    223  *
    224  * Encodes given security descriptor in the reply buffer.
    225  */
    226 static void
    227 smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo)
    228 {
    229 	uint32_t offset = SMB_SD_HDRSIZE;
    230 
    231 	/* encode header */
    232 	(void) smb_mbc_encodef(&xa->rep_data_mb, "b.w",
    233 	    sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE);
    234 
    235 	/* owner offset */
    236 	if (secinfo & SMB_OWNER_SECINFO) {
    237 		ASSERT(sd->sd_owner);
    238 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
    239 		offset += smb_sid_len(sd->sd_owner);
    240 	} else {
    241 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
    242 	}
    243 
    244 	/* group offset */
    245 	if (secinfo & SMB_GROUP_SECINFO) {
    246 		ASSERT(sd->sd_group);
    247 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
    248 		offset += smb_sid_len(sd->sd_group);
    249 	} else {
    250 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
    251 	}
    252 
    253 	/* SACL offset */
    254 	if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) {
    255 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
    256 		offset += smb_acl_len(sd->sd_sacl);
    257 	} else {
    258 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
    259 	}
    260 
    261 	/* DACL offset */
    262 	if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl))
    263 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
    264 	else
    265 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
    266 
    267 	if (secinfo & SMB_OWNER_SECINFO)
    268 		smb_encode_sid(xa, sd->sd_owner);
    269 
    270 	if (secinfo & SMB_GROUP_SECINFO)
    271 		smb_encode_sid(xa, sd->sd_group);
    272 
    273 	if (secinfo & SMB_SACL_SECINFO)
    274 		smb_encode_sacl(xa, sd->sd_sacl);
    275 
    276 	if (secinfo & SMB_DACL_SECINFO)
    277 		smb_encode_dacl(xa, sd->sd_dacl);
    278 }
    279 
    280 /*
    281  * smb_encode_sid
    282  *
    283  * Encodes given SID in the reply buffer.
    284  */
    285 void
    286 smb_encode_sid(struct smb_xa *xa, smb_sid_t *sid)
    287 {
    288 	int i;
    289 
    290 	(void) smb_mbc_encodef(&xa->rep_data_mb, "bb",
    291 	    sid->sid_revision, sid->sid_subauthcnt);
    292 
    293 	for (i = 0; i < NT_SID_AUTH_MAX; i++) {
    294 		(void) smb_mbc_encodef(&xa->rep_data_mb, "b",
    295 		    sid->sid_authority[i]);
    296 	}
    297 
    298 	for (i = 0; i < sid->sid_subauthcnt; i++) {
    299 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
    300 		    sid->sid_subauth[i]);
    301 	}
    302 }
    303 
    304 /*
    305  * smb_encode_sacl
    306  *
    307  * Encodes given SACL in the reply buffer.
    308  */
    309 static void
    310 smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl)
    311 {
    312 	smb_ace_t *ace;
    313 	int i;
    314 
    315 	if (acl == NULL)
    316 		return;
    317 
    318 	/* encode header */
    319 	(void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
    320 	    acl->sl_bsize, acl->sl_acecnt);
    321 
    322 	for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
    323 		(void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl",
    324 		    ace->se_hdr.se_type, ace->se_hdr.se_flags,
    325 		    ace->se_hdr.se_bsize, ace->se_mask);
    326 
    327 		smb_encode_sid(xa, ace->se_sid);
    328 	}
    329 }
    330 
    331 /*
    332  * smb_encode_dacl
    333  *
    334  * Encodes given DACL in the reply buffer.
    335  */
    336 static void
    337 smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl)
    338 {
    339 	smb_ace_t *ace;
    340 
    341 	if (acl == NULL)
    342 		return;
    343 
    344 	/* encode header */
    345 	(void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
    346 	    acl->sl_bsize, acl->sl_acecnt);
    347 
    348 	ace = list_head(&acl->sl_sorted);
    349 	while (ace) {
    350 		(void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl",
    351 		    ace->se_hdr.se_type, ace->se_hdr.se_flags,
    352 		    ace->se_hdr.se_bsize, ace->se_mask);
    353 
    354 		smb_encode_sid(xa, ace->se_sid);
    355 		ace = list_next(&acl->sl_sorted, ace);
    356 	}
    357 }
    358 
    359 /*
    360  * smb_decode_sd
    361  *
    362  * Decodes the security descriptor in the request buffer
    363  * and set the fields of 'sd' appropraitely. Upon successful
    364  * return, caller must free allocated memories by calling
    365  * smb_sd_term().
    366  */
    367 uint32_t
    368 smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd)
    369 {
    370 	struct mbuf_chain sdbuf;
    371 	uint32_t owner_offs;
    372 	uint32_t group_offs;
    373 	uint32_t sacl_offs;
    374 	uint32_t dacl_offs;
    375 
    376 	smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
    377 
    378 	(void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb,
    379 	    xa->req_data_mb.chain_offset,
    380 	    xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset);
    381 
    382 	if (smb_mbc_decodef(&sdbuf, "b.wllll",
    383 	    &sd->sd_revision, &sd->sd_control,
    384 	    &owner_offs, &group_offs, &sacl_offs, &dacl_offs))
    385 		goto decode_error;
    386 
    387 	sd->sd_control &= ~SE_SELF_RELATIVE;
    388 
    389 	if (owner_offs != 0) {
    390 		if (owner_offs < SMB_SD_HDRSIZE)
    391 			goto decode_error;
    392 
    393 		sd->sd_owner = smb_decode_sid(xa, owner_offs);
    394 		if (sd->sd_owner == NULL)
    395 			goto decode_error;
    396 	}
    397 
    398 	if (group_offs != 0) {
    399 		if (group_offs < SMB_SD_HDRSIZE)
    400 			goto decode_error;
    401 
    402 		sd->sd_group = smb_decode_sid(xa, group_offs);
    403 		if (sd->sd_group == NULL)
    404 			goto decode_error;
    405 	}
    406 
    407 	if (sacl_offs != 0) {
    408 		if ((sd->sd_control & SE_SACL_PRESENT) == 0)
    409 			goto decode_error;
    410 
    411 		if (sacl_offs < SMB_SD_HDRSIZE)
    412 			goto decode_error;
    413 
    414 		sd->sd_sacl = smb_decode_acl(xa, sacl_offs);
    415 		if (sd->sd_sacl == NULL)
    416 			goto decode_error;
    417 	}
    418 
    419 	if (dacl_offs != 0) {
    420 		if ((sd->sd_control & SE_DACL_PRESENT) == 0)
    421 			goto decode_error;
    422 
    423 		if (dacl_offs < SMB_SD_HDRSIZE)
    424 			goto decode_error;
    425 
    426 		sd->sd_dacl = smb_decode_acl(xa, dacl_offs);
    427 		if (sd->sd_dacl == NULL)
    428 			goto decode_error;
    429 	}
    430 
    431 	return (NT_STATUS_SUCCESS);
    432 
    433 decode_error:
    434 	smb_sd_term(sd);
    435 	return (NT_STATUS_INVALID_SECURITY_DESCR);
    436 }
    437 
    438 /*
    439  * smb_decode_sid
    440  *
    441  * Allocates memory and decodes the SID in the request buffer
    442  * Upon successful return, caller must free the allocated memory
    443  * by calling smb_sid_free()
    444  */
    445 static smb_sid_t *
    446 smb_decode_sid(struct smb_xa *xa, uint32_t offset)
    447 {
    448 	uint8_t revision;
    449 	uint8_t subauth_cnt;
    450 	struct mbuf_chain sidbuf;
    451 	smb_sid_t *sid;
    452 	int sidlen;
    453 	int bytes_left;
    454 	int i;
    455 
    456 	offset += xa->req_data_mb.chain_offset;
    457 	bytes_left = xa->req_data_mb.max_bytes - offset;
    458 	if (bytes_left < sizeof (smb_sid_t))
    459 		return (NULL);
    460 
    461 	(void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left);
    462 
    463 	if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt))
    464 		return (NULL);
    465 
    466 	sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) +
    467 	    (subauth_cnt * sizeof (uint32_t));
    468 	sid = kmem_alloc(sidlen, KM_SLEEP);
    469 
    470 	sid->sid_revision = revision;
    471 	sid->sid_subauthcnt = subauth_cnt;
    472 
    473 	for (i = 0; i < NT_SID_AUTH_MAX; i++) {
    474 		if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i]))
    475 			goto decode_err;
    476 	}
    477 
    478 	for (i = 0; i < sid->sid_subauthcnt; i++) {
    479 		if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i]))
    480 			goto decode_err;
    481 	}
    482 
    483 	return (sid);
    484 
    485 decode_err:
    486 	kmem_free(sid, sidlen);
    487 	return (NULL);
    488 }
    489 
    490 /*
    491  * smb_decode_acl
    492  *
    493  * Allocates memory and decodes the ACL in the request buffer
    494  * Upon successful return, caller must free the allocated memory
    495  * by calling smb_acl_free().
    496  */
    497 static smb_acl_t *
    498 smb_decode_acl(struct smb_xa *xa, uint32_t offset)
    499 {
    500 	struct mbuf_chain aclbuf;
    501 	smb_acl_t *acl;
    502 	smb_ace_t *ace;
    503 	uint8_t revision;
    504 	uint16_t size;
    505 	uint16_t acecnt;
    506 	int bytes_left;
    507 	uint32_t sid_offs = offset;
    508 	int sidlen;
    509 	int i;
    510 
    511 	offset += xa->req_data_mb.chain_offset;
    512 	bytes_left = xa->req_data_mb.max_bytes - offset;
    513 	if (bytes_left < SMB_ACL_HDRSIZE)
    514 		return (NULL);
    515 
    516 	(void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left);
    517 
    518 	if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt))
    519 		return (NULL);
    520 
    521 	if (size == 0)
    522 		return (NULL);
    523 
    524 	acl = smb_acl_alloc(revision, size, acecnt);
    525 
    526 	sid_offs += SMB_ACL_HDRSIZE;
    527 	for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
    528 		if (smb_mbc_decodef(&aclbuf, "bbwl",
    529 		    &ace->se_hdr.se_type, &ace->se_hdr.se_flags,
    530 		    &ace->se_hdr.se_bsize, &ace->se_mask))
    531 			goto decode_error;
    532 
    533 		sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask);
    534 		ace->se_sid = smb_decode_sid(xa, sid_offs);
    535 		if (ace->se_sid == NULL)
    536 			goto decode_error;
    537 		/* This is SID length plus any paddings between ACEs */
    538 		sidlen = ace->se_hdr.se_bsize -
    539 		    (SMB_ACE_HDRSIZE + sizeof (ace->se_mask));
    540 		aclbuf.chain_offset += sidlen;
    541 		sid_offs += sidlen;
    542 	}
    543 
    544 	return (acl);
    545 
    546 decode_error:
    547 	smb_acl_free(acl);
    548 	return (NULL);
    549 }
    550