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