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 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 #include <smbsrv/smb_kproto.h> 28 29 static void smb_encode_sacl(mbuf_chain_t *, smb_acl_t *); 30 static void smb_encode_dacl(mbuf_chain_t *, smb_acl_t *); 31 static smb_acl_t *smb_decode_acl(mbuf_chain_t *, 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 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->rep_data_mb, &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 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->req_data_mb, &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 void 226 smb_encode_sd(mbuf_chain_t *mbc, smb_sd_t *sd, uint32_t secinfo) 227 { 228 uint32_t offset = SMB_SD_HDRSIZE; 229 230 /* encode header */ 231 (void) smb_mbc_encodef(mbc, "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(mbc, "l", offset); 238 offset += smb_sid_len(sd->sd_owner); 239 } else { 240 (void) smb_mbc_encodef(mbc, "l", 0); 241 } 242 243 /* group offset */ 244 if (secinfo & SMB_GROUP_SECINFO) { 245 ASSERT(sd->sd_group); 246 (void) smb_mbc_encodef(mbc, "l", offset); 247 offset += smb_sid_len(sd->sd_group); 248 } else { 249 (void) smb_mbc_encodef(mbc, "l", 0); 250 } 251 252 /* SACL offset */ 253 if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) { 254 (void) smb_mbc_encodef(mbc, "l", offset); 255 offset += smb_acl_len(sd->sd_sacl); 256 } else { 257 (void) smb_mbc_encodef(mbc, "l", 0); 258 } 259 260 /* DACL offset */ 261 if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl)) 262 (void) smb_mbc_encodef(mbc, "l", offset); 263 else 264 (void) smb_mbc_encodef(mbc, "l", 0); 265 266 if (secinfo & SMB_OWNER_SECINFO) 267 smb_encode_sid(mbc, sd->sd_owner); 268 269 if (secinfo & SMB_GROUP_SECINFO) 270 smb_encode_sid(mbc, sd->sd_group); 271 272 if (secinfo & SMB_SACL_SECINFO) 273 smb_encode_sacl(mbc, sd->sd_sacl); 274 275 if (secinfo & SMB_DACL_SECINFO) 276 smb_encode_dacl(mbc, sd->sd_dacl); 277 } 278 279 /* 280 * smb_encode_sid 281 * 282 * Encodes given SID in the reply buffer. 283 */ 284 void 285 smb_encode_sid(mbuf_chain_t *mbc, smb_sid_t *sid) 286 { 287 int i; 288 289 (void) smb_mbc_encodef(mbc, "bb", 290 sid->sid_revision, sid->sid_subauthcnt); 291 292 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 293 (void) smb_mbc_encodef(mbc, "b", 294 sid->sid_authority[i]); 295 } 296 297 for (i = 0; i < sid->sid_subauthcnt; i++) { 298 (void) smb_mbc_encodef(mbc, "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 309 smb_encode_sacl(mbuf_chain_t *mbc, 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(mbc, "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(mbc, "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(mbc, ace->se_sid); 327 } 328 } 329 330 /* 331 * smb_encode_dacl 332 * 333 * Encodes given DACL in the reply buffer. 334 */ 335 static void 336 smb_encode_dacl(mbuf_chain_t *mbc, 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(mbc, "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(mbc, "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(mbc, 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 367 smb_decode_sd(mbuf_chain_t *mbc, 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 int rc; 375 376 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 377 378 (void) MBC_SHADOW_CHAIN(&sdbuf, mbc, 379 mbc->chain_offset, 380 mbc->max_bytes - mbc->chain_offset); 381 382 rc = smb_mbc_decodef(&sdbuf, "b.wllll", 383 &sd->sd_revision, &sd->sd_control, 384 &owner_offs, &group_offs, &sacl_offs, &dacl_offs); 385 386 /* Prevent disallowed flags in smb_sd_term. */ 387 sd->sd_control &= ~SE_SELF_RELATIVE; 388 if (rc != 0) 389 goto decode_error; 390 391 if (owner_offs != 0) { 392 if (owner_offs < SMB_SD_HDRSIZE) 393 goto decode_error; 394 395 sd->sd_owner = smb_decode_sid(mbc, owner_offs); 396 if (sd->sd_owner == NULL) 397 goto decode_error; 398 } 399 400 if (group_offs != 0) { 401 if (group_offs < SMB_SD_HDRSIZE) 402 goto decode_error; 403 404 sd->sd_group = smb_decode_sid(mbc, group_offs); 405 if (sd->sd_group == NULL) 406 goto decode_error; 407 } 408 409 if (sacl_offs != 0) { 410 if ((sd->sd_control & SE_SACL_PRESENT) == 0) 411 goto decode_error; 412 413 if (sacl_offs < SMB_SD_HDRSIZE) 414 goto decode_error; 415 416 sd->sd_sacl = smb_decode_acl(mbc, sacl_offs); 417 if (sd->sd_sacl == NULL) 418 goto decode_error; 419 } 420 421 if (dacl_offs != 0) { 422 if ((sd->sd_control & SE_DACL_PRESENT) == 0) 423 goto decode_error; 424 425 if (dacl_offs < SMB_SD_HDRSIZE) 426 goto decode_error; 427 428 sd->sd_dacl = smb_decode_acl(mbc, dacl_offs); 429 if (sd->sd_dacl == NULL) 430 goto decode_error; 431 } 432 433 return (NT_STATUS_SUCCESS); 434 435 decode_error: 436 smb_sd_term(sd); 437 return (NT_STATUS_INVALID_SECURITY_DESCR); 438 } 439 440 /* 441 * smb_decode_sid 442 * 443 * Allocates memory and decodes the SID in the request buffer 444 * Upon successful return, caller must free the allocated memory 445 * by calling smb_sid_free() 446 */ 447 smb_sid_t * 448 smb_decode_sid(mbuf_chain_t *mbc, uint32_t offset) 449 { 450 uint8_t revision; 451 uint8_t subauth_cnt; 452 struct mbuf_chain sidbuf; 453 smb_sid_t *sid; 454 int sidlen; 455 int bytes_left; 456 int i; 457 458 offset += mbc->chain_offset; 459 bytes_left = mbc->max_bytes - offset; 460 if (bytes_left < (int)sizeof (smb_sid_t)) 461 return (NULL); 462 463 if (MBC_SHADOW_CHAIN(&sidbuf, mbc, offset, bytes_left) != 0) 464 return (NULL); 465 466 if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt)) 467 return (NULL); 468 469 sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) + 470 (subauth_cnt * sizeof (uint32_t)); 471 sid = kmem_alloc(sidlen, KM_SLEEP); 472 473 sid->sid_revision = revision; 474 sid->sid_subauthcnt = subauth_cnt; 475 476 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 477 if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i])) 478 goto decode_err; 479 } 480 481 for (i = 0; i < sid->sid_subauthcnt; i++) { 482 if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i])) 483 goto decode_err; 484 } 485 486 return (sid); 487 488 decode_err: 489 kmem_free(sid, sidlen); 490 return (NULL); 491 } 492 493 /* 494 * smb_decode_acl 495 * 496 * Allocates memory and decodes the ACL in the request buffer 497 * Upon successful return, caller must free the allocated memory 498 * by calling smb_acl_free(). 499 */ 500 static smb_acl_t * 501 smb_decode_acl(mbuf_chain_t *mbc, uint32_t offset) 502 { 503 struct mbuf_chain aclbuf; 504 smb_acl_t *acl; 505 smb_ace_t *ace; 506 uint8_t revision; 507 uint16_t size; 508 uint16_t acecnt; 509 int bytes_left; 510 uint32_t sid_offs = offset; 511 int sidlen; 512 int i; 513 514 offset += mbc->chain_offset; 515 bytes_left = mbc->max_bytes - offset; 516 if (bytes_left < SMB_ACL_HDRSIZE) 517 return (NULL); 518 519 if (MBC_SHADOW_CHAIN(&aclbuf, mbc, offset, bytes_left) != 0) 520 return (NULL); 521 522 if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt)) 523 return (NULL); 524 525 if (size == 0) 526 return (NULL); 527 528 acl = smb_acl_alloc(revision, size, acecnt); 529 530 sid_offs += SMB_ACL_HDRSIZE; 531 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { 532 if (smb_mbc_decodef(&aclbuf, "bbwl", 533 &ace->se_hdr.se_type, &ace->se_hdr.se_flags, 534 &ace->se_hdr.se_bsize, &ace->se_mask)) 535 goto decode_error; 536 537 sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask); 538 ace->se_sid = smb_decode_sid(mbc, sid_offs); 539 if (ace->se_sid == NULL) 540 goto decode_error; 541 /* This is SID length plus any paddings between ACEs */ 542 sidlen = ace->se_hdr.se_bsize - 543 (SMB_ACE_HDRSIZE + sizeof (ace->se_mask)); 544 aclbuf.chain_offset += sidlen; 545 sid_offs += sidlen; 546 } 547 548 return (acl); 549 550 decode_error: 551 smb_acl_free(acl); 552 return (NULL); 553 } 554