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 2010 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 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 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.severity = ERROR_SEVERITY_ERROR; 120 err.status = NT_STATUS_BUFFER_TOO_SMALL; 121 err.errcls = ERRDOS; 122 err.errcode = ERROR_INSUFFICIENT_BUFFER; 123 smbsr_set_error(sr, &err); 124 smb_sd_term(&sd); 125 return (SDRC_SUCCESS); 126 } 127 128 smb_encode_sd(xa, &sd, secinfo); 129 (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen); 130 smb_sd_term(&sd); 131 return (SDRC_SUCCESS); 132 } 133 134 /* 135 * smb_nt_transact_set_security_info 136 * 137 * This command allows the client to change the security descriptor on a 138 * file. All we do here is decode the parameters and the data. The data 139 * is passed directly to smb_nt_set_security_object, with the security 140 * information describing the information to set. There are no response 141 * parameters or data. 142 * 143 * Client Parameter Block Encoding Description 144 * ================================== ================================== 145 * USHORT Fid; FID of target 146 * USHORT Reserved; MBZ 147 * ULONG SecurityInformation; Fields of SD that to set 148 * 149 * Data Block Encoding Description 150 * ================================== ================================== 151 * Data[TotalDataCount] Security Descriptor information 152 */ 153 smb_sdrc_t 154 smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) 155 { 156 smb_sd_t sd; 157 uint32_t secinfo; 158 uint32_t status; 159 160 if (smb_mbc_decodef(&xa->req_param_mb, "w2.l", 161 &sr->smb_fid, &secinfo) != 0) { 162 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 163 return (SDRC_ERROR); 164 } 165 166 smbsr_lookup_file(sr); 167 if (sr->fid_ofile == NULL) { 168 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 169 return (SDRC_ERROR); 170 } 171 172 if ((sr->fid_ofile->f_node == NULL) || 173 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 174 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); 175 return (SDRC_ERROR); 176 } 177 178 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 179 180 if (SMB_TREE_IS_READONLY(sr)) { 181 smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); 182 return (SDRC_ERROR); 183 } 184 185 if (sr->tid_tree->t_acltype != ACE_T) { 186 /* 187 * If target filesystem doesn't support ACE_T acls then 188 * don't process SACL 189 */ 190 secinfo &= ~SMB_SACL_SECINFO; 191 } 192 193 if ((secinfo & SMB_ALL_SECINFO) == 0) { 194 return (NT_STATUS_SUCCESS); 195 } 196 197 status = smb_decode_sd(xa, &sd); 198 if (status != NT_STATUS_SUCCESS) { 199 smbsr_error(sr, status, 0, 0); 200 return (SDRC_ERROR); 201 } 202 203 if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || 204 ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { 205 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 206 return (SDRC_ERROR); 207 } 208 209 if (!smb_node_is_system(sr->fid_ofile->f_node)) 210 status = smb_sd_write(sr, &sd, secinfo); 211 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 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