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