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/smb_kproto.h> 29 #include <smbsrv/ntstatus.h> 30 #include <smbsrv/nterror.h> 31 #include <smbsrv/doserror.h> 32 #include <smbsrv/cifs.h> 33 34 static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t); 35 static void smb_encode_sid(struct smb_xa *, smb_sid_t *); 36 static void smb_encode_sacl(struct smb_xa *, smb_acl_t *); 37 static void smb_encode_dacl(struct smb_xa *, smb_acl_t *); 38 39 uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); 40 static smb_sid_t *smb_decode_sid(struct smb_xa *, uint32_t); 41 static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t); 42 43 /* 44 * smb_nt_transact_query_security_info 45 * 46 * This command allows the client to retrieve the security descriptor 47 * on a file. The result of the call is returned to the client in the 48 * Data part of the transaction response. 49 * 50 * Some clients specify a non-zero maximum data return size (mdrcnt) 51 * for the SD and some specify zero. In either case, if the mdrcnt is 52 * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer 53 * size hint. The client should then retry with the appropriate buffer 54 * size. 55 * 56 * Client Parameter Block Description 57 * ================================== ================================= 58 * 59 * USHORT Fid; FID of target 60 * USHORT Reserved; MBZ 61 * ULONG secinfo; Fields of descriptor to set 62 * 63 * Data Block Encoding Description 64 * ================================== ================================== 65 * 66 * Data[TotalDataCount] Security Descriptor information 67 */ 68 69 smb_sdrc_t 70 smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) 71 { 72 smb_sd_t sd; 73 uint32_t secinfo; 74 uint32_t sdlen; 75 uint32_t status; 76 smb_error_t err; 77 78 if (smb_decode_mbc(&xa->req_param_mb, "w2.l", 79 &sr->smb_fid, &secinfo) != 0) { 80 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 81 return (SDRC_ERROR); 82 } 83 84 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 85 if (sr->fid_ofile == NULL) { 86 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 87 return (SDRC_ERROR); 88 } 89 90 91 if ((sr->fid_ofile->f_node == NULL) || 92 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 93 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 94 ERRDOS, ERROR_ACCESS_DENIED); 95 return (SDRC_ERROR); 96 } 97 98 if (sr->tid_tree->t_acltype != ACE_T) { 99 /* 100 * If target filesystem doesn't support ACE_T acls then 101 * don't process SACL 102 */ 103 secinfo &= ~SMB_SACL_SECINFO; 104 } 105 106 status = smb_sd_read(sr, &sd, secinfo); 107 if (status != NT_STATUS_SUCCESS) { 108 smbsr_error(sr, status, 0, 0); 109 return (SDRC_ERROR); 110 } 111 112 sdlen = smb_sd_len(&sd, secinfo); 113 if (sdlen == 0) { 114 smb_sd_term(&sd); 115 smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0); 116 return (SDRC_ERROR); 117 } 118 119 if (sdlen > xa->smb_mdrcnt) { 120 /* 121 * The maximum data return count specified by the 122 * client is not big enough to hold the security 123 * descriptor. We have to return an error but we 124 * should provide a buffer size hint for the client. 125 */ 126 (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); 127 err.severity = ERROR_SEVERITY_ERROR; 128 err.status = NT_STATUS_BUFFER_TOO_SMALL; 129 err.errcls = ERRDOS; 130 err.errcode = ERROR_INSUFFICIENT_BUFFER; 131 smbsr_set_error(sr, &err); 132 smb_sd_term(&sd); 133 return (SDRC_SUCCESS); 134 } 135 136 smb_encode_sd(xa, &sd, secinfo); 137 (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); 138 smb_sd_term(&sd); 139 return (SDRC_SUCCESS); 140 } 141 142 /* 143 * smb_nt_transact_set_security_info 144 * 145 * This command allows the client to change the security descriptor on a 146 * file. All we do here is decode the parameters and the data. The data 147 * is passed directly to smb_nt_set_security_object, with the security 148 * information describing the information to set. There are no response 149 * parameters or data. 150 * 151 * Client Parameter Block Encoding Description 152 * ================================== ================================== 153 * USHORT Fid; FID of target 154 * USHORT Reserved; MBZ 155 * ULONG SecurityInformation; Fields of SD that to set 156 * 157 * Data Block Encoding Description 158 * ================================== ================================== 159 * Data[TotalDataCount] Security Descriptor information 160 */ 161 smb_sdrc_t 162 smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) 163 { 164 smb_sd_t sd; 165 uint32_t secinfo; 166 uint32_t status; 167 168 if (smb_decode_mbc(&xa->req_param_mb, "w2.l", 169 &sr->smb_fid, &secinfo) != 0) { 170 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 171 return (SDRC_ERROR); 172 } 173 174 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 175 if (sr->fid_ofile == NULL) { 176 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 177 return (SDRC_ERROR); 178 } 179 180 if ((sr->fid_ofile->f_node == NULL) || 181 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 182 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); 183 return (SDRC_ERROR); 184 } 185 186 if (sr->fid_ofile->f_node->flags & NODE_READ_ONLY) { 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_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 += smb_sid_len(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 += smb_sid_len(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, smb_sid_t *sid) 291 { 292 int i; 293 294 (void) smb_encode_mbc(&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_encode_mbc(&xa->rep_data_mb, "b", 299 sid->sid_authority[i]); 300 } 301 302 for (i = 0; i < sid->sid_subauthcnt; i++) { 303 (void) smb_encode_mbc(&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_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 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_decode_mbc(&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_decode_mbc(&sidbuf, "b", &sid->sid_authority[i])) 479 goto decode_err; 480 } 481 482 for (i = 0; i < sid->sid_subauthcnt; i++) { 483 if (smb_decode_mbc(&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_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 = smb_sid_len(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