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 #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_sid(struct smb_xa *, smb_sid_t *); 34 static void smb_encode_sacl(struct smb_xa *, smb_acl_t *); 35 static void smb_encode_dacl(struct smb_xa *, smb_acl_t *); 36 37 uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); 38 static smb_sid_t *smb_decode_sid(struct smb_xa *, uint32_t); 39 static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t); 40 41 /* 42 * smb_nt_transact_query_security_info 43 * 44 * This command allows the client to retrieve the security descriptor 45 * on a file. The result of the call is returned to the client in the 46 * Data part of the transaction response. 47 * 48 * Some clients specify a non-zero maximum data return size (mdrcnt) 49 * for the SD and some specify zero. In either case, if the mdrcnt is 50 * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer 51 * size hint. The client should then retry with the appropriate buffer 52 * size. 53 * 54 * Client Parameter Block Description 55 * ================================== ================================= 56 * 57 * USHORT Fid; FID of target 58 * USHORT Reserved; MBZ 59 * ULONG secinfo; Fields of descriptor to set 60 * 61 * Data Block Encoding Description 62 * ================================== ================================== 63 * 64 * Data[TotalDataCount] Security Descriptor information 65 */ 66 67 smb_sdrc_t 68 smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) 69 { 70 smb_sd_t sd; 71 uint32_t secinfo; 72 uint32_t sdlen; 73 uint32_t status; 74 smb_error_t err; 75 76 if (smb_mbc_decodef(&xa->req_param_mb, "w2.l", 77 &sr->smb_fid, &secinfo) != 0) { 78 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 79 return (SDRC_ERROR); 80 } 81 82 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 83 if (sr->fid_ofile == NULL) { 84 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 85 return (SDRC_ERROR); 86 } 87 88 89 if ((sr->fid_ofile->f_node == NULL) || 90 (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 91 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 92 ERRDOS, ERROR_ACCESS_DENIED); 93 return (SDRC_ERROR); 94 } 95 96 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 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_mbc_encodef(&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_mbc_encodef(&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_mbc_decodef(&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 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 187 188 if (SMB_TREE_IS_READONLY(sr)) { 189 smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); 190 return (SDRC_ERROR); 191 } 192 193 if (sr->tid_tree->t_acltype != ACE_T) { 194 /* 195 * If target filesystem doesn't support ACE_T acls then 196 * don't process SACL 197 */ 198 secinfo &= ~SMB_SACL_SECINFO; 199 } 200 201 if ((secinfo & SMB_ALL_SECINFO) == 0) { 202 return (NT_STATUS_SUCCESS); 203 } 204 205 status = smb_decode_sd(xa, &sd); 206 if (status != NT_STATUS_SUCCESS) { 207 smbsr_error(sr, status, 0, 0); 208 return (SDRC_ERROR); 209 } 210 211 if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || 212 ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { 213 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 214 return (SDRC_ERROR); 215 } 216 217 status = smb_sd_write(sr, &sd, secinfo); 218 smb_sd_term(&sd); 219 if (status != NT_STATUS_SUCCESS) { 220 smbsr_error(sr, status, 0, 0); 221 return (SDRC_ERROR); 222 } 223 224 return (SDRC_SUCCESS); 225 } 226 227 /* 228 * smb_encode_sd 229 * 230 * Encodes given security descriptor in the reply buffer. 231 */ 232 static void 233 smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo) 234 { 235 uint32_t offset = SMB_SD_HDRSIZE; 236 237 /* encode header */ 238 (void) smb_mbc_encodef(&xa->rep_data_mb, "b.w", 239 sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE); 240 241 /* owner offset */ 242 if (secinfo & SMB_OWNER_SECINFO) { 243 ASSERT(sd->sd_owner); 244 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 245 offset += smb_sid_len(sd->sd_owner); 246 } else { 247 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 248 } 249 250 /* group offset */ 251 if (secinfo & SMB_GROUP_SECINFO) { 252 ASSERT(sd->sd_group); 253 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 254 offset += smb_sid_len(sd->sd_group); 255 } else { 256 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 257 } 258 259 /* SACL offset */ 260 if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) { 261 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 262 offset += smb_acl_len(sd->sd_sacl); 263 } else { 264 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 265 } 266 267 /* DACL offset */ 268 if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl)) 269 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 270 else 271 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 272 273 if (secinfo & SMB_OWNER_SECINFO) 274 smb_encode_sid(xa, sd->sd_owner); 275 276 if (secinfo & SMB_GROUP_SECINFO) 277 smb_encode_sid(xa, sd->sd_group); 278 279 if (secinfo & SMB_SACL_SECINFO) 280 smb_encode_sacl(xa, sd->sd_sacl); 281 282 if (secinfo & SMB_DACL_SECINFO) 283 smb_encode_dacl(xa, sd->sd_dacl); 284 } 285 286 /* 287 * smb_encode_sid 288 * 289 * Encodes given SID in the reply buffer. 290 */ 291 static void 292 smb_encode_sid(struct smb_xa *xa, smb_sid_t *sid) 293 { 294 int i; 295 296 (void) smb_mbc_encodef(&xa->rep_data_mb, "bb", 297 sid->sid_revision, sid->sid_subauthcnt); 298 299 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 300 (void) smb_mbc_encodef(&xa->rep_data_mb, "b", 301 sid->sid_authority[i]); 302 } 303 304 for (i = 0; i < sid->sid_subauthcnt; i++) { 305 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 306 sid->sid_subauth[i]); 307 } 308 } 309 310 /* 311 * smb_encode_sacl 312 * 313 * Encodes given SACL in the reply buffer. 314 */ 315 static void 316 smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl) 317 { 318 smb_ace_t *ace; 319 int i; 320 321 if (acl == NULL) 322 return; 323 324 /* encode header */ 325 (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, 326 acl->sl_bsize, acl->sl_acecnt); 327 328 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { 329 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl", 330 ace->se_hdr.se_type, ace->se_hdr.se_flags, 331 ace->se_hdr.se_bsize, ace->se_mask); 332 333 smb_encode_sid(xa, ace->se_sid); 334 } 335 } 336 337 /* 338 * smb_encode_dacl 339 * 340 * Encodes given DACL in the reply buffer. 341 */ 342 static void 343 smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl) 344 { 345 smb_ace_t *ace; 346 347 if (acl == NULL) 348 return; 349 350 /* encode header */ 351 (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, 352 acl->sl_bsize, acl->sl_acecnt); 353 354 ace = list_head(&acl->sl_sorted); 355 while (ace) { 356 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl", 357 ace->se_hdr.se_type, ace->se_hdr.se_flags, 358 ace->se_hdr.se_bsize, ace->se_mask); 359 360 smb_encode_sid(xa, ace->se_sid); 361 ace = list_next(&acl->sl_sorted, ace); 362 } 363 } 364 365 /* 366 * smb_decode_sd 367 * 368 * Decodes the security descriptor in the request buffer 369 * and set the fields of 'sd' appropraitely. Upon successful 370 * return, caller must free allocated memories by calling 371 * smb_sd_term(). 372 */ 373 uint32_t 374 smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd) 375 { 376 struct mbuf_chain sdbuf; 377 uint32_t owner_offs; 378 uint32_t group_offs; 379 uint32_t sacl_offs; 380 uint32_t dacl_offs; 381 382 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 383 384 (void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb, 385 xa->req_data_mb.chain_offset, 386 xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset); 387 388 if (smb_mbc_decodef(&sdbuf, "b.wllll", 389 &sd->sd_revision, &sd->sd_control, 390 &owner_offs, &group_offs, &sacl_offs, &dacl_offs)) 391 goto decode_error; 392 393 sd->sd_control &= ~SE_SELF_RELATIVE; 394 395 if (owner_offs != 0) { 396 if (owner_offs < SMB_SD_HDRSIZE) 397 goto decode_error; 398 399 sd->sd_owner = smb_decode_sid(xa, owner_offs); 400 if (sd->sd_owner == NULL) 401 goto decode_error; 402 } 403 404 if (group_offs != 0) { 405 if (group_offs < SMB_SD_HDRSIZE) 406 goto decode_error; 407 408 sd->sd_group = smb_decode_sid(xa, group_offs); 409 if (sd->sd_group == NULL) 410 goto decode_error; 411 } 412 413 if (sacl_offs != 0) { 414 if ((sd->sd_control & SE_SACL_PRESENT) == 0) 415 goto decode_error; 416 417 if (sacl_offs < SMB_SD_HDRSIZE) 418 goto decode_error; 419 420 sd->sd_sacl = smb_decode_acl(xa, sacl_offs); 421 if (sd->sd_sacl == NULL) 422 goto decode_error; 423 } 424 425 if (dacl_offs != 0) { 426 if ((sd->sd_control & SE_DACL_PRESENT) == 0) 427 goto decode_error; 428 429 if (dacl_offs < SMB_SD_HDRSIZE) 430 goto decode_error; 431 432 sd->sd_dacl = smb_decode_acl(xa, dacl_offs); 433 if (sd->sd_dacl == NULL) 434 goto decode_error; 435 } 436 437 return (NT_STATUS_SUCCESS); 438 439 decode_error: 440 smb_sd_term(sd); 441 return (NT_STATUS_INVALID_SECURITY_DESCR); 442 } 443 444 /* 445 * smb_decode_sid 446 * 447 * Allocates memory and decodes the SID in the request buffer 448 * Upon successful return, caller must free the allocated memory 449 * by calling smb_sid_free() 450 */ 451 static smb_sid_t * 452 smb_decode_sid(struct smb_xa *xa, uint32_t offset) 453 { 454 uint8_t revision; 455 uint8_t subauth_cnt; 456 struct mbuf_chain sidbuf; 457 smb_sid_t *sid; 458 int sidlen; 459 int bytes_left; 460 int i; 461 462 offset += xa->req_data_mb.chain_offset; 463 bytes_left = xa->req_data_mb.max_bytes - offset; 464 if (bytes_left < sizeof (smb_sid_t)) 465 return (NULL); 466 467 (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left); 468 469 if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt)) 470 return (NULL); 471 472 sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) + 473 (subauth_cnt * sizeof (uint32_t)); 474 sid = kmem_alloc(sidlen, KM_SLEEP); 475 476 sid->sid_revision = revision; 477 sid->sid_subauthcnt = subauth_cnt; 478 479 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 480 if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i])) 481 goto decode_err; 482 } 483 484 for (i = 0; i < sid->sid_subauthcnt; i++) { 485 if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i])) 486 goto decode_err; 487 } 488 489 return (sid); 490 491 decode_err: 492 kmem_free(sid, sidlen); 493 return (NULL); 494 } 495 496 /* 497 * smb_decode_acl 498 * 499 * Allocates memory and decodes the ACL in the request buffer 500 * Upon successful return, caller must free the allocated memory 501 * by calling smb_acl_free(). 502 */ 503 static smb_acl_t * 504 smb_decode_acl(struct smb_xa *xa, uint32_t offset) 505 { 506 struct mbuf_chain aclbuf; 507 smb_acl_t *acl; 508 smb_ace_t *ace; 509 uint8_t revision; 510 uint16_t size; 511 uint16_t acecnt; 512 int bytes_left; 513 uint32_t sid_offs = offset; 514 int sidlen; 515 int i; 516 517 offset += xa->req_data_mb.chain_offset; 518 bytes_left = xa->req_data_mb.max_bytes - offset; 519 if (bytes_left < SMB_ACL_HDRSIZE) 520 return (NULL); 521 522 (void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left); 523 524 if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt)) 525 return (NULL); 526 527 if (size == 0) 528 return (NULL); 529 530 acl = smb_acl_alloc(revision, size, acecnt); 531 532 sid_offs += SMB_ACL_HDRSIZE; 533 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { 534 if (smb_mbc_decodef(&aclbuf, "bbwl", 535 &ace->se_hdr.se_type, &ace->se_hdr.se_flags, 536 &ace->se_hdr.se_bsize, &ace->se_mask)) 537 goto decode_error; 538 539 sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask); 540 ace->se_sid = smb_decode_sid(xa, sid_offs); 541 if (ace->se_sid == NULL) 542 goto decode_error; 543 /* This is SID length plus any paddings between ACEs */ 544 sidlen = ace->se_hdr.se_bsize - 545 (SMB_ACE_HDRSIZE + sizeof (ace->se_mask)); 546 aclbuf.chain_offset += sidlen; 547 sid_offs += sidlen; 548 } 549 550 return (acl); 551 552 decode_error: 553 smb_acl_free(acl); 554 return (NULL); 555 } 556