Print this page
NEX-16502 libshare needs to support SMB in a zone
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10019 SMB server min_protocol setting
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-4598 SMB2 credit shortage with Mac client
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3629 CLONE NEX-3624 SMB server max_workers cannot be increased above 1024
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
4295 libshare sa_get_proto_status sometimes returns unallocated strings
Reviewed by: Marcel Telka <marcel@telka.sk>
Approved by: Garrett D'Amore <garrett@damore.org>
NEX-1050 enable_smb2 should be smb2_enable
NEX-1022 SMB2 should be enabled by default
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
re #13470 rb4432 Sync some SMB differences from illumos
re #7930 rb3848 failover error: cannot share pool/folder - smb add share failed


   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 2015 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * SMB specific functions
  29  */
  30 #include <stdio.h>
  31 #include <string.h>
  32 #include <ctype.h>
  33 #include <stdlib.h>
  34 #include <unistd.h>
  35 #include <zone.h>
  36 #include <errno.h>
  37 #include <locale.h>
  38 #include <fcntl.h>
  39 #include <sys/types.h>
  40 #include <sys/stat.h>
  41 #include <syslog.h>
  42 #include "libshare.h"
  43 #include "libshare_impl.h"
  44 #include <pwd.h>


  67 static int smb_disable_share(sa_share_t share, char *);
  68 static int smb_validate_property(sa_handle_t, sa_property_t, sa_optionset_t);
  69 static int smb_set_proto_prop(sa_property_t);
  70 static sa_protocol_properties_t smb_get_proto_set(void);
  71 static char *smb_get_status(void);
  72 static int smb_parse_optstring(sa_group_t, char *);
  73 static char *smb_format_options(sa_group_t, int);
  74 
  75 static int smb_enable_service(void);
  76 
  77 static int range_check_validator(int, char *);
  78 static int range_check_validator_zero_ok(int, char *);
  79 static int string_length_check_validator(int, char *);
  80 static int print_enable_validator(int, char *);
  81 static int true_false_validator(int, char *);
  82 static int ipv4_validator(int, char *);
  83 static int hostname_validator(int, char *);
  84 static int path_validator(int, char *);
  85 static int cmd_validator(int, char *);
  86 static int disposition_validator(int, char *);
  87 static int max_protocol_validator(int, char *);

  88 
  89 static int smb_enable_resource(sa_resource_t);
  90 static int smb_disable_resource(sa_resource_t);
  91 static uint64_t smb_share_features(void);
  92 static int smb_list_transient(sa_handle_t);
  93 
  94 static int smb_build_shareinfo(sa_share_t, sa_resource_t, smb_share_t *);
  95 static void smb_csc_option(const char *, smb_share_t *);
  96 static char *smb_csc_name(const smb_share_t *);
  97 static sa_group_t smb_get_defaultgrp(sa_handle_t);
  98 static int interface_validator(int, char *);
  99 static int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
 100 
 101 static boolean_t smb_saprop_getbool(sa_optionset_t, char *);
 102 static boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
 103 
 104 static struct {
 105         char *value;
 106         uint32_t flag;
 107 } cscopt[] = {
 108         { "disabled",   SMB_SHRF_CSC_DISABLED },
 109         { "manual",     SMB_SHRF_CSC_MANUAL },
 110         { "auto",       SMB_SHRF_CSC_AUTO },
 111         { "vdo",        SMB_SHRF_CSC_VDO }
 112 };
 113 
 114 /* size of basic format allocation */
 115 #define OPT_CHUNK       1024
 116 
 117 /* size of string for types - big enough to hold "dependency" */
 118 #define SCFTYPE_LEN     32
 119 
 120 /*
 121  * Indexes of entries in smb_proto_options table.


 161         smb_list_transient,
 162         smb_resource_changed,
 163         smb_rename_resource,
 164         NULL,   /* run_command */
 165         NULL,   /* command_help */
 166         NULL    /* delete_proto_section */
 167 };
 168 
 169 struct option_defs optdefs[] = {
 170         { SHOPT_AD_CONTAINER,   OPT_TYPE_STRING },
 171         { SHOPT_ABE,            OPT_TYPE_BOOLEAN },
 172         { SHOPT_NAME,           OPT_TYPE_NAME },
 173         { SHOPT_RO,             OPT_TYPE_ACCLIST },
 174         { SHOPT_RW,             OPT_TYPE_ACCLIST },
 175         { SHOPT_NONE,           OPT_TYPE_ACCLIST },
 176         { SHOPT_CATIA,          OPT_TYPE_BOOLEAN },
 177         { SHOPT_CSC,            OPT_TYPE_CSC },
 178         { SHOPT_GUEST,          OPT_TYPE_BOOLEAN },
 179         { SHOPT_DFSROOT,        OPT_TYPE_BOOLEAN },
 180         { SHOPT_DESCRIPTION,    OPT_TYPE_STRING },




 181         { NULL, NULL }
 182 };
 183 
 184 /*
 185  * findopt(name)
 186  *
 187  * Lookup option "name" in the option table and return the table
 188  * index.
 189  */
 190 static int
 191 findopt(char *name)
 192 {
 193         int i;
 194         if (name != NULL) {
 195                 for (i = 0; optdefs[i].tag != NULL; i++) {
 196                         if (strcmp(optdefs[i].tag, name) == 0)
 197                                 return (i);
 198                 }
 199         }
 200         return (-1);


 369         if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) {
 370                 ret = (strcmp(str, SCF_STATE_STRING_MAINT) == 0);
 371                 free(str);
 372         }
 373         return (ret);
 374 }
 375 
 376 /*
 377  * smb_enable_share tells the implementation that it is to enable the share.
 378  * This entails converting the path and options into the appropriate ioctl
 379  * calls. It is assumed that all error checking of paths, etc. were
 380  * done earlier.
 381  */
 382 static int
 383 smb_enable_share(sa_share_t share)
 384 {
 385         char *path;
 386         smb_share_t si;
 387         sa_resource_t resource;
 388         boolean_t iszfs;
 389         boolean_t privileged;
 390         int err = SA_OK;
 391         priv_set_t *priv_effective;
 392         boolean_t online;
 393 
 394         /*
 395          * Don't support Trusted Extensions.
 396          */
 397         if (is_system_labeled()) {
 398                 (void) printf(dgettext(TEXT_DOMAIN,
 399                     "SMB: service not supported with Trusted Extensions\n"));
 400                 return (SA_NOT_SUPPORTED);
 401         }
 402 
 403         priv_effective = priv_allocset();
 404         (void) getppriv(PRIV_EFFECTIVE, priv_effective);
 405         privileged = (priv_isfullset(priv_effective) == B_TRUE);
 406         priv_freeset(priv_effective);
 407 
 408         /* get the path since it is important in several places */
 409         path = sa_get_share_attr(share, "path");
 410         if (path == NULL)
 411                 return (SA_NO_SUCH_PATH);
 412 
 413         /*
 414          * If administratively disabled, don't try to start anything.
 415          */
 416         online = smb_isonline();
 417         if (!online && !smb_isautoenable() && smb_isdisabled())
 418                 goto done;
 419 
 420         iszfs = sa_path_is_zfs(path);
 421 
 422         if (iszfs) {
 423 
 424                 if (privileged == B_FALSE && !online) {
 425 
 426                         if (!online) {
 427                                 (void) printf(dgettext(TEXT_DOMAIN,
 428                                     "SMB: Cannot share remove "
 429                                     "file system: %s\n"), path);
 430                                 (void) printf(dgettext(TEXT_DOMAIN,
 431                                     "SMB: Service needs to be enabled "
 432                                     "by a privileged user\n"));
 433                                 err = SA_NO_PERMISSION;
 434                                 errno = EPERM;
 435                         }
 436                         if (err) {
 437                                 sa_free_attr_string(path);
 438                                 return (err);
 439                         }
 440 
 441                 }
 442         }
 443 
 444         if (privileged == B_TRUE && !online) {
 445                 err = smb_enable_service();
 446                 if (err != SA_OK) {
 447                         (void) printf(dgettext(TEXT_DOMAIN,
 448                             "SMB: Unable to enable service\n"));
 449                 } else {
 450                         online = B_TRUE;
 451                 }
 452         }
 453 
 454         /*
 455          * Don't bother trying to start shares if the service isn't
 456          * running.
 457          */
 458         if (!online)
 459                 goto done;
 460 
 461         /* Each share can have multiple resources */
 462         for (resource = sa_get_share_resource(share, NULL);
 463             resource != NULL;
 464             resource = sa_get_next_resource(resource)) {


 897             SMB_REFRESH_REFRESH },
 898         { SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator,
 899             SMB_REFRESH_REFRESH },
 900         { SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN,
 901             hostname_validator, SMB_REFRESH_REFRESH },
 902         { SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN,
 903             string_length_check_validator, SMB_REFRESH_REFRESH },
 904         { SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, 0 },
 905         { SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, path_validator, 0 },
 906         { SMB_CI_IPV6_ENABLE, 0, 0, true_false_validator,
 907             SMB_REFRESH_REFRESH },
 908         { SMB_CI_PRINT_ENABLE, 0, 0, print_enable_validator,
 909             SMB_REFRESH_REFRESH },
 910         { SMB_CI_TRAVERSE_MOUNTS, 0, 0, true_false_validator,
 911             SMB_REFRESH_REFRESH },
 912         { SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
 913         { SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
 914             SMB_REFRESH_REFRESH },
 915         { SMB_CI_DISPOSITION, 0, MAX_VALUE_BUFLEN,
 916             disposition_validator, SMB_REFRESH_REFRESH },
 917         { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, max_protocol_validator,
 918             SMB_REFRESH_REFRESH },








 919 };
 920 
 921 #define SMB_OPT_NUM \
 922         (sizeof (smb_proto_options) / sizeof (smb_proto_options[0]))
 923 


















 924 /*
 925  * Check the range of value as int range.
 926  */
 927 static int
 928 range_check_validator(int index, char *value)
 929 {
 930         int ret = SA_OK;
 931 
 932         if (!is_a_number(value)) {
 933                 ret = SA_BAD_VALUE;
 934         } else {
 935                 int val;
 936                 val = strtoul(value, NULL, 0);
 937                 if (val < smb_proto_options[index].minval ||
 938                     val > smb_proto_options[index].maxval)
 939                         ret = SA_BAD_VALUE;
 940         }
 941         return (ret);
 942 }
 943 


1517 static int
1518 smb_set_proto_prop(sa_property_t prop)
1519 {
1520         int ret = SA_OK;
1521         char *name;
1522         char *value;
1523         int index = -1;
1524         struct smb_proto_option_defs *opt;
1525 
1526         name = sa_get_property_attr(prop, "type");
1527         value = sa_get_property_attr(prop, "value");
1528         if (name != NULL && value != NULL) {
1529                 index = findprotoopt(name);
1530                 if (index >= 0) {
1531                         /* should test for valid value */
1532                         ret = smb_validate_proto_prop(index, name, value);
1533                         if (ret == SA_OK) {
1534                                 opt = &smb_proto_options[index];
1535 
1536                                 /* Save to SMF */
1537                                 (void) smb_config_set(opt->smb_index, value);




1538                                 /*
1539                                  * Specialized refresh mechanisms can
1540                                  * be flagged in the proto_options and
1541                                  * processed here.
1542                                  */
1543                                 if (opt->refresh & SMB_REFRESH_REFRESH)
1544                                         (void) smf_refresh_instance(
1545                                             SMBD_DEFAULT_INSTANCE_FMRI);
1546                                 else if (opt->refresh & SMB_REFRESH_RESTART)
1547                                         (void) smf_restart_instance(
1548                                             SMBD_DEFAULT_INSTANCE_FMRI);
1549                         }
1550                 }
1551         }
1552 

1553         if (name != NULL)
1554                 sa_free_attr_string(name);
1555         if (value != NULL)
1556                 sa_free_attr_string(value);
1557 
1558         return (ret);
1559 }
1560 
1561 /*
1562  * smb_get_status()
1563  *
1564  * What is the current status of the smbd? We use the SMF state here.
1565  * Caller must free the returned value.
1566  */
1567 
1568 static char *
1569 smb_get_status(void)
1570 {
1571         return (smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI));
1572 }


2098                 break;
2099         case NERR_DuplicateShare:
2100                 ret = SA_DUPLICATE_NAME;
2101                 break;
2102         default:
2103                 ret = SA_CONFIG_ERR;
2104                 break;
2105         }
2106 
2107         return (ret);
2108 }
2109 
2110 static int
2111 smb_build_shareinfo(sa_share_t share, sa_resource_t resource, smb_share_t *si)
2112 {
2113         sa_optionset_t opts;
2114         char *path;
2115         char *rname;
2116         char *val = NULL;
2117         char csc_value[SMB_CSC_BUFSZ];

2118 
2119         bzero(si, sizeof (smb_share_t));
2120 
2121         if ((path = sa_get_share_attr(share, "path")) == NULL)
2122                 return (SA_NO_SUCH_PATH);
2123 
2124         if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
2125                 sa_free_attr_string(path);
2126                 return (SA_NO_SUCH_RESOURCE);
2127         }
2128 
2129         (void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
2130         (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
2131         sa_free_attr_string(path);
2132         sa_free_attr_string(rname);
2133 
2134         val = sa_get_resource_description(resource);
2135         if (val == NULL)
2136                 val = sa_get_share_description(share);
2137 
2138         if (val != NULL) {
2139                 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
2140                 sa_free_share_description(val);
2141         }
2142 
2143         si->shr_flags = (sa_is_persistent(share))
2144             ? SMB_SHRF_PERM : SMB_SHRF_TRANS;
2145 
2146         opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
2147         if (opts == NULL)
2148                 return (SA_OK);
2149 
2150         if (smb_saprop_getbool(opts, SHOPT_CATIA))
2151                 si->shr_flags |= SMB_SHRF_CATIA;
2152 
2153         if (smb_saprop_getbool(opts, SHOPT_ABE))
2154                 si->shr_flags |= SMB_SHRF_ABE;
2155 
2156         if (smb_saprop_getbool(opts, SHOPT_GUEST))
2157                 si->shr_flags |= SMB_SHRF_GUEST_OK;
2158 
2159         if (smb_saprop_getbool(opts, SHOPT_DFSROOT))
2160                 si->shr_flags |= SMB_SHRF_DFSROOT;
2161 













2162         (void) smb_saprop_getstr(opts, SHOPT_AD_CONTAINER, si->shr_container,
2163             sizeof (si->shr_container));
2164 
2165         if (smb_saprop_getstr(opts, SHOPT_CSC, csc_value, sizeof (csc_value)))
2166                 smb_csc_option(csc_value, si);
2167 
2168         if (smb_saprop_getstr(opts, SHOPT_RO, si->shr_access_ro,
2169             sizeof (si->shr_access_ro)))
2170                 si->shr_flags |= SMB_SHRF_ACC_RO;
2171 
2172         if (smb_saprop_getstr(opts, SHOPT_RW, si->shr_access_rw,
2173             sizeof (si->shr_access_rw)))
2174                 si->shr_flags |= SMB_SHRF_ACC_RW;
2175 
2176         if (smb_saprop_getstr(opts, SHOPT_NONE, si->shr_access_none,
2177             sizeof (si->shr_access_none)))
2178                 si->shr_flags |= SMB_SHRF_ACC_NONE;
2179 
2180         sa_free_derived_optionset(opts);
2181         return (SA_OK);


2330 
2331 /*ARGSUSED*/
2332 static int
2333 disposition_validator(int index, char *value)
2334 {
2335         if (value == NULL)
2336                 return (SA_BAD_VALUE);
2337 
2338         if (*value == '\0')
2339                 return (SA_OK);
2340 
2341         if ((strcasecmp(value, SMB_EXEC_DISP_CONTINUE) == 0) ||
2342             (strcasecmp(value, SMB_EXEC_DISP_TERMINATE) == 0))
2343                 return (SA_OK);
2344 
2345         return (SA_BAD_VALUE);
2346 }
2347 
2348 /*ARGSUSED*/
2349 static int
2350 max_protocol_validator(int index, char *value)
2351 {
2352         if (value == NULL)
2353                 return (SA_BAD_VALUE);
2354 
2355         if (*value == '\0')
2356                 return (SA_OK);
2357 
2358         if (smb_config_check_protocol(value) == 0)
2359                 return (SA_OK);
2360 
2361         return (SA_BAD_VALUE);
2362 
2363 }
2364 
2365 /*
2366  * Updates the optionset properties of the share resource.
2367  * The properties are given as a list of name-value pair.
2368  * The name argument should be the optionset property name and the value
2369  * should be a valid value for the specified property.
2370  *


2406                                         (void) sa_remove_property(prop);
2407                                         break;
2408                                 }
2409                         }
2410                         err = sa_add_property(opts, prop);
2411                         if (err != SA_OK)
2412                                 break;
2413                 } else {
2414                         err = sa_update_property(prop, val);
2415                         if (err != SA_OK)
2416                                 break;
2417                 }
2418 
2419                 cur = nvlist_next_nvpair(nvl, cur);
2420         }
2421 
2422         return (err);
2423 }
2424 
2425 static boolean_t
2426 smb_saprop_getbool(sa_optionset_t opts, char *propname)
2427 {
2428         sa_property_t prop;
2429         char *val;
2430         boolean_t propval = B_FALSE;
2431 
2432         prop = sa_get_property(opts, propname);
2433         if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2434                 if ((strcasecmp(val, "true") == 0) || (strcmp(val, "1") == 0))
2435                         propval = B_TRUE;









2436                 free(val);
2437         }
2438 
2439         return (propval);
2440 }
2441 
2442 static boolean_t
2443 smb_saprop_getstr(sa_optionset_t opts, char *propname, char *buf, size_t bufsz)
2444 {
2445         sa_property_t prop;
2446         char *val;
2447 
2448         prop = sa_get_property(opts, propname);
2449         if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2450                 (void) strlcpy(buf, val, bufsz);
2451                 free(val);
2452                 return (B_TRUE);
2453         }
2454 
2455         return (B_FALSE);
2456 }


   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  */
  26 
  27 /*
  28  * SMB specific functions
  29  */
  30 #include <stdio.h>
  31 #include <string.h>
  32 #include <ctype.h>
  33 #include <stdlib.h>
  34 #include <unistd.h>
  35 #include <zone.h>
  36 #include <errno.h>
  37 #include <locale.h>
  38 #include <fcntl.h>
  39 #include <sys/types.h>
  40 #include <sys/stat.h>
  41 #include <syslog.h>
  42 #include "libshare.h"
  43 #include "libshare_impl.h"
  44 #include <pwd.h>


  67 static int smb_disable_share(sa_share_t share, char *);
  68 static int smb_validate_property(sa_handle_t, sa_property_t, sa_optionset_t);
  69 static int smb_set_proto_prop(sa_property_t);
  70 static sa_protocol_properties_t smb_get_proto_set(void);
  71 static char *smb_get_status(void);
  72 static int smb_parse_optstring(sa_group_t, char *);
  73 static char *smb_format_options(sa_group_t, int);
  74 
  75 static int smb_enable_service(void);
  76 
  77 static int range_check_validator(int, char *);
  78 static int range_check_validator_zero_ok(int, char *);
  79 static int string_length_check_validator(int, char *);
  80 static int print_enable_validator(int, char *);
  81 static int true_false_validator(int, char *);
  82 static int ipv4_validator(int, char *);
  83 static int hostname_validator(int, char *);
  84 static int path_validator(int, char *);
  85 static int cmd_validator(int, char *);
  86 static int disposition_validator(int, char *);
  87 static int protocol_validator(int, char *);
  88 static int require_validator(int, char *);
  89 
  90 static int smb_enable_resource(sa_resource_t);
  91 static int smb_disable_resource(sa_resource_t);
  92 static uint64_t smb_share_features(void);
  93 static int smb_list_transient(sa_handle_t);
  94 
  95 static int smb_build_shareinfo(sa_share_t, sa_resource_t, smb_share_t *);
  96 static void smb_csc_option(const char *, smb_share_t *);
  97 static char *smb_csc_name(const smb_share_t *);
  98 static sa_group_t smb_get_defaultgrp(sa_handle_t);
  99 static int interface_validator(int, char *);
 100 static int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
 101 
 102 static boolean_t smb_saprop_getbool(sa_optionset_t, char *, boolean_t);
 103 static boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
 104 
 105 static struct {
 106         char *value;
 107         uint32_t flag;
 108 } cscopt[] = {
 109         { "disabled",   SMB_SHRF_CSC_DISABLED },
 110         { "manual",     SMB_SHRF_CSC_MANUAL },
 111         { "auto",       SMB_SHRF_CSC_AUTO },
 112         { "vdo",        SMB_SHRF_CSC_VDO }
 113 };
 114 
 115 /* size of basic format allocation */
 116 #define OPT_CHUNK       1024
 117 
 118 /* size of string for types - big enough to hold "dependency" */
 119 #define SCFTYPE_LEN     32
 120 
 121 /*
 122  * Indexes of entries in smb_proto_options table.


 162         smb_list_transient,
 163         smb_resource_changed,
 164         smb_rename_resource,
 165         NULL,   /* run_command */
 166         NULL,   /* command_help */
 167         NULL    /* delete_proto_section */
 168 };
 169 
 170 struct option_defs optdefs[] = {
 171         { SHOPT_AD_CONTAINER,   OPT_TYPE_STRING },
 172         { SHOPT_ABE,            OPT_TYPE_BOOLEAN },
 173         { SHOPT_NAME,           OPT_TYPE_NAME },
 174         { SHOPT_RO,             OPT_TYPE_ACCLIST },
 175         { SHOPT_RW,             OPT_TYPE_ACCLIST },
 176         { SHOPT_NONE,           OPT_TYPE_ACCLIST },
 177         { SHOPT_CATIA,          OPT_TYPE_BOOLEAN },
 178         { SHOPT_CSC,            OPT_TYPE_CSC },
 179         { SHOPT_GUEST,          OPT_TYPE_BOOLEAN },
 180         { SHOPT_DFSROOT,        OPT_TYPE_BOOLEAN },
 181         { SHOPT_DESCRIPTION,    OPT_TYPE_STRING },
 182         { SHOPT_CA,             OPT_TYPE_BOOLEAN },
 183         { SHOPT_FSO,            OPT_TYPE_BOOLEAN },
 184         { SHOPT_QUOTAS,         OPT_TYPE_BOOLEAN },
 185         { SHOPT_ENCRYPT,        OPT_TYPE_STRING },
 186         { NULL, NULL }
 187 };
 188 
 189 /*
 190  * findopt(name)
 191  *
 192  * Lookup option "name" in the option table and return the table
 193  * index.
 194  */
 195 static int
 196 findopt(char *name)
 197 {
 198         int i;
 199         if (name != NULL) {
 200                 for (i = 0; optdefs[i].tag != NULL; i++) {
 201                         if (strcmp(optdefs[i].tag, name) == 0)
 202                                 return (i);
 203                 }
 204         }
 205         return (-1);


 374         if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) {
 375                 ret = (strcmp(str, SCF_STATE_STRING_MAINT) == 0);
 376                 free(str);
 377         }
 378         return (ret);
 379 }
 380 
 381 /*
 382  * smb_enable_share tells the implementation that it is to enable the share.
 383  * This entails converting the path and options into the appropriate ioctl
 384  * calls. It is assumed that all error checking of paths, etc. were
 385  * done earlier.
 386  */
 387 static int
 388 smb_enable_share(sa_share_t share)
 389 {
 390         char *path;
 391         smb_share_t si;
 392         sa_resource_t resource;
 393         boolean_t iszfs;

 394         int err = SA_OK;

 395         boolean_t online;
 396 
 397         /*
 398          * Don't support Trusted Extensions.
 399          */
 400         if (is_system_labeled()) {
 401                 (void) printf(dgettext(TEXT_DOMAIN,
 402                     "SMB: service not supported with Trusted Extensions\n"));
 403                 return (SA_NOT_SUPPORTED);
 404         }
 405 





 406         /* get the path since it is important in several places */
 407         path = sa_get_share_attr(share, "path");
 408         if (path == NULL)
 409                 return (SA_NO_SUCH_PATH);
 410 
 411         /*
 412          * If administratively disabled, don't try to start anything.
 413          */
 414         online = smb_isonline();
 415         if (!online && !smb_isautoenable() && smb_isdisabled())
 416                 goto done;
 417 
 418         iszfs = sa_path_is_zfs(path);
 419 




 420         if (!online) {


















 421                 err = smb_enable_service();
 422                 if (err != SA_OK) {
 423                         (void) printf(dgettext(TEXT_DOMAIN,
 424                             "SMB: Unable to enable service\n"));
 425                 } else {
 426                         online = B_TRUE;
 427                 }
 428         }
 429 
 430         /*
 431          * Don't bother trying to start shares if the service isn't
 432          * running.
 433          */
 434         if (!online)
 435                 goto done;
 436 
 437         /* Each share can have multiple resources */
 438         for (resource = sa_get_share_resource(share, NULL);
 439             resource != NULL;
 440             resource = sa_get_next_resource(resource)) {


 873             SMB_REFRESH_REFRESH },
 874         { SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator,
 875             SMB_REFRESH_REFRESH },
 876         { SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN,
 877             hostname_validator, SMB_REFRESH_REFRESH },
 878         { SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN,
 879             string_length_check_validator, SMB_REFRESH_REFRESH },
 880         { SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, 0 },
 881         { SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, path_validator, 0 },
 882         { SMB_CI_IPV6_ENABLE, 0, 0, true_false_validator,
 883             SMB_REFRESH_REFRESH },
 884         { SMB_CI_PRINT_ENABLE, 0, 0, print_enable_validator,
 885             SMB_REFRESH_REFRESH },
 886         { SMB_CI_TRAVERSE_MOUNTS, 0, 0, true_false_validator,
 887             SMB_REFRESH_REFRESH },
 888         { SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
 889         { SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
 890             SMB_REFRESH_REFRESH },
 891         { SMB_CI_DISPOSITION, 0, MAX_VALUE_BUFLEN,
 892             disposition_validator, SMB_REFRESH_REFRESH },
 893         { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
 894             SMB_REFRESH_REFRESH },
 895         { SMB_CI_ENCRYPT, 0, MAX_VALUE_BUFLEN, require_validator,
 896             SMB_REFRESH_REFRESH },
 897         { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
 898             SMB_REFRESH_REFRESH },
 899         { SMB_CI_BYPASS_TRAVERSE_CHECKING, 0, 0, true_false_validator,
 900             SMB_REFRESH_REFRESH },
 901         { SMB_CI_OPLOCK_ENABLE, 0, 0, true_false_validator,
 902             SMB_REFRESH_REFRESH },
 903 };
 904 
 905 #define SMB_OPT_NUM \
 906         (sizeof (smb_proto_options) / sizeof (smb_proto_options[0]))
 907 
 908 static int
 909 require_validator(int index, char *value)
 910 {
 911         if (string_length_check_validator(index, value) != SA_OK)
 912                 return (SA_BAD_VALUE);
 913 
 914         if (strcmp(value, "required") == 0)
 915                 return (SA_OK);
 916 
 917         if (strcmp(value, "disabled") == 0)
 918                 return (SA_OK);
 919 
 920         if (strcmp(value, "enabled") == 0)
 921                 return (SA_OK);
 922 
 923         return (SA_BAD_VALUE);
 924 }
 925 
 926 /*
 927  * Check the range of value as int range.
 928  */
 929 static int
 930 range_check_validator(int index, char *value)
 931 {
 932         int ret = SA_OK;
 933 
 934         if (!is_a_number(value)) {
 935                 ret = SA_BAD_VALUE;
 936         } else {
 937                 int val;
 938                 val = strtoul(value, NULL, 0);
 939                 if (val < smb_proto_options[index].minval ||
 940                     val > smb_proto_options[index].maxval)
 941                         ret = SA_BAD_VALUE;
 942         }
 943         return (ret);
 944 }
 945 


1519 static int
1520 smb_set_proto_prop(sa_property_t prop)
1521 {
1522         int ret = SA_OK;
1523         char *name;
1524         char *value;
1525         int index = -1;
1526         struct smb_proto_option_defs *opt;
1527 
1528         name = sa_get_property_attr(prop, "type");
1529         value = sa_get_property_attr(prop, "value");
1530         if (name != NULL && value != NULL) {
1531                 index = findprotoopt(name);
1532                 if (index >= 0) {
1533                         /* should test for valid value */
1534                         ret = smb_validate_proto_prop(index, name, value);
1535                         if (ret == SA_OK) {
1536                                 opt = &smb_proto_options[index];
1537 
1538                                 /* Save to SMF */
1539                                 if (smb_config_set(opt->smb_index,
1540                                     value) != 0) {
1541                                         ret = SA_BAD_VALUE;
1542                                         goto out;
1543                                 }
1544                                 /*
1545                                  * Specialized refresh mechanisms can
1546                                  * be flagged in the proto_options and
1547                                  * processed here.
1548                                  */
1549                                 if (opt->refresh & SMB_REFRESH_REFRESH)
1550                                         (void) smf_refresh_instance(
1551                                             SMBD_DEFAULT_INSTANCE_FMRI);
1552                                 else if (opt->refresh & SMB_REFRESH_RESTART)
1553                                         (void) smf_restart_instance(
1554                                             SMBD_DEFAULT_INSTANCE_FMRI);
1555                         }
1556                 }
1557         }
1558 
1559 out:
1560         if (name != NULL)
1561                 sa_free_attr_string(name);
1562         if (value != NULL)
1563                 sa_free_attr_string(value);
1564 
1565         return (ret);
1566 }
1567 
1568 /*
1569  * smb_get_status()
1570  *
1571  * What is the current status of the smbd? We use the SMF state here.
1572  * Caller must free the returned value.
1573  */
1574 
1575 static char *
1576 smb_get_status(void)
1577 {
1578         return (smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI));
1579 }


2105                 break;
2106         case NERR_DuplicateShare:
2107                 ret = SA_DUPLICATE_NAME;
2108                 break;
2109         default:
2110                 ret = SA_CONFIG_ERR;
2111                 break;
2112         }
2113 
2114         return (ret);
2115 }
2116 
2117 static int
2118 smb_build_shareinfo(sa_share_t share, sa_resource_t resource, smb_share_t *si)
2119 {
2120         sa_optionset_t opts;
2121         char *path;
2122         char *rname;
2123         char *val = NULL;
2124         char csc_value[SMB_CSC_BUFSZ];
2125         char strbuf[sizeof ("required")];
2126 
2127         bzero(si, sizeof (smb_share_t));
2128 
2129         if ((path = sa_get_share_attr(share, "path")) == NULL)
2130                 return (SA_NO_SUCH_PATH);
2131 
2132         if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
2133                 sa_free_attr_string(path);
2134                 return (SA_NO_SUCH_RESOURCE);
2135         }
2136 
2137         (void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
2138         (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
2139         sa_free_attr_string(path);
2140         sa_free_attr_string(rname);
2141 
2142         val = sa_get_resource_description(resource);
2143         if (val == NULL)
2144                 val = sa_get_share_description(share);
2145 
2146         if (val != NULL) {
2147                 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
2148                 sa_free_share_description(val);
2149         }
2150 
2151         si->shr_flags = (sa_is_persistent(share))
2152             ? SMB_SHRF_PERM : SMB_SHRF_TRANS;
2153 
2154         opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
2155         if (opts == NULL)
2156                 return (SA_OK);
2157 
2158         if (smb_saprop_getbool(opts, SHOPT_CATIA, B_FALSE))
2159                 si->shr_flags |= SMB_SHRF_CATIA;
2160 
2161         if (smb_saprop_getbool(opts, SHOPT_ABE, B_FALSE))
2162                 si->shr_flags |= SMB_SHRF_ABE;
2163 
2164         if (smb_saprop_getbool(opts, SHOPT_GUEST, B_FALSE))
2165                 si->shr_flags |= SMB_SHRF_GUEST_OK;
2166 
2167         if (smb_saprop_getbool(opts, SHOPT_DFSROOT, B_FALSE))
2168                 si->shr_flags |= SMB_SHRF_DFSROOT;
2169 
2170         if (smb_saprop_getbool(opts, SHOPT_CA, B_FALSE))
2171                 si->shr_flags |= SMB_SHRF_CA;
2172 
2173         if (smb_saprop_getbool(opts, SHOPT_FSO, B_FALSE))
2174                 si->shr_flags |= SMB_SHRF_FSO;
2175 
2176         /* Quotas are enabled by default. */
2177         if (smb_saprop_getbool(opts, SHOPT_QUOTAS, B_TRUE))
2178                 si->shr_flags |= SMB_SHRF_QUOTAS;
2179 
2180         if (smb_saprop_getstr(opts, SHOPT_ENCRYPT, strbuf, sizeof (strbuf)))
2181                 smb_cfg_set_require(strbuf, &si->shr_encrypt);
2182 
2183         (void) smb_saprop_getstr(opts, SHOPT_AD_CONTAINER, si->shr_container,
2184             sizeof (si->shr_container));
2185 
2186         if (smb_saprop_getstr(opts, SHOPT_CSC, csc_value, sizeof (csc_value)))
2187                 smb_csc_option(csc_value, si);
2188 
2189         if (smb_saprop_getstr(opts, SHOPT_RO, si->shr_access_ro,
2190             sizeof (si->shr_access_ro)))
2191                 si->shr_flags |= SMB_SHRF_ACC_RO;
2192 
2193         if (smb_saprop_getstr(opts, SHOPT_RW, si->shr_access_rw,
2194             sizeof (si->shr_access_rw)))
2195                 si->shr_flags |= SMB_SHRF_ACC_RW;
2196 
2197         if (smb_saprop_getstr(opts, SHOPT_NONE, si->shr_access_none,
2198             sizeof (si->shr_access_none)))
2199                 si->shr_flags |= SMB_SHRF_ACC_NONE;
2200 
2201         sa_free_derived_optionset(opts);
2202         return (SA_OK);


2351 
2352 /*ARGSUSED*/
2353 static int
2354 disposition_validator(int index, char *value)
2355 {
2356         if (value == NULL)
2357                 return (SA_BAD_VALUE);
2358 
2359         if (*value == '\0')
2360                 return (SA_OK);
2361 
2362         if ((strcasecmp(value, SMB_EXEC_DISP_CONTINUE) == 0) ||
2363             (strcasecmp(value, SMB_EXEC_DISP_TERMINATE) == 0))
2364                 return (SA_OK);
2365 
2366         return (SA_BAD_VALUE);
2367 }
2368 
2369 /*ARGSUSED*/
2370 static int
2371 protocol_validator(int index, char *value)
2372 {
2373         if (value == NULL)
2374                 return (SA_BAD_VALUE);
2375 
2376         if (*value == '\0')
2377                 return (SA_OK);
2378 
2379         if (smb_config_check_protocol(value) == 0)
2380                 return (SA_OK);
2381 
2382         return (SA_BAD_VALUE);
2383 
2384 }
2385 
2386 /*
2387  * Updates the optionset properties of the share resource.
2388  * The properties are given as a list of name-value pair.
2389  * The name argument should be the optionset property name and the value
2390  * should be a valid value for the specified property.
2391  *


2427                                         (void) sa_remove_property(prop);
2428                                         break;
2429                                 }
2430                         }
2431                         err = sa_add_property(opts, prop);
2432                         if (err != SA_OK)
2433                                 break;
2434                 } else {
2435                         err = sa_update_property(prop, val);
2436                         if (err != SA_OK)
2437                                 break;
2438                 }
2439 
2440                 cur = nvlist_next_nvpair(nvl, cur);
2441         }
2442 
2443         return (err);
2444 }
2445 
2446 static boolean_t
2447 smb_saprop_getbool(sa_optionset_t opts, char *propname, boolean_t def)
2448 {
2449         sa_property_t prop;
2450         char *val;
2451         boolean_t ret = def;
2452 
2453         prop = sa_get_property(opts, propname);
2454         if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2455                 if (def) {
2456                         /* Default is true, ret false if... */
2457                         if ((strcasecmp(val, "false") == 0) ||
2458                             (strcmp(val, "0") == 0))
2459                                 ret = B_FALSE;
2460                 } else {
2461                         /* Default is false, ret true if... */
2462                         if ((strcasecmp(val, "true") == 0) ||
2463                             (strcmp(val, "1") == 0))
2464                                 ret = B_TRUE;
2465                 }
2466                 free(val);
2467         }
2468 
2469         return (ret);
2470 }
2471 
2472 static boolean_t
2473 smb_saprop_getstr(sa_optionset_t opts, char *propname, char *buf, size_t bufsz)
2474 {
2475         sa_property_t prop;
2476         char *val;
2477 
2478         prop = sa_get_property(opts, propname);
2479         if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2480                 (void) strlcpy(buf, val, bufsz);
2481                 free(val);
2482                 return (B_TRUE);
2483         }
2484 
2485         return (B_FALSE);
2486 }