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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * SMB specific functions 31 */ 32 #include <stdio.h> 33 #include <string.h> 34 #include <ctype.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <zone.h> 38 #include <errno.h> 39 #include <locale.h> 40 #include <fcntl.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <syslog.h> 44 #include "libshare.h" 45 #include "libshare_impl.h" 46 #include <pwd.h> 47 #include <limits.h> 48 #include <libscf.h> 49 #include <strings.h> 50 #include "libshare_smb.h" 51 #include <rpcsvc/daemon_utils.h> 52 #include <smbsrv/smb_share.h> 53 #include <smbsrv/smbinfo.h> 54 #include <smbsrv/libsmb.h> 55 56 /* internal functions */ 57 static int smb_share_init(void); 58 static void smb_share_fini(void); 59 static int smb_enable_share(sa_share_t); 60 static int smb_share_changed(sa_share_t); 61 static int smb_resource_changed(sa_resource_t); 62 static int smb_rename_resource(sa_handle_t, sa_resource_t, char *); 63 static int smb_disable_share(sa_share_t share, char *); 64 static int smb_validate_property(sa_handle_t, sa_property_t, sa_optionset_t); 65 static int smb_set_proto_prop(sa_property_t); 66 static sa_protocol_properties_t smb_get_proto_set(void); 67 static char *smb_get_status(void); 68 static int smb_parse_optstring(sa_group_t, char *); 69 static char *smb_format_options(sa_group_t, int); 70 71 static int smb_enable_service(void); 72 73 static int range_check_validator(int, char *); 74 static int range_check_validator_zero_ok(int, char *); 75 static int string_length_check_validator(int, char *); 76 static int true_false_validator(int, char *); 77 static int ip_address_validator_empty_ok(int, char *); 78 static int ip_address_csv_list_validator_empty_ok(int, char *); 79 static int path_validator(int, char *); 80 81 static int smb_enable_resource(sa_resource_t); 82 static int smb_disable_resource(sa_resource_t); 83 static uint64_t smb_share_features(void); 84 static int smb_list_transient(sa_handle_t); 85 86 /* size of basic format allocation */ 87 #define OPT_CHUNK 1024 88 89 /* size of string for types - big enough to hold "dependency" */ 90 #define SCFTYPE_LEN 32 91 92 /* 93 * Indexes of entries in smb_proto_options table. 94 * Changes to smb_proto_options table may require 95 * an update to these values. 96 */ 97 #define PROTO_OPT_WINS1 6 98 #define PROTO_OPT_WINS_EXCLUDE 8 99 100 101 /* 102 * ops vector that provides the protocol specific info and operations 103 * for share management. 104 */ 105 106 struct sa_plugin_ops sa_plugin_ops = { 107 SA_PLUGIN_VERSION, 108 SMB_PROTOCOL_NAME, 109 smb_share_init, 110 smb_share_fini, 111 smb_enable_share, 112 smb_disable_share, 113 smb_validate_property, 114 NULL, /* valid_space */ 115 NULL, /* security_prop */ 116 smb_parse_optstring, 117 smb_format_options, 118 smb_set_proto_prop, 119 smb_get_proto_set, 120 smb_get_status, 121 NULL, /* space_alias */ 122 NULL, /* update_legacy */ 123 NULL, /* delete_legacy */ 124 smb_share_changed, 125 smb_enable_resource, 126 smb_disable_resource, 127 smb_share_features, 128 smb_list_transient, 129 smb_resource_changed, 130 smb_rename_resource, 131 NULL, /* run_command */ 132 NULL, /* command_help */ 133 NULL /* delete_proto_section */ 134 }; 135 136 /* 137 * option definitions. Make sure to keep the #define for the option 138 * index just before the entry it is the index for. Changing the order 139 * can cause breakage. 140 */ 141 142 struct option_defs optdefs[] = { 143 {SMB_SHROPT_AD_CONTAINER, OPT_TYPE_STRING}, 144 {SMB_SHROPT_NAME, OPT_TYPE_NAME}, 145 {NULL, NULL}, 146 }; 147 148 /* 149 * findopt(name) 150 * 151 * Lookup option "name" in the option table and return the table 152 * index. 153 */ 154 155 static int 156 findopt(char *name) 157 { 158 int i; 159 if (name != NULL) { 160 for (i = 0; optdefs[i].tag != NULL; i++) { 161 if (strcmp(optdefs[i].tag, name) == 0) 162 return (i); 163 } 164 } 165 return (-1); 166 } 167 168 /* 169 * is_a_number(number) 170 * 171 * is the string a number in one of the forms we want to use? 172 */ 173 174 static int 175 is_a_number(char *number) 176 { 177 int ret = 1; 178 int hex = 0; 179 180 if (strncmp(number, "0x", 2) == 0) { 181 number += 2; 182 hex = 1; 183 } else if (*number == '-') { 184 number++; /* skip the minus */ 185 } 186 187 while (ret == 1 && *number != '\0') { 188 if (hex) { 189 ret = isxdigit(*number++); 190 } else { 191 ret = isdigit(*number++); 192 } 193 } 194 return (ret); 195 } 196 197 /* 198 * validresource(name) 199 * 200 * Check that name only has valid characters in it. The current valid 201 * set are the printable characters but not including: 202 * " / \ [ ] : | < > + ; , ? * = \t 203 * Note that space is included and there is a maximum length. 204 */ 205 static int 206 validresource(const char *name) 207 { 208 const char *cp; 209 size_t len; 210 211 if (name == NULL) 212 return (B_FALSE); 213 214 len = strlen(name); 215 if (len == 0 || len > SA_MAX_RESOURCE_NAME) 216 return (B_FALSE); 217 218 if (strpbrk(name, "\"/\\[]:|<>+;,?*=\t") != NULL) { 219 return (B_FALSE); 220 } 221 222 for (cp = name; *cp != '\0'; cp++) 223 if (iscntrl(*cp)) 224 return (B_FALSE); 225 226 return (B_TRUE); 227 } 228 229 /* 230 * smb_isonline() 231 * 232 * Determine if the SMF service instance is in the online state or 233 * not. A number of operations depend on this state. 234 */ 235 static boolean_t 236 smb_isonline(void) 237 { 238 char *str; 239 boolean_t ret = B_FALSE; 240 241 if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { 242 ret = (strcmp(str, SCF_STATE_STRING_ONLINE) == 0); 243 free(str); 244 } 245 return (ret); 246 } 247 248 /* 249 * smb_isdisabled() 250 * 251 * Determine if the SMF service instance is in the disabled state or 252 * not. A number of operations depend on this state. 253 */ 254 static boolean_t 255 smb_isdisabled(void) 256 { 257 char *str; 258 boolean_t ret = B_FALSE; 259 260 if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { 261 ret = (strcmp(str, SCF_STATE_STRING_DISABLED) == 0); 262 free(str); 263 } 264 return (ret); 265 } 266 267 /* 268 * smb_isautoenable() 269 * 270 * Determine if the SMF service instance auto_enabled set or not. A 271 * number of operations depend on this state. The property not being 272 * set or being set to true means autoenable. Only being set to false 273 * is not autoenabled. 274 */ 275 static boolean_t 276 smb_isautoenable(void) 277 { 278 boolean_t ret = B_TRUE; 279 scf_simple_prop_t *prop; 280 uint8_t *retstr; 281 282 prop = scf_simple_prop_get(NULL, SMBD_DEFAULT_INSTANCE_FMRI, 283 "application", "auto_enable"); 284 if (prop != NULL) { 285 retstr = scf_simple_prop_next_boolean(prop); 286 ret = *retstr != 0; 287 scf_simple_prop_free(prop); 288 } 289 return (ret); 290 } 291 292 /* 293 * smb_ismaint() 294 * 295 * Determine if the SMF service instance is in the disabled state or 296 * not. A number of operations depend on this state. 297 */ 298 static boolean_t 299 smb_ismaint(void) 300 { 301 char *str; 302 boolean_t ret = B_FALSE; 303 304 if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { 305 ret = (strcmp(str, SCF_STATE_STRING_MAINT) == 0); 306 free(str); 307 } 308 return (ret); 309 } 310 311 /* 312 * smb_enable_share tells the implementation that it is to enable the share. 313 * This entails converting the path and options into the appropriate ioctl 314 * calls. It is assumed that all error checking of paths, etc. were 315 * done earlier. 316 */ 317 static int 318 smb_enable_share(sa_share_t share) 319 { 320 char *path; 321 char *rname; 322 smb_share_t si; 323 sa_resource_t resource; 324 boolean_t iszfs; 325 boolean_t privileged; 326 int err = SA_OK; 327 priv_set_t *priv_effective; 328 boolean_t online; 329 330 /* 331 * We only start in the global zone and only run if we aren't 332 * running Trusted Extensions. 333 */ 334 if (getzoneid() != GLOBAL_ZONEID) { 335 (void) printf(dgettext(TEXT_DOMAIN, 336 "SMB: service not supported in local zone\n")); 337 return (SA_NOT_SUPPORTED); 338 } 339 if (is_system_labeled()) { 340 (void) printf(dgettext(TEXT_DOMAIN, 341 "SMB: service not supported with Trusted Extensions\n")); 342 return (SA_NOT_SUPPORTED); 343 } 344 345 priv_effective = priv_allocset(); 346 (void) getppriv(PRIV_EFFECTIVE, priv_effective); 347 privileged = (priv_isfullset(priv_effective) == B_TRUE); 348 priv_freeset(priv_effective); 349 350 /* get the path since it is important in several places */ 351 path = sa_get_share_attr(share, "path"); 352 if (path == NULL) 353 return (SA_NO_SUCH_PATH); 354 355 /* 356 * If administratively disabled, don't try to start anything. 357 */ 358 online = smb_isonline(); 359 if (!online && !smb_isautoenable() && smb_isdisabled()) 360 goto done; 361 362 iszfs = sa_path_is_zfs(path); 363 364 if (iszfs) { 365 366 if (privileged == B_FALSE && !online) { 367 368 if (!online) { 369 (void) printf(dgettext(TEXT_DOMAIN, 370 "SMB: Cannot share remove " 371 "file system: %s\n"), path); 372 (void) printf(dgettext(TEXT_DOMAIN, 373 "SMB: Service needs to be enabled " 374 "by a privileged user\n")); 375 err = SA_NO_PERMISSION; 376 errno = EPERM; 377 } 378 if (err) { 379 sa_free_attr_string(path); 380 return (err); 381 } 382 383 } 384 } 385 386 if (privileged == B_TRUE && !online) { 387 err = smb_enable_service(); 388 if (err != SA_OK) { 389 (void) printf(dgettext(TEXT_DOMAIN, 390 "SMB: Unable to enable service\n")); 391 /* 392 * For now, it is OK to not be able to enable 393 * the service. 394 */ 395 if (err == SA_BUSY || err == SA_SYSTEM_ERR) 396 err = SA_OK; 397 } else { 398 online = B_TRUE; 399 } 400 } 401 402 /* 403 * Don't bother trying to start shares if the service isn't 404 * running. 405 */ 406 if (!online) 407 goto done; 408 409 /* Each share can have multiple resources */ 410 for (resource = sa_get_share_resource(share, NULL); 411 resource != NULL; 412 resource = sa_get_next_resource(resource)) { 413 bzero(&si, sizeof (smb_share_t)); 414 rname = sa_get_resource_attr(resource, "name"); 415 if (rname == NULL) { 416 sa_free_attr_string(path); 417 return (SA_NO_SUCH_RESOURCE); 418 } 419 420 smb_build_lmshare_info(rname, path, resource, &si); 421 sa_free_attr_string(rname); 422 423 if (!iszfs) { 424 err = smb_share_add(&si); 425 } else { 426 share_t sh; 427 428 sa_sharetab_fill_zfs(share, &sh, "smb"); 429 err = sa_share_zfs(share, (char *)path, &sh, 430 &si, ZFS_SHARE_SMB); 431 432 sa_emptyshare(&sh); 433 } 434 } 435 if (!iszfs) 436 (void) sa_update_sharetab(share, "smb"); 437 done: 438 sa_free_attr_string(path); 439 440 return (err == NERR_DuplicateShare ? 0 : err); 441 } 442 443 /* 444 * This is the share for CIFS all shares have resource names. 445 * Enable tells the smb server to update its hash. If it fails 446 * because smb server is down, we just ignore as smb server loads 447 * the resources from sharemanager at startup. 448 */ 449 450 static int 451 smb_enable_resource(sa_resource_t resource) 452 { 453 char *path; 454 char *rname; 455 sa_share_t share; 456 smb_share_t si; 457 int ret = SA_OK; 458 int err; 459 boolean_t isonline; 460 461 share = sa_get_resource_parent(resource); 462 if (share == NULL) 463 return (SA_NO_SUCH_PATH); 464 465 /* 466 * If administratively disabled, don't try to start anything. 467 */ 468 isonline = smb_isonline(); 469 if (!isonline && !smb_isautoenable() && smb_isdisabled()) 470 goto done; 471 472 if (!isonline) 473 ret = smb_enable_service(); 474 if (!smb_isonline()) { 475 ret = SA_OK; 476 goto done; 477 } 478 479 path = sa_get_share_attr(share, "path"); 480 if (path == NULL) 481 return (SA_SYSTEM_ERR); 482 rname = sa_get_resource_attr(resource, "name"); 483 if (rname == NULL) { 484 sa_free_attr_string(path); 485 return (SA_NO_SUCH_RESOURCE); 486 } 487 488 smb_build_lmshare_info(rname, path, resource, &si); 489 sa_free_attr_string(path); 490 sa_free_attr_string(rname); 491 492 /* 493 * Attempt to add the share. Any error that occurs if it was 494 * online is an error but don't count NERR_DuplicateName if 495 * smb/server had to be brought online since bringing the 496 * service up will enable the share that was just added prior 497 * to the attempt to enable. 498 */ 499 500 err = smb_share_add(&si); 501 if (err == NERR_Success || !(!isonline && err == NERR_DuplicateName)) 502 (void) sa_update_sharetab(share, "smb"); 503 else 504 return (SA_NOT_SHARED); 505 506 done: 507 return (ret); 508 } 509 510 /* 511 * Remove it from smb server hash. 512 */ 513 static int 514 smb_disable_resource(sa_resource_t resource) 515 { 516 char *rname; 517 uint32_t res; 518 sa_share_t share; 519 520 rname = sa_get_resource_attr(resource, "name"); 521 if (rname == NULL) 522 return (SA_NO_SUCH_RESOURCE); 523 524 if (smb_isonline()) { 525 res = smb_share_del(rname); 526 if (res != NERR_Success) { 527 sa_free_attr_string(rname); 528 return (SA_CONFIG_ERR); 529 } 530 } 531 532 sa_free_attr_string(rname); 533 534 share = sa_get_resource_parent(resource); 535 if (share != NULL) { 536 rname = sa_get_share_attr(share, "path"); 537 if (rname != NULL) { 538 sa_handle_t handle; 539 540 handle = sa_find_group_handle((sa_group_t)resource); 541 (void) sa_delete_sharetab(handle, rname, "smb"); 542 sa_free_attr_string(rname); 543 } 544 } 545 /* 546 * Always return OK as smb/server may be down and 547 * Shares will be picked up when loaded. 548 */ 549 return (SA_OK); 550 } 551 552 /* 553 * smb_share_changed(sa_share_t share) 554 * 555 * The specified share has changed. 556 */ 557 static int 558 smb_share_changed(sa_share_t share) 559 { 560 char *path; 561 sa_resource_t resource; 562 563 /* get the path since it is important in several places */ 564 path = sa_get_share_attr(share, "path"); 565 if (path == NULL) 566 return (SA_NO_SUCH_PATH); 567 for (resource = sa_get_share_resource(share, NULL); 568 resource != NULL; 569 resource = sa_get_next_resource(resource)) 570 (void) smb_resource_changed(resource); 571 572 sa_free_attr_string(path); 573 574 return (SA_OK); 575 } 576 577 /* 578 * smb_resource_changed(sa_resource_t resource) 579 * 580 * The specified resource has changed. 581 */ 582 static int 583 smb_resource_changed(sa_resource_t resource) 584 { 585 uint32_t res; 586 smb_share_t si; 587 smb_share_t new_si; 588 char *rname, *path; 589 sa_share_t share; 590 591 rname = sa_get_resource_attr(resource, "name"); 592 if (rname == NULL) 593 return (SA_NO_SUCH_RESOURCE); 594 595 share = sa_get_resource_parent(resource); 596 if (share == NULL) { 597 sa_free_attr_string(rname); 598 return (SA_CONFIG_ERR); 599 } 600 601 path = sa_get_share_attr(share, "path"); 602 if (path == NULL) { 603 sa_free_attr_string(rname); 604 return (SA_NO_SUCH_PATH); 605 } 606 607 if (!smb_isonline()) { 608 sa_free_attr_string(rname); 609 return (SA_OK); 610 } 611 612 /* Update the share cache in smb/server */ 613 res = smb_share_get(rname, &si); 614 if (res != NERR_Success) { 615 sa_free_attr_string(path); 616 sa_free_attr_string(rname); 617 return (SA_CONFIG_ERR); 618 } 619 620 smb_build_lmshare_info(rname, path, resource, &new_si); 621 sa_free_attr_string(path); 622 sa_free_attr_string(rname); 623 624 /* 625 * Update all fields from sa_share_t 626 * Get derived values. 627 */ 628 if (smb_share_set(&new_si) != SMB_SHARE_DSUCCESS) 629 return (SA_CONFIG_ERR); 630 return (smb_enable_service()); 631 } 632 633 /* 634 * smb_disable_share(sa_share_t share, char *path) 635 * 636 * Unshare the specified share. Note that "path" is the same 637 * path as what is in the "share" object. It is passed in to avoid an 638 * additional lookup. A missing "path" value makes this a no-op 639 * function. 640 */ 641 static int 642 smb_disable_share(sa_share_t share, char *path) 643 { 644 char *rname; 645 sa_resource_t resource; 646 sa_group_t parent; 647 boolean_t iszfs; 648 int err = SA_OK; 649 sa_handle_t handle; 650 651 if (path == NULL) 652 return (err); 653 654 /* 655 * If the share is in a ZFS group we need to handle it 656 * differently. Just being on a ZFS file system isn't 657 * enough since we may be in a legacy share case. 658 */ 659 parent = sa_get_parent_group(share); 660 iszfs = sa_group_is_zfs(parent); 661 662 if (!smb_isonline()) 663 goto done; 664 665 for (resource = sa_get_share_resource(share, NULL); 666 resource != NULL; 667 resource = sa_get_next_resource(resource)) { 668 rname = sa_get_resource_attr(resource, "name"); 669 if (rname == NULL) { 670 continue; 671 } 672 if (!iszfs) { 673 err = smb_share_del(rname); 674 switch (err) { 675 case NERR_NetNameNotFound: 676 case NERR_Success: 677 err = SA_OK; 678 break; 679 default: 680 err = SA_CONFIG_ERR; 681 break; 682 } 683 } else { 684 share_t sh; 685 686 sa_sharetab_fill_zfs(share, &sh, "smb"); 687 err = sa_share_zfs(share, (char *)path, &sh, 688 rname, ZFS_UNSHARE_SMB); 689 sa_emptyshare(&sh); 690 } 691 sa_free_attr_string(rname); 692 } 693 done: 694 if (!iszfs) { 695 handle = sa_find_group_handle((sa_group_t)share); 696 if (handle != NULL) 697 (void) sa_delete_sharetab(handle, path, "smb"); 698 else 699 err = SA_SYSTEM_ERR; 700 } 701 return (err); 702 } 703 704 /* 705 * smb_validate_property(handle, property, parent) 706 * 707 * Check that the property has a legitimate value for its type. 708 * Handle isn't currently used but may need to be in the future. 709 */ 710 711 /*ARGSUSED*/ 712 static int 713 smb_validate_property(sa_handle_t handle, sa_property_t property, 714 sa_optionset_t parent) 715 { 716 int ret = SA_OK; 717 char *propname; 718 int optindex; 719 sa_group_t parent_group; 720 char *value; 721 722 propname = sa_get_property_attr(property, "type"); 723 724 if ((optindex = findopt(propname)) < 0) 725 ret = SA_NO_SUCH_PROP; 726 727 /* need to validate value range here as well */ 728 if (ret == SA_OK) { 729 parent_group = sa_get_parent_group((sa_share_t)parent); 730 if (optdefs[optindex].share && !sa_is_share(parent_group)) 731 ret = SA_PROP_SHARE_ONLY; 732 } 733 if (ret != SA_OK) { 734 if (propname != NULL) 735 sa_free_attr_string(propname); 736 return (ret); 737 } 738 739 value = sa_get_property_attr(property, "value"); 740 if (value != NULL) { 741 /* first basic type checking */ 742 switch (optdefs[optindex].type) { 743 case OPT_TYPE_NUMBER: 744 /* check that the value is all digits */ 745 if (!is_a_number(value)) 746 ret = SA_BAD_VALUE; 747 break; 748 case OPT_TYPE_BOOLEAN: 749 if (strlen(value) == 0 || 750 strcasecmp(value, "true") == 0 || 751 strcmp(value, "1") == 0 || 752 strcasecmp(value, "false") == 0 || 753 strcmp(value, "0") == 0) { 754 ret = SA_OK; 755 } else { 756 ret = SA_BAD_VALUE; 757 } 758 break; 759 case OPT_TYPE_NAME: 760 /* 761 * Make sure no invalid characters 762 */ 763 if (validresource(value) == B_FALSE) 764 ret = SA_BAD_VALUE; 765 break; 766 case OPT_TYPE_STRING: 767 /* whatever is here should be ok */ 768 break; 769 default: 770 break; 771 } 772 } 773 774 if (value != NULL) 775 sa_free_attr_string(value); 776 if (ret == SA_OK && optdefs[optindex].check != NULL) 777 /* do the property specific check */ 778 ret = optdefs[optindex].check(property); 779 780 if (propname != NULL) 781 sa_free_attr_string(propname); 782 return (ret); 783 } 784 785 /* 786 * Protocol management functions 787 * 788 * properties defined in the default files are defined in 789 * proto_option_defs for parsing and validation. 790 */ 791 792 struct smb_proto_option_defs { 793 int smb_index; 794 int32_t minval; 795 int32_t maxval; /* In case of length of string this should be max */ 796 int (*validator)(int, char *); 797 int32_t refresh; 798 } smb_proto_options[] = { 799 { SMB_CI_SYS_CMNT, 0, MAX_VALUE_BUFLEN, 800 string_length_check_validator, SMB_REFRESH_REFRESH }, 801 { SMB_CI_MAX_WORKERS, 64, 1024, range_check_validator, 802 SMB_REFRESH_REFRESH }, 803 { SMB_CI_NBSCOPE, 0, MAX_VALUE_BUFLEN, 804 string_length_check_validator, 0 }, 805 { SMB_CI_LM_LEVEL, 2, 5, range_check_validator, 0 }, 806 { SMB_CI_KEEPALIVE, 20, 5400, range_check_validator_zero_ok, 807 SMB_REFRESH_REFRESH }, 808 { SMB_CI_WINS_SRV1, 0, MAX_VALUE_BUFLEN, 809 ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, 810 { SMB_CI_WINS_SRV2, 0, MAX_VALUE_BUFLEN, 811 ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, 812 { SMB_CI_WINS_EXCL, 0, MAX_VALUE_BUFLEN, 813 ip_address_csv_list_validator_empty_ok, SMB_REFRESH_REFRESH }, 814 { SMB_CI_SIGNING_ENABLE, 0, 0, true_false_validator, 815 SMB_REFRESH_REFRESH }, 816 { SMB_CI_SIGNING_REQD, 0, 0, true_false_validator, 817 SMB_REFRESH_REFRESH }, 818 { SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator, 819 SMB_REFRESH_REFRESH }, 820 { SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN, 821 ip_address_validator_empty_ok, 0 }, 822 { SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN, 823 string_length_check_validator, SMB_REFRESH_REFRESH }, 824 { SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, 0 }, 825 { SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, path_validator, 0 }, 826 }; 827 828 #define SMB_OPT_NUM \ 829 (sizeof (smb_proto_options) / sizeof (smb_proto_options[0])) 830 831 /* 832 * Check the range of value as int range. 833 */ 834 static int 835 range_check_validator(int index, char *value) 836 { 837 int ret = SA_OK; 838 839 if (!is_a_number(value)) { 840 ret = SA_BAD_VALUE; 841 } else { 842 int val; 843 val = strtoul(value, NULL, 0); 844 if (val < smb_proto_options[index].minval || 845 val > smb_proto_options[index].maxval) 846 ret = SA_BAD_VALUE; 847 } 848 return (ret); 849 } 850 851 /* 852 * Check the range of value as int range. 853 */ 854 static int 855 range_check_validator_zero_ok(int index, char *value) 856 { 857 int ret = SA_OK; 858 859 if (!is_a_number(value)) { 860 ret = SA_BAD_VALUE; 861 } else { 862 int val; 863 val = strtoul(value, NULL, 0); 864 if (val == 0) 865 ret = SA_OK; 866 else { 867 if (val < smb_proto_options[index].minval || 868 val > smb_proto_options[index].maxval) 869 ret = SA_BAD_VALUE; 870 } 871 } 872 return (ret); 873 } 874 875 /* 876 * Check the length of the string 877 */ 878 static int 879 string_length_check_validator(int index, char *value) 880 { 881 int ret = SA_OK; 882 883 if (value == NULL) 884 return (SA_BAD_VALUE); 885 if (strlen(value) > smb_proto_options[index].maxval) 886 ret = SA_BAD_VALUE; 887 return (ret); 888 } 889 890 /* 891 * Check yes/no 892 */ 893 /*ARGSUSED*/ 894 static int 895 true_false_validator(int index, char *value) 896 { 897 if (value == NULL) 898 return (SA_BAD_VALUE); 899 if ((strcasecmp(value, "true") == 0) || 900 (strcasecmp(value, "false") == 0)) 901 return (SA_OK); 902 return (SA_BAD_VALUE); 903 } 904 905 /* 906 * Check IP address. 907 */ 908 /*ARGSUSED*/ 909 static int 910 ip_address_validator_empty_ok(int index, char *value) 911 { 912 char sbytes[16]; 913 int len; 914 915 if (value == NULL) 916 return (SA_OK); 917 len = strlen(value); 918 if (len == 0) 919 return (SA_OK); 920 if (inet_pton(AF_INET, value, (void *)sbytes) != 1) 921 return (SA_BAD_VALUE); 922 923 return (SA_OK); 924 } 925 926 /* 927 * Check IP address list 928 */ 929 /*ARGSUSED*/ 930 static int 931 ip_address_csv_list_validator_empty_ok(int index, char *value) 932 { 933 char sbytes[16]; 934 char *ip, *tmp, *ctx; 935 936 if (value == NULL || *value == '\0') 937 return (SA_OK); 938 939 if (strlen(value) > MAX_VALUE_BUFLEN) 940 return (SA_BAD_VALUE); 941 942 if ((tmp = strdup(value)) == NULL) 943 return (SA_NO_MEMORY); 944 945 ip = strtok_r(tmp, ",", &ctx); 946 while (ip) { 947 if (strlen(ip) == 0) { 948 free(tmp); 949 return (SA_BAD_VALUE); 950 } 951 if (*ip != 0) { 952 if (inet_pton(AF_INET, ip, 953 (void *)sbytes) != 1) { 954 free(tmp); 955 return (SA_BAD_VALUE); 956 } 957 } 958 ip = strtok_r(0, ",", &ctx); 959 } 960 961 free(tmp); 962 return (SA_OK); 963 } 964 965 /* 966 * Check path 967 */ 968 /*ARGSUSED*/ 969 static int 970 path_validator(int index, char *value) 971 { 972 struct stat buffer; 973 int fd, status; 974 975 if (value == NULL) 976 return (SA_BAD_VALUE); 977 978 fd = open(value, O_RDONLY); 979 if (fd < 0) 980 return (SA_BAD_VALUE); 981 982 status = fstat(fd, &buffer); 983 (void) close(fd); 984 985 if (status < 0) 986 return (SA_BAD_VALUE); 987 988 if (buffer.st_mode & S_IFDIR) 989 return (SA_OK); 990 return (SA_BAD_VALUE); 991 } 992 993 /* 994 * the protoset holds the defined options so we don't have to read 995 * them multiple times 996 */ 997 static sa_protocol_properties_t protoset; 998 999 static int 1000 findprotoopt(char *name) 1001 { 1002 int i; 1003 char *sc_name; 1004 1005 for (i = 0; i < SMB_OPT_NUM; i++) { 1006 sc_name = smb_config_getname(smb_proto_options[i].smb_index); 1007 if (strcasecmp(sc_name, name) == 0) 1008 return (i); 1009 } 1010 1011 return (-1); 1012 } 1013 1014 /* 1015 * smb_load_proto_properties() 1016 * 1017 * read the smb config values from SMF. 1018 */ 1019 1020 static int 1021 smb_load_proto_properties() 1022 { 1023 sa_property_t prop; 1024 char value[MAX_VALUE_BUFLEN]; 1025 char *name; 1026 int index; 1027 int ret = SA_OK; 1028 int rc; 1029 1030 protoset = sa_create_protocol_properties(SMB_PROTOCOL_NAME); 1031 if (protoset == NULL) 1032 return (SA_NO_MEMORY); 1033 1034 for (index = 0; index < SMB_OPT_NUM && ret == SA_OK; index++) { 1035 rc = smb_config_get(smb_proto_options[index].smb_index, 1036 value, sizeof (value)); 1037 if (rc != SMBD_SMF_OK) 1038 continue; 1039 name = smb_config_getname(smb_proto_options[index].smb_index); 1040 prop = sa_create_property(name, value); 1041 if (prop != NULL) 1042 ret = sa_add_protocol_property(protoset, prop); 1043 else 1044 ret = SA_NO_MEMORY; 1045 } 1046 return (ret); 1047 } 1048 1049 /* 1050 * smb_share_init() 1051 * 1052 * Initialize the smb plugin. 1053 */ 1054 1055 static int 1056 smb_share_init(void) 1057 { 1058 int ret = SA_OK; 1059 1060 if (sa_plugin_ops.sa_init != smb_share_init) 1061 return (SA_SYSTEM_ERR); 1062 1063 ret = smb_load_proto_properties(); 1064 1065 return (ret); 1066 } 1067 1068 /* 1069 * smb_share_fini() 1070 * 1071 */ 1072 static void 1073 smb_share_fini(void) 1074 { 1075 xmlFreeNode(protoset); 1076 protoset = NULL; 1077 1078 (void) smb_share_dclose(); 1079 } 1080 1081 /* 1082 * smb_get_proto_set() 1083 * 1084 * Return an optionset with all the protocol specific properties in 1085 * it. 1086 */ 1087 static sa_protocol_properties_t 1088 smb_get_proto_set(void) 1089 { 1090 return (protoset); 1091 } 1092 1093 /* 1094 * smb_enable_dependencies() 1095 * 1096 * SMBD_DEFAULT_INSTANCE_FMRI may have some dependencies that aren't 1097 * enabled. This will attempt to enable all of them. 1098 */ 1099 static void 1100 smb_enable_dependencies(const char *fmri) 1101 { 1102 scf_handle_t *handle; 1103 scf_service_t *service; 1104 scf_instance_t *inst = NULL; 1105 scf_iter_t *iter; 1106 scf_property_t *prop; 1107 scf_value_t *value; 1108 scf_propertygroup_t *pg; 1109 scf_scope_t *scope; 1110 char type[SCFTYPE_LEN]; 1111 char *dependency; 1112 char *servname; 1113 int maxlen; 1114 1115 /* 1116 * Get all required handles and storage. 1117 */ 1118 handle = scf_handle_create(SCF_VERSION); 1119 if (handle == NULL) 1120 return; 1121 1122 if (scf_handle_bind(handle) != 0) { 1123 scf_handle_destroy(handle); 1124 return; 1125 } 1126 1127 maxlen = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 1128 if (maxlen == (ssize_t)-1) 1129 maxlen = MAXPATHLEN; 1130 1131 dependency = malloc(maxlen); 1132 1133 service = scf_service_create(handle); 1134 1135 iter = scf_iter_create(handle); 1136 1137 pg = scf_pg_create(handle); 1138 1139 prop = scf_property_create(handle); 1140 1141 value = scf_value_create(handle); 1142 1143 scope = scf_scope_create(handle); 1144 1145 if (service == NULL || iter == NULL || pg == NULL || prop == NULL || 1146 value == NULL || scope == NULL || dependency == NULL) 1147 goto done; 1148 1149 /* 1150 * We passed in the FMRI for the default instance but for 1151 * some things we need the simple form so construct it. Since 1152 * we reuse the storage that dependency points to, we need to 1153 * use the servname early. 1154 */ 1155 (void) snprintf(dependency, maxlen, "%s", fmri + sizeof ("svc:")); 1156 servname = strrchr(dependency, ':'); 1157 if (servname == NULL) 1158 goto done; 1159 *servname = '\0'; 1160 servname = dependency; 1161 1162 /* 1163 * Setup to iterate over the service property groups, only 1164 * looking at those that are "dependency" types. The "entity" 1165 * property will have the FMRI of the service we are dependent 1166 * on. 1167 */ 1168 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) != 0) 1169 goto done; 1170 1171 if (scf_scope_get_service(scope, servname, service) != 0) 1172 goto done; 1173 1174 if (scf_iter_service_pgs(iter, service) != 0) 1175 goto done; 1176 1177 while (scf_iter_next_pg(iter, pg) > 0) { 1178 char *services[2]; 1179 /* 1180 * Have a property group for the service. See if it is 1181 * a dependency pg and only do operations on those. 1182 */ 1183 if (scf_pg_get_type(pg, type, SCFTYPE_LEN) <= 0) 1184 continue; 1185 1186 if (strncmp(type, SCF_GROUP_DEPENDENCY, SCFTYPE_LEN) != 0) 1187 continue; 1188 /* 1189 * Have a dependency. Attempt to enable it. 1190 */ 1191 if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) != 0) 1192 continue; 1193 1194 if (scf_property_get_value(prop, value) != 0) 1195 continue; 1196 1197 services[1] = NULL; 1198 1199 if (scf_value_get_as_string(value, dependency, maxlen) > 0) { 1200 services[0] = dependency; 1201 _check_services(services); 1202 } 1203 } 1204 1205 done: 1206 if (dependency != NULL) 1207 free(dependency); 1208 if (value != NULL) 1209 scf_value_destroy(value); 1210 if (prop != NULL) 1211 scf_property_destroy(prop); 1212 if (pg != NULL) 1213 scf_pg_destroy(pg); 1214 if (iter != NULL) 1215 scf_iter_destroy(iter); 1216 if (scope != NULL) 1217 scf_scope_destroy(scope); 1218 if (inst != NULL) 1219 scf_instance_destroy(inst); 1220 if (service != NULL) 1221 scf_service_destroy(service); 1222 1223 (void) scf_handle_unbind(handle); 1224 scf_handle_destroy(handle); 1225 } 1226 1227 /* 1228 * How long to wait for service to come online 1229 */ 1230 #define WAIT_FOR_SERVICE 15 1231 1232 /* 1233 * smb_enable_service() 1234 * 1235 */ 1236 static int 1237 smb_enable_service(void) 1238 { 1239 int i; 1240 int ret = SA_OK; 1241 char *service[] = { SMBD_DEFAULT_INSTANCE_FMRI, NULL }; 1242 1243 if (!smb_isonline()) { 1244 /* 1245 * Attempt to start the idmap, and other dependent 1246 * services, first. If it fails, the SMB service will 1247 * ultimately fail so we use that as the error. If we 1248 * don't try to enable idmap, smb won't start the 1249 * first time unless the admin has done it 1250 * manually. The service could be administratively 1251 * disabled so we won't always get started. 1252 */ 1253 smb_enable_dependencies(SMBD_DEFAULT_INSTANCE_FMRI); 1254 _check_services(service); 1255 1256 /* Wait for service to come online */ 1257 for (i = 0; i < WAIT_FOR_SERVICE; i++) { 1258 if (smb_isonline()) { 1259 ret = SA_OK; 1260 break; 1261 } else if (smb_ismaint()) { 1262 /* maintenance requires help */ 1263 ret = SA_SYSTEM_ERR; 1264 break; 1265 } else if (smb_isdisabled()) { 1266 /* disabled is ok */ 1267 ret = SA_OK; 1268 break; 1269 } else { 1270 /* try another time */ 1271 ret = SA_BUSY; 1272 (void) sleep(1); 1273 } 1274 } 1275 } 1276 return (ret); 1277 } 1278 1279 /* 1280 * smb_validate_proto_prop(index, name, value) 1281 * 1282 * Verify that the property specified by name can take the new 1283 * value. This is a sanity check to prevent bad values getting into 1284 * the default files. 1285 */ 1286 static int 1287 smb_validate_proto_prop(int index, char *name, char *value) 1288 { 1289 if ((name == NULL) || (index < 0)) 1290 return (SA_BAD_VALUE); 1291 1292 if (smb_proto_options[index].validator == NULL) 1293 return (SA_OK); 1294 1295 if (smb_proto_options[index].validator(index, value) == SA_OK) 1296 return (SA_OK); 1297 return (SA_BAD_VALUE); 1298 } 1299 1300 /* 1301 * smb_set_proto_prop(prop) 1302 * 1303 * check that prop is valid. 1304 */ 1305 /*ARGSUSED*/ 1306 static int 1307 smb_set_proto_prop(sa_property_t prop) 1308 { 1309 int ret = SA_OK; 1310 char *name; 1311 char *value; 1312 int index = -1; 1313 struct smb_proto_option_defs *opt; 1314 1315 name = sa_get_property_attr(prop, "type"); 1316 value = sa_get_property_attr(prop, "value"); 1317 if (name != NULL && value != NULL) { 1318 index = findprotoopt(name); 1319 if (index >= 0) { 1320 /* should test for valid value */ 1321 ret = smb_validate_proto_prop(index, name, value); 1322 if (ret == SA_OK) { 1323 opt = &smb_proto_options[index]; 1324 1325 /* Save to SMF */ 1326 (void) smb_config_set(opt->smb_index, value); 1327 /* 1328 * Specialized refresh mechanisms can 1329 * be flagged in the proto_options and 1330 * processed here. 1331 */ 1332 if (opt->refresh & SMB_REFRESH_REFRESH) 1333 (void) smf_refresh_instance( 1334 SMBD_DEFAULT_INSTANCE_FMRI); 1335 else if (opt->refresh & SMB_REFRESH_RESTART) 1336 (void) smf_restart_instance( 1337 SMBD_DEFAULT_INSTANCE_FMRI); 1338 } 1339 } 1340 } 1341 1342 if (name != NULL) 1343 sa_free_attr_string(name); 1344 if (value != NULL) 1345 sa_free_attr_string(value); 1346 1347 return (ret); 1348 } 1349 1350 /* 1351 * smb_get_status() 1352 * 1353 * What is the current status of the smbd? We use the SMF state here. 1354 * Caller must free the returned value. 1355 */ 1356 1357 static char * 1358 smb_get_status(void) 1359 { 1360 char *state = NULL; 1361 state = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI); 1362 return (state != NULL ? state : "-"); 1363 } 1364 1365 /* 1366 * This protocol plugin require resource names 1367 */ 1368 static uint64_t 1369 smb_share_features(void) 1370 { 1371 return (SA_FEATURE_RESOURCE | SA_FEATURE_ALLOWSUBDIRS | 1372 SA_FEATURE_ALLOWPARDIRS | SA_FEATURE_SERVER); 1373 } 1374 1375 /* 1376 * This should be used to convert lmshare_info to sa_resource_t 1377 * Should only be needed to build temp shares/resources to be 1378 * supplied to sharemanager to display temp shares. 1379 */ 1380 static int 1381 smb_build_tmp_sa_resource(sa_handle_t handle, smb_share_t *si) 1382 { 1383 int err; 1384 sa_share_t share; 1385 sa_group_t group; 1386 sa_resource_t resource; 1387 1388 if (si == NULL) 1389 return (SA_INVALID_NAME); 1390 1391 /* 1392 * First determine if the "share path" is already shared 1393 * somewhere. If it is, we have to use it as the authority on 1394 * where the transient share lives so will use it's parent 1395 * group. If it doesn't exist, it needs to land in "smb". 1396 */ 1397 1398 share = sa_find_share(handle, si->shr_path); 1399 if (share != NULL) { 1400 group = sa_get_parent_group(share); 1401 } else { 1402 group = smb_get_smb_share_group(handle); 1403 if (group == NULL) 1404 return (SA_NO_SUCH_GROUP); 1405 share = sa_get_share(group, si->shr_path); 1406 if (share == NULL) { 1407 share = sa_add_share(group, si->shr_path, 1408 SA_SHARE_TRANSIENT, &err); 1409 if (share == NULL) 1410 return (SA_NO_SUCH_PATH); 1411 } 1412 } 1413 1414 /* 1415 * Now handle the resource. Make sure that the resource is 1416 * transient and added to the share. 1417 */ 1418 resource = sa_get_share_resource(share, si->shr_name); 1419 if (resource == NULL) { 1420 resource = sa_add_resource(share, 1421 si->shr_name, SA_SHARE_TRANSIENT, &err); 1422 if (resource == NULL) 1423 return (SA_NO_SUCH_RESOURCE); 1424 } 1425 1426 /* set resource attributes now */ 1427 (void) sa_set_resource_attr(resource, "description", si->shr_cmnt); 1428 (void) sa_set_resource_attr(resource, SMB_SHROPT_AD_CONTAINER, 1429 si->shr_container); 1430 1431 return (SA_OK); 1432 } 1433 1434 /* 1435 * Return smb transient shares. Note that we really want to look at 1436 * all current shares from SMB in order to determine this. Transient 1437 * shares should be those that don't appear in either the SMF or ZFS 1438 * configurations. Those that are in the repositories will be 1439 * filtered out by smb_build_tmp_sa_resource. 1440 */ 1441 static int 1442 smb_list_transient(sa_handle_t handle) 1443 { 1444 int i, offset, num; 1445 smb_shrlist_t list; 1446 int res; 1447 1448 num = smb_share_count(); 1449 if (num <= 0) 1450 return (SA_OK); 1451 offset = 0; 1452 while (smb_share_list(offset, &list) != NERR_InternalError) { 1453 if (list.no == 0) 1454 break; 1455 for (i = 0; i < list.no; i++) { 1456 res = smb_build_tmp_sa_resource(handle, 1457 &(list.smbshr[i])); 1458 if (res != SA_OK) 1459 return (res); 1460 } 1461 offset += list.no; 1462 } 1463 1464 return (SA_OK); 1465 } 1466 1467 /* 1468 * fix_resource_name(share, name, prefix) 1469 * 1470 * Construct a name where the ZFS dataset has the prefix replaced with "name". 1471 */ 1472 static char * 1473 fix_resource_name(sa_share_t share, char *name, char *prefix) 1474 { 1475 char *dataset = NULL; 1476 char *newname = NULL; 1477 size_t psize; 1478 size_t nsize; 1479 1480 dataset = sa_get_share_attr(share, "dataset"); 1481 1482 if (dataset != NULL && strcmp(dataset, prefix) != 0) { 1483 psize = strlen(prefix); 1484 if (strncmp(dataset, prefix, psize) == 0) { 1485 /* need string plus ',' and NULL */ 1486 nsize = (strlen(dataset) - psize) + strlen(name) + 2; 1487 newname = calloc(nsize, 1); 1488 if (newname != NULL) { 1489 (void) snprintf(newname, nsize, "%s%s", name, 1490 dataset + psize); 1491 sa_fix_resource_name(newname); 1492 } 1493 sa_free_attr_string(dataset); 1494 return (newname); 1495 } 1496 } 1497 if (dataset != NULL) 1498 sa_free_attr_string(dataset); 1499 return (strdup(name)); 1500 } 1501 1502 /* 1503 * smb_parse_optstring(group, options) 1504 * 1505 * parse a compact option string into individual options. This allows 1506 * ZFS sharesmb and sharemgr "share" command to work. group can be a 1507 * group, a share or a resource. 1508 */ 1509 static int 1510 smb_parse_optstring(sa_group_t group, char *options) 1511 { 1512 char *dup; 1513 char *base; 1514 char *lasts; 1515 char *token; 1516 sa_optionset_t optionset; 1517 sa_group_t parent = NULL; 1518 sa_resource_t resource = NULL; 1519 int iszfs = 0; 1520 int persist = 0; 1521 int need_optionset = 0; 1522 int ret = SA_OK; 1523 sa_property_t prop; 1524 1525 /* 1526 * In order to not attempt to change ZFS properties unless 1527 * absolutely necessary, we never do it in the legacy parsing 1528 * so we need to keep track of this. 1529 */ 1530 if (sa_is_share(group)) { 1531 char *zfs; 1532 1533 parent = sa_get_parent_group(group); 1534 if (parent != NULL) { 1535 zfs = sa_get_group_attr(parent, "zfs"); 1536 if (zfs != NULL) { 1537 sa_free_attr_string(zfs); 1538 iszfs = 1; 1539 } 1540 } 1541 } else { 1542 iszfs = sa_group_is_zfs(group); 1543 /* 1544 * If a ZFS group, then we need to see if a resource 1545 * name is being set. If so, bail with 1546 * SA_PROP_SHARE_ONLY, so we come back in with a share 1547 * instead of a group. 1548 */ 1549 if (strncmp(options, "name=", sizeof ("name=") - 1) == 0 || 1550 strstr(options, ",name=") != NULL) { 1551 return (SA_PROP_SHARE_ONLY); 1552 } 1553 } 1554 1555 /* do we have an existing optionset? */ 1556 optionset = sa_get_optionset(group, "smb"); 1557 if (optionset == NULL) { 1558 /* didn't find existing optionset so create one */ 1559 optionset = sa_create_optionset(group, "smb"); 1560 if (optionset == NULL) 1561 return (SA_NO_MEMORY); 1562 } else { 1563 /* 1564 * If an optionset already exists, we've come through 1565 * twice so ignore the second time. 1566 */ 1567 return (ret); 1568 } 1569 1570 /* We need a copy of options for the next part. */ 1571 dup = strdup(options); 1572 if (dup == NULL) 1573 return (SA_NO_MEMORY); 1574 1575 /* 1576 * SMB properties are straightforward and are strings, 1577 * integers or booleans. Properties are separated by 1578 * commas. It will be necessary to parse quotes due to some 1579 * strings not having a restricted characters set. 1580 * 1581 * Note that names will create a resource. For now, if there 1582 * is a set of properties "before" the first name="", those 1583 * properties will be placed on the group. 1584 */ 1585 persist = sa_is_persistent(group); 1586 base = dup; 1587 token = dup; 1588 lasts = NULL; 1589 while (token != NULL && ret == SA_OK) { 1590 ret = SA_OK; 1591 token = strtok_r(base, ",", &lasts); 1592 base = NULL; 1593 if (token != NULL) { 1594 char *value; 1595 /* 1596 * All SMB properties have values so there 1597 * MUST be an '=' character. If it doesn't, 1598 * it is a syntax error. 1599 */ 1600 value = strchr(token, '='); 1601 if (value != NULL) { 1602 *value++ = '\0'; 1603 } else { 1604 ret = SA_SYNTAX_ERR; 1605 break; 1606 } 1607 /* 1608 * We may need to handle a "name" property 1609 * that is a ZFS imposed resource name. Each 1610 * name would trigger getting a new "resource" 1611 * to put properties on. For now, assume no 1612 * "name" property for special handling. 1613 */ 1614 1615 if (strcmp(token, "name") == 0) { 1616 char *prefix; 1617 char *name = NULL; 1618 /* 1619 * We have a name, so now work on the 1620 * resource level. We have a "share" 1621 * in "group" due to the caller having 1622 * added it. If we are called with a 1623 * group, the check for group/share 1624 * at the beginning of this function 1625 * will bail out the parse if there is a 1626 * "name" but no share. 1627 */ 1628 if (!iszfs) { 1629 ret = SA_SYNTAX_ERR; 1630 break; 1631 } 1632 /* 1633 * Make sure the parent group has the 1634 * "prefix" property since we will 1635 * need to use this for constructing 1636 * inherited name= values. 1637 */ 1638 prefix = sa_get_group_attr(parent, "prefix"); 1639 if (prefix == NULL) { 1640 prefix = sa_get_group_attr(parent, 1641 "name"); 1642 if (prefix != NULL) { 1643 (void) sa_set_group_attr(parent, 1644 "prefix", prefix); 1645 } 1646 } 1647 name = fix_resource_name((sa_share_t)group, 1648 value, prefix); 1649 if (name != NULL) { 1650 resource = sa_add_resource( 1651 (sa_share_t)group, name, 1652 SA_SHARE_TRANSIENT, &ret); 1653 sa_free_attr_string(name); 1654 } else { 1655 ret = SA_NO_MEMORY; 1656 } 1657 if (prefix != NULL) 1658 sa_free_attr_string(prefix); 1659 1660 /* A resource level optionset is needed */ 1661 1662 need_optionset = 1; 1663 if (resource == NULL) { 1664 ret = SA_NO_MEMORY; 1665 break; 1666 } 1667 continue; 1668 } 1669 1670 if (need_optionset) { 1671 optionset = sa_create_optionset(resource, 1672 "smb"); 1673 need_optionset = 0; 1674 } 1675 1676 prop = sa_create_property(token, value); 1677 if (prop == NULL) 1678 ret = SA_NO_MEMORY; 1679 else 1680 ret = sa_add_property(optionset, prop); 1681 if (ret != SA_OK) 1682 break; 1683 if (!iszfs) 1684 ret = sa_commit_properties(optionset, !persist); 1685 } 1686 } 1687 free(dup); 1688 return (ret); 1689 } 1690 1691 /* 1692 * smb_sprint_option(rbuff, rbuffsize, incr, prop, sep) 1693 * 1694 * provides a mechanism to format SMB properties into legacy output 1695 * format. If the buffer would overflow, it is reallocated and grown 1696 * as appropriate. Special cases of converting internal form of values 1697 * to those used by "share" are done. this function does one property 1698 * at a time. 1699 */ 1700 1701 static void 1702 smb_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr, 1703 sa_property_t prop, int sep) 1704 { 1705 char *name; 1706 char *value; 1707 int curlen; 1708 char *buff = *rbuff; 1709 size_t buffsize = *rbuffsize; 1710 1711 name = sa_get_property_attr(prop, "type"); 1712 value = sa_get_property_attr(prop, "value"); 1713 if (buff != NULL) 1714 curlen = strlen(buff); 1715 else 1716 curlen = 0; 1717 if (name != NULL) { 1718 int len; 1719 len = strlen(name) + sep; 1720 1721 /* 1722 * A future RFE would be to replace this with more 1723 * generic code and to possibly handle more types. 1724 * 1725 * For now, everything else is treated as a string. If 1726 * we get any properties that aren't exactly 1727 * name/value pairs, we may need to 1728 * interpret/transform. 1729 */ 1730 if (value != NULL) 1731 len += 1 + strlen(value); 1732 1733 while (buffsize <= (curlen + len)) { 1734 /* need more room */ 1735 buffsize += incr; 1736 buff = realloc(buff, buffsize); 1737 *rbuff = buff; 1738 *rbuffsize = buffsize; 1739 if (buff == NULL) { 1740 /* realloc failed so free everything */ 1741 if (*rbuff != NULL) 1742 free(*rbuff); 1743 goto err; 1744 } 1745 } 1746 if (buff == NULL) 1747 goto err; 1748 (void) snprintf(buff + curlen, buffsize - curlen, 1749 "%s%s=%s", sep ? "," : "", 1750 name, value != NULL ? value : "\"\""); 1751 1752 } 1753 err: 1754 if (name != NULL) 1755 sa_free_attr_string(name); 1756 if (value != NULL) 1757 sa_free_attr_string(value); 1758 } 1759 1760 /* 1761 * smb_format_resource_options(resource, hier) 1762 * 1763 * format all the options on the group into a flattened option 1764 * string. If hier is non-zero, walk up the tree to get inherited 1765 * options. 1766 */ 1767 1768 static char * 1769 smb_format_options(sa_group_t group, int hier) 1770 { 1771 sa_optionset_t options = NULL; 1772 sa_property_t prop; 1773 int sep = 0; 1774 char *buff; 1775 size_t buffsize; 1776 1777 1778 buff = malloc(OPT_CHUNK); 1779 if (buff == NULL) 1780 return (NULL); 1781 1782 buff[0] = '\0'; 1783 buffsize = OPT_CHUNK; 1784 1785 /* 1786 * We may have a an optionset relative to this item. format 1787 * these if we find them and then add any security definitions. 1788 */ 1789 1790 options = sa_get_derived_optionset(group, "smb", hier); 1791 1792 /* 1793 * do the default set first but skip any option that is also 1794 * in the protocol specific optionset. 1795 */ 1796 if (options != NULL) { 1797 for (prop = sa_get_property(options, NULL); 1798 prop != NULL; prop = sa_get_next_property(prop)) { 1799 /* 1800 * use this one since we skipped any 1801 * of these that were also in 1802 * optdefault 1803 */ 1804 smb_sprint_option(&buff, &buffsize, OPT_CHUNK, 1805 prop, sep); 1806 if (buff == NULL) { 1807 /* 1808 * buff could become NULL if there 1809 * isn't enough memory for 1810 * smb_sprint_option to realloc() 1811 * as necessary. We can't really 1812 * do anything about it at this 1813 * point so we return NULL. The 1814 * caller should handle the 1815 * failure. 1816 */ 1817 if (options != NULL) 1818 sa_free_derived_optionset( 1819 options); 1820 return (buff); 1821 } 1822 sep = 1; 1823 } 1824 } 1825 1826 if (options != NULL) 1827 sa_free_derived_optionset(options); 1828 return (buff); 1829 } 1830 1831 /* 1832 * smb_rename_resource(resource, newname) 1833 * 1834 * Change the current exported name of the resource to newname. 1835 */ 1836 /*ARGSUSED*/ 1837 int 1838 smb_rename_resource(sa_handle_t handle, sa_resource_t resource, char *newname) 1839 { 1840 int ret = SA_OK; 1841 int err; 1842 char *oldname; 1843 1844 oldname = sa_get_resource_attr(resource, "name"); 1845 if (oldname == NULL) 1846 return (SA_NO_SUCH_RESOURCE); 1847 1848 err = smb_share_ren(oldname, newname); 1849 1850 /* improve error values somewhat */ 1851 switch (err) { 1852 case NERR_Success: 1853 break; 1854 case NERR_InternalError: 1855 ret = SA_SYSTEM_ERR; 1856 break; 1857 case NERR_DuplicateShare: 1858 ret = SA_DUPLICATE_NAME; 1859 break; 1860 default: 1861 ret = SA_CONFIG_ERR; 1862 break; 1863 } 1864 1865 return (ret); 1866 } 1867