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