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 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 25 * Copyright 2017 Joyent, Inc. 26 */ 27 28 #include <smbsrv/smb_door.h> 29 #include <smbsrv/smb_ktypes.h> 30 #include <smbsrv/smb2_kproto.h> 31 #include <smbsrv/smb_kstat.h> 32 33 typedef struct smb_unshare { 34 list_node_t us_lnd; 35 char us_sharename[MAXNAMELEN]; 36 } smb_unshare_t; 37 38 static kmem_cache_t *smb_kshare_cache_share; 39 static kmem_cache_t *smb_kshare_cache_unexport; 40 41 static int smb_kshare_cmp(const void *, const void *); 42 static void smb_kshare_hold(const void *); 43 static boolean_t smb_kshare_rele(const void *); 44 static void smb_kshare_destroy(void *); 45 static char *smb_kshare_oemname(const char *); 46 static int smb_kshare_is_special(const char *); 47 static boolean_t smb_kshare_is_admin(const char *); 48 static smb_kshare_t *smb_kshare_decode(nvlist_t *); 49 static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t); 50 static void smb_kshare_unexport_thread(smb_thread_t *, void *); 51 static int smb_kshare_export(smb_server_t *, smb_kshare_t *); 52 static int smb_kshare_unexport(smb_server_t *, const char *); 53 static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *); 54 static void smb_kshare_csc_flags(smb_kshare_t *, const char *); 55 56 static boolean_t smb_export_isready(smb_server_t *); 57 58 #ifdef _KERNEL 59 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); 60 #endif /* _KERNEL */ 61 62 static const smb_avl_nops_t smb_kshare_avlops = { 63 smb_kshare_cmp, 64 smb_kshare_hold, 65 smb_kshare_rele, 66 smb_kshare_destroy 67 }; 68 69 #ifdef _KERNEL 70 /* 71 * This function is not MultiThread safe. The caller has to make sure only one 72 * thread calls this function. 73 */ 74 door_handle_t 75 smb_kshare_door_init(int door_id) 76 { 77 return (door_ki_lookup(door_id)); 78 } 79 80 /* 81 * This function is not MultiThread safe. The caller has to make sure only one 82 * thread calls this function. 83 */ 84 void 85 smb_kshare_door_fini(door_handle_t dhdl) 86 { 87 if (dhdl) 88 door_ki_rele(dhdl); 89 } 90 91 /* 92 * This is a special interface that will be utilized by ZFS to cause 93 * a share to be added/removed 94 * 95 * arg is either a smb_share_t or share_name from userspace. 96 * It will need to be copied into the kernel. It is smb_share_t 97 * for add operations and share_name for delete operations. 98 */ 99 int 100 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) 101 { 102 door_arg_t doorarg = { 0 }; 103 char *buf = NULL; 104 char *str = NULL; 105 int error; 106 int rc; 107 unsigned int used; 108 smb_dr_ctx_t *dec_ctx; 109 smb_dr_ctx_t *enc_ctx; 110 smb_share_t *lmshare = NULL; 111 int opcode; 112 113 opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE; 114 115 buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP); 116 enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE); 117 smb_dr_put_uint32(enc_ctx, opcode); 118 119 switch (opcode) { 120 case SMB_SHROP_ADD: 121 lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP); 122 error = xcopyin(arg, lmshare, sizeof (smb_share_t)); 123 if (error != 0) { 124 kmem_free(lmshare, sizeof (smb_share_t)); 125 kmem_free(buf, SMB_SHARE_DSIZE); 126 return (error); 127 } 128 smb_dr_put_share(enc_ctx, lmshare); 129 break; 130 131 case SMB_SHROP_DELETE: 132 str = kmem_alloc(MAXPATHLEN, KM_SLEEP); 133 error = copyinstr(arg, str, MAXPATHLEN, NULL); 134 if (error != 0) { 135 kmem_free(str, MAXPATHLEN); 136 kmem_free(buf, SMB_SHARE_DSIZE); 137 return (error); 138 } 139 smb_dr_put_string(enc_ctx, str); 140 kmem_free(str, MAXPATHLEN); 141 break; 142 } 143 144 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 145 kmem_free(buf, SMB_SHARE_DSIZE); 146 if (lmshare) 147 kmem_free(lmshare, sizeof (smb_share_t)); 148 return (NERR_InternalError); 149 } 150 151 doorarg.data_ptr = buf; 152 doorarg.data_size = used; 153 doorarg.rbuf = buf; 154 doorarg.rsize = SMB_SHARE_DSIZE; 155 156 error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0); 157 158 if (error) { 159 kmem_free(buf, SMB_SHARE_DSIZE); 160 if (lmshare) 161 kmem_free(lmshare, sizeof (smb_share_t)); 162 return (error); 163 } 164 165 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); 166 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 167 kmem_free(buf, SMB_SHARE_DSIZE); 168 if (lmshare) 169 kmem_free(lmshare, sizeof (smb_share_t)); 170 return (NERR_InternalError); 171 } 172 173 rc = smb_dr_get_uint32(dec_ctx); 174 if (opcode == SMB_SHROP_ADD) 175 smb_dr_get_share(dec_ctx, lmshare); 176 177 if (smb_dr_decode_finish(dec_ctx)) 178 rc = NERR_InternalError; 179 180 kmem_free(buf, SMB_SHARE_DSIZE); 181 if (lmshare) 182 kmem_free(lmshare, sizeof (smb_share_t)); 183 184 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); 185 } 186 #endif /* _KERNEL */ 187 188 /* 189 * Executes map and unmap command for shares. 190 */ 191 int 192 smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo) 193 { 194 int exec_rc = 0; 195 196 (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC, 197 execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int); 198 199 return (exec_rc); 200 } 201 202 /* 203 * Obtains any host access restriction on the specified 204 * share for the given host (ipaddr) by calling smbd 205 */ 206 uint32_t 207 smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session) 208 { 209 smb_shr_hostaccess_query_t req; 210 smb_inaddr_t *ipaddr = &session->ipaddr; 211 uint32_t host_access = SMB_SHRF_ACC_OPEN; 212 uint32_t flag = SMB_SHRF_ACC_OPEN; 213 uint32_t access; 214 215 if (smb_inet_iszero(ipaddr)) 216 return (ACE_ALL_PERMS); 217 218 if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') && 219 (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') && 220 (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0')) 221 return (ACE_ALL_PERMS); 222 223 if (shr->shr_access_none != NULL) 224 flag |= SMB_SHRF_ACC_NONE; 225 if (shr->shr_access_ro != NULL) 226 flag |= SMB_SHRF_ACC_RO; 227 if (shr->shr_access_rw != NULL) 228 flag |= SMB_SHRF_ACC_RW; 229 230 req.shq_none = shr->shr_access_none; 231 req.shq_ro = shr->shr_access_ro; 232 req.shq_rw = shr->shr_access_rw; 233 req.shq_flag = flag; 234 req.shq_ipaddr = *ipaddr; 235 236 (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS, 237 &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t); 238 239 switch (host_access) { 240 case SMB_SHRF_ACC_RO: 241 access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS; 242 break; 243 case SMB_SHRF_ACC_OPEN: 244 case SMB_SHRF_ACC_RW: 245 access = ACE_ALL_PERMS; 246 break; 247 case SMB_SHRF_ACC_NONE: 248 default: 249 access = 0; 250 } 251 252 return (access); 253 } 254 255 /* 256 * This function is called when smb_server_t is 257 * created which means smb/service is ready for 258 * exporting SMB shares 259 */ 260 void 261 smb_export_start(smb_server_t *sv) 262 { 263 mutex_enter(&sv->sv_export.e_mutex); 264 if (sv->sv_export.e_ready) { 265 mutex_exit(&sv->sv_export.e_mutex); 266 return; 267 } 268 269 sv->sv_export.e_ready = B_TRUE; 270 mutex_exit(&sv->sv_export.e_mutex); 271 272 smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t), 273 offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops); 274 275 (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC"); 276 (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share"); 277 (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS"); 278 } 279 280 /* 281 * This function is called when smb_server_t goes 282 * away which means SMB shares should not be made 283 * available to clients 284 */ 285 void 286 smb_export_stop(smb_server_t *sv) 287 { 288 mutex_enter(&sv->sv_export.e_mutex); 289 if (!sv->sv_export.e_ready) { 290 mutex_exit(&sv->sv_export.e_mutex); 291 return; 292 } 293 sv->sv_export.e_ready = B_FALSE; 294 mutex_exit(&sv->sv_export.e_mutex); 295 296 smb_avl_destroy(&sv->sv_export.e_share_avl); 297 } 298 299 void 300 smb_kshare_g_init(void) 301 { 302 smb_kshare_cache_share = kmem_cache_create("smb_share_cache", 303 sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 304 305 smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache", 306 sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 307 } 308 309 void 310 smb_kshare_init(smb_server_t *sv) 311 { 312 313 smb_slist_constructor(&sv->sv_export.e_unexport_list, 314 sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd)); 315 } 316 317 int 318 smb_kshare_start(smb_server_t *sv) 319 { 320 smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport", 321 smb_kshare_unexport_thread, sv, smbsrv_base_pri); 322 323 return (smb_thread_start(&sv->sv_export.e_unexport_thread)); 324 } 325 326 void 327 smb_kshare_stop(smb_server_t *sv) 328 { 329 smb_thread_stop(&sv->sv_export.e_unexport_thread); 330 smb_thread_destroy(&sv->sv_export.e_unexport_thread); 331 } 332 333 void 334 smb_kshare_fini(smb_server_t *sv) 335 { 336 smb_unshare_t *ux; 337 338 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 339 != NULL) { 340 smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 341 kmem_cache_free(smb_kshare_cache_unexport, ux); 342 } 343 smb_slist_destructor(&sv->sv_export.e_unexport_list); 344 } 345 346 void 347 smb_kshare_g_fini(void) 348 { 349 kmem_cache_destroy(smb_kshare_cache_unexport); 350 kmem_cache_destroy(smb_kshare_cache_share); 351 } 352 353 /* 354 * A list of shares in nvlist format can be sent down 355 * from userspace thourgh the IOCTL interface. The nvlist 356 * is unpacked here and all the shares in the list will 357 * be exported. 358 */ 359 int 360 smb_kshare_export_list(smb_ioc_share_t *ioc) 361 { 362 smb_server_t *sv = NULL; 363 nvlist_t *shrlist = NULL; 364 nvlist_t *share; 365 nvpair_t *nvp; 366 smb_kshare_t *shr; 367 char *shrname; 368 int rc; 369 370 if ((rc = smb_server_lookup(&sv)) != 0) 371 return (rc); 372 373 if (!smb_export_isready(sv)) { 374 rc = ENOTACTIVE; 375 goto out; 376 } 377 378 /* 379 * Reality check that the nvlist's reported length doesn't exceed the 380 * ioctl's total length. We then assume the nvlist_unpack() will 381 * sanity check the nvlist itself. 382 */ 383 if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) { 384 rc = EINVAL; 385 goto out; 386 } 387 rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP); 388 if (rc != 0) 389 goto out; 390 391 for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 392 nvp = nvlist_next_nvpair(shrlist, nvp)) { 393 394 /* 395 * Since this loop can run for a while we want to exit 396 * as soon as the server state is anything but RUNNING 397 * to allow shutdown to proceed. 398 */ 399 if (sv->sv_state != SMB_SERVER_STATE_RUNNING) 400 goto out; 401 402 if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 403 continue; 404 405 shrname = nvpair_name(nvp); 406 ASSERT(shrname); 407 408 if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) { 409 cmn_err(CE_WARN, "export[%s]: failed accessing", 410 shrname); 411 continue; 412 } 413 414 if ((shr = smb_kshare_decode(share)) == NULL) { 415 cmn_err(CE_WARN, "export[%s]: failed decoding", 416 shrname); 417 continue; 418 } 419 420 /* smb_kshare_export consumes shr so it's not leaked */ 421 if ((rc = smb_kshare_export(sv, shr)) != 0) { 422 smb_kshare_destroy(shr); 423 continue; 424 } 425 } 426 rc = 0; 427 428 out: 429 nvlist_free(shrlist); 430 smb_server_release(sv); 431 return (rc); 432 } 433 434 /* 435 * This function is invoked when a share is disabled to disconnect trees 436 * and close files. Cleaning up may involve VOP and/or VFS calls, which 437 * may conflict/deadlock with stuck threads if something is amiss with the 438 * file system. Queueing the request for asynchronous processing allows the 439 * call to return immediately so that, if the unshare is being done in the 440 * context of a forced unmount, the forced unmount will always be able to 441 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 442 * processes to complete). 443 * 444 * The path lookup to find the root vnode of the VFS in question and the 445 * release of this vnode are done synchronously prior to any associated 446 * unmount. Doing these asynchronous to an associated unmount could run 447 * the risk of a spurious EBUSY for a standard unmount or an EIO during 448 * the path lookup due to a forced unmount finishing first. 449 */ 450 int 451 smb_kshare_unexport_list(smb_ioc_share_t *ioc) 452 { 453 smb_server_t *sv = NULL; 454 smb_unshare_t *ux; 455 nvlist_t *shrlist = NULL; 456 nvpair_t *nvp; 457 boolean_t unexport = B_FALSE; 458 char *shrname; 459 int rc; 460 461 if ((rc = smb_server_lookup(&sv)) != 0) 462 return (rc); 463 464 /* 465 * Reality check that the nvlist's reported length doesn't exceed the 466 * ioctl's total length. We then assume the nvlist_unpack() will 467 * sanity check the nvlist itself. 468 */ 469 if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) { 470 rc = EINVAL; 471 goto out; 472 } 473 if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0) 474 goto out; 475 476 for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; 477 nvp = nvlist_next_nvpair(shrlist, nvp)) { 478 if (nvpair_type(nvp) != DATA_TYPE_NVLIST) 479 continue; 480 481 shrname = nvpair_name(nvp); 482 ASSERT(shrname); 483 484 if ((rc = smb_kshare_unexport(sv, shrname)) != 0) 485 continue; 486 487 ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP); 488 (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN); 489 490 smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux); 491 unexport = B_TRUE; 492 } 493 494 if (unexport) 495 smb_thread_signal(&sv->sv_export.e_unexport_thread); 496 rc = 0; 497 498 out: 499 nvlist_free(shrlist); 500 smb_server_release(sv); 501 return (rc); 502 } 503 504 /* 505 * Get properties (currently only shortname enablement) 506 * of specified share. 507 */ 508 int 509 smb_kshare_info(smb_ioc_shareinfo_t *ioc) 510 { 511 ioc->shortnames = smb_shortnames; 512 return (0); 513 } 514 515 /* 516 * This function builds a response for a NetShareEnum RAP request. 517 * List of shares is scanned twice. In the first round the total number 518 * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal) 519 * and also the number of shares that fit in the given buffer are calculated. 520 * In the second round the shares data are encoded in the buffer. 521 * 522 * The data associated with each share has two parts, a fixed size part and 523 * a variable size part which is share's comment. The outline of the response 524 * buffer is so that fixed part for all the shares will appear first and follows 525 * with the comments for all those shares and that's why the data cannot be 526 * encoded in one round without unnecessarily complicating the code. 527 */ 528 void 529 smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi) 530 { 531 smb_avl_t *share_avl; 532 smb_avl_cursor_t cursor; 533 smb_kshare_t *shr; 534 int remained; 535 uint16_t infolen = 0; 536 uint16_t cmntlen = 0; 537 uint16_t sharelen; 538 uint16_t clen; 539 uint32_t cmnt_offs; 540 smb_msgbuf_t info_mb; 541 smb_msgbuf_t cmnt_mb; 542 boolean_t autohome_added = B_FALSE; 543 544 if (!smb_export_isready(sv)) { 545 esi->es_ntotal = esi->es_nsent = 0; 546 esi->es_datasize = 0; 547 return; 548 } 549 550 esi->es_ntotal = esi->es_nsent = 0; 551 remained = esi->es_bufsize; 552 share_avl = &sv->sv_export.e_share_avl; 553 554 /* Do the necessary calculations in the first round */ 555 smb_avl_iterinit(share_avl, &cursor); 556 557 while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 558 if (shr->shr_oemname == NULL) { 559 smb_avl_release(share_avl, shr); 560 continue; 561 } 562 563 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 564 if (esi->es_posix_uid == shr->shr_uid) { 565 autohome_added = B_TRUE; 566 } else { 567 smb_avl_release(share_avl, shr); 568 continue; 569 } 570 } 571 572 esi->es_ntotal++; 573 574 if (remained <= 0) { 575 smb_avl_release(share_avl, shr); 576 continue; 577 } 578 579 clen = strlen(shr->shr_cmnt) + 1; 580 sharelen = SHARE_INFO_1_SIZE + clen; 581 582 if (sharelen <= remained) { 583 infolen += SHARE_INFO_1_SIZE; 584 cmntlen += clen; 585 } 586 587 remained -= sharelen; 588 smb_avl_release(share_avl, shr); 589 } 590 591 esi->es_datasize = infolen + cmntlen; 592 593 smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0); 594 smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0); 595 cmnt_offs = infolen; 596 597 /* Encode the data in the second round */ 598 smb_avl_iterinit(share_avl, &cursor); 599 autohome_added = B_FALSE; 600 601 while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) { 602 if (shr->shr_oemname == NULL) { 603 smb_avl_release(share_avl, shr); 604 continue; 605 } 606 607 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { 608 if (esi->es_posix_uid == shr->shr_uid) { 609 autohome_added = B_TRUE; 610 } else { 611 smb_avl_release(share_avl, shr); 612 continue; 613 } 614 } 615 616 if (smb_msgbuf_encode(&info_mb, "13c.wl", 617 shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) { 618 smb_avl_release(share_avl, shr); 619 break; 620 } 621 622 if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) { 623 smb_avl_release(share_avl, shr); 624 break; 625 } 626 627 cmnt_offs += strlen(shr->shr_cmnt) + 1; 628 esi->es_nsent++; 629 630 smb_avl_release(share_avl, shr); 631 } 632 633 smb_msgbuf_term(&info_mb); 634 smb_msgbuf_term(&cmnt_mb); 635 } 636 637 /* 638 * Looks up the given share and returns a pointer 639 * to its definition if it's found. A hold on the 640 * object is taken before the pointer is returned 641 * in which case the caller MUST always call 642 * smb_kshare_release(). 643 */ 644 smb_kshare_t * 645 smb_kshare_lookup(smb_server_t *sv, const char *shrname) 646 { 647 smb_kshare_t key; 648 smb_kshare_t *shr; 649 650 ASSERT(shrname); 651 652 if (!smb_export_isready(sv)) 653 return (NULL); 654 655 key.shr_name = (char *)shrname; 656 shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key); 657 return (shr); 658 } 659 660 /* 661 * Releases the hold taken on the specified share object 662 */ 663 void 664 smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr) 665 { 666 ASSERT(shr); 667 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 668 669 smb_avl_release(&sv->sv_export.e_share_avl, shr); 670 } 671 672 /* 673 * Add the given share in the specified server. 674 * If the share is a disk share, lookup the share path 675 * and hold the smb_node_t for the share root. 676 * 677 * If the share is an Autohome share and it is 678 * already in the AVL only a reference count for 679 * that share is incremented. 680 */ 681 static int 682 smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr) 683 { 684 smb_avl_t *share_avl; 685 smb_kshare_t *auto_shr; 686 smb_node_t *snode = NULL; 687 int rc = 0; 688 689 share_avl = &sv->sv_export.e_share_avl; 690 691 if (!STYPE_ISDSK(shr->shr_type)) { 692 if ((rc = smb_avl_add(share_avl, shr)) != 0) { 693 cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 694 shr->shr_name, rc); 695 } 696 697 return (rc); 698 } 699 700 if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) { 701 rc = EEXIST; 702 if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 703 mutex_enter(&auto_shr->shr_mutex); 704 auto_shr->shr_autocnt++; 705 mutex_exit(&auto_shr->shr_mutex); 706 rc = 0; 707 } 708 smb_avl_release(share_avl, auto_shr); 709 return (rc); 710 } 711 712 /* 713 * Get the root smb_node_t for this share, held. 714 * This hold is normally released during AVL destroy, 715 * via the element destructor: smb_kshare_destroy 716 */ 717 rc = smb_server_share_lookup(sv, shr->shr_path, &snode); 718 if (rc != 0) { 719 cmn_err(CE_WARN, "export[%s(%s)]: lookup failed (%d)", 720 shr->shr_name, shr->shr_path, rc); 721 return (rc); 722 } 723 724 shr->shr_root_node = snode; 725 if ((rc = smb_avl_add(share_avl, shr)) != 0) { 726 cmn_err(CE_WARN, "export[%s]: failed caching (%d)", 727 shr->shr_name, rc); 728 shr->shr_root_node = NULL; 729 smb_node_release(snode); 730 return (rc); 731 } 732 733 /* 734 * For CA shares, find or create the CA handle dir, 735 * and (if restarted) import persistent handles. 736 */ 737 if ((shr->shr_flags & SMB_SHRF_CA) != 0) { 738 rc = smb2_dh_new_ca_share(sv, shr); 739 if (rc != 0) { 740 /* Just make it a non-CA share. */ 741 mutex_enter(&shr->shr_mutex); 742 shr->shr_flags &= ~SMB_SHRF_CA; 743 mutex_exit(&shr->shr_mutex); 744 rc = 0; 745 } 746 } 747 748 return (rc); 749 } 750 751 /* 752 * Removes the share specified by 'shrname' from the AVL 753 * tree of the given server if it's there. 754 * 755 * If the share is an Autohome share, the autohome count 756 * is decremented and the share is only removed if the 757 * count goes to zero. 758 * 759 * If the share is a disk share, the hold on the corresponding 760 * file system is released before removing the share from 761 * the AVL tree. 762 */ 763 static int 764 smb_kshare_unexport(smb_server_t *sv, const char *shrname) 765 { 766 smb_avl_t *share_avl; 767 smb_kshare_t key; 768 smb_kshare_t *shr; 769 boolean_t auto_unexport; 770 771 share_avl = &sv->sv_export.e_share_avl; 772 773 key.shr_name = (char *)shrname; 774 if ((shr = smb_avl_lookup(share_avl, &key)) == NULL) 775 return (ENOENT); 776 777 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) { 778 mutex_enter(&shr->shr_mutex); 779 shr->shr_autocnt--; 780 auto_unexport = (shr->shr_autocnt == 0); 781 mutex_exit(&shr->shr_mutex); 782 if (!auto_unexport) { 783 smb_avl_release(share_avl, shr); 784 return (0); 785 } 786 } 787 788 smb_avl_remove(share_avl, shr); 789 790 mutex_enter(&shr->shr_mutex); 791 shr->shr_flags |= SMB_SHRF_REMOVED; 792 mutex_exit(&shr->shr_mutex); 793 794 smb_avl_release(share_avl, shr); 795 796 return (0); 797 } 798 799 /* 800 * Exports IPC$ or Admin shares 801 */ 802 static int 803 smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt) 804 { 805 smb_kshare_t *shr; 806 807 ASSERT(name); 808 ASSERT(path); 809 810 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 811 bzero(shr, sizeof (smb_kshare_t)); 812 813 shr->shr_magic = SMB_SHARE_MAGIC; 814 shr->shr_refcnt = 1; 815 shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name); 816 if (strcasecmp(name, "IPC$") == 0) 817 shr->shr_type = STYPE_IPC; 818 else 819 shr->shr_type = STYPE_DISKTREE; 820 821 shr->shr_type |= smb_kshare_is_special(shr->shr_name); 822 823 shr->shr_name = smb_mem_strdup(name); 824 if (path) 825 shr->shr_path = smb_mem_strdup(path); 826 if (cmnt) 827 shr->shr_cmnt = smb_mem_strdup(cmnt); 828 shr->shr_oemname = smb_kshare_oemname(name); 829 830 return (smb_kshare_export(sv, shr)); 831 } 832 833 /* 834 * Decodes share information in an nvlist format into a smb_kshare_t 835 * structure. 836 * 837 * This is a temporary function and will be replaced by functions 838 * provided by libsharev2 code after it's available. 839 */ 840 static smb_kshare_t * 841 smb_kshare_decode(nvlist_t *share) 842 { 843 smb_kshare_t tmp; 844 smb_kshare_t *shr; 845 nvlist_t *smb; 846 char *csc_name = NULL, *strbuf = NULL; 847 int rc; 848 849 ASSERT(share); 850 851 bzero(&tmp, sizeof (smb_kshare_t)); 852 853 rc = nvlist_lookup_string(share, "name", &tmp.shr_name); 854 rc |= nvlist_lookup_string(share, "path", &tmp.shr_path); 855 (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt); 856 857 ASSERT(tmp.shr_name && tmp.shr_path); 858 859 rc |= nvlist_lookup_nvlist(share, "smb", &smb); 860 if (rc != 0) { 861 cmn_err(CE_WARN, "kshare: failed looking up SMB properties" 862 " (%d)", rc); 863 return (NULL); 864 } 865 866 rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type); 867 if (rc != 0) { 868 cmn_err(CE_WARN, "kshare[%s]: failed getting the share type" 869 " (%d)", tmp.shr_name, rc); 870 return (NULL); 871 } 872 873 (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER, 874 &tmp.shr_container); 875 (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none); 876 (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro); 877 (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw); 878 879 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE); 880 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA, 881 SMB_SHRF_CATIA); 882 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST, 883 SMB_SHRF_GUEST_OK); 884 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT, 885 SMB_SHRF_DFSROOT); 886 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS, 887 SMB_SHRF_QUOTAS); 888 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CA, SMB_SHRF_CA); 889 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_FSO, SMB_SHRF_FSO); 890 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME, 891 SMB_SHRF_AUTOHOME); 892 893 if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) { 894 rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid); 895 rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid); 896 if (rc != 0) { 897 cmn_err(CE_WARN, "kshare: failed looking up uid/gid" 898 " (%d)", rc); 899 return (NULL); 900 } 901 } 902 903 (void) nvlist_lookup_string(smb, SHOPT_ENCRYPT, &strbuf); 904 smb_cfg_set_require(strbuf, &tmp.shr_encrypt); 905 906 (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name); 907 smb_kshare_csc_flags(&tmp, csc_name); 908 909 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP); 910 bzero(shr, sizeof (smb_kshare_t)); 911 912 shr->shr_magic = SMB_SHARE_MAGIC; 913 shr->shr_refcnt = 1; 914 915 shr->shr_name = smb_mem_strdup(tmp.shr_name); 916 shr->shr_path = smb_mem_strdup(tmp.shr_path); 917 if (tmp.shr_cmnt) 918 shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt); 919 if (tmp.shr_container) 920 shr->shr_container = smb_mem_strdup(tmp.shr_container); 921 if (tmp.shr_access_none) 922 shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none); 923 if (tmp.shr_access_ro) 924 shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro); 925 if (tmp.shr_access_rw) 926 shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw); 927 928 shr->shr_oemname = smb_kshare_oemname(shr->shr_name); 929 shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name); 930 shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name); 931 shr->shr_encrypt = tmp.shr_encrypt; 932 933 shr->shr_uid = tmp.shr_uid; 934 shr->shr_gid = tmp.shr_gid; 935 936 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) 937 shr->shr_autocnt = 1; 938 939 return (shr); 940 } 941 942 #if 0 943 static void 944 smb_kshare_log(smb_kshare_t *shr) 945 { 946 cmn_err(CE_NOTE, "Share info:"); 947 cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : ""); 948 cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : ""); 949 cmn_err(CE_NOTE, "\tcmnt: (%s)", 950 (shr->shr_cmnt) ? shr->shr_cmnt : "NULL"); 951 cmn_err(CE_NOTE, "\toemname: (%s)", 952 (shr->shr_oemname) ? shr->shr_oemname : "NULL"); 953 cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags); 954 cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type); 955 } 956 #endif 957 958 /* 959 * Compare function used by shares AVL 960 */ 961 static int 962 smb_kshare_cmp(const void *p1, const void *p2) 963 { 964 smb_kshare_t *shr1 = (smb_kshare_t *)p1; 965 smb_kshare_t *shr2 = (smb_kshare_t *)p2; 966 int rc; 967 968 ASSERT(shr1); 969 ASSERT(shr1->shr_name); 970 971 ASSERT(shr2); 972 ASSERT(shr2->shr_name); 973 974 rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0); 975 976 if (rc < 0) 977 return (-1); 978 979 if (rc > 0) 980 return (1); 981 982 return (0); 983 } 984 985 /* 986 * This function is called by smb_avl routines whenever 987 * there is a need to take a hold on a share structure 988 * inside AVL 989 */ 990 static void 991 smb_kshare_hold(const void *p) 992 { 993 smb_kshare_t *shr = (smb_kshare_t *)p; 994 995 ASSERT(shr); 996 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 997 998 mutex_enter(&shr->shr_mutex); 999 shr->shr_refcnt++; 1000 mutex_exit(&shr->shr_mutex); 1001 } 1002 1003 /* 1004 * This function must be called by smb_avl routines whenever 1005 * smb_kshare_hold is called and the hold needs to be released. 1006 */ 1007 static boolean_t 1008 smb_kshare_rele(const void *p) 1009 { 1010 smb_kshare_t *shr = (smb_kshare_t *)p; 1011 boolean_t destroy; 1012 1013 ASSERT(shr); 1014 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 1015 1016 mutex_enter(&shr->shr_mutex); 1017 ASSERT(shr->shr_refcnt > 0); 1018 shr->shr_refcnt--; 1019 destroy = (shr->shr_refcnt == 0); 1020 mutex_exit(&shr->shr_mutex); 1021 1022 return (destroy); 1023 } 1024 1025 /* 1026 * Frees all the memory allocated for the given 1027 * share structure. It also removes the structure 1028 * from the share cache. 1029 */ 1030 static void 1031 smb_kshare_destroy(void *p) 1032 { 1033 smb_kshare_t *shr = (smb_kshare_t *)p; 1034 1035 ASSERT(shr); 1036 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC); 1037 1038 if (shr->shr_ca_dir != NULL) 1039 smb_node_release(shr->shr_ca_dir); 1040 if (shr->shr_root_node) 1041 smb_node_release(shr->shr_root_node); 1042 1043 smb_mem_free(shr->shr_name); 1044 smb_mem_free(shr->shr_path); 1045 smb_mem_free(shr->shr_cmnt); 1046 smb_mem_free(shr->shr_container); 1047 smb_mem_free(shr->shr_oemname); 1048 smb_mem_free(shr->shr_access_none); 1049 smb_mem_free(shr->shr_access_ro); 1050 smb_mem_free(shr->shr_access_rw); 1051 1052 kmem_cache_free(smb_kshare_cache_share, shr); 1053 } 1054 1055 1056 /* 1057 * Generate an OEM name for the given share name. If the name is 1058 * shorter than 13 bytes the oemname will be returned; otherwise NULL 1059 * is returned. 1060 */ 1061 static char * 1062 smb_kshare_oemname(const char *shrname) 1063 { 1064 smb_wchar_t *unibuf; 1065 char *oem_name; 1066 int length; 1067 1068 length = strlen(shrname) + 1; 1069 1070 oem_name = smb_mem_alloc(length); 1071 unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t)); 1072 1073 (void) smb_mbstowcs(unibuf, shrname, length); 1074 1075 if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0) 1076 (void) strcpy(oem_name, shrname); 1077 1078 smb_mem_free(unibuf); 1079 1080 if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) { 1081 smb_mem_free(oem_name); 1082 return (NULL); 1083 } 1084 1085 return (oem_name); 1086 } 1087 1088 /* 1089 * Special share reserved for interprocess communication (IPC$) or 1090 * remote administration of the server (ADMIN$). Can also refer to 1091 * administrative shares such as C$, D$, E$, and so forth. 1092 */ 1093 static int 1094 smb_kshare_is_special(const char *sharename) 1095 { 1096 int len; 1097 1098 if (sharename == NULL) 1099 return (0); 1100 1101 if ((len = strlen(sharename)) == 0) 1102 return (0); 1103 1104 if (sharename[len - 1] == '$') 1105 return (STYPE_SPECIAL); 1106 1107 return (0); 1108 } 1109 1110 /* 1111 * Check whether or not this is a default admin share: C$, D$ etc. 1112 */ 1113 static boolean_t 1114 smb_kshare_is_admin(const char *sharename) 1115 { 1116 if (sharename == NULL) 1117 return (B_FALSE); 1118 1119 if (strlen(sharename) == 2 && 1120 smb_isalpha(sharename[0]) && sharename[1] == '$') { 1121 return (B_TRUE); 1122 } 1123 1124 return (B_FALSE); 1125 } 1126 1127 /* 1128 * Decodes the given boolean share option. 1129 * If the option is present in the nvlist and it's value is true 1130 * returns the corresponding flag value, otherwise returns 0. 1131 */ 1132 static uint32_t 1133 smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag) 1134 { 1135 char *boolp; 1136 1137 if (nvlist_lookup_string(nvl, propname, &boolp) == 0) 1138 if (strcasecmp(boolp, "true") == 0) 1139 return (flag); 1140 1141 return (0); 1142 } 1143 1144 /* 1145 * Map a client-side caching (CSC) option to the appropriate share 1146 * flag. Only one option is allowed; an error will be logged if 1147 * multiple options have been specified. We don't need to do anything 1148 * about multiple values here because the SRVSVC will not recognize 1149 * a value containing multiple flags and will return the default value. 1150 * 1151 * If the option value is not recognized, it will be ignored: invalid 1152 * values will typically be caught and rejected by sharemgr. 1153 */ 1154 static void 1155 smb_kshare_csc_flags(smb_kshare_t *shr, const char *value) 1156 { 1157 int i; 1158 static struct { 1159 char *value; 1160 uint32_t flag; 1161 } cscopt[] = { 1162 { "disabled", SMB_SHRF_CSC_DISABLED }, 1163 { "manual", SMB_SHRF_CSC_MANUAL }, 1164 { "auto", SMB_SHRF_CSC_AUTO }, 1165 { "vdo", SMB_SHRF_CSC_VDO } 1166 }; 1167 1168 if (value == NULL) 1169 return; 1170 1171 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) { 1172 if (strcasecmp(value, cscopt[i].value) == 0) { 1173 shr->shr_flags |= cscopt[i].flag; 1174 break; 1175 } 1176 } 1177 1178 switch (shr->shr_flags & SMB_SHRF_CSC_MASK) { 1179 case 0: 1180 case SMB_SHRF_CSC_DISABLED: 1181 case SMB_SHRF_CSC_MANUAL: 1182 case SMB_SHRF_CSC_AUTO: 1183 case SMB_SHRF_CSC_VDO: 1184 break; 1185 1186 default: 1187 cmn_err(CE_NOTE, "csc option conflict: 0x%08x", 1188 shr->shr_flags & SMB_SHRF_CSC_MASK); 1189 break; 1190 } 1191 } 1192 1193 /* 1194 * This function processes the unexport event list and disconnects shares 1195 * asynchronously. The function executes as a zone-specific thread. 1196 * 1197 * The server arg passed in is safe to use without a reference count, because 1198 * the server cannot be deleted until smb_thread_stop()/destroy() return, 1199 * which is also when the thread exits. 1200 */ 1201 /*ARGSUSED*/ 1202 static void 1203 smb_kshare_unexport_thread(smb_thread_t *thread, void *arg) 1204 { 1205 smb_server_t *sv = arg; 1206 smb_unshare_t *ux; 1207 1208 while (smb_thread_continue(thread)) { 1209 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list)) 1210 != NULL) { 1211 smb_slist_remove(&sv->sv_export.e_unexport_list, ux); 1212 (void) smb_server_unshare(ux->us_sharename); 1213 kmem_cache_free(smb_kshare_cache_unexport, ux); 1214 } 1215 } 1216 } 1217 1218 static boolean_t 1219 smb_export_isready(smb_server_t *sv) 1220 { 1221 boolean_t ready; 1222 1223 mutex_enter(&sv->sv_export.e_mutex); 1224 ready = sv->sv_export.e_ready; 1225 mutex_exit(&sv->sv_export.e_mutex); 1226 1227 return (ready); 1228 } 1229 1230 #ifdef _KERNEL 1231 /* 1232 * Return 0 upon success. Otherwise > 0 1233 */ 1234 static int 1235 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) 1236 { 1237 int status = smb_dr_get_int32(dec_ctx); 1238 int err; 1239 1240 switch (status) { 1241 case SMB_SHARE_DSUCCESS: 1242 return (0); 1243 1244 case SMB_SHARE_DERROR: 1245 err = smb_dr_get_uint32(dec_ctx); 1246 cmn_err(CE_WARN, "%d: Encountered door server error %d", 1247 opcode, err); 1248 (void) smb_dr_decode_finish(dec_ctx); 1249 return (err); 1250 } 1251 1252 ASSERT(0); 1253 return (EINVAL); 1254 } 1255 #endif /* _KERNEL */ 1256