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