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