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 2007 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 int 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 78 79 if (smb_decode_mbc(&xa->req_param_mb, "w2.l", 80 &sr->smb_fid, &secinfo) != 0) { 81 smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); 82 /* NOTREACHED */ 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_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 88 ERRDOS, ERRbadfid); 89 /* NOTREACHED */ 90 } 91 92 93 if ((sr->fid_ofile->f_node == NULL) || 94 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 95 smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, 96 ERRDOS, ERROR_ACCESS_DENIED); 97 /* NOTREACHED */ 98 } 99 100 if (sr->tid_tree->t_acltype != ACE_T) { 101 /* 102 * If target filesystem doesn't support ACE_T acls then 103 * don't process SACL 104 */ 105 secinfo &= ~SMB_SACL_SECINFO; 106 } 107 108 status = smb_sd_read(sr, &sd, secinfo); 109 if (status != NT_STATUS_SUCCESS) { 110 smbsr_raise_nt_error(sr, status); 111 /* NOTREACHED */ 112 } 113 114 sdlen = smb_sd_len(&sd, secinfo); 115 if (sdlen == 0) { 116 smb_sd_term(&sd); 117 smbsr_raise_nt_error(sr, NT_STATUS_INVALID_SECURITY_DESCR); 118 /* NOTREACHED */ 119 } 120 121 if (sdlen > xa->smb_mdrcnt) { 122 /* 123 * The maximum data return count specified by the 124 * client is not big enough to hold the security 125 * descriptor. We have to return an error but we 126 * should provide a buffer size hint for the client. 127 */ 128 (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); 129 smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, 130 NT_STATUS_BUFFER_TOO_SMALL); 131 smb_sd_term(&sd); 132 return (SDRC_NORMAL_REPLY); 133 } 134 135 smb_encode_sd(xa, &sd, secinfo); 136 (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); 137 smb_sd_term(&sd); 138 return (SDRC_NORMAL_REPLY); 139 } 140 141 /* 142 * smb_nt_transact_set_security_info 143 * 144 * This command allows the client to change the security descriptor on a 145 * file. All we do here is decode the parameters and the data. The data 146 * is passed directly to smb_nt_set_security_object, with the security 147 * information describing the information to set. There are no response 148 * parameters or data. 149 * 150 * Client Parameter Block Encoding Description 151 * ================================== ================================== 152 * USHORT Fid; FID of target 153 * USHORT Reserved; MBZ 154 * ULONG SecurityInformation; Fields of SD that to set 155 * 156 * Data Block Encoding Description 157 * ================================== ================================== 158 * Data[TotalDataCount] Security Descriptor information 159 */ 160 int 161 smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) 162 { 163 smb_sd_t sd; 164 uint32_t secinfo; 165 uint32_t status; 166 167 if (smb_decode_mbc(&xa->req_param_mb, "w2.l", 168 &sr->smb_fid, &secinfo) != 0) { 169 smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); 170 /* NOTREACHED */ 171 } 172 173 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 174 if (sr->fid_ofile == NULL) { 175 smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 176 ERRDOS, ERRbadfid); 177 /* NOTREACHED */ 178 } 179 180 if ((sr->fid_ofile->f_node == NULL) || 181 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 182 smbsr_raise_nt_error(sr, NT_STATUS_ACCESS_DENIED); 183 /* NOTREACHED */ 184 } 185 186 if (sr->fid_ofile->f_node->flags & NODE_READ_ONLY) { 187 smbsr_raise_nt_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED); 188 /* NOTREACHED */ 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_raise_nt_error(sr, status); 206 /* NOTREACHED */ 207 } 208 209 if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || 210 ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { 211 smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); 212 /* NOTREACHED */ 213 } 214 215 status = smb_sd_write(sr, &sd, secinfo); 216 smb_sd_term(&sd); 217 if (status != NT_STATUS_SUCCESS) { 218 smbsr_raise_nt_error(sr, status); 219 /* NOTREACHED */ 220 } 221 222 return (SDRC_NORMAL_REPLY); 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_encode_mbc(&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_encode_mbc(&xa->rep_data_mb, "l", offset); 243 offset += nt_sid_length(sd->sd_owner); 244 } else { 245 (void) smb_encode_mbc(&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_encode_mbc(&xa->rep_data_mb, "l", offset); 252 offset += nt_sid_length(sd->sd_group); 253 } else { 254 (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); 255 } 256 257 /* SACL offset */ 258 if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) { 259 (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); 260 offset += smb_acl_len(sd->sd_sacl); 261 } else { 262 (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0); 263 } 264 265 /* DACL offset */ 266 if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl)) 267 (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset); 268 else 269 (void) smb_encode_mbc(&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 static void 290 smb_encode_sid(struct smb_xa *xa, nt_sid_t *sid) 291 { 292 int i; 293 294 (void) smb_encode_mbc(&xa->rep_data_mb, "bb", 295 sid->Revision, sid->SubAuthCount); 296 297 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 298 (void) smb_encode_mbc(&xa->rep_data_mb, "b", 299 sid->Authority[i]); 300 } 301 302 for (i = 0; i < sid->SubAuthCount; i++) { 303 (void) smb_encode_mbc(&xa->rep_data_mb, "l", 304 sid->SubAuthority[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_encode_mbc(&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_encode_mbc(&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_encode_mbc(&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_encode_mbc(&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_decode_mbc(&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 MEM_FREE() 448 */ 449 static nt_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 nt_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 (nt_sid_t)) 463 return (NULL); 464 465 (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left); 466 467 if (smb_decode_mbc(&sidbuf, "bb", &revision, &subauth_cnt)) 468 return (NULL); 469 470 sidlen = sizeof (nt_sid_t) - sizeof (uint32_t) + 471 (subauth_cnt * sizeof (uint32_t)); 472 sid = MEM_MALLOC("smbsrv", sidlen); 473 474 sid->Revision = revision; 475 sid->SubAuthCount = subauth_cnt; 476 477 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 478 if (smb_decode_mbc(&sidbuf, "b", &sid->Authority[i])) 479 goto decode_err; 480 } 481 482 for (i = 0; i < sid->SubAuthCount; i++) { 483 if (smb_decode_mbc(&sidbuf, "l", &sid->SubAuthority[i])) 484 goto decode_err; 485 } 486 487 return (sid); 488 489 decode_err: 490 MEM_FREE("smbsrv", sid); 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_decode_mbc(&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_decode_mbc(&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 sidlen = nt_sid_length(ace->se_sid); 542 aclbuf.chain_offset += sidlen; 543 sid_offs += sidlen; 544 } 545 546 return (acl); 547 548 decode_error: 549 smb_acl_free(acl); 550 return (NULL); 551 } 552